diff mbox

[08/40] xenner: kernel: 64-bit files

Message ID 1288623713-28062-9-git-send-email-agraf@suse.de
State New
Headers show

Commit Message

Alexander Graf Nov. 1, 2010, 3:01 p.m. UTC
This patch adds various header files required for the xenner kernel on 64 bit
systems.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 pc-bios/xenner/xenner64.S   |  400 +++++++++++++++++++++++++++++++++++++++++++
 pc-bios/xenner/xenner64.h   |  117 +++++++++++++
 pc-bios/xenner/xenner64.lds |   38 ++++
 3 files changed, 555 insertions(+), 0 deletions(-)
 create mode 100644 pc-bios/xenner/xenner64.S
 create mode 100644 pc-bios/xenner/xenner64.h
 create mode 100644 pc-bios/xenner/xenner64.lds

Comments

Anthony Liguori Nov. 1, 2010, 3:44 p.m. UTC | #1
On 11/01/2010 10:01 AM, Alexander Graf wrote:
> This patch adds various header files required for the xenner kernel on 64 bit
> systems.
>
> Signed-off-by: Alexander Graf<agraf@suse.de>
>    

I think it might make more sense to put this on a separate git.qemu.org 
repository and then use a submodule in roms/.

I'm happy to setup access for you/Gerd and it can use qemu-devel as a 
mailing list.

Regards,

Anthony Liguori

> ---
>   pc-bios/xenner/xenner64.S   |  400 +++++++++++++++++++++++++++++++++++++++++++
>   pc-bios/xenner/xenner64.h   |  117 +++++++++++++
>   pc-bios/xenner/xenner64.lds |   38 ++++
>   3 files changed, 555 insertions(+), 0 deletions(-)
>   create mode 100644 pc-bios/xenner/xenner64.S
>   create mode 100644 pc-bios/xenner/xenner64.h
>   create mode 100644 pc-bios/xenner/xenner64.lds
>
> diff --git a/pc-bios/xenner/xenner64.S b/pc-bios/xenner/xenner64.S
> new file mode 100644
> index 0000000..b140214
> --- /dev/null
> +++ b/pc-bios/xenner/xenner64.S
> @@ -0,0 +1,400 @@
> +#define	ENTRY(name) \
> +	.globl name; \
> +	.align 16; \
> +	name:
> +
> +	.macro PUSH_ERROR
> +	sub $8, %rsp		/* space for error code */
> +	.endm
> +
> +	.macro PUSH_TRAP_RBP trapno
> +	sub $8, %rsp		/* space for trap number */
> +	push %rbp
> +	mov $\trapno, %rbp
> +	mov %rbp, 8(%rsp)	/* save trap number on stack */
> +	.endm
> +
> +	.macro PUSH_REGS
> +	push %rdi
> +	push %rsi
> +	push %r15
> +	push %r14
> +	push %r13
> +	push %r12
> +	push %r11
> +	push %r10
> +	push %r9
> +	push %r8
> +	push %rdx
> +	push %rcx
> +	push %rbx
> +	push %rax
> +	mov  %rsp,%rdi		/* struct regs pointer */
> +	.endm
> +
> +	.macro POP_REGS
> +	pop %rax
> +	pop %rbx
> +	pop %rcx
> +	pop %rdx
> +	pop %r8
> +	pop %r9
> +	pop %r10
> +	pop %r11
> +	pop %r12
> +	pop %r13
> +	pop %r14
> +	pop %r15
> +	pop %rsi
> +	pop %rdi
> +	pop %rbp
> +	.endm
> +
> +	.macro RETURN
> +	add $16, %rsp		/* remove error code&  trap number */
> +	iretq			/* jump back */
> +	.endm
> +
> +	.macro DO_TRAP trapno func
> +	PUSH_TRAP_RBP \trapno
> +	PUSH_REGS
> +	call \func
> +	POP_REGS
> +	RETURN
> +	.endm
> +
> +/* ------------------------------------------------------------------ */
> +
> +	.code64
> +	.text
> +
> +/* --- 16-bit boot entry point --- */
> +
> +ENTRY(boot)
> +	.code16
> +
> +	cli
> +
> +	/* load the GDT */
> +	lgdt	(gdt_desc - boot)
> +
> +	/* turn on long mode and paging */
> +	mov	$0x1, %eax
> +	mov	%eax, %cr0
> +
> +	/* enable pagetables */
> +	mov	$(boot_pgd - boot), %eax
> +	mov	%eax, %cr3
> +
> +	/* set PSE,  PAE */
> +	mov	$0x30, %eax
> +	mov	%eax, %cr4
> +
> +	/* long mode */
> +	mov	$0xc0000080, %ecx
> +	rdmsr
> +	or	$0x101, %eax
> +	wrmsr
> +
> +	/* turn on long mode and paging */
> +	mov	$0x80010001, %eax
> +	mov	%eax, %cr0
> +
> +	ljmp	$0x8, $(boot64 - boot)
> +
> +
> +.align 4, 0
> +gdt:
> +.byte   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* dummy */
> +.byte   0xff, 0xff, 0x00, 0x00, 0x00, 0x9b, 0xaf, 0x00 /* code64 */
> +.byte   0xff, 0xff, 0x00, 0x00, 0x00, 0x93, 0xaf, 0x00 /* data64 */
> +
> +gdt_desc:
> +.short  (3 * 8) - 1
> +.long   (gdt - boot)
> +
> +
> +/* --- 64-bit entry point --- */
> +
> +boot64:
> +	.code64
> +
> +	mov $0x10, %ax
> +	mov %ax, %ds
> +	mov %ax, %es
> +	mov %ax, %fs
> +	mov %ax, %gs
> +	mov %ax, %ss
> +
> +	jmpq	*(boot64_ind - boot)
> +
> +boot64_ind:
> +	.quad boot64_real
> +
> +boot64_real:
> +
> +	/* switch to real pagetables */
> +	mov	$(emu_pgd - boot), %rax
> +	mov	%rax, %cr3
> +
> +	lea boot_stack_high(%rip), %rsp	/* setup stack */
> +	sub $176, %rsp			/* sizeof(struct regs_64) */
> +	mov  %rsp,%rdi			/* struct regs pointer */
> +	cmp $0, %rbx
> +	jne secondary
> +	call do_boot
> +	POP_REGS
> +	RETURN
> +
> +secondary:
> +	mov  %rdi,%rsi
> +	mov  %rbx,%rdi
> +	call do_boot_secondary
> +	POP_REGS
> +	RETURN
> +
> +/* --- traps/faults handled by emu --- */
> +
> +ENTRY(debug_int1)
> +	PUSH_ERROR
> +	DO_TRAP 1 do_int1
> +
> +ENTRY(debug_int3)
> +	PUSH_ERROR
> +	DO_TRAP 3 do_int3
> +
> +ENTRY(illegal_instruction)
> +	PUSH_ERROR
> +	DO_TRAP 6 do_illegal_instruction
> +
> +ENTRY(no_device)
> +	PUSH_ERROR
> +	DO_TRAP 7 do_lazy_fpu
> +
> +ENTRY(double_fault)
> +	DO_TRAP 8 do_double_fault
> +
> +ENTRY(general_protection)
> +	DO_TRAP 13 do_general_protection
> +
> +ENTRY(page_fault)
> +	DO_TRAP 14 do_page_fault
> +
> +/* --- traps/faults forwarded to guest --- */
> +
> +ENTRY(division_by_zero)
> +	PUSH_ERROR
> +	PUSH_TRAP_RBP 0
> +	jmp guest_forward
> +
> +ENTRY(nmi)
> +	PUSH_ERROR
> +	PUSH_TRAP_RBP 2
> +	jmp guest_forward
> +
> +ENTRY(overflow)
> +	PUSH_ERROR
> +	PUSH_TRAP_RBP 4
> +	jmp guest_forward
> +
> +ENTRY(bound_check)
> +	PUSH_ERROR
> +	PUSH_TRAP_RBP 5
> +	jmp guest_forward
> +
> +ENTRY(coprocessor)
> +	PUSH_ERROR
> +	PUSH_TRAP_RBP 9
> +	jmp guest_forward
> +
> +ENTRY(invalid_tss)
> +	PUSH_TRAP_RBP 10
> +	jmp guest_forward
> +
> +ENTRY(segment_not_present)
> +	PUSH_TRAP_RBP 11
> +	jmp guest_forward
> +
> +ENTRY(stack_fault)
> +	PUSH_TRAP_RBP 12
> +	jmp guest_forward
> +
> +ENTRY(floating_point)
> +	PUSH_ERROR
> +	PUSH_TRAP_RBP 16
> +	jmp guest_forward
> +
> +ENTRY(alignment)
> +	PUSH_TRAP_RBP 17
> +	jmp guest_forward
> +
> +ENTRY(machine_check)
> +	PUSH_ERROR
> +	PUSH_TRAP_RBP 18
> +	jmp guest_forward
> +
> +ENTRY(simd_floating_point)
> +	PUSH_ERROR
> +	PUSH_TRAP_RBP 19
> +	jmp guest_forward
> +
> +guest_forward:
> +	PUSH_REGS
> +	call do_guest_forward
> +	POP_REGS
> +	RETURN
> +
> +/* --- interrupts 32 ... 255 --- */
> +
> +ENTRY(smp_flush_tlb)
> +	PUSH_ERROR
> +	DO_TRAP -1 do_smp_flush_tlb
> +
> +ENTRY(int_80)
> +	PUSH_ERROR
> +	DO_TRAP -1 do_int_80
> +
> +ENTRY(irq_entries)
> +vector=0
> +.rept 256
> +	.align 16
> +	PUSH_ERROR
> +	PUSH_TRAP_RBP vector
> +	jmp irq_common
> +vector=vector+1
> +.endr
> +
> +ENTRY(irq_common)
> +	PUSH_REGS
> +	call do_irq
> +	POP_REGS
> +	RETURN
> +
> +/* --- syscall --- */
> +
> +ENTRY(trampoline_syscall)
> +	/* we arrive here via per-cpu trampoline
> +	 * which sets up the stack for us */
> +	PUSH_ERROR
> +	PUSH_TRAP_RBP -1
> +	PUSH_REGS
> +	call do_syscall
> +	POP_REGS
> +
> +	add $16, %rsp			/* remove error code + trapno */
> +	cmp $-1, -8(%rsp)
> +	je syscall_vmexit
> +	cmp $-2, -8(%rsp)
> +	je syscall_iretq
> +
> +syscall_default:
> +	/* default sysret path */
> +	popq %rcx			/* rip    */
> +	popq %r11			/* cs     */
> +	popq %r11			/* rflags */
> +	popq %rsp			/* rsp    */
> +	sysretq
> +
> +syscall_vmexit:
> +	/* bounce hypercall to userspace */
> +	popq %rcx			/* rip    */
> +	popq %r11			/* cs     */
> +	popq %r11			/* rflags */
> +	popq %rsp			/* rsp    */
> +	out %al, $0xe0			/* let userspace handle it */
> +	sysretq
> +
> +syscall_iretq:
> +	/* return from syscall via iretq */
> +	iretq
> +
> +/* helpers */
> +
> +ENTRY(broken_memcpy_pf)
> +	mov %rdx,%rcx
> +	cld
> +1:	rep movsb
> +	xor %rax,%rax
> +8:	ret
> +
> +	.section .exfix, "ax"
> +9:	mov $-1, %rax
> +	jmp 8b
> +	.previous
> +
> +	.section .extab, "a"
> +	.align 8
> +	.quad 1b,9b
> +	.previous
> +
> +/* some 16 bit code for smp boot */
> +
> +	.code16
> +	.align 4096
> +ENTRY(sipi)
> +	mov $0x00060000, %eax  /* EMUDEV_CMD_INIT_SECONDARY_VCPU */
> +	outl %eax, $0xe8       /* EMUDEV_REG_COMMAND */
> +	hlt
> +	.code64
> +
> +/* emu boot stack, including syscall trampoline template */
> +
> +	.data
> +	.globl boot_stack_low, boot_stack_high
> +	.globl cpu_ptr
> +	.globl trampoline_start, trampoline_patch, trampoline_stop
> +	.align 4096
> +boot_stack_low:
> +cpu_ptr:
> +	.quad 0
> +trampoline_start:
> +	movq %rsp, boot_stack_high-16(%rip)
> +	leaq boot_stack_high-16(%rip), %rsp
> +	push %r11				/* rflags	 */
> +	mov  $0xdeadbeef, %r11			/* C code must fix cs&  ss */
> +	movq %r11, boot_stack_high-8(%rip)	/* ss	     */
> +	push %r11				/* cs	     */
> +	push %rcx				/* rip	    */
> +
> +	.byte 0x49, 0xbb			/* mov data, %r11 ...	 */
> +trampoline_patch:
> +	.quad 0					/* ... data, for jump to ...  */
> +	jmpq *%r11				/* ... trampoline_syscall     */
> +trampoline_stop:
> +	.align 4096
> +boot_stack_high:
> +
> +/* boot page tables */
> +
> +#define pageflags 0x063 /* preset, rw, accessed, dirty */
> +#define largepage 0x080 /* pse */
> +
> +	.section .pt, "aw"
> +	.globl emu_pgd
> +
> +	.align 4096
> +boot_pgd:
> +	.quad emu_pud - 0xffff830000000000 + pageflags
> +	.fill 261,8,0
> +	.quad emu_pud - 0xffff830000000000 + pageflags
> +	.fill 249,8,0
> +
> +	.align 4096
> +emu_pgd:
> +	.fill 262,8,0
> +	.quad emu_pud - 0xffff830000000000 + pageflags
> +	.fill 249,8,0
> +
> +	.align 4096
> +emu_pud:
> +	.quad emu_pmd - 0xffff830000000000 + pageflags
> +	.fill 511,8,0
> +
> +	.align 4096
> +emu_pmd:
> +i = 0
> +	.rept 512
> +	.quad pageflags + largepage | (i<<  21)
> +	i = i + 1
> +	.endr
> +	.align 4096
> diff --git a/pc-bios/xenner/xenner64.h b/pc-bios/xenner/xenner64.h
> new file mode 100644
> index 0000000..92d956e
> --- /dev/null
> +++ b/pc-bios/xenner/xenner64.h
> @@ -0,0 +1,117 @@
> +#include<xen/foreign/x86_64.h>
> +
> +struct regs_64 {
> +    /* pushed onto stack before calling into C code */
> +    uint64_t rax;
> +    uint64_t rbx;
> +    uint64_t rcx;
> +    uint64_t rdx;
> +    uint64_t r8;
> +    uint64_t r9;
> +    uint64_t r10;
> +    uint64_t r11;
> +    uint64_t r12;
> +    uint64_t r13;
> +    uint64_t r14;
> +    uint64_t r15;
> +    uint64_t rsi;
> +    uint64_t rdi;
> +    uint64_t rbp;
> +    uint64_t trapno;
> +    /* trap / fault / int created */
> +    uint64_t error;
> +    uint64_t rip;
> +    uint64_t cs;
> +    uint64_t rflags;
> +    uint64_t rsp;
> +    uint64_t ss;
> +};
> +
> +/* 64bit defines */
> +#define EMUNAME   "xenner64"
> +#define regs      regs_64
> +#define fix_sel   fix_sel64
> +#define fix_desc  fix_desc64
> +#define ureg_t    uint64_t
> +#define sreg_t    int64_t
> +#define PRIxREG   PRIx64
> +#define tss(_v)   ((0xe000>>  3) +  8 + (((_v)->id)<<  2))
> +#define ldt(_v)   ((0xe000>>  3) + 10 + (((_v)->id)<<  2))
> +
> +/* xenner-data.c */
> +extern struct idt_64 page_aligned xen_idt[256];
> +
> +/* xenner-main.c */
> +asmlinkage void do_int_80(struct regs_64 *regs);
> +
> +/* xenner-hcall.c */
> +void switch_mode(struct xen_cpu *cpu);
> +int is_kernel(struct xen_cpu *cpu);
> +asmlinkage void do_syscall(struct regs_64 *regs);
> +
> +/* xenner-mm.c */
> +void pgtable_walk(int level, uint64_t va, uint64_t root_mfn);
> +int pgtable_fixup_flag(struct xen_cpu *cpu, uint64_t va, uint32_t flag);
> +int pgtable_is_present(uint64_t va, uint64_t root_mfn);
> +void *map_page(uint64_t maddr);
> +void *fixmap_page(struct xen_cpu *cpu, uint64_t maddr);
> +static inline void free_page(void *ptr) {}
> +uint64_t *find_pte_64(uint64_t va);
> +
> +/* macros */
> +#define context_is_emu(_r)       (((_r)->cs&  0x03) == 0x00)
> +#define context_is_kernel(_v,_r) (((_r)->cs&  0x03) == 0x03&&  is_kernel(_v))
> +#define context_is_user(_v,_r)   (((_r)->cs&  0x03) == 0x03&&  !is_kernel(_v))
> +
> +#define addr_is_emu(va)     (((va)>= XEN_M2P_64)&&  ((va)<  XEN_DOM_64))
> +#define addr_is_kernel(va)  ((va)>= XEN_DOM_64)
> +#define addr_is_user(va)    ((va)<  XEN_M2P_64)
> +
> +/* inline asm bits */
> +static inline int wrmsr_safe(uint32_t msr, uint32_t ax, uint32_t dx)
> +{
> +    int ret;
> +    asm volatile("1:  wrmsr                \n"
> +                 "    xorl %0,%0           \n"
> +                 "2:  nop                  \n"
> +
> +                 ".section .exfix, \"ax\"  \n"
> +                 "3:  mov $-1,%0           \n"
> +                 "    jmp 2b               \n"
> +                 ".previous                \n"
> +
> +                 ".section .extab, \"a\"   \n"
> +                 "    .align 8             \n"
> +                 "    .quad 1b,3b          \n"
> +                 ".previous                \n"
> +                 : "=r" (ret)
> +                 : "c" (msr), "a" (ax), "d" (dx));
> +    return ret;
> +}
> +
> +static inline int memcpy_pf(void *dest, const void *src, size_t bytes)
> +{
> +    int ret;
> +
> +    asm volatile("    cld                  \n"
> +                 "91: rep movsb            \n"
> +                 "    xor %[ret],%[ret]    \n"
> +                 "98:                      \n"
> +
> +                 ".section .exfix, \"ax\"  \n"
> +                 "99: mov $-1, %[ret]      \n"
> +                 "    jmp 98b              \n"
> +                 ".previous                \n"
> +
> +                 ".section .extab, \"a\"   \n"
> +                 "    .align 8             \n"
> +                 "    .quad 91b,99b        \n"
> +                 ".previous                \n"
> +                 : [ ret ] "=a" (ret),
> +                   [ rsi ] "+S" (src),
> +                   [ rdi ] "+D" (dest),
> +                   [ rcx ] "+c" (bytes)
> +                 :
> +                 : "memory" );
> +    return ret;
> +}
> diff --git a/pc-bios/xenner/xenner64.lds b/pc-bios/xenner/xenner64.lds
> new file mode 100644
> index 0000000..0b580a9
> --- /dev/null
> +++ b/pc-bios/xenner/xenner64.lds
> @@ -0,0 +1,38 @@
> +OUTPUT_FORMAT("elf64-x86-64")
> +
> +SECTIONS
> +{
> +    . = 0xffff830000000000;
> +    _vstart = .;
> +    phys_startup_64 = 0x0;
> +
> +    /* code */
> +    .text : AT(ADDR(.text) - 0xffff830000000000) { *(.text) }
> +    . = ALIGN(4k);
> +    .exfix  : { *(.exfix)  }
> +
> +    /* data, ro */
> +    . = ALIGN(4k);
> +    .note.gnu.build-id : { *(.note.gnu.build-id) }
> +    . = ALIGN(4k);
> +    _estart = .;
> +    .extab  : { *(.extab)  }
> +    _estop  = .;
> +    . = ALIGN(4k);
> +    .rodata : { *(.rodata) }
> +
> +    /* data, rw */
> +    . = ALIGN(4k);
> +    .pt     : { *(.pt) }
> +    . = ALIGN(4k);
> +    .pgdata : { *(.pgdata) }
> +    . = ALIGN(4k);
> +    .data   : { *(.data)   }
> +
> +    /* bss */
> +    . = ALIGN(4k);
> +    .bss    : { *(.bss)    }
> +
> +    . = ALIGN(4k);
> +    _vstop  = .;
> +}
>
Alexander Graf Nov. 1, 2010, 3:47 p.m. UTC | #2
On 01.11.2010, at 11:44, Anthony Liguori wrote:

