# 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
|