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>
memcpy(thread->tls_array, &per_cpu(cpu_gdt_table, cpu),
GDT_ENTRY_TLS_ENTRIES * 8);
- __asm__ __volatile__("lgdt %0" : : "m" (cpu_gdt_descr[cpu]));
- __asm__ __volatile__("lidt %0" : : "m" (idt_descr));
+ load_gdt(&cpu_gdt_descr[cpu]);
+ load_idt(&idt_descr);
/*
* Delete NT
struct Xgt_desc_struct gdt_desc = {0, 0};
unsigned long gdt, tss;
- __asm__ __volatile__("sgdt %0": "=m" (gdt_desc): :"memory");
+ store_gdt(&gdt_desc);
gdt = gdt_desc.address;
printk("double fault, gdt at %08lx [%d bytes]\n", gdt, gdt_desc.size);
local_flush_tlb();
cpu_gdt_descr[0].address = __pa(cpu_gdt_descr[0].address);
- __asm__ __volatile__("lgdt %0":"=m"
- (*(struct Xgt_desc_struct *) __pa(&cpu_gdt_descr[0])));
+ load_gdt((struct Xgt_desc_struct *) __pa(&cpu_gdt_descr[0]));
}
static void efi_call_phys_epilog(void)
cpu_gdt_descr[0].address =
(unsigned long) __va(cpu_gdt_descr[0].address);
- __asm__ __volatile__("lgdt %0":"=m"(cpu_gdt_descr));
+ load_gdt(&cpu_gdt_descr[0]);
cr4 = read_cr4();
if (cr4 & X86_CR4_PSE) {
#include <linux/dmi.h>
#include <asm/uaccess.h>
#include <asm/apic.h>
+#include <asm/desc.h>
#include "mach_reboot.h"
#include <linux/reboot_fixups.h>
/* Set up the IDT for real mode. */
- __asm__ __volatile__ ("lidt %0" : : "m" (real_mode_idt));
+ load_idt(&real_mode_idt);
/* Set up a GDT from which we can load segment descriptors for real
mode. The GDT is not used in real mode; it is just needed here to
prepare the descriptors. */
- __asm__ __volatile__ ("lgdt %0" : : "m" (real_mode_gdt));
+ load_gdt(&real_mode_gdt);
/* Load the data segment registers, and thus the descriptors ready for
real mode. The base address of each segment is 0x100, 16 times the
if (!reboot_thru_bios) {
if (efi_enabled) {
efi.reset_system(EFI_RESET_COLD, EFI_SUCCESS, 0, NULL);
- __asm__ __volatile__("lidt %0": :"m" (no_idt));
+ load_idt(&no_idt);
__asm__ __volatile__("int3");
}
/* rebooting needs to touch the page at absolute addr 0 */
mach_reboot_fixups(); /* for board specific fixups */
mach_reboot();
/* That didn't work - force a triple fault.. */
- __asm__ __volatile__("lidt %0": :"m" (no_idt));
+ load_idt(&no_idt);
__asm__ __volatile__("int3");
}
}
int tmp, err = 0;
tmp = 0;
- __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
+ savesegment(gs, tmp);
err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
- __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp));
+ savesegment(fs, tmp);
err |= __put_user(tmp, (unsigned int __user *)&sc->fs);
err |= __put_user(regs->xes, (unsigned int __user *)&sc->es);
* it uses the read-only mapped virtual address.
*/
idt_descr.address = fix_to_virt(FIX_F00F_IDT);
- __asm__ __volatile__("lidt %0" : : "m" (idt_descr));
+ load_idt(&idt_descr);
}
#endif
*/
info->regs32->eax = 0;
tsk->thread.saved_esp0 = tsk->thread.esp0;
- asm volatile("mov %%fs,%0":"=m" (tsk->thread.saved_fs));
- asm volatile("mov %%gs,%0":"=m" (tsk->thread.saved_gs));
+ savesegment(fs, tsk->thread.saved_fs);
+ savesegment(gs, tsk->thread.saved_gs);
tss = &per_cpu(init_tss, get_cpu());
tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
{
struct desc_struct descriptor;
unsigned long base_address, limit, address, seg_top;
- unsigned short selector;
segment--;
/* fs and gs aren't used by the kernel, so they still have their
user-space values. */
case PREFIX_FS_-1:
- /* The cast is needed here to get gcc 2.8.0 to use a 16 bit register
- in the assembler statement. */
-
- __asm__("mov %%fs,%0":"=r" (selector));
- addr->selector = selector;
+ /* N.B. - movl %seg, mem is a 2 byte write regardless of prefix */
+ savesegment(fs, addr->selector);
break;
case PREFIX_GS_-1:
- /* The cast is needed here to get gcc 2.8.0 to use a 16 bit register
- in the assembler statement. */
- __asm__("mov %%gs,%0":"=r" (selector));
- addr->selector = selector;
+ savesegment(gs, addr->selector);
break;
default:
addr->selector = PM_REG_(segment);
/*
* descriptor tables
*/
- asm volatile ("sgdt %0" : "=m" (ctxt->gdt_limit));
- asm volatile ("sidt %0" : "=m" (ctxt->idt_limit));
- asm volatile ("str %0" : "=m" (ctxt->tr));
+ store_gdt(&ctxt->gdt_limit);
+ store_idt(&ctxt->idt_limit);
+ store_tr(ctxt->tr);
/*
* segment registers
*/
- asm volatile ("movw %%es, %0" : "=m" (ctxt->es));
- asm volatile ("movw %%fs, %0" : "=m" (ctxt->fs));
- asm volatile ("movw %%gs, %0" : "=m" (ctxt->gs));
- asm volatile ("movw %%ss, %0" : "=m" (ctxt->ss));
+ savesegment(es, ctxt->es);
+ savesegment(fs, ctxt->fs);
+ savesegment(gs, ctxt->gs);
+ savesegment(ss, ctxt->ss);
/*
* control registers
* now restore the descriptor tables to their proper values
* ltr is done i fix_processor_context().
*/
- asm volatile ("lgdt %0" :: "m" (ctxt->gdt_limit));
- asm volatile ("lidt %0" :: "m" (ctxt->idt_limit));
+ load_gdt(&ctxt->gdt_limit);
+ load_idt(&ctxt->idt_limit);
/*
* segment registers
*/
- asm volatile ("movw %0, %%es" :: "r" (ctxt->es));
- asm volatile ("movw %0, %%fs" :: "r" (ctxt->fs));
- asm volatile ("movw %0, %%gs" :: "r" (ctxt->gs));
- asm volatile ("movw %0, %%ss" :: "r" (ctxt->ss));
+ loadsegment(es, ctxt->es);
+ loadsegment(fs, ctxt->fs);
+ loadsegment(gs, ctxt->gs);
+ loadsegment(ss, ctxt->ss);
/*
* sysenter MSRs
#define load_TR_desc() __asm__ __volatile__("ltr %%ax"::"a" (GDT_ENTRY_TSS*8))
#define load_LDT_desc() __asm__ __volatile__("lldt %%ax"::"a" (GDT_ENTRY_LDT*8))
+#define load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr))
+#define load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr))
+#define load_tr(tr) __asm__ __volatile("ltr %0"::"mr" (tr))
+#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"mr" (ldt))
+
+#define store_gdt(dtr) __asm__ ("sgdt %0":"=m" (*dtr))
+#define store_idt(dtr) __asm__ ("sidt %0":"=m" (*dtr))
+#define store_tr(tr) __asm__ ("str %0":"=mr" (tr))
+#define store_ldt(ldt) __asm__ ("sldt %0":"=mr" (ldt))
+
/*
* This is the ldt that every process will get unless we need
* something other than this.
".align 4\n\t" \
".long 1b,3b\n" \
".previous" \
- : :"m" (value))
+ : :"rm" (value))
/*
* Save a segment register away
*/
#define savesegment(seg, value) \
- asm volatile("mov %%" #seg ",%0":"=m" (value))
+ asm volatile("mov %%" #seg ",%0":"=rm" (value))
/*
* Clear and set 'TS' bit respectively