> On 11/01/2010 10:01 AM, Alexander Graf wrote:
>> This patch adds various header files required for the xenner kernel on 64 bit
>> systems.
>> 
>> Signed-off-by: Alexander Graf<agraf@suse.de>
>>   
> 
> I think it might make more sense to put this on a separate git.qemu.org repository and then use a submodule in roms/.

The main reason why I wanted to have it fully in the qemu tree is so that we can guarantee the qemu<->xenner interface is 100% private. I'm not sure how much it'll be in a flux, but I don't want to go through the hassle of defining stable ABIs where we don't have to :)


Alex
Anthony Liguori Nov. 1, 2010, 3:59 p.m. UTC | #3
On 11/01/2010 10:47 AM, Alexander Graf wrote:
> On 01.11.2010, at 11:44, Anthony Liguori wrote:
>
>    
>> On 11/01/2010 10:01 AM, Alexander Graf wrote:
>>      
>>> This patch adds various header files required for the xenner kernel on 64 bit
>>> systems.
>>>
>>> Signed-off-by: Alexander Graf<agraf@suse.de>
>>>
>>>        
>> I think it might make more sense to put this on a separate git.qemu.org repository and then use a submodule in roms/.
>>      
> The main reason why I wanted to have it fully in the qemu tree is so that we can guarantee the qemu<->xenner interface is 100% private. I'm not sure how much it'll be in a flux, but I don't want to go through the hassle of defining stable ABIs where we don't have to :)
>    

