1 Subject: kexec: Move asm segment handling code to the assembly file (x86_64)
2 From: http://xenbits.xensource.com/xen-unstable.hg (tip 13816)
3 Patch-mainline: obsolete
5 This patch moves the idt, gdt, and segment handling code from machine_kexec.c
6 to relocate_kernel.S. The main reason behind this move is to avoid code
7 duplication in the Xen hypervisor. With this patch all code required to kexec
8 is put on the control page.
10 On top of that this patch also counts as a cleanup - I think it is much
11 nicer to write assembly directly in assembly files than wrap inline assembly
12 in C functions for no apparent reason.
14 Signed-off-by: Magnus Damm <magnus@valinux.co.jp>
15 Acked-by: jbeulich@novell.com
18 Applies to 2.6.19-rc1.
20 machine_kexec.c | 58 -----------------------------------------------------
21 relocate_kernel.S | 50 +++++++++++++++++++++++++++++++++++++++++----
22 2 files changed, 45 insertions(+), 63 deletions(-)
24 Index: head-2008-08-18/arch/x86/kernel/machine_kexec_64.c
25 ===================================================================
26 --- head-2008-08-18.orig/arch/x86/kernel/machine_kexec_64.c 2008-08-18 09:05:04.000000000 +0200
27 +++ head-2008-08-18/arch/x86/kernel/machine_kexec_64.c 2008-08-18 10:13:08.000000000 +0200
28 @@ -115,47 +115,6 @@ static int init_pgtable(struct kimage *i
29 return init_level4_page(image, level4p, 0, max_pfn << PAGE_SHIFT);
32 -static void set_idt(void *newidt, u16 limit)
34 - struct desc_ptr curidt;
36 - /* x86-64 supports unaliged loads & stores */
37 - curidt.size = limit;
38 - curidt.address = (unsigned long)newidt;
40 - __asm__ __volatile__ (
47 -static void set_gdt(void *newgdt, u16 limit)
49 - struct desc_ptr curgdt;
51 - /* x86-64 supports unaligned loads & stores */
52 - curgdt.size = limit;
53 - curgdt.address = (unsigned long)newgdt;
55 - __asm__ __volatile__ (
61 -static void load_segments(void)
63 - __asm__ __volatile__ (
69 - : : "a" (__KERNEL_DS) : "memory"
73 int machine_kexec_prepare(struct kimage *image)
75 unsigned long start_pgtable;
76 @@ -214,23 +173,6 @@ void machine_kexec(struct kimage *image)
77 page_list[PA_TABLE_PAGE] =
78 (unsigned long)__pa(page_address(image->control_code_page));
80 - /* The segment registers are funny things, they have both a
81 - * visible and an invisible part. Whenever the visible part is
82 - * set to a specific selector, the invisible part is loaded
83 - * with from a table in memory. At no other time is the
84 - * descriptor table in memory accessed.
86 - * I take advantage of this here by force loading the
87 - * segments, before I zap the gdt with an invalid value.
90 - /* The gdt & idt are now invalid.
91 - * If you want to load them you must set up your own idt & gdt.
93 - set_gdt(phys_to_virt(0),0);
94 - set_idt(phys_to_virt(0),0);
97 relocate_kernel((unsigned long)image->head, (unsigned long)page_list,
100 Index: head-2008-08-18/arch/x86/kernel/relocate_kernel_64.S
101 ===================================================================
102 --- head-2008-08-18.orig/arch/x86/kernel/relocate_kernel_64.S 2008-07-13 23:51:29.000000000 +0200
103 +++ head-2008-08-18/arch/x86/kernel/relocate_kernel_64.S 2008-08-18 10:13:08.000000000 +0200
104 @@ -160,13 +160,39 @@ relocate_new_kernel:
105 movq PTR(PA_PGD)(%rsi), %r9
110 + addq $(idt_80 - relocate_kernel), %rax
115 + addq $(gdt - relocate_kernel), %rax
117 + addq $((gdt_80 - relocate_kernel) + 2), %r9
121 + addq $(gdt_80 - relocate_kernel), %rax
124 + /* setup data segment registers */
132 /* setup a new stack at the end of the physical control page */
133 lea PAGE_SIZE(%r8), %rsp
135 - /* jump to identity mapped page */
136 - addq $(identity_mapped - relocate_kernel), %r8
139 + /* load new code segment and jump to identity mapped page */
141 + addq $(identity_mapped - relocate_kernel), %rax
142 + pushq $(gdt_cs - gdt)
147 /* store the start address on the stack */
148 @@ -262,5 +288,19 @@ identity_mapped:
157 + .quad 0x0000000000000000 /* NULL descriptor */
159 + .quad 0x00af9a000000ffff
163 + .word gdt_end - gdt - 1 /* limit */
164 + .quad 0 /* base - filled in by code above */
167 + .word 0 /* limit */