]> xenbits.xensource.com Git - people/royger/xen.git/commitdiff
x86/IDT: Collect IDT related content idt.h
authorAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 1 Jan 2025 15:43:20 +0000 (15:43 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Tue, 4 Mar 2025 19:46:41 +0000 (19:46 +0000)
Logic concerning the IDT is somewhat different to the other system tables, and
in particular ought not to be in asm/processor.h.  Collect it together a new
header.

While doing so, make a few minor adjustments:

 * Make set_ist() use volatile rather than ACCESS_ONCE(), as
   _write_gate_lower() already does, removing the need for xen/lib.h.

 * Move the BUILD_BUG_ON() from subarch_percpu_traps_init() into mm.c's
   build_assertions(), rather than including idt.h into x86_64/traps.c.

 * Drop UL from IST constants.

No functional change.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
14 files changed:
xen/arch/x86/cpu/common.c
xen/arch/x86/crash.c
xen/arch/x86/domain.c
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/vmx/vmcs.c
xen/arch/x86/include/asm/desc.h
xen/arch/x86/include/asm/idt.h [new file with mode: 0644]
xen/arch/x86/include/asm/processor.h
xen/arch/x86/machine_kexec.c
xen/arch/x86/mm.c
xen/arch/x86/pv/traps.c
xen/arch/x86/smpboot.c
xen/arch/x86/traps.c
xen/arch/x86/x86_64/traps.c

index 1cc4adccb4718bb1c3ebdc907e5dfe375b3f8d50..1540ab0007a062f7a88a462ef66005870c632b3b 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/cpu-policy.h>
 #include <asm/current.h>
 #include <asm/debugreg.h>
+#include <asm/idt.h>
 #include <asm/io.h>
 #include <asm/mpspec.h>
 #include <asm/msr.h>
index 4afe0ad859a748292118b77c6365ddde7f280f88..5f7d7b392a1f3b0905d7dc531eed6aef77ed42d2 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/atomic.h>
 #include <asm/elf.h>
 #include <asm/hpet.h>
+#include <asm/idt.h>
 #include <asm/io_apic.h>
 #include <asm/nmi.h>
 #include <asm/shared.h>
index 7b2549091fd38db34fc91c10b1607ebb5f998568..d3db76833f3cd69799a0bdd7c03e0fbabec1e223 100644 (file)
@@ -47,6 +47,7 @@
 #include <asm/hvm/svm/svm.h>
 #include <asm/hvm/viridian.h>
 #include <asm/i387.h>
+#include <asm/idt.h>
 #include <asm/io.h>
 #include <asm/ldt.h>
 #include <asm/mc146818rtc.h>
index 62905c2c7acdbc0b2174a6e5c1678337ac225ac8..ea78da4f42105a5b3fba8e8cf7e493752408db7b 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/cpufeature.h>
 #include <asm/current.h>
 #include <asm/debugreg.h>
+#include <asm/idt.h>
 #include <asm/gdbsx.h>
 #include <asm/hvm/emulate.h>
 #include <asm/hvm/hvm.h>
index fa9d8b3267eaecf6586ae69267346d965c66b264..0136830ebcb70b8f63f38c331fb62e8693493880 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/hvm/vmx/vmcs.h>
 #include <asm/hvm/vmx/vmx.h>
 #include <asm/hvm/vmx/vvmx.h>
+#include <asm/idt.h>
 #include <asm/monitor.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
index a1e0807d97edd02ab4ac2b0cb59bc0dfa4272da6..85fae6b2f9ae85d2a3b577413353fd09525896e5 100644 (file)
@@ -115,82 +115,6 @@ typedef union {
     };
 } seg_desc_t;
 