Yeah, I'm not suggesting it be a separate project.  But we've been 
keeping firmware out of tree for the most part and using submodules.  I 
like this model (even though git submodules don't always work the way 
you expect them to..).

I'm not passionate either way.  If you feel strongly about it being in 
the main source tree, I don't have a problem with it.  But stick it in 
roms/ instead of pc-bios.

Regards,

Anthony Liguori

> Alex
>
>
Blue Swirl Nov. 1, 2010, 7 p.m. UTC | #4
On Mon, Nov 1, 2010 at 3:47 PM, Alexander Graf <agraf@suse.de> wrote:
>
> On 01.11.2010, at 11:44, Anthony Liguori wrote:
>
>> On 11/01/2010 10:01 AM, Alexander Graf wrote:
>>> This patch adds various header files required for the xenner kernel on 64 bit
>>> systems.
>>>
>>> Signed-off-by: Alexander Graf<agraf@suse.de>
>>>
>>
>> I think it might make more sense to put this on a separate git.qemu.org repository and then use a submodule in roms/.
>
> The main reason why I wanted to have it fully in the qemu tree is so that we can guarantee the qemu<->xenner interface is 100% private. I'm not sure how much it'll be in a flux, but I don't want to go through the hassle of defining stable ABIs where we don't have to :)

How is this different from SeaBIOS or OpenBIOS, both use fw_cfg
interface? Also, after the ABI has stabilized (in the future), will
you detach xenner from QEMU tree since this argument is no longer
valid?
Anthony Liguori Nov. 1, 2010, 7:02 p.m. UTC | #5
On 11/01/2010 02:00 PM, Blue Swirl wrote:
> On Mon, Nov 1, 2010 at 3:47 PM, Alexander Graf<agraf@suse.de>  wrote:
>    
>> On 01.11.2010, at 11:44, Anthony Liguori wrote:
>>
>>      
>>> On 11/01/2010 10:01 AM, Alexander Graf wrote:
>>>        
>>>> This patch adds various header files required for the xenner kernel on 64 bit
>>>> systems.
>>>>
>>>> Signed-off-by: Alexander Graf<agraf@suse.de>
>>>>
>>>>          
>>> I think it might make more sense to put this on a separate git.qemu.org repository and then use a submodule in roms/.
>>>        
>> The main reason why I wanted to have it fully in the qemu tree is so that we can guarantee the qemu<->xenner interface is 100% private. I'm not sure how much it'll be in a flux, but I don't want to go through the hassle of defining stable ABIs where we don't have to :)
>>      
> How is this different from SeaBIOS or OpenBIOS, both use fw_cfg
> interface?

At least with SeaBIOS, we don't provide a stable ABI.  That's why we 
ship a specific version in roms/.

Regards,

Anthony Liguori

>   Also, after the ABI has stabilized (in the future), will
> you detach xenner from QEMU tree since this argument is no longer
> valid?
>
Alexander Graf Nov. 1, 2010, 7:05 p.m. UTC | #6
On 01.11.2010, at 15:02, Anthony Liguori wrote:

> On 11/01/2010 02:00 PM, Blue Swirl wrote:
>> On Mon, Nov 1, 2010 at 3:47 PM, Alexander Graf<agraf@suse.de>  wrote:
>>   
>>> On 01.11.2010, at 11:44, Anthony Liguori wrote:
>>> 
>>>     
>>>> On 11/01/2010 10:01 AM, Alexander Graf wrote:
>>>>       
>>>>> This patch adds various header files required for the xenner kernel on 64 bit
>>>>> systems.
>>>>> 
>>>>> Signed-off-by: Alexander Graf<agraf@suse.de>
>>>>> 
>>>>>         
>>>> I think it might make more sense to put this on a separate git.qemu.org repository and then use a submodule in roms/.
>>>>       
>>> The main reason why I wanted to have it fully in the qemu tree is so that we can guarantee the qemu<->xenner interface is 100% private. I'm not sure how much it'll be in a flux, but I don't want to go through the hassle of defining stable ABIs where we don't have to :)
>>>     
>> How is this different from SeaBIOS or OpenBIOS, both use fw_cfg
>> interface?
> 
> At least with SeaBIOS, we don't provide a stable ABI.  That's why we ship a specific version in roms/.

So if we can assume that the interface is 100% internal and can break at any time and there's no guarantee that a newer version of qemu works with an older version of xenner or vice versa, I'm perfectly fine in making it its own project :)


Alex
Blue Swirl Nov. 1, 2010, 7:23 p.m. UTC | #7
On Mon, Nov 1, 2010 at 7:05 PM, Alexander Graf <agraf@suse.de> wrote:
>
> On 01.11.2010, at 15:02, Anthony Liguori wrote:
>
>> On 11/01/2010 02:00 PM, Blue Swirl wrote:
>>> On Mon, Nov 1, 2010 at 3:47 PM, Alexander Graf<agraf@suse.de>  wrote:
>>>
>>>> On 01.11.2010, at 11:44, Anthony Liguori wrote:
>>>>
>>>>
>>>>> On 11/01/2010 10:01 AM, Alexander Graf wrote:
>>>>>
>>>>>> This patch adds various header files required for the xenner kernel on 64 bit
>>>>>> systems.
>>>>>>
>>>>>> Signed-off-by: Alexander Graf<agraf@suse.de>
>>>>>>
>>>>>>
>>>>> I think it might make more sense to put this on a separate git.qemu.org repository and then use a submodule in roms/.
>>>>>
>>>> The main reason why I wanted to have it fully in the qemu tree is so that we can guarantee the qemu<->xenner interface is 100% private. I'm not sure how much it'll be in a flux, but I don't want to go through the hassle of defining stable ABIs where we don't have to :)
>>>>
>>> How is this different from SeaBIOS or OpenBIOS, both use fw_cfg
>>> interface?
>>
>> At least with SeaBIOS, we don't provide a stable ABI.  That's why we ship a specific version in roms/.
>
> So if we can assume that the interface is 100% internal and can break at any time and there's no guarantee that a newer version of qemu works with an older version of xenner or vice versa, I'm perfectly fine in making it its own project :)

This is the same situation as with OpenBIOS. We also ship known good
pc-bios/openbios-* files to help bisection etc.
Anthony Liguori Nov. 1, 2010, 7:37 p.m. UTC | #8
On 11/01/2010 02:05 PM, Alexander Graf wrote:
> So if we can assume that the interface is 100% internal and can break at any time and there's no guarantee that a newer version of qemu works with an older version of xenner or vice versa, I'm perfectly fine in making it its own project :)
>    

Not necessarily a totally independent project, just another repository 
or module.  It helps scale the project overall I think.

Regards,

Anthony Liguori

>
> Alex
>
>
diff mbox

Patch

diff --git a/pc-bios/xenner/xenner64.S b/pc-bios/xenner/xenner64.S
new file mode 100644
index 0000000..b140214
--- /dev/null
+++ b/pc-bios/xenner/xenner64.S
@@ -0,0 +1,400 @@ 
+#define	ENTRY(name) \
+	.globl name; \
+	.align 16; \
+	name:
+
+	.macro PUSH_ERROR
+	sub $8, %rsp		/* space for error code */
+	.endm
+
+	.macro PUSH_TRAP_RBP trapno
+	sub $8, %rsp		/* space for trap number */
+	push %rbp
+	mov $\trapno, %rbp
+	mov %rbp, 8(%rsp)	/* save trap number on stack */
+	.endm
+
+	.macro PUSH_REGS
+	push %rdi
+	push %rsi
+	push %r15
+	push %r14
+	push %r13
+	push %r12
+	push %r11
+	push %r10
+	push %r9
+	push %r8
+	push %rdx
+	push %rcx
+	push %rbx
+	push %rax
+	mov  %rsp,%rdi		/* struct regs pointer */
+	.endm
+
+	.macro POP_REGS
+	pop %rax
+	pop %rbx
+	pop %rcx
+	pop %rdx
+	pop %r8
+	pop %r9
+	pop %r10
+	pop %r11
+	pop %r12
+	pop %r13
+	pop %r14
+	pop %r15
+	pop %rsi
+	pop %rdi
+	pop %rbp
+	.endm
+
+	.macro RETURN
+	add $16, %rsp		/* remove error code & trap number */
+	iretq			/* jump back */
+	.endm
+
+	.macro DO_TRAP trapno func
+	PUSH_TRAP_RBP \trapno
+	PUSH_REGS
+	call \func
+	POP_REGS
+	RETURN
+	.endm
+
+/* ------------------------------------------------------------------ */
+
+	.code64
+	.text
+
+/* --- 16-bit boot entry point --- */
+
+ENTRY(boot)
+	.code16
+
+	cli
+
+	/* load the GDT */
+	lgdt	(gdt_desc - boot)
+
+	/* turn on long mode and paging */
+	mov	$0x1, %eax
+	mov	%eax, %cr0
+
+	/* enable pagetables */
+	mov	$(boot_pgd - boot), %eax
+	mov	%eax, %cr3
+
+	/* set PSE,  PAE */
+	mov	$0x30, %eax
+	mov	%eax, %cr4
+
+	/* long mode */
+	mov	$0xc0000080, %ecx
+	rdmsr
+	or	$0x101, %eax
+	wrmsr
+
+	/* turn on long mode and paging */
+	mov	$0x80010001, %eax
+	mov	%eax, %cr0
+
+	ljmp	$0x8, $(boot64 - boot)
+
+
+.align 4, 0
+gdt:
+.byte   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* dummy */
+.byte   0xff, 0xff, 0x00, 0x00, 0x00, 0x9b, 0xaf, 0x00 /* code64 */
+.byte   0xff, 0xff, 0x00, 0x00, 0x00, 0x93, 0xaf, 0x00 /* data64 */
+
+gdt_desc:
+.short  (3 * 8) - 1
+.long   (gdt - boot)
+
+
+/* --- 64-bit entry point --- */
+
+boot64:
+	.code64
+
+	mov $0x10, %ax
+	mov %ax, %ds
+	mov %ax, %es
+	mov %ax, %fs
+	mov %ax, %gs
+	mov %ax, %ss
+
+	jmpq	*(boot64_ind - boot)
+
+boot64_ind:
+	.quad boot64_real
+
+boot64_real:
+
+	/* switch to real pagetables */
+	mov	$(emu_pgd - boot), %rax
+	mov	%rax, %cr3
+
+	lea boot_stack_high(%rip), %rsp	/* setup stack */
+	sub $176, %rsp			/* sizeof(struct regs_64) */
+	mov  %rsp,%rdi			/* struct regs pointer */
+	cmp $0, %rbx
+	jne secondary
+	call do_boot
+	POP_REGS
+	RETURN
+
+secondary:
+	mov  %rdi,%rsi
+	mov  %rbx,%rdi
+	call do_boot_secondary
+	POP_REGS
+	RETURN
+
+/* --- traps/faults handled by emu --- */
+
+ENTRY(debug_int1)
+	PUSH_ERROR
+	DO_TRAP 1 do_int1
+
+ENTRY(debug_int3)
+	PUSH_ERROR
+	DO_TRAP 3 do_int3
+
+ENTRY(illegal_instruction)
+	PUSH_ERROR
+	DO_TRAP 6 do_illegal_instruction
+
+ENTRY(no_device)
+	PUSH_ERROR
+	DO_TRAP 7 do_lazy_fpu
+
+ENTRY(double_fault)
+	DO_TRAP 8 do_double_fault
+
+ENTRY(general_protection)
+	DO_TRAP 13 do_general_protection
+
+ENTRY(page_fault)
+	DO_TRAP 14 do_page_fault
+
+/* --- traps/faults forwarded to guest --- */
+
+ENTRY(division_by_zero)
+	PUSH_ERROR
+	PUSH_TRAP_RBP 0
+	jmp guest_forward
+
+ENTRY(nmi)
+	PUSH_ERROR
+	PUSH_TRAP_RBP 2
+	jmp guest_forward
+
+ENTRY(overflow)
+	PUSH_ERROR
+	PUSH_TRAP_RBP 4
+	jmp guest_forward
+
+ENTRY(bound_check)
+	PUSH_ERROR
+	PUSH_TRAP_RBP 5
+	jmp guest_forward
+
+ENTRY(coprocessor)
+	PUSH_ERROR
+	PUSH_TRAP_RBP 9
+	jmp guest_forward
+
+ENTRY(invalid_tss)
+	PUSH_TRAP_RBP 10
+	jmp guest_forward
+
+ENTRY(segment_not_present)
+	PUSH_TRAP_RBP 11
+	jmp guest_forward
+
+ENTRY(stack_fault)
+	PUSH_TRAP_RBP 12
+	jmp guest_forward
+
+ENTRY(floating_point)
+	PUSH_ERROR
+	PUSH_TRAP_RBP 16
+	jmp guest_forward
+
+ENTRY(alignment)
+	PUSH_TRAP_RBP 17
+	jmp guest_forward
+
+ENTRY(machine_check)
+	PUSH_ERROR
+	PUSH_TRAP_RBP 18
+	jmp guest_forward
+
+ENTRY(simd_floating_point)
+	PUSH_ERROR
+	PUSH_TRAP_RBP 19
+	jmp guest_forward
+
+guest_forward:
+	PUSH_REGS
+	call do_guest_forward
+	POP_REGS
+	RETURN
+
+/* --- interrupts 32 ... 255 --- */
+
+ENTRY(smp_flush_tlb)
+	PUSH_ERROR
+	DO_TRAP -1 do_smp_flush_tlb
+
+ENTRY(int_80)
+	PUSH_ERROR
+	DO_TRAP -1 do_int_80
+
+ENTRY(irq_entries)
+vector=0
+.rept 256
+	.align 16
+	PUSH_ERROR
+	PUSH_TRAP_RBP vector
+	jmp irq_common
+vector=vector+1
+.endr
+
+ENTRY(irq_common)
+	PUSH_REGS
+	call do_irq
+	POP_REGS
+	RETURN
+
+/* --- syscall --- */
+
+ENTRY(trampoline_syscall)
+	/* we arrive here via per-cpu trampoline
+	 * which sets up the stack for us */
+	PUSH_ERROR
+	PUSH_TRAP_RBP -1
+	PUSH_REGS
+	call do_syscall
+	POP_REGS
+
+	add $16, %rsp			/* remove error code + trapno */
+	cmp $-1, -8(%rsp)
+	je syscall_vmexit
+	cmp $-2, -8(%rsp)
+	je syscall_iretq
+
+syscall_default:
+	/* default sysret path */
+	popq %rcx			/* rip    */
+	popq %r11			/* cs     */
+	popq %r11			/* rflags */
+	popq %rsp			/* rsp    */
+	sysretq
+
+syscall_vmexit:
+	/* bounce hypercall to userspace */
+	popq %rcx			/* rip    */
+	popq %r11			/* cs     */
+	popq %r11			/* rflags */
+	popq %rsp			/* rsp    */
+	out %al, $0xe0			/* let userspace handle it */
+	sysretq
+
+syscall_iretq:
+	/* return from syscall via iretq */
+	iretq
+
+/* helpers */
+
+ENTRY(broken_memcpy_pf)
+	mov %rdx,%rcx
+	cld
+1:	rep movsb
+	xor %rax,%rax
+8:	ret
+
+	.section .exfix, "ax"
+9:	mov $-1, %rax
+	jmp 8b
+	.previous
+
+	.section .extab, "a"
+	.align 8
+	.quad 1b,9b
+	.previous
+
+/* some 16 bit code for smp boot */
+
+	.code16
+	.align 4096
+ENTRY(sipi)
+	mov $0x00060000, %eax  /* EMUDEV_CMD_INIT_SECONDARY_VCPU */
+	outl %eax, $0xe8       /* EMUDEV_REG_COMMAND */
+	hlt
+	.code64
+
+/* emu boot stack, including syscall trampoline template */
+
+	.data
+	.globl boot_stack_low, boot_stack_high
+	.globl cpu_ptr
+	.globl trampoline_start, trampoline_patch, trampoline_stop
+	.align 4096
+boot_stack_low:
+cpu_ptr:
+	.quad 0
+trampoline_start:
+	movq %rsp, boot_stack_high-16(%rip)
+	leaq boot_stack_high-16(%rip), %rsp
+	push %r11				/* rflags	 */
+	mov  $0xdeadbeef, %r11			/* C code must fix cs & ss */
+	movq %r11, boot_stack_high-8(%rip)	/* ss	     */
+	push %r11				/* cs	     */
+	push %rcx				/* rip	    */
+
+	.byte 0x49, 0xbb			/* mov data, %r11 ...	 */
+trampoline_patch:
+	.quad 0					/* ... data, for jump to ...  */
+	jmpq *%r11				/* ... trampoline_syscall     */
+trampoline_stop:
+	.align 4096
+boot_stack_high:
+
+/* boot page tables */
+
+#define pageflags 0x063 /* preset, rw, accessed, dirty */
+#define largepage 0x080 /* pse */
+
+	.section .pt, "aw"
+	.globl emu_pgd
+
+	.align 4096
+boot_pgd:
+	.quad emu_pud - 0xffff830000000000 + pageflags
+	.fill 261,8,0
+	.quad emu_pud - 0xffff830000000000 + pageflags
+	.fill 249,8,0
+
+	.align 4096
+emu_pgd:
+	.fill 262,8,0
+	.quad emu_pud - 0xffff830000000000 + pageflags
+	.fill 249,8,0
+
+	.align 4096
+emu_pud:
+	.quad emu_pmd - 0xffff830000000000 + pageflags
+	.fill 511,8,0
+
+	.align 4096
+emu_pmd:
+i = 0
+	.rept 512
+	.quad pageflags + largepage | (i << 21)
+	i = i + 1
+	.endr
+	.align 4096
diff --git a/pc-bios/xenner/xenner64.h b/pc-bios/xenner/xenner64.h
new file mode 100644
index 0000000..92d956e
--- /dev/null
+++ b/pc-bios/xenner/xenner64.h
@@ -0,0 +1,117 @@ 
+#include <xen/foreign/x86_64.h>
+
+struct regs_64 {
+    /* pushed onto stack before calling into C code */
+    uint64_t rax;
+    uint64_t rbx;
+    uint64_t rcx;
+    uint64_t rdx;
+    uint64_t r8;
+    uint64_t r9;
+    uint64_t r10;
+    uint64_t r11;
+    uint64_t r12;
+    uint64_t r13;
+    uint64_t r14;
+    uint64_t r15;
+    uint64_t rsi;
+    uint64_t rdi;
+    uint64_t rbp;
+    uint64_t trapno;
+    /* trap / fault / int created */
+    uint64_t error;
+    uint64_t rip;
+    uint64_t cs;
+    uint64_t rflags;
+    uint64_t rsp;
+    uint64_t ss;
+};
+
+/* 64bit defines */
+#define EMUNAME   "xenner64"
+#define regs      regs_64
+#define fix_sel   fix_sel64
+#define fix_desc  fix_desc64
+#define ureg_t    uint64_t
+#define sreg_t    int64_t
+#define PRIxREG   PRIx64
+#define tss(_v)   ((0xe000 >> 3) +  8 + (((_v)->id) << 2))
+#define ldt(_v)   ((0xe000 >> 3) + 10 + (((_v)->id) << 2))
+
+/* xenner-data.c */
+extern struct idt_64 page_aligned xen_idt[256];
+
+/* xenner-main.c */
+asmlinkage void do_int_80(struct regs_64 *regs);
+
+/* xenner-hcall.c */
+void switch_mode(struct xen_cpu *cpu);
+int is_kernel(struct xen_cpu *cpu);
+asmlinkage void do_syscall(struct regs_64 *regs);
+
+/* xenner-mm.c */
+void pgtable_walk(int level, uint64_t va, uint64_t root_mfn);
+int pgtable_fixup_flag(struct xen_cpu *cpu, uint64_t va, uint32_t flag);
+int pgtable_is_present(uint64_t va, uint64_t root_mfn);
+void *map_page(uint64_t maddr);
+void *fixmap_page(struct xen_cpu *cpu, uint64_t maddr);
+static inline void free_page(void *ptr) {}
+uint64_t *find_pte_64(uint64_t va);
+
+/* macros */
+#define context_is_emu(_r)       (((_r)->cs & 0x03) == 0x00)
+#define context_is_kernel(_v,_r) (((_r)->cs & 0x03) == 0x03 && is_kernel(_v))
+#define context_is_user(_v,_r)   (((_r)->cs & 0x03) == 0x03 && !is_kernel(_v))
+
+#define addr_is_emu(va)     (((va) >= XEN_M2P_64) && ((va) < XEN_DOM_64))
+#define addr_is_kernel(va)  ((va) >= XEN_DOM_64)
+#define addr_is_user(va)    ((va) < XEN_M2P_64)
+
+/* inline asm bits */
+static inline int wrmsr_safe(uint32_t msr, uint32_t ax, uint32_t dx)
+{
+    int ret;
+    asm volatile("1:  wrmsr                \n"
+                 "    xorl %0,%0           \n"
+                 "2:  nop                  \n"
+
+                 ".section .exfix, \"ax\"  \n"
+                 "3:  mov $-1,%0           \n"
+                 "    jmp 2b               \n"
+                 ".previous                \n"
+
+                 ".section .extab, \"a\"   \n"
+                 "    .align 8             \n"
+                 "    .quad 1b,3b          \n"
+                 ".previous                \n"
+                 : "=r" (ret)
+                 : "c" (msr), "a" (ax), "d" (dx));
+    return ret;
+}
+
+static inline int memcpy_pf(void *dest, const void *src, size_t bytes)
+{
+    int ret;
+
+    asm volatile("    cld                  \n"
+                 "91: rep movsb            \n"
+                 "    xor %[ret],%[ret]    \n"
+                 "98:                      \n"
+
+                 ".section .exfix, \"ax\"  \n"
+                 "99: mov $-1, %[ret]      \n"
+                 "    jmp 98b              \n"
+                 ".previous                \n"
+
+                 ".section .extab, \"a\"   \n"
+                 "    .align 8             \n"
+                 "    .quad 91b,99b        \n"
+                 ".previous                \n"
+                 : [ ret ] "=a" (ret),
+                   [ rsi ] "+S" (src),
+                   [ rdi ] "+D" (dest),
+                   [ rcx ] "+c" (bytes)
+                 :
+                 : "memory" );
+    return ret;
+}
diff --git a/pc-bios/xenner/xenner64.lds b/pc-bios/xenner/xenner64.lds
new file mode 100644
index 0000000..0b580a9
--- /dev/null
+++ b/pc-bios/xenner/xenner64.lds
@@ -0,0 +1,38 @@ 
+OUTPUT_FORMAT("elf64-x86-64")
+
+SECTIONS
+{
+    . = 0xffff830000000000;
+    _vstart = .;
+    phys_startup_64 = 0x0;
+
+    /* code */
+    .text : AT(ADDR(.text) - 0xffff830000000000) { *(.text) }
+    . = ALIGN(4k);
+    .exfix  : { *(.exfix)  }
+
+    /* data, ro */
+    . = ALIGN(4k);
+    .note.gnu.build-id : { *(.note.gnu.build-id) }
+    . = ALIGN(4k);
+    _estart = .;
+    .extab  : { *(.extab)  }
+    _estop  = .;
+    . = ALIGN(4k);
+    .rodata : { *(.rodata) }
+
+    /* data, rw */
+    . = ALIGN(4k);
+    .pt     : { *(.pt) }
+    . = ALIGN(4k);
+    .pgdata : { *(.pgdata) }
+    . = ALIGN(4k);
+    .data   : { *(.data)   }
+
+    /* bss */
+    . = ALIGN(4k);
+    .bss    : { *(.bss)    }
+
+    . = ALIGN(4k);
+    _vstop  = .;
+}