aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZachary Amsden <zach@vmware.com>2005-09-03 18:56:38 -0400
committerLinus Torvalds <torvalds@evo.osdl.org>2005-09-05 03:06:11 -0400
commit4d37e7e3fd851428dede4d05d3e69d03795a744a (patch)
treef830928a0baf81f462bc9176dacbaad2dac2bb65
parent245067d1674d451855692fcd4647daf9fd47f82d (diff)
[PATCH] i386: inline assembler: cleanup and encapsulate descriptor and task register management
i386 inline assembler cleanup. This change encapsulates descriptor and task register management. Also, it is possible to improve assembler generation in two cases; savesegment may store the value in a register instead of a memory location, which allows GCC to optimize stack variables into registers, and MOV MEM, SEG is always a 16-bit write to memory, making the casting in math-emu unnecessary. Signed-off-by: Zachary Amsden <zach@vmware.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/i386/kernel/cpu/common.c4
-rw-r--r--arch/i386/kernel/doublefault.c2
-rw-r--r--arch/i386/kernel/efi.c5
-rw-r--r--arch/i386/kernel/reboot.c9
-rw-r--r--arch/i386/kernel/signal.c4
-rw-r--r--arch/i386/kernel/traps.c2
-rw-r--r--arch/i386/kernel/vm86.c4
-rw-r--r--arch/i386/math-emu/get_address.c13
-rw-r--r--arch/i386/power/cpu.c26
-rw-r--r--include/asm-i386/desc.h10
-rw-r--r--include/asm-i386/system.h4
11 files changed, 43 insertions, 40 deletions
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 361f2e7ccb12..46ce9b248f55 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -613,8 +613,8 @@ void __devinit cpu_init(void)
613 memcpy(thread->tls_array, &per_cpu(cpu_gdt_table, cpu), 613 memcpy(thread->tls_array, &per_cpu(cpu_gdt_table, cpu),
614 GDT_ENTRY_TLS_ENTRIES * 8); 614 GDT_ENTRY_TLS_ENTRIES * 8);
615 615
616 __asm__ __volatile__("lgdt %0" : : "m" (cpu_gdt_descr[cpu])); 616 load_gdt(&cpu_gdt_descr[cpu]);
617 __asm__ __volatile__("lidt %0" : : "m" (idt_descr)); 617 load_idt(&idt_descr);
618 618
619 /* 619 /*
620 * Delete NT 620 * Delete NT
diff --git a/arch/i386/kernel/doublefault.c b/arch/i386/kernel/doublefault.c
index 789af3e9fb1f..5edb1d379add 100644
--- a/arch/i386/kernel/doublefault.c
+++ b/arch/i386/kernel/doublefault.c
@@ -20,7 +20,7 @@ static void doublefault_fn(void)
20 struct Xgt_desc_struct gdt_desc = {0, 0}; 20 struct Xgt_desc_struct gdt_desc = {0, 0};
21 unsigned long gdt, tss; 21 unsigned long gdt, tss;
22 22
23 __asm__ __volatile__("sgdt %0": "=m" (gdt_desc): :"memory"); 23 store_gdt(&gdt_desc);
24 gdt = gdt_desc.address; 24 gdt = gdt_desc.address;
25 25
26 printk("double fault, gdt at %08lx [%d bytes]\n", gdt, gdt_desc.size); 26 printk("double fault, gdt at %08lx [%d bytes]\n", gdt, gdt_desc.size);
diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c
index 921fdb15fc9b..ecad519fd395 100644
--- a/arch/i386/kernel/efi.c
+++ b/arch/i386/kernel/efi.c
@@ -104,8 +104,7 @@ static void efi_call_phys_prelog(void)
104 local_flush_tlb(); 104 local_flush_tlb();
105 105
106 cpu_gdt_descr[0].address = __pa(cpu_gdt_descr[0].address); 106 cpu_gdt_descr[0].address = __pa(cpu_gdt_descr[0].address);
107 __asm__ __volatile__("lgdt %0":"=m" 107 load_gdt((struct Xgt_desc_struct *) __pa(&cpu_gdt_descr[0]));
108 (*(struct Xgt_desc_struct *) __pa(&cpu_gdt_descr[0])));
109} 108}
110 109
111static void efi_call_phys_epilog(void) 110static void efi_call_phys_epilog(void)
@@ -114,7 +113,7 @@ static void efi_call_phys_epilog(void)
114 113
115 cpu_gdt_descr[0].address = 114 cpu_gdt_descr[0].address =
116 (unsigned long) __va(cpu_gdt_descr[0].address); 115 (unsigned long) __va(cpu_gdt_descr[0].address);
117 __asm__ __volatile__("lgdt %0":"=m"(cpu_gdt_descr)); 116 load_gdt(&cpu_gdt_descr[0]);
118 cr4 = read_cr4(); 117 cr4 = read_cr4();
119 118
120 if (cr4 & X86_CR4_PSE) { 119 if (cr4 & X86_CR4_PSE) {
diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c
index c71fef31dc47..1cbb9c0f4704 100644
--- a/arch/i386/kernel/reboot.c
+++ b/arch/i386/kernel/reboot.c
@@ -13,6 +13,7 @@
13#include <linux/dmi.h> 13#include <linux/dmi.h>
14#include <asm/uaccess.h> 14#include <asm/uaccess.h>
15#include <asm/apic.h> 15#include <asm/apic.h>
16#include <asm/desc.h>
16#include "mach_reboot.h" 17#include "mach_reboot.h"
17#include <linux/reboot_fixups.h> 18#include <linux/reboot_fixups.h>
18 19
@@ -242,13 +243,13 @@ void machine_real_restart(unsigned char *code, int length)
242 243
243 /* Set up the IDT for real mode. */ 244 /* Set up the IDT for real mode. */
244 245
245 __asm__ __volatile__ ("lidt %0" : : "m" (real_mode_idt)); 246 load_idt(&real_mode_idt);
246 247
247 /* Set up a GDT from which we can load segment descriptors for real 248 /* Set up a GDT from which we can load segment descriptors for real
248 mode. The GDT is not used in real mode; it is just needed here to 249 mode. The GDT is not used in real mode; it is just needed here to
249 prepare the descriptors. */ 250 prepare the descriptors. */
250 251
251 __asm__ __volatile__ ("lgdt %0" : : "m" (real_mode_gdt)); 252 load_gdt(&real_mode_gdt);
252 253
253 /* Load the data segment registers, and thus the descriptors ready for 254 /* Load the data segment registers, and thus the descriptors ready for
254 real mode. The base address of each segment is 0x100, 16 times the 255 real mode. The base address of each segment is 0x100, 16 times the
@@ -316,7 +317,7 @@ void machine_emergency_restart(void)
316 if (!reboot_thru_bios) { 317 if (!reboot_thru_bios) {
317 if (efi_enabled) { 318 if (efi_enabled) {
318 efi.reset_system(EFI_RESET_COLD, EFI_SUCCESS, 0, NULL); 319 efi.reset_system(EFI_RESET_COLD, EFI_SUCCESS, 0, NULL);
319 __asm__ __volatile__("lidt %0": :"m" (no_idt)); 320 load_idt(&no_idt);
320 __asm__ __volatile__("int3"); 321 __asm__ __volatile__("int3");
321 } 322 }
322 /* rebooting needs to touch the page at absolute addr 0 */ 323 /* rebooting needs to touch the page at absolute addr 0 */
@@ -325,7 +326,7 @@ void machine_emergency_restart(void)
325 mach_reboot_fixups(); /* for board specific fixups */ 326 mach_reboot_fixups(); /* for board specific fixups */
326 mach_reboot(); 327 mach_reboot();
327 /* That didn't work - force a triple fault.. */ 328 /* That didn't work - force a triple fault.. */
328 __asm__ __volatile__("lidt %0": :"m" (no_idt)); 329 load_idt(&no_idt);
329 __asm__ __volatile__("int3"); 330 __asm__ __volatile__("int3");
330 } 331 }
331 } 332 }
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
index 140e340569c6..7bcda6d69d87 100644
--- a/arch/i386/kernel/signal.c
+++ b/arch/i386/kernel/signal.c
@@ -278,9 +278,9 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
278 int tmp, err = 0; 278 int tmp, err = 0;
279 279
280 tmp = 0; 280 tmp = 0;
281 __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp)); 281 savesegment(gs, tmp);
282 err |= __put_user(tmp, (unsigned int __user *)&sc->gs); 282 err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
283 __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp)); 283 savesegment(fs, tmp);
284 err |= __put_user(tmp, (unsigned int __user *)&sc->fs); 284 err |= __put_user(tmp, (unsigned int __user *)&sc->fs);
285 285
286 err |= __put_user(regs->xes, (unsigned int __user *)&sc->es); 286 err |= __put_user(regs->xes, (unsigned int __user *)&sc->es);
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index cd2d5d5514fe..1144df0c48d6 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -1008,7 +1008,7 @@ void __init trap_init_f00f_bug(void)
1008 * it uses the read-only mapped virtual address. 1008 * it uses the read-only mapped virtual address.
1009 */ 1009 */
1010 idt_descr.address = fix_to_virt(FIX_F00F_IDT); 1010 idt_descr.address = fix_to_virt(FIX_F00F_IDT);
1011 __asm__ __volatile__("lidt %0" : : "m" (idt_descr)); 1011 load_idt(&idt_descr);
1012} 1012}
1013#endif 1013#endif
1014 1014
diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
index 2daa06fb4a88..16b485009622 100644
--- a/arch/i386/kernel/vm86.c
+++ b/arch/i386/kernel/vm86.c
@@ -294,8 +294,8 @@ static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk
294 */ 294 */
295 info->regs32->eax = 0; 295 info->regs32->eax = 0;
296 tsk->thread.saved_esp0 = tsk->thread.esp0; 296 tsk->thread.saved_esp0 = tsk->thread.esp0;
297 asm volatile("mov %%fs,%0":"=m" (tsk->thread.saved_fs)); 297 savesegment(fs, tsk->thread.saved_fs);
298 asm volatile("mov %%gs,%0":"=m" (tsk->thread.saved_gs)); 298 savesegment(gs, tsk->thread.saved_gs);
299 299
300 tss = &per_cpu(init_tss, get_cpu()); 300 tss = &per_cpu(init_tss, get_cpu());
301 tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0; 301 tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
diff --git a/arch/i386/math-emu/get_address.c b/arch/i386/math-emu/get_address.c
index 91175738e948..9819b705efa4 100644
--- a/arch/i386/math-emu/get_address.c
+++ b/arch/i386/math-emu/get_address.c
@@ -155,7 +155,6 @@ static long pm_address(u_char FPU_modrm, u_char segment,
155{ 155{
156 struct desc_struct descriptor; 156 struct desc_struct descriptor;
157 unsigned long base_address, limit, address, seg_top; 157 unsigned long base_address, limit, address, seg_top;
158 unsigned short selector;
159 158
160 segment--; 159 segment--;
161 160
@@ -173,17 +172,11 @@ static long pm_address(u_char FPU_modrm, u_char segment,
173 /* fs and gs aren't used by the kernel, so they still have their 172 /* fs and gs aren't used by the kernel, so they still have their
174 user-space values. */ 173 user-space values. */
175 case PREFIX_FS_-1: 174 case PREFIX_FS_-1:
176 /* The cast is needed here to get gcc 2.8.0 to use a 16 bit register 175 /* N.B. - movl %seg, mem is a 2 byte write regardless of prefix */
177 in the assembler statement. */ 176 savesegment(fs, addr->selector);
178
179 __asm__("mov %%fs,%0":"=r" (selector));
180 addr->selector = selector;
181 break; 177 break;
182 case PREFIX_GS_-1: 178 case PREFIX_GS_-1:
183 /* The cast is needed here to get gcc 2.8.0 to use a 16 bit register 179 savesegment(gs, addr->selector);
184 in the assembler statement. */
185 __asm__("mov %%gs,%0":"=r" (selector));
186 addr->selector = selector;
187 break; 180 break;
188 default: 181 default:
189 addr->selector = PM_REG_(segment); 182 addr->selector = PM_REG_(segment);
diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c
index 4e19c43e0954..c7a6436aa938 100644
--- a/arch/i386/power/cpu.c
+++ b/arch/i386/power/cpu.c
@@ -42,17 +42,17 @@ void __save_processor_state(struct saved_context *ctxt)
42 /* 42 /*
43 * descriptor tables 43 * descriptor tables
44 */ 44 */
45 asm volatile ("sgdt %0" : "=m" (ctxt->gdt_limit)); 45 store_gdt(&ctxt->gdt_limit);
46 asm volatile ("sidt %0" : "=m" (ctxt->idt_limit)); 46 store_idt(&ctxt->idt_limit);
47 asm volatile ("str %0" : "=m" (ctxt->tr)); 47 store_tr(ctxt->tr);
48 48
49 /* 49 /*
50 * segment registers 50 * segment registers
51 */ 51 */
52 asm volatile ("movw %%es, %0" : "=m" (ctxt->es)); 52 savesegment(es, ctxt->es);
53 asm volatile ("movw %%fs, %0" : "=m" (ctxt->fs)); 53 savesegment(fs, ctxt->fs);
54 asm volatile ("movw %%gs, %0" : "=m" (ctxt->gs)); 54 savesegment(gs, ctxt->gs);
55 asm volatile ("movw %%ss, %0" : "=m" (ctxt->ss)); 55 savesegment(ss, ctxt->ss);
56 56
57 /* 57 /*
58 * control registers 58 * control registers
@@ -118,16 +118,16 @@ void __restore_processor_state(struct saved_context *ctxt)
118 * now restore the descriptor tables to their proper values 118 * now restore the descriptor tables to their proper values
119 * ltr is done i fix_processor_context(). 119 * ltr is done i fix_processor_context().
120 */ 120 */
121 asm volatile ("lgdt %0" :: "m" (ctxt->gdt_limit)); 121 load_gdt(&ctxt->gdt_limit);
122 asm volatile ("lidt %0" :: "m" (ctxt->idt_limit)); 122 load_idt(&ctxt->idt_limit);
123 123
124 /* 124 /*
125 * segment registers 125 * segment registers
126 */ 126 */
127 asm volatile ("movw %0, %%es" :: "r" (ctxt->es)); 127 loadsegment(es, ctxt->es);
128 asm volatile ("movw %0, %%fs" :: "r" (ctxt->fs)); 128 loadsegment(fs, ctxt->fs);
129 asm volatile ("movw %0, %%gs" :: "r" (ctxt->gs)); 129 loadsegment(gs, ctxt->gs);
130 asm volatile ("movw %0, %%ss" :: "r" (ctxt->ss)); 130 loadsegment(ss, ctxt->ss);
131 131
132 /* 132 /*
133 * sysenter MSRs 133 * sysenter MSRs
diff --git a/include/asm-i386/desc.h b/include/asm-i386/desc.h
index 11e67811a990..9a0b85a52e71 100644
--- a/include/asm-i386/desc.h
+++ b/include/asm-i386/desc.h
@@ -30,6 +30,16 @@ extern struct Xgt_desc_struct idt_descr, cpu_gdt_descr[NR_CPUS];
30#define load_TR_desc() __asm__ __volatile__("ltr %%ax"::"a" (GDT_ENTRY_TSS*8)) 30#define load_TR_desc() __asm__ __volatile__("ltr %%ax"::"a" (GDT_ENTRY_TSS*8))
31#define load_LDT_desc() __asm__ __volatile__("lldt %%ax"::"a" (GDT_ENTRY_LDT*8)) 31#define load_LDT_desc() __asm__ __volatile__("lldt %%ax"::"a" (GDT_ENTRY_LDT*8))
32 32
33#define load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr))
34#define load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr))
35#define load_tr(tr) __asm__ __volatile("ltr %0"::"mr" (tr))
36#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"mr" (ldt))
37
38#define store_gdt(dtr) __asm__ ("sgdt %0":"=m" (*dtr))
39#define store_idt(dtr) __asm__ ("sidt %0":"=m" (*dtr))
40#define store_tr(tr) __asm__ ("str %0":"=mr" (tr))
41#define store_ldt(ldt) __asm__ ("sldt %0":"=mr" (ldt))
42
33/* 43/*
34 * This is the ldt that every process will get unless we need 44 * This is the ldt that every process will get unless we need
35 * something other than this. 45 * something other than this.
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h
index 8048a5e018cd..37fd2f8c7196 100644
--- a/include/asm-i386/system.h
+++ b/include/asm-i386/system.h
@@ -93,13 +93,13 @@ static inline unsigned long _get_base(char * addr)
93 ".align 4\n\t" \ 93 ".align 4\n\t" \
94 ".long 1b,3b\n" \ 94 ".long 1b,3b\n" \
95 ".previous" \ 95 ".previous" \
96 : :"m" (value)) 96 : :"rm" (value))
97 97
98/* 98/*
99 * Save a segment register away 99 * Save a segment register away
100 */ 100 */
101#define savesegment(seg, value) \ 101#define savesegment(seg, value) \
102 asm volatile("mov %%" #seg ",%0":"=m" (value)) 102 asm volatile("mov %%" #seg ",%0":"=rm" (value))
103 103
104/* 104/*
105 * Clear and set 'TS' bit respectively 105 * Clear and set 'TS' bit respectively