[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XEN] kexec: add compatability shim for kexec in 32on64 mode.
# HG changeset patch # User Ian Campbell <ian.campbell@xxxxxxxxxxxxx> # Date 1170932612 0 # Node ID 3ad4691d1d34595951c72527e0977e1669383366 # Parent b50350fb0fde6bbd1e8ad3c41ed0ba686713ae7c [XEN] kexec: add compatability shim for kexec in 32on64 mode. Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxxxxx> --- xen/arch/x86/machine_kexec.c | 48 ++++++++++++-- xen/arch/x86/x86_64/Makefile | 1 xen/arch/x86/x86_64/compat_kexec.S | 126 +++++++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 7 deletions(-) diff -r b50350fb0fde -r 3ad4691d1d34 xen/arch/x86/machine_kexec.c --- a/xen/arch/x86/machine_kexec.c Thu Feb 08 11:03:29 2007 +0000 +++ b/xen/arch/x86/machine_kexec.c Thu Feb 08 11:03:32 2007 +0000 @@ -21,7 +21,7 @@ typedef void (*relocate_new_kernel_t)( unsigned long indirection_page, - unsigned long page_list, + unsigned long *page_list, unsigned long start_address); int machine_kexec_load(int type, int slot, xen_kexec_image_t *image) @@ -44,8 +44,26 @@ int machine_kexec_load(int type, int slo else { /* Odd pages: va for previous ma. */ - set_fixmap(fix_base + (k >> 1), prev_ma); - image->page_list[k] = fix_to_virt(fix_base + (k >> 1)); + if ( IS_COMPAT(dom0) ) + { + + /* + * The compatability bounce code sets up a page table + * with a 1-1 mapping of the first 1G of memory so + * VA==PA here. + * + * This Linux purgatory code still sets up separate + * high and low mappings on the control page (entries + * 0 and 1) but it is harmless if they are equal since + * that PT is not live at the time. + */ + image->page_list[k] = prev_ma; + } + else + { + set_fixmap(fix_base + (k >> 1), prev_ma); + image->page_list[k] = fix_to_virt(fix_base + (k >> 1)); + } } } @@ -100,11 +118,27 @@ void machine_reboot_kexec(xen_kexec_imag void machine_kexec(xen_kexec_image_t *image) { - relocate_new_kernel_t rnk; +#ifdef CONFIG_COMPAT + if ( IS_COMPAT(dom0) ) + { + extern void compat_machine_kexec(unsigned long rnk, + unsigned long indirection_page, + unsigned long *page_list, + unsigned long start_address); + compat_machine_kexec(image->page_list[1], + image->indirection_page, + image->page_list, + image->start_address); + } + else +#endif + { + relocate_new_kernel_t rnk; - rnk = (relocate_new_kernel_t) image->page_list[1]; - (*rnk)(image->indirection_page, (unsigned long)image->page_list, - image->start_address); + rnk = (relocate_new_kernel_t) image->page_list[1]; + (*rnk)(image->indirection_page, image->page_list, + image->start_address); + } } /* diff -r b50350fb0fde -r 3ad4691d1d34 xen/arch/x86/x86_64/Makefile --- a/xen/arch/x86/x86_64/Makefile Thu Feb 08 11:03:29 2007 +0000 +++ b/xen/arch/x86/x86_64/Makefile Thu Feb 08 11:03:32 2007 +0000 @@ -1,4 +1,5 @@ obj-y += entry.o obj-y += entry.o +obj-y += compat_kexec.o obj-y += gpr_switch.o obj-y += mm.o obj-y += traps.o diff -r b50350fb0fde -r 3ad4691d1d34 xen/arch/x86/x86_64/compat_kexec.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/x86/x86_64/compat_kexec.S Thu Feb 08 11:03:32 2007 +0000 @@ -0,0 +1,126 @@ +/* + * Compatibility kexec handler. + */ + +#include <xen/config.h> + +#include <asm/asm_defns.h> +#include <asm/msr.h> +#include <asm/page.h> + +.text + + .code64 + +ENTRY(compat_machine_kexec) + /* x86/64 x86/32 */ + /* %rdi - relocate_new_kernel_t CALL */ + /* %rsi - indirection page 4(%esp) */ + /* %rdx - page_list 8(%esp) */ + /* %rcx - start address 12(%esp) */ + /* cpu has pae 16(%esp) */ + + /* Shim the 64 bit page_list into a 32 bit page_list. */ + mov $12,%r9 + lea compat_page_list(%rip), %rbx +1: dec %r9 + movl (%rdx,%r9,8),%eax + movl %eax,(%rbx,%r9,4) + test %r9,%r9 + jnz 1b + + movq %rbx,%rdx + mov $__PAGE_OFFSET,%rbx + sub %rbx, %rdx + + /* + * Setup an identity mapped region in PML4[0] of idle page + * table. + */ + lea idle_pg_table_l3(%rip),%rax + sub %rbx,%rax + or $0x63,%rax + mov %rax, idle_pg_table(%rip) + + /* Switch to idle page table. */ + movq $(idle_pg_table - __PAGE_OFFSET), %rax + movq %rax, %cr3 + + /* Jump to low identity mapping in compatibility mode. */ + ljmp *compatibility_mode_far(%rip) + ud2 + +compatibility_mode_far: + .long compatibility_mode - __PAGE_OFFSET + .long __HYPERVISOR_CS32 + + .code32 + +compatibility_mode: + /* Setup some sane segments. */ + movl $__HYPERVISOR_DS32, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %fs + movl %eax, %gs + movl %eax, %ss + + /* Push arguments onto stack. */ + pushl $1 /* 16(%esp) - cpu has pae */ + pushl %ecx /* 12(%esp) - start address */ + pushl %edx /* 8(%esp) - page list */ + pushl %esi /* 4(%esp) - indirection page */ + pushl %edi /* 0(%esp) - CALL */ + + /* Disable paging and therefore leave 64 bit mode. */ + movl %cr0, %eax + andl $~X86_CR0_PG, %eax + movl %eax, %cr0 + + /* Switch to 32 bit page table. */ + movl $compat_pg_table - __PAGE_OFFSET, %eax + movl %eax, %cr3 + + /* Clear MSR_EFER[LME], disabling long mode */ + movl $MSR_EFER,%ecx + rdmsr + btcl $_EFER_LME,%eax + wrmsr + + /* Re-enable paging, but only 32 bit mode now. */ + movl %cr0, %eax + orl $X86_CR0_PG, %eax + movl %eax, %cr0 + + popl %eax + call *%eax + ud2 + +compat_page_list: + .fill 12,4,0 + + .align 32,0 + + /* + * These compat page tables contain an identity mapping of the + * first 1G of the physical address space. + */ +compat_pg_table: + .long compat_pg_table_l2 + 0*PAGE_SIZE + 0x01 - __PAGE_OFFSET, 0 + .long 0, 0 + .long 0, 0 + .long 0, 0 + + .align 4096,0 + +compat_pg_table_l2: + .macro identmap from=0, count=512 + .if \count-1 + identmap "(\from+0)","(\count/2)" + identmap "(\from+(0x200000*(\count/2)))","(\count/2)" + .else + .quad 0x00000000000000e3 + \from + .endif + .endm + + identmap _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |