x86/idt: Unify gate_struct handling for 32/64-bit kernels
authorThomas Gleixner <tglx@linutronix.de>
Mon, 28 Aug 2017 06:47:37 +0000 (08:47 +0200)
committerIngo Molnar <mingo@kernel.org>
Tue, 29 Aug 2017 10:07:24 +0000 (12:07 +0200)
The first 32 bits of gate struct are the same for 32 and 64 bit kernels.

The 32-bit version uses desc_struct and no designated data structure,
so we need different accessors for 32 and 64 bit kernels.

Aside of that the macros which are necessary to build the 32-bit
gate descriptor are horrible to read.

Unify the gate structs and switch all code fiddling with it over.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: http://lkml.kernel.org/r/20170828064957.861974317@linutronix.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/boot/compressed/eboot.c
arch/x86/include/asm/desc.h
arch/x86/include/asm/desc_defs.h
arch/x86/kvm/vmx.c
arch/x86/xen/enlighten_pv.c

index c3e869eaef0c625b98f5bcafabd1a2aba02ab8c7..65f0b24f60db3d1dfc1699d91117fbdef76d4998 100644 (file)
@@ -1058,7 +1058,7 @@ struct boot_params *efi_main(struct efi_config *c,
                desc->s = DESC_TYPE_CODE_DATA;
                desc->dpl = 0;
                desc->p = 1;
-               desc->limit = 0xf;
+               desc->limit1 = 0xf;
                desc->avl = 0;
                desc->l = 0;
                desc->d = SEG_OP_SIZE_32BIT;
@@ -1078,7 +1078,7 @@ struct boot_params *efi_main(struct efi_config *c,
        desc->s = DESC_TYPE_CODE_DATA;
        desc->dpl = 0;
        desc->p = 1;
-       desc->limit = 0xf;
+       desc->limit1 = 0xf;
        desc->avl = 0;
        if (IS_ENABLED(CONFIG_X86_64)) {
                desc->l = 1;
@@ -1099,7 +1099,7 @@ struct boot_params *efi_main(struct efi_config *c,
        desc->s = DESC_TYPE_CODE_DATA;
        desc->dpl = 0;
        desc->p = 1;
-       desc->limit = 0xf;
+       desc->limit1 = 0xf;
        desc->avl = 0;
        desc->l = 0;
        desc->d = SEG_OP_SIZE_32BIT;
@@ -1116,7 +1116,7 @@ struct boot_params *efi_main(struct efi_config *c,
                desc->s = 0;
                desc->dpl = 0;
                desc->p = 1;
-               desc->limit = 0x0;
+               desc->limit1 = 0x0;
                desc->avl = 0;
                desc->l = 0;
                desc->d = 0;
index d18a604a0941c0613b5cdc6b69675a665e3245bd..0731064c633bf89e41e92c152446ffdcf6571a70 100644 (file)
@@ -84,33 +84,25 @@ static inline phys_addr_t get_cpu_gdt_paddr(unsigned int cpu)
        return per_cpu_ptr_to_phys(get_cpu_gdt_rw(cpu));
 }
 
-#ifdef CONFIG_X86_64
-
 static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func,
                             unsigned dpl, unsigned ist, unsigned seg)
 {
-       gate->offset_low        = PTR_LOW(func);
+       gate->offset_low        = (u16) func;
+       gate->bits.p            = 1;
+       gate->bits.dpl          = dpl;
+       gate->bits.zero         = 0;
+       gate->bits.type         = type;
+       gate->offset_middle     = (u16) (func >> 16);
+#ifdef CONFIG_X86_64
        gate->segment           = __KERNEL_CS;
-       gate->ist               = ist;
-       gate->p                 = 1;
-       gate->dpl               = dpl;
-       gate->zero0             = 0;
-       gate->zero1             = 0;
-       gate->type              = type;
-       gate->offset_middle     = PTR_MIDDLE(func);
-       gate->offset_high       = PTR_HIGH(func);
-}
-
+       gate->bits.ist          = ist;
+       gate->reserved          = 0;
+       gate->offset_high       = (u32) (func >> 32);
 #else
-static inline void pack_gate(gate_desc *gate, unsigned char type,
-                            unsigned long base, unsigned dpl, unsigned flags,
-                            unsigned short seg)
-{
-       gate->a = (seg << 16) | (base & 0xffff);
-       gate->b = (base & 0xffff0000) | (((0x80 | type | (dpl << 5)) & 0xff) << 8);
-}
-
+       gate->segment           = seg;
+       gate->bits.ist          = 0;
 #endif
+}
 
 static inline int desc_empty(const void *ptr)
 {
@@ -186,7 +178,8 @@ static inline void pack_descriptor(struct desc_struct *desc, unsigned long base,
 }
 
 
-static inline void set_tssldt_descriptor(void *d, unsigned long addr, unsigned type, unsigned size)
+static inline void set_tssldt_descriptor(void *d, unsigned long addr,
+                                        unsigned type, unsigned size)
 {
 #ifdef CONFIG_X86_64
        struct ldttss_desc64 *desc = d;
@@ -194,13 +187,13 @@ static inline void set_tssldt_descriptor(void *d, unsigned long addr, unsigned t
        memset(desc, 0, sizeof(*desc));
 
        desc->limit0            = size & 0xFFFF;
-       desc->base0             = PTR_LOW(addr);
-       desc->base1             = PTR_MIDDLE(addr) & 0xFF;
+       desc->base0             = (u16) addr;
+       desc->base1             = (addr >> 16) & 0xFF;
        desc->type              = type;
        desc->p                 = 1;
        desc->limit1            = (size >> 16) & 0xF;
-       desc->base2             = (PTR_MIDDLE(addr) >> 8) & 0xFF;
-       desc->base3             = PTR_HIGH(addr);
+       desc->base2             = (addr >> 24) & 0xFF;
+       desc->base3             = (u32) (addr >> 32);
 #else
        pack_descriptor((struct desc_struct *)d, addr, size, 0x80 | type, 0);
 #endif
index 49265345d4d223ffcf15e03ba2843ddaabe82668..d684bee8a59a3e9f9ea717d7b466d55941aa858b 100644 (file)
@@ -47,20 +47,6 @@ enum {
        GATE_TASK = 0x5,
 };
 
-/* 16byte gate */
-struct gate_struct64 {
-       u16 offset_low;
-       u16 segment;
-       unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
-       u16 offset_middle;
-       u32 offset_high;
-       u32 zero1;
-} __attribute__((packed));
-
-#define PTR_LOW(x) ((unsigned long long)(x) & 0xFFFF)
-#define PTR_MIDDLE(x) (((unsigned long long)(x) >> 16) & 0xFFFF)
-#define PTR_HIGH(x) ((unsigned long long)(x) >> 32)
-
 enum {
        DESC_TSS = 0x9,
        DESC_LDT = 0x2,
@@ -77,20 +63,51 @@ struct ldttss_desc64 {
        u32 zero1;
 } __attribute__((packed));
 
+
 #ifdef CONFIG_X86_64
-typedef struct gate_struct64 gate_desc;
 typedef struct ldttss_desc64 ldt_desc;
 typedef struct ldttss_desc64 tss_desc;
-#define gate_offset(g) ((g).offset_low | ((unsigned long)(g).offset_middle << 16) | ((unsigned long)(g).offset_high << 32))
-#define gate_segment(g) ((g).segment)
 #else
-typedef struct desc_struct gate_desc;
 typedef struct desc_struct ldt_desc;
 typedef struct desc_struct tss_desc;
-#define gate_offset(g)         (((g).b & 0xffff0000) | ((g).a & 0x0000ffff))
-#define gate_segment(g)                ((g).a >> 16)
 #endif
 
+struct idt_bits {
+       u16             ist     : 3,
+                       zero    : 5,
+                       type    : 5,
+                       dpl     : 2,
+                       p       : 1;
+} __attribute__((packed));
+
+struct gate_struct {
+       u16             offset_low;
+       u16             segment;
+       struct idt_bits bits;
+       u16             offset_middle;
+#ifdef CONFIG_X86_64
+       u32             offset_high;
+       u32             reserved;
+#endif
+} __attribute__((packed));
+
+typedef struct gate_struct gate_desc;
+
+static inline unsigned long gate_offset(const gate_desc *g)
+{
+#ifdef CONFIG_X86_64
+       return g->offset_low | ((unsigned long)g->offset_middle << 16) |
+               ((unsigned long) g->offset_high << 32);
+#else
+       return g->offset_low | ((unsigned long)g->offset_middle << 16);
+#endif
+}
+
+static inline unsigned long gate_segment(const gate_desc *g)
+{
+       return g->segment;
+}
+
 struct desc_ptr {
        unsigned short size;
        unsigned long address;
index c6ef2940119bfdfb00f0547c321697280ebae0fa..08d00eefabeacbff275d3a78a1153546421d4f7e 100644 (file)
@@ -8779,7 +8779,7 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
 
                vector =  exit_intr_info & INTR_INFO_VECTOR_MASK;
                desc = (gate_desc *)vmx->host_idt_base + vector;
-               entry = gate_offset(*desc);
+               entry = gate_offset(desc);
                asm volatile(
 #ifdef CONFIG_X86_64
                        "mov %%" _ASM_SP ", %[sp]\n\t"
index 98491521bb434063f0a9a502915e8679268e7579..4c5d72b8aada79a2369d699e3b398e64112c1984 100644 (file)
@@ -584,12 +584,12 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val,
 {
        unsigned long addr;
 
-       if (val->type != GATE_TRAP && val->type != GATE_INTERRUPT)
+       if (val->bits.type != GATE_TRAP && val->bits.type != GATE_INTERRUPT)
                return 0;
 
        info->vector = vector;
 
-       addr = gate_offset(*val);
+       addr = gate_offset(val);
 #ifdef CONFIG_X86_64
        /*
         * Look for known traps using IST, and substitute them
@@ -622,16 +622,16 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val,
                ;
        else {
                /* Some other trap using IST? */
-               if (WARN_ON(val->ist != 0))
+               if (WARN_ON(val->bits.ist != 0))
                        return 0;
        }
 #endif /* CONFIG_X86_64 */
        info->address = addr;
 
-       info->cs = gate_segment(*val);
-       info->flags = val->dpl;
+       info->cs = gate_segment(val);
+       info->flags = val->bits.dpl;
        /* interrupt gates clear IF */
-       if (val->type == GATE_INTERRUPT)
+       if (val->bits.type == GATE_INTERRUPT)
                info->flags |= 1 << 2;
 
        return 1;