diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2005-07-29 15:02:09 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-29 15:17:27 -0400 |
commit | 36c4fd23cc06f81d68ee968c4c1bf1cebb3dcea5 (patch) | |
tree | 53bbd9c8fef8b84e26e0ae0471eb6c912e7ba553 /arch | |
parent | e7b47ccaf655cbaf336745a9b65cf7b22a536fca (diff) |
[PATCH] x86_64 machine_kexec: Cleanup inline assembly.
In an uncensored copy of code from i386 to x86_64 I wound up
with inline assembly with the wrong constraints. Use input
constraints instead of output constraints.
So I know the assembler will do the right thing specify the size
of the operand lidtq and lgdtq instead of just lidt and lgdt.
Make load_segments use an input constraint, and delete the macro fun.
Without having to reload %cs like I do on i386 this code is noticeably
simpler.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86_64/kernel/machine_kexec.c | 34 |
1 files changed, 16 insertions, 18 deletions
diff --git a/arch/x86_64/kernel/machine_kexec.c b/arch/x86_64/kernel/machine_kexec.c index 60d1eff41567..717f7db4b532 100644 --- a/arch/x86_64/kernel/machine_kexec.c +++ b/arch/x86_64/kernel/machine_kexec.c | |||
@@ -122,45 +122,43 @@ static int init_pgtable(struct kimage *image, unsigned long start_pgtable) | |||
122 | 122 | ||
123 | static void set_idt(void *newidt, u16 limit) | 123 | static void set_idt(void *newidt, u16 limit) |
124 | { | 124 | { |
125 | unsigned char curidt[10]; | 125 | struct desc_ptr curidt; |
126 | 126 | ||
127 | /* x86-64 supports unaliged loads & stores */ | 127 | /* x86-64 supports unaliged loads & stores */ |
128 | (*(u16 *)(curidt)) = limit; | 128 | curidt.size = limit; |
129 | (*(u64 *)(curidt +2)) = (unsigned long)(newidt); | 129 | curidt.address = (unsigned long)newidt; |
130 | 130 | ||
131 | __asm__ __volatile__ ( | 131 | __asm__ __volatile__ ( |
132 | "lidt %0\n" | 132 | "lidtq %0\n" |
133 | : "=m" (curidt) | 133 | : : "m" (curidt) |
134 | ); | 134 | ); |
135 | }; | 135 | }; |
136 | 136 | ||
137 | 137 | ||
138 | static void set_gdt(void *newgdt, u16 limit) | 138 | static void set_gdt(void *newgdt, u16 limit) |
139 | { | 139 | { |
140 | unsigned char curgdt[10]; | 140 | struct desc_ptr curgdt; |
141 | 141 | ||
142 | /* x86-64 supports unaligned loads & stores */ | 142 | /* x86-64 supports unaligned loads & stores */ |
143 | (*(u16 *)(curgdt)) = limit; | 143 | curgdt.size = limit; |
144 | (*(u64 *)(curgdt +2)) = (unsigned long)(newgdt); | 144 | curgdt.address = (unsigned long)newgdt; |
145 | 145 | ||
146 | __asm__ __volatile__ ( | 146 | __asm__ __volatile__ ( |
147 | "lgdt %0\n" | 147 | "lgdtq %0\n" |
148 | : "=m" (curgdt) | 148 | : : "m" (curgdt) |
149 | ); | 149 | ); |
150 | }; | 150 | }; |
151 | 151 | ||
152 | static void load_segments(void) | 152 | static void load_segments(void) |
153 | { | 153 | { |
154 | __asm__ __volatile__ ( | 154 | __asm__ __volatile__ ( |
155 | "\tmovl $"STR(__KERNEL_DS)",%eax\n" | 155 | "\tmovl %0,%%ds\n" |
156 | "\tmovl %eax,%ds\n" | 156 | "\tmovl %0,%%es\n" |
157 | "\tmovl %eax,%es\n" | 157 | "\tmovl %0,%%ss\n" |
158 | "\tmovl %eax,%ss\n" | 158 | "\tmovl %0,%%fs\n" |
159 | "\tmovl %eax,%fs\n" | 159 | "\tmovl %0,%%gs\n" |
160 | "\tmovl %eax,%gs\n" | 160 | : : "a" (__KERNEL_DS) |
161 | ); | 161 | ); |
162 | #undef STR | ||
163 | #undef __STR | ||
164 | } | 162 | } |
165 | 163 | ||
166 | typedef NORET_TYPE void (*relocate_new_kernel_t)(unsigned long indirection_page, | 164 | typedef NORET_TYPE void (*relocate_new_kernel_t)(unsigned long indirection_page, |