-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
- * bits of the address not changing, which is a safe assumption as all
- * functions we are likely to load will live inside the 1GB
- * code/data/bss address range.
- *
- * Ideally, we would use cmpxchg16b, but this is not supported on some
- * old AMD 64bit capable processors, and has no safe equivalent.
- */
-static inline void _write_gate_lower(volatile idt_entry_t *gate,
-                                     const idt_entry_t *new)
-{
-    ASSERT(gate->b == new->b);
-    gate->a = new->a;
-}
-
-#define _set_gate(gate_addr,type,dpl,addr)               \
-do {                                                     \
-    (gate_addr)->a = 0;                                  \
-    smp_wmb(); /* disable gate /then/ rewrite */         \
-    (gate_addr)->b =                                     \
-        ((unsigned long)(addr) >> 32);                   \
-    smp_wmb(); /* rewrite /then/ enable gate */          \
-    (gate_addr)->a =                                     \
-        (((unsigned long)(addr) & 0xFFFF0000UL) << 32) | \
-        ((unsigned long)(dpl) << 45) |                   \
-        ((unsigned long)(type) << 40) |                  \
-        ((unsigned long)(addr) & 0xFFFFUL) |             \
-        ((unsigned long)__HYPERVISOR_CS << 16) |         \
-        (1UL << 47);                                     \
-} while (0)
-
-static inline void _set_gate_lower(idt_entry_t *gate, unsigned long type,
-                                   unsigned long dpl, void *addr)
-{
-    idt_entry_t idte;
-    idte.b = gate->b;
-    idte.a =
-        (((unsigned long)(addr) & 0xFFFF0000UL) << 32) |
-        ((unsigned long)(dpl) << 45) |
-        ((unsigned long)(type) << 40) |
-        ((unsigned long)(addr) & 0xFFFFUL) |
-        ((unsigned long)__HYPERVISOR_CS << 16) |
-        (1UL << 47);
-    _write_gate_lower(gate, &idte);
-}
-
-/* Update the lower half handler of an IDT Entry, without changing any
- * other configuration. */
-static inline void _update_gate_addr_lower(idt_entry_t *gate, void *addr)
-{
-    idt_entry_t idte;
-    idte.a = gate->a;
-
-    idte.b = ((unsigned long)(addr) >> 32);
-    idte.a &= 0x0000FFFFFFFF0000ULL;
-    idte.a |= (((unsigned long)(addr) & 0xFFFF0000UL) << 32) |
-        ((unsigned long)(addr) & 0xFFFFUL);
-
-    _write_gate_lower(gate, &idte);
-}
-
 #define _set_tssldt_desc(desc,addr,limit,type)           \
 do {                                                     \
     (desc)[0].b = (desc)[1].b = 0;                       \
diff --git a/xen/arch/x86/include/asm/idt.h b/xen/arch/x86/include/asm/idt.h
new file mode 100644 (file)
index 0000000..3689fde
--- /dev/null
@@ -0,0 +1,124 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef X86_ASM_IDT_H
+#define X86_ASM_IDT_H
+
+#include <xen/bug.h>
+
+#include <asm/x86-defns.h>
+
+#define IST_NONE 0
+#define IST_MCE  1
+#define IST_NMI  2
+#define IST_DB   3
+#define IST_DF   4
+#define IST_MAX  4
+
+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;
+
+#define IDT_ENTRIES 256
+extern idt_entry_t idt_table[];
+extern idt_entry_t *idt_tables[];
+
+/*
+ * Set the Interrupt Stack Table used by a particular IDT entry.  Typically
+ * used on a live IDT, so volatile to disuade clever optimisations.
+ */
+static inline void set_ist(volatile idt_entry_t *idt, unsigned int ist)
+{
+    /* IST is a 3 bit field, 32 bits into the IDT entry. */
+    ASSERT(ist <= IST_MAX);
+
+    idt->ist = ist;
+}
+
+static inline void enable_each_ist(idt_entry_t *idt)
+{
+    set_ist(&idt[X86_EXC_DF],  IST_DF);
+    set_ist(&idt[X86_EXC_NMI], IST_NMI);
+    set_ist(&idt[X86_EXC_MC],  IST_MCE);
+    set_ist(&idt[X86_EXC_DB],  IST_DB);
+}
+
+static inline void disable_each_ist(idt_entry_t *idt)
+{
+    set_ist(&idt[X86_EXC_DF],  IST_NONE);
+    set_ist(&idt[X86_EXC_NMI], IST_NONE);
+    set_ist(&idt[X86_EXC_MC],  IST_NONE);
+    set_ist(&idt[X86_EXC_DB],  IST_NONE);
+}
+
+#define _set_gate(gate_addr,type,dpl,addr)               \
+do {                                                     \
+    (gate_addr)->a = 0;                                  \
+    smp_wmb(); /* disable gate /then/ rewrite */         \
+    (gate_addr)->b =                                     \
+        ((unsigned long)(addr) >> 32);                   \
+    smp_wmb(); /* rewrite /then/ enable gate */          \
+    (gate_addr)->a =                                     \
+        (((unsigned long)(addr) & 0xFFFF0000UL) << 32) | \
+        ((unsigned long)(dpl) << 45) |                   \
+        ((unsigned long)(type) << 40) |                  \
+        ((unsigned long)(addr) & 0xFFFFUL) |             \
+        ((unsigned long)__HYPERVISOR_CS << 16) |         \
+        (1UL << 47);                                     \
+} while (0)
+
+/*
+ * Write the lower 64 bits of an IDT Entry. This relies on the upper 32
+ * bits of the address not changing, which is a safe assumption as all
+ * functions we are likely to load will live inside the 1GB
+ * code/data/bss address range.
+ */
+static inline void _write_gate_lower(volatile idt_entry_t *gate,
+                                     const idt_entry_t *new)
+{
+    ASSERT(gate->b == new->b);
+    gate->a = new->a;
+}
+
+static inline void _set_gate_lower(idt_entry_t *gate, unsigned long type,
+                                   unsigned long dpl, void *addr)
+{
+    idt_entry_t idte;
+    idte.b = gate->b;
+    idte.a =
+        (((unsigned long)(addr) & 0xFFFF0000UL) << 32) |
+        ((unsigned long)(dpl) << 45) |
+        ((unsigned long)(type) << 40) |
+        ((unsigned long)(addr) & 0xFFFFUL) |
+        ((unsigned long)__HYPERVISOR_CS << 16) |
+        (1UL << 47);
+    _write_gate_lower(gate, &idte);
+}
+
+/*
+ * Update the lower half handler of an IDT entry, without changing any other
+ * configuration.
+ */
+static inline void _update_gate_addr_lower(idt_entry_t *gate, void *addr)
+{
+    idt_entry_t idte;
+    idte.a = gate->a;
+
+    idte.b = ((unsigned long)(addr) >> 32);
+    idte.a &= 0x0000FFFFFFFF0000ULL;
+    idte.a |= (((unsigned long)(addr) & 0xFFFF0000UL) << 32) |
+        ((unsigned long)(addr) & 0xFFFFUL);
+
+    _write_gate_lower(gate, &idte);
+}
+
+#endif /* X86_ASM_IDT_H */
index 6bc88b031761211341c77268b483671e1bb4a389..75af7ea3c4766983d85b56198fe77dfe39f02ba2 100644 (file)
@@ -353,43 +353,6 @@ struct tss_page {
 };
 DECLARE_PER_CPU(struct tss_page, tss_page);
 
-#define IST_NONE 0UL
-#define IST_MCE  1UL
-#define IST_NMI  2UL
-#define IST_DB   3UL
-#define IST_DF   4UL
-#define IST_MAX  4UL
-
-/* Set the Interrupt Stack Table used by a particular IDT entry. */
-static inline void set_ist(idt_entry_t *idt, unsigned int ist)
-{
-    /* IST is a 3 bit field, 32 bits into the IDT entry. */
-    ASSERT(ist <= IST_MAX);
-
-    /* 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)
-{
-    set_ist(&idt[X86_EXC_DF],  IST_DF);
-    set_ist(&idt[X86_EXC_NMI], IST_NMI);
-    set_ist(&idt[X86_EXC_MC],  IST_MCE);
-    set_ist(&idt[X86_EXC_DB],  IST_DB);
-}
-
-static inline void disable_each_ist(idt_entry_t *idt)
-{
-    set_ist(&idt[X86_EXC_DF],  IST_NONE);
-    set_ist(&idt[X86_EXC_NMI], IST_NONE);
-    set_ist(&idt[X86_EXC_MC],  IST_NONE);
-    set_ist(&idt[X86_EXC_DB],  IST_NONE);
-}
-
-#define IDT_ENTRIES 256
-extern idt_entry_t idt_table[];
-extern idt_entry_t *idt_tables[];
-
 DECLARE_PER_CPU(root_pgentry_t *, root_pgt);
 
 extern void write_ptbase(struct vcpu *v);
index e20e8d0b1563f3ef9f08da00de1ad5a337363689..f775e526d59bb3ce9c7c4cab46b5f38165351fef 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <asm/fixmap.h>
 #include <asm/hpet.h>
+#include <asm/idt.h>
 #include <asm/machine_kexec.h>
 #include <asm/page.h>
 
index 6b34b908efcdb00e20a30d3c925db165f05d30d0..bfdc8fb0194972b2a18dc6e3c7b3eb6ca8fe12b3 100644 (file)
 #include <asm/fixmap.h>
 #include <asm/flushtlb.h>
 #include <asm/guest.h>
+#include <asm/idt.h>
 #include <asm/io.h>
 #include <asm/io_apic.h>
 #include <asm/ldt.h>
@@ -6639,6 +6640,9 @@ static void __init __maybe_unused build_assertions(void)
      * using different PATs will not work.
      */
     BUILD_BUG_ON(XEN_MSR_PAT != 0x050100070406ULL);
+
+    /* IST_MAX IST pages + at least 1 guard page + primary stack. */
+    BUILD_BUG_ON((IST_MAX + 1) * PAGE_SIZE + PRIMARY_STACK_SIZE > STACK_SIZE);
 }
 
 /*
index fd1597d0bdeaf447223e9fa733738706dc119e63..77b034e4dc73ae35a42ee1e625624a2e21cd0a25 100644 (file)
@@ -13,6 +13,7 @@
 #include <xen/softirq.h>
 
 #include <asm/debugreg.h>
+#include <asm/idt.h>
 #include <asm/irq-vectors.h>
 #include <asm/pv/trace.h>
 #include <asm/shared.h>
index f904d562327291895585c3e76890d345af5e42d9..f3d60d5bae35394c189ff68e61e375790a2d3b81 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/div64.h>
 #include <asm/flushtlb.h>
 #include <asm/guest.h>
+#include <asm/idt.h>
 #include <asm/io_apic.h>
 #include <asm/irq-vectors.h>
 #include <asm/mc146818rtc.h>
index 3613ce573cdef2e0f801703e38005696ca3c04c0..e466a260ca11ed72031f074b0e74e1922c049472 100644 (file)
@@ -53,6 +53,7 @@
 #include <asm/hpet.h>
 #include <asm/hvm/vpt.h>
 #include <asm/i387.h>
+#include <asm/idt.h>
 #include <asm/io.h>
 #include <asm/irq-vectors.h>
 #include <asm/mc146818rtc.h>
index 7a370fae7d2241b2c3d2dab6311df7fb67290c17..ac0fafd72d31086ae42f392fa3a107f7c85c6d7b 100644 (file)
@@ -342,9 +342,6 @@ void subarch_percpu_traps_init(void)
     unsigned char *stub_page;
     unsigned int offset;
 
-    /* IST_MAX IST pages + at least 1 guard page + primary stack. */
-    BUILD_BUG_ON((IST_MAX + 1) * PAGE_SIZE + PRIMARY_STACK_SIZE > STACK_SIZE);
-
     /* No PV guests?  No need to set up SYSCALL/SYSENTER infrastructure. */
     if ( !IS_ENABLED(CONFIG_PV) )
         return;