diff --git a/xen/include/asm-x86/desc.h b/xen/include/asm-x86/desc.h index 4093c65faa..58efc1d896 100644 --- a/xen/include/asm-x86/desc.h +++ b/xen/include/asm-x86/desc.h @@ -106,8 +106,19 @@ struct desc_struct { u32 a, b; }; -typedef struct { - u64 a, b; +typedef union { + struct { + uint64_t a, b; + }; + struct { + uint16_t addr0; + uint16_t cs; + uint8_t ist; /* :3, 5 bits rsvd, but this yields far better code. */ + uint8_t type:4, s:1, dpl:2, p:1; + uint16_t addr1; + uint32_t addr2; + /* 32 bits rsvd. */ + }; } idt_entry_t; /* Write the lower 64 bits of an IDT Entry. This relies on the upper 32 diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index db9988ab33..1bc2f90d04 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -406,16 +406,14 @@ struct __packed __cacheline_aligned tss_struct { #define IST_MCE 3UL #define IST_MAX 3UL -/* Set the interrupt stack table used by a particular interrupt - * descriptor table entry. */ -static always_inline void set_ist(idt_entry_t *idt, unsigned long ist) +/* Set the Interrupt Stack Table used by a particular IDT entry. */ +static inline void set_ist(idt_entry_t *idt, unsigned int ist) { - idt_entry_t new = *idt; - /* IST is a 3 bit field, 32 bits into the IDT entry. */ ASSERT(ist <= IST_MAX); - new.a = (idt->a & ~(7UL << 32)) | (ist << 32); - _write_gate_lower(idt, &new); + + /* Typically used on a live idt. Disuade any clever optimisations. */ + ACCESS_ONCE(idt->ist) = ist; } static inline void enable_each_ist(idt_entry_t *idt)