# HG changeset patch
# User Ian Campbell <ian.campbell@xxxxxxxxxxxxx>
# Date 1182247585 -3600
# Node ID 75d82009ec707d013ac170b7896bd612099e43f7
# Parent c3f280acf41af0ca876002e6e501cd67e72b3725
Fix 32on64 kexec trampoline. This was broken when Xen was modified to
physically relocate itself.
Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxxxxx>
---
xen/arch/x86/x86_64/compat_kexec.S | 53 ++++++++++++++++++++++++++++++++-----
1 files changed, 47 insertions(+), 6 deletions(-)
diff -r c3f280acf41a -r 75d82009ec70 xen/arch/x86/x86_64/compat_kexec.S
--- a/xen/arch/x86/x86_64/compat_kexec.S Mon Jun 18 16:59:06 2007 +0100
+++ b/xen/arch/x86/x86_64/compat_kexec.S Tue Jun 19 11:06:25 2007 +0100
@@ -1,5 +1,11 @@
/*
* Compatibility kexec handler.
+ */
+
+/*
+ * NOTE: We rely on Xen not relocating itself above the 4G boundary. This is
+ * currently true but if it ever changes then compat_pg_table will
+ * need to be moved back below 4G at run time.
*/
#include <xen/config.h>
@@ -8,7 +14,20 @@
#include <asm/msr.h>
#include <asm/page.h>
-#define SYM_PHYS(sym) ((sym) - __XEN_VIRT_START)
+/* The unrelocated physical address of a symbol. */
+#define SYM_PHYS(sym) ((sym) - __XEN_VIRT_START)
+
+/* Load physical address of symbol into register and relocate it. */
+#define RELOCATE_SYM(sym,reg) mov $SYM_PHYS(sym), reg ; \
+ add xen_phys_start(%rip), reg
+
+/*
+ * Relocate a physical address in memory. Size of temporary register
+ * determines size of the value to relocate.
+ */
+#define RELOCATE_MEM(addr,reg) mov addr(%rip), reg ; \
+ add xen_phys_start(%rip), reg ; \
+ mov reg, addr(%rip)
.text
@@ -31,20 +50,31 @@ 1: dec %r9
test %r9,%r9
jnz 1b
- mov $SYM_PHYS(compat_page_list),%rdx
+ RELOCATE_SYM(compat_page_list,%rdx)
+
+ /* Relocate compatibility mode entry point address. */
+ RELOCATE_MEM(compatibility_mode_far,%eax)
+
+ /* Relocate compat_pg_table. */
+ RELOCATE_MEM(compat_pg_table, %rax)
+ RELOCATE_MEM(compat_pg_table+0x8, %rax)
+ RELOCATE_MEM(compat_pg_table+0x10,%rax)
+ RELOCATE_MEM(compat_pg_table+0x18,%rax)
/*
* Setup an identity mapped region in PML4[0] of idle page
* table.
*/
- lea l3_identmap(%rip),%rax
- sub %rbx,%rax
+ RELOCATE_SYM(l3_identmap,%rax)
or $0x63,%rax
mov %rax, idle_pg_table(%rip)
/* Switch to idle page table. */
- movq $SYM_PHYS(idle_pg_table), %rax
+ RELOCATE_SYM(idle_pg_table,%rax)
movq %rax, %cr3
+
+ /* Save xen_phys_start for 32 bit code. */
+ movq xen_phys_start(%rip), %rbx
/* Jump to low identity mapping in compatibility mode. */
ljmp *compatibility_mode_far(%rip)
@@ -55,6 +85,17 @@ compatibility_mode_far:
.long __HYPERVISOR_CS32
.code32
+
+#undef RELOCATE_SYM
+#undef RELOCATE_MEM
+
+/*
+ * Load physical address of symbol into register and relocate it. %rbx
+ * contains xen_phys_start(%rip) saved before jump to compatibility
+ * mode.
+ */
+#define RELOCATE_SYM(sym,reg) mov $SYM_PHYS(sym), reg ; \
+ add %ebx, reg
compatibility_mode:
/* Setup some sane segments. */
@@ -78,7 +119,7 @@ compatibility_mode:
movl %eax, %cr0
/* Switch to 32 bit page table. */
- movl $SYM_PHYS(compat_pg_table), %eax
+ RELOCATE_SYM(compat_pg_table, %eax)
movl %eax, %cr3
/* Clear MSR_EFER[LME], disabling long mode */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|