1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Thomas Gleixner <tglx@linutronix.de>
3 Date: Mon, 28 Aug 2017 08:47:37 +0200
4 Subject: [PATCH] x86/idt: Unify gate_struct handling for 32/64-bit kernels
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
11 The first 32 bits of gate struct are the same for 32 and 64 bit kernels.
13 The 32-bit version uses desc_struct and no designated data structure,
14 so we need different accessors for 32 and 64 bit kernels.
16 Aside of that the macros which are necessary to build the 32-bit
17 gate descriptor are horrible to read.
19 Unify the gate structs and switch all code fiddling with it over.
21 Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
22 Cc: Andy Lutomirski <luto@kernel.org>
23 Cc: Borislav Petkov <bp@alien8.de>
24 Cc: Brian Gerst <brgerst@gmail.com>
25 Cc: Denys Vlasenko <dvlasenk@redhat.com>
26 Cc: H. Peter Anvin <hpa@zytor.com>
27 Cc: Josh Poimboeuf <jpoimboe@redhat.com>
28 Cc: Linus Torvalds <torvalds@linux-foundation.org>
29 Cc: Peter Zijlstra <peterz@infradead.org>
30 Cc: Steven Rostedt <rostedt@goodmis.org>
31 Link: http://lkml.kernel.org/r/20170828064957.861974317@linutronix.de
32 Signed-off-by: Ingo Molnar <mingo@kernel.org>
33 (cherry picked from commit 64b163fab684e3de47aa8db6cc08ae7d2e194373)
34 Signed-off-by: Andy Whitcroft <apw@canonical.com>
35 Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
36 (cherry picked from commit 587719b1926757eb7531e0631d63fb93cd60d0d3)
37 Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
39 arch/x86/include/asm/desc.h | 45 ++++++++++++++-----------------
40 arch/x86/include/asm/desc_defs.h | 57 ++++++++++++++++++++++++++--------------
41 arch/x86/kvm/vmx.c | 2 +-
42 arch/x86/xen/enlighten_pv.c | 12 ++++-----
43 4 files changed, 63 insertions(+), 53 deletions(-)
45 diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
46 index d0a21b12dd58..57e502a4e92f 100644
47 --- a/arch/x86/include/asm/desc.h
48 +++ b/arch/x86/include/asm/desc.h
49 @@ -83,33 +83,25 @@ static inline phys_addr_t get_cpu_gdt_paddr(unsigned int cpu)
50 return per_cpu_ptr_to_phys(get_cpu_gdt_rw(cpu));
55 static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func,
56 unsigned dpl, unsigned ist, unsigned seg)
58 - gate->offset_low = PTR_LOW(func);
59 + gate->offset_low = (u16) func;
61 + gate->bits.dpl = dpl;
62 + gate->bits.zero = 0;
63 + gate->bits.type = type;
64 + gate->offset_middle = (u16) (func >> 16);
66 gate->segment = __KERNEL_CS;
73 - gate->offset_middle = PTR_MIDDLE(func);
74 - gate->offset_high = PTR_HIGH(func);
77 + gate->bits.ist = ist;
79 + gate->offset_high = (u32) (func >> 32);
81 -static inline void pack_gate(gate_desc *gate, unsigned char type,
82 - unsigned long base, unsigned dpl, unsigned flags,
85 - gate->a = (seg << 16) | (base & 0xffff);
86 - gate->b = (base & 0xffff0000) | (((0x80 | type | (dpl << 5)) & 0xff) << 8);
89 + gate->segment = seg;
94 static inline int desc_empty(const void *ptr)
96 @@ -185,7 +177,8 @@ static inline void pack_descriptor(struct desc_struct *desc, unsigned long base,
100 -static inline void set_tssldt_descriptor(void *d, unsigned long addr, unsigned type, unsigned size)
101 +static inline void set_tssldt_descriptor(void *d, unsigned long addr,
102 + unsigned type, unsigned size)
105 struct ldttss_desc64 *desc = d;
106 @@ -193,13 +186,13 @@ static inline void set_tssldt_descriptor(void *d, unsigned long addr, unsigned t
107 memset(desc, 0, sizeof(*desc));
109 desc->limit0 = size & 0xFFFF;
110 - desc->base0 = PTR_LOW(addr);
111 - desc->base1 = PTR_MIDDLE(addr) & 0xFF;
112 + desc->base0 = (u16) addr;
113 + desc->base1 = (addr >> 16) & 0xFF;
116 desc->limit1 = (size >> 16) & 0xF;
117 - desc->base2 = (PTR_MIDDLE(addr) >> 8) & 0xFF;
118 - desc->base3 = PTR_HIGH(addr);
119 + desc->base2 = (addr >> 24) & 0xFF;
120 + desc->base3 = (u32) (addr >> 32);
122 pack_descriptor((struct desc_struct *)d, addr, size, 0x80 | type, 0);
124 diff --git a/arch/x86/include/asm/desc_defs.h b/arch/x86/include/asm/desc_defs.h
125 index 49265345d4d2..d684bee8a59a 100644
126 --- a/arch/x86/include/asm/desc_defs.h
127 +++ b/arch/x86/include/asm/desc_defs.h
128 @@ -47,20 +47,6 @@ enum {
133 -struct gate_struct64 {
136 - unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
140 -} __attribute__((packed));
142 -#define PTR_LOW(x) ((unsigned long long)(x) & 0xFFFF)
143 -#define PTR_MIDDLE(x) (((unsigned long long)(x) >> 16) & 0xFFFF)
144 -#define PTR_HIGH(x) ((unsigned long long)(x) >> 32)
149 @@ -77,20 +63,51 @@ struct ldttss_desc64 {
151 } __attribute__((packed));
155 -typedef struct gate_struct64 gate_desc;
156 typedef struct ldttss_desc64 ldt_desc;
157 typedef struct ldttss_desc64 tss_desc;
158 -#define gate_offset(g) ((g).offset_low | ((unsigned long)(g).offset_middle << 16) | ((unsigned long)(g).offset_high << 32))
159 -#define gate_segment(g) ((g).segment)
161 -typedef struct desc_struct gate_desc;
162 typedef struct desc_struct ldt_desc;
163 typedef struct desc_struct tss_desc;
164 -#define gate_offset(g) (((g).b & 0xffff0000) | ((g).a & 0x0000ffff))
165 -#define gate_segment(g) ((g).a >> 16)
174 +} __attribute__((packed));
176 +struct gate_struct {
179 + struct idt_bits bits;
181 +#ifdef CONFIG_X86_64
185 +} __attribute__((packed));
187 +typedef struct gate_struct gate_desc;
189 +static inline unsigned long gate_offset(const gate_desc *g)
191 +#ifdef CONFIG_X86_64
192 + return g->offset_low | ((unsigned long)g->offset_middle << 16) |
193 + ((unsigned long) g->offset_high << 32);
195 + return g->offset_low | ((unsigned long)g->offset_middle << 16);
199 +static inline unsigned long gate_segment(const gate_desc *g)
206 unsigned long address;
207 diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
208 index a2c95522ac99..7b447d126d17 100644
209 --- a/arch/x86/kvm/vmx.c
210 +++ b/arch/x86/kvm/vmx.c
211 @@ -8838,7 +8838,7 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
213 vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
214 desc = (gate_desc *)vmx->host_idt_base + vector;
215 - entry = gate_offset(*desc);
216 + entry = gate_offset(desc);
219 "mov %%" _ASM_SP ", %[sp]\n\t"
220 diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
221 index 6c279c8f0a0e..49ee3315b9f7 100644
222 --- a/arch/x86/xen/enlighten_pv.c
223 +++ b/arch/x86/xen/enlighten_pv.c
224 @@ -591,12 +591,12 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val,
228 - if (val->type != GATE_TRAP && val->type != GATE_INTERRUPT)
229 + if (val->bits.type != GATE_TRAP && val->bits.type != GATE_INTERRUPT)
232 info->vector = vector;
234 - addr = gate_offset(*val);
235 + addr = gate_offset(val);
238 * Look for known traps using IST, and substitute them
239 @@ -629,16 +629,16 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val,
242 /* Some other trap using IST? */
243 - if (WARN_ON(val->ist != 0))
244 + if (WARN_ON(val->bits.ist != 0))
247 #endif /* CONFIG_X86_64 */
248 info->address = addr;
250 - info->cs = gate_segment(*val);
251 - info->flags = val->dpl;
252 + info->cs = gate_segment(val);
253 + info->flags = val->bits.dpl;
254 /* interrupt gates clear IF */
255 - if (val->type == GATE_INTERRUPT)
256 + if (val->bits.type == GATE_INTERRUPT)
257 info->flags |= 1 << 2;