From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Xen-devel <xen-devel@lists.xenproject.org>
Cc: "Andrew Cooper" <andrew.cooper3@citrix.com>,
"Jan Beulich" <JBeulich@suse.com>,
"Roger Pau Monné" <roger.pau@citrix.com>
Subject: [PATCH 2/8] x86/IDT: Collect IDT related content idt.h
Date: Mon, 24 Feb 2025 16:05:03 +0000 [thread overview]
Message-ID: <20250224160509.1117847-3-andrew.cooper3@citrix.com> (raw)
In-Reply-To: <20250224160509.1117847-1-andrew.cooper3@citrix.com>
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>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
---
xen/arch/x86/cpu/common.c | 1 +
xen/arch/x86/crash.c | 1 +
xen/arch/x86/domain.c | 1 +
xen/arch/x86/hvm/svm/svm.c | 1 +
xen/arch/x86/hvm/vmx/vmcs.c | 1 +
xen/arch/x86/include/asm/desc.h | 76 ----------------
xen/arch/x86/include/asm/idt.h | 125 +++++++++++++++++++++++++++
xen/arch/x86/include/asm/processor.h | 37 --------
xen/arch/x86/machine_kexec.c | 1 +
xen/arch/x86/mm.c | 4 +
xen/arch/x86/pv/traps.c | 1 +
xen/arch/x86/smpboot.c | 1 +
xen/arch/x86/traps.c | 1 +
xen/arch/x86/x86_64/traps.c | 3 -
14 files changed, 138 insertions(+), 116 deletions(-)
create mode 100644 xen/arch/x86/include/asm/idt.h
diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c
index 1cc4adccb471..1540ab0007a0 100644
--- a/xen/arch/x86/cpu/common.c
+++ b/xen/arch/x86/cpu/common.c
@@ -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>
diff --git a/xen/arch/x86/crash.c b/xen/arch/x86/crash.c
index 4afe0ad859a7..5f7d7b392a1f 100644
--- a/xen/arch/x86/crash.c
+++ b/xen/arch/x86/crash.c
@@ -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>
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 7b2549091fd3..d3db76833f3c 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -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>
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 62905c2c7acd..ea78da4f4210 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -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>
diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index fa9d8b3267ea..0136830ebcb7 100644
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -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>
diff --git a/xen/arch/x86/include/asm/desc.h b/xen/arch/x86/include/asm/desc.h
index a1e0807d97ed..85fae6b2f9ae 100644
--- a/xen/arch/x86/include/asm/desc.h
+++ b/xen/arch/x86/include/asm/desc.h
@@ -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
index 000000000000..4ef52050a11b
--- /dev/null
+++ b/xen/arch/x86/include/asm/idt.h
@@ -0,0 +1,125 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef X86_ASM_IDT_H
+#define X86_ASM_IDT_H
+
+#include <xen/bug.h>
+#include <xen/types.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);
+}
+
+/*
+ * 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;
+}
+
+#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);
+}
+
+#endif /* X86_ASM_IDT_H */
diff --git a/xen/arch/x86/include/asm/processor.h b/xen/arch/x86/include/asm/processor.h
index d247ef8dd226..86174cce5821 100644
--- a/xen/arch/x86/include/asm/processor.h
+++ b/xen/arch/x86/include/asm/processor.h
@@ -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);
diff --git a/xen/arch/x86/machine_kexec.c b/xen/arch/x86/machine_kexec.c
index e20e8d0b1563..f775e526d59b 100644
--- a/xen/arch/x86/machine_kexec.c
+++ b/xen/arch/x86/machine_kexec.c
@@ -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>
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 6b34b908efcd..bfdc8fb01949 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -115,6 +115,7 @@
#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);
}
/*
diff --git a/xen/arch/x86/pv/traps.c b/xen/arch/x86/pv/traps.c
index fd1597d0bdea..77b034e4dc73 100644
--- a/xen/arch/x86/pv/traps.c
+++ b/xen/arch/x86/pv/traps.c
@@ -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>
diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
index f904d5623272..f3d60d5bae35 100644
--- a/xen/arch/x86/smpboot.c
+++ b/xen/arch/x86/smpboot.c
@@ -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>
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index e8d5aa9fd46b..1a53bb4aa481 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -52,6 +52,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>
diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c
index 93f32ac66c92..8b9f0949d348 100644
--- a/xen/arch/x86/x86_64/traps.c
+++ b/xen/arch/x86/x86_64/traps.c
@@ -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;
--
2.39.5
next prev parent reply other threads:[~2025-02-24 16:07 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-24 16:05 [PATCH 0/8] x86/IDT: Generate the IDT at build time Andrew Cooper
2025-02-24 16:05 ` [PATCH 1/8] x86: Sort includes in various files Andrew Cooper
2025-02-24 16:11 ` Jan Beulich
2025-02-24 16:05 ` Andrew Cooper [this message]
2025-02-25 8:27 ` [PATCH 2/8] x86/IDT: Collect IDT related content idt.h Jan Beulich
2025-02-26 17:15 ` Andrew Cooper
2025-02-27 7:49 ` Jan Beulich
2025-02-24 16:05 ` [PATCH 3/8] x86/IDT: Rename X86_NR_VECTORS to X86_IDT_VECTORS Andrew Cooper
2025-02-25 8:31 ` Jan Beulich
2025-02-26 17:27 ` Andrew Cooper
2025-02-27 7:57 ` Jan Beulich
2025-02-24 16:05 ` [PATCH 4/8] x86/IDT: Rename idt_table[] to bsp_idt[] Andrew Cooper
2025-02-25 9:00 ` Jan Beulich
2025-02-25 12:54 ` Andrew Cooper
2025-02-25 14:33 ` Jan Beulich
2025-02-25 16:20 ` Andrew Cooper
2025-02-25 16:29 ` Jan Beulich
2025-02-24 16:05 ` [PATCH 5/8] x86/IDT: Make idt_tables[] be per_cpu(idt) Andrew Cooper
2025-02-25 9:07 ` Jan Beulich
2025-02-25 15:40 ` Andrew Cooper
2025-02-25 16:33 ` Jan Beulich
2025-03-04 14:40 ` Andrew Cooper
2025-02-24 16:05 ` [PATCH 6/8] x86/IDT: Generate bsp_idt[] at build time Andrew Cooper
2025-02-26 12:39 ` Jan Beulich
2025-02-26 13:37 ` Andrew Cooper
2025-02-26 14:14 ` Jan Beulich
2025-02-26 15:14 ` Andrew Cooper
2025-02-24 16:05 ` [PATCH 7/8] x86/IDT: Don't rewrite bsp_idt[] at boot time Andrew Cooper
2025-02-26 12:48 ` Jan Beulich
2025-02-26 12:53 ` Andrew Cooper
2025-02-26 13:18 ` Jan Beulich
2025-02-26 13:23 ` Andrew Cooper
2025-02-24 16:05 ` [PATCH 8/8] x86/traps: Convert pv_trap_init() to being an initcall Andrew Cooper
2025-02-26 12:53 ` Jan Beulich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250224160509.1117847-3-andrew.cooper3@citrix.com \
--to=andrew.cooper3@citrix.com \
--cc=JBeulich@suse.com \
--cc=roger.pau@citrix.com \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.