mirror of https://gitee.com/openkylin/linux.git
x86/idt: Unify gate_struct handling for 32/64-bit kernels
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>
This commit is contained in:
parent
7328552780
commit
64b163fab6
arch/x86
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue