[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen staging] x86/traps: Move load_system_tables() into traps-setup.c
commit 5222af8bb213e3068c9cf4939ed3dc42b62cf227 Author: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> AuthorDate: Wed Jan 1 15:16:33 2025 +0000 Commit: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> CommitDate: Fri Aug 15 11:13:41 2025 +0100 x86/traps: Move load_system_tables() into traps-setup.c Switch it to Xen coding style and fix MISRA violations (ul -> UL). Make it static as there are no external caller now. Since commit a35816b5cae8 ("x86/traps: Introduce early_traps_init() and simplify setup"), load_system_tables() is called later on the BSP, so the SYS_STATE_early_boot check can be dropped from the safety BUG_ON(). Move the BUILD_BUG_ON() into build_assertions(), and introduce an endof_field() helper to make the expression clearer. Swap wrmsrl(MSR_ISST, ...) for wrmsrns(). No serialisation is needed at this point. Drop the comment about Clang 3.5. It's no longer a supported toolchain, and while the comment is true, the code should have been written with a local pointer anyway. No functional change. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Acked-by: Jan Beulich <jbeulich@xxxxxxxx> --- xen/arch/x86/cpu/common.c | 118 ----------------------------------- xen/arch/x86/include/asm/system.h | 1 - xen/arch/x86/traps-setup.c | 126 ++++++++++++++++++++++++++++++++++++++ xen/include/xen/macros.h | 2 + 4 files changed, 128 insertions(+), 119 deletions(-) diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c index cdc41248d4..da05015578 100644 --- a/xen/arch/x86/cpu/common.c +++ b/xen/arch/x86/cpu/common.c @@ -843,124 +843,6 @@ void print_cpu_info(unsigned int cpu) static cpumask_t cpu_initialized; -/* - * Sets up system tables and descriptors. - * - * - Sets up TSS with stack pointers, including ISTs - * - Inserts TSS selector into regular and compat GDTs - * - Loads GDT, IDT, TR then null LDT - * - Sets up IST references in the IDT - */ -void load_system_tables(void) -{ - unsigned int i, cpu = smp_processor_id(); - unsigned long stack_bottom = get_stack_bottom(), - stack_top = stack_bottom & ~(STACK_SIZE - 1); - /* - * NB: define tss_page as a local variable because clang 3.5 doesn't - * support using ARRAY_SIZE against per-cpu variables. - */ - struct tss_page *tss_page = &this_cpu(tss_page); - idt_entry_t *idt = this_cpu(idt); - - /* The TSS may be live. Disuade any clever optimisations. */ - volatile struct tss64 *tss = &tss_page->tss; - seg_desc_t *gdt = - this_cpu(gdt) - FIRST_RESERVED_GDT_ENTRY; - - const struct desc_ptr gdtr = { - .base = (unsigned long)gdt, - .limit = LAST_RESERVED_GDT_BYTE, - }; - const struct desc_ptr idtr = { - .base = (unsigned long)idt, - .limit = sizeof(bsp_idt) - 1, - }; - - /* - * Set up the TSS. Warning - may be live, and the NMI/#MC must remain - * valid on every instruction boundary. (Note: these are all - * semantically ACCESS_ONCE() due to tss's volatile qualifier.) - * - * rsp0 refers to the primary stack. #MC, NMI, #DB and #DF handlers - * each get their own stacks. No IO Bitmap. - */ - tss->rsp0 = stack_bottom; - tss->ist[IST_MCE - 1] = stack_top + (1 + IST_MCE) * PAGE_SIZE; - tss->ist[IST_NMI - 1] = stack_top + (1 + IST_NMI) * PAGE_SIZE; - tss->ist[IST_DB - 1] = stack_top + (1 + IST_DB) * PAGE_SIZE; - tss->ist[IST_DF - 1] = stack_top + (1 + IST_DF) * PAGE_SIZE; - tss->bitmap = IOBMP_INVALID_OFFSET; - - /* All other stack pointers poisioned. */ - for ( i = IST_MAX; i < ARRAY_SIZE(tss->ist); ++i ) - tss->ist[i] = 0x8600111111111111ul; - tss->rsp1 = 0x8600111111111111ul; - tss->rsp2 = 0x8600111111111111ul; - - /* - * Set up the shadow stack IST. Used entries must point at the - * supervisor stack token. Unused entries are poisoned. - * - * This IST Table may be live, and the NMI/#MC entries must - * remain valid on every instruction boundary, hence the - * volatile qualifier. - */ - if (cpu_has_xen_shstk) { - volatile uint64_t *ist_ssp = tss_page->ist_ssp; - unsigned long - mce_ssp = stack_top + (IST_MCE * IST_SHSTK_SIZE) - 8, - nmi_ssp = stack_top + (IST_NMI * IST_SHSTK_SIZE) - 8, - db_ssp = stack_top + (IST_DB * IST_SHSTK_SIZE) - 8, - df_ssp = stack_top + (IST_DF * IST_SHSTK_SIZE) - 8; - - ist_ssp[0] = 0x8600111111111111ul; - ist_ssp[IST_MCE] = mce_ssp; - ist_ssp[IST_NMI] = nmi_ssp; - ist_ssp[IST_DB] = db_ssp; - ist_ssp[IST_DF] = df_ssp; - for ( i = IST_DF + 1; i < ARRAY_SIZE(tss_page->ist_ssp); ++i ) - ist_ssp[i] = 0x8600111111111111ul; - - if (IS_ENABLED(CONFIG_XEN_SHSTK) && rdssp() != SSP_NO_SHSTK) { - /* - * Rewrite supervisor tokens when shadow stacks are - * active. This resets any busy bits left across S3. - */ - wrss(mce_ssp, _p(mce_ssp)); - wrss(nmi_ssp, _p(nmi_ssp)); - wrss(db_ssp, _p(db_ssp)); - wrss(df_ssp, _p(df_ssp)); - } - - wrmsrl(MSR_ISST, (unsigned long)ist_ssp); - } - - _set_tssldt_desc(gdt + TSS_ENTRY, (unsigned long)tss, - sizeof(*tss) - 1, SYS_DESC_tss_avail); - if ( IS_ENABLED(CONFIG_PV32) ) - _set_tssldt_desc( - this_cpu(compat_gdt) - FIRST_RESERVED_GDT_ENTRY + TSS_ENTRY, - (unsigned long)tss, sizeof(*tss) - 1, SYS_DESC_tss_busy); - - per_cpu(full_gdt_loaded, cpu) = false; - lgdt(&gdtr); - lidt(&idtr); - ltr(TSS_SELECTOR); - lldt(0); - - enable_each_ist(idt); - - /* - * Bottom-of-stack must be 16-byte aligned! - * - * Defer checks until exception support is sufficiently set up. - */ - BUILD_BUG_ON((sizeof(struct cpu_info) - - sizeof(struct cpu_user_regs)) & 0xf); - BUG_ON(system_state != SYS_STATE_early_boot && (stack_bottom & 0xf)); -} - static void skinit_enable_intr(void) { uint64_t val; diff --git a/xen/arch/x86/include/asm/system.h b/xen/arch/x86/include/asm/system.h index 57446c5b46..3cdc56e4ba 100644 --- a/xen/arch/x86/include/asm/system.h +++ b/xen/arch/x86/include/asm/system.h @@ -256,7 +256,6 @@ static inline int local_irq_is_enabled(void) #define BROKEN_ACPI_Sx 0x0001 #define BROKEN_INIT_AFTER_S1 0x0002 -void load_system_tables(void); void subarch_percpu_traps_init(void); #endif diff --git a/xen/arch/x86/traps-setup.c b/xen/arch/x86/traps-setup.c index 758c67b335..d089833121 100644 --- a/xen/arch/x86/traps-setup.c +++ b/xen/arch/x86/traps-setup.c @@ -7,6 +7,7 @@ #include <asm/idt.h> #include <asm/msr.h> +#include <asm/shstk.h> #include <asm/system.h> #include <asm/traps.h> @@ -19,6 +20,118 @@ boolean_param("ler", opt_ler); void nocall entry_PF(void); +/* + * Sets up system tables and descriptors for IDT devliery. + * + * - Sets up TSS with stack pointers, including ISTs + * - Inserts TSS selector into regular and compat GDTs + * - Loads GDT, IDT, TR then null LDT + * - Sets up IST references in the IDT + */ +static void load_system_tables(void) +{ + unsigned int i, cpu = smp_processor_id(); + unsigned long stack_bottom = get_stack_bottom(), + stack_top = stack_bottom & ~(STACK_SIZE - 1); + struct tss_page *tss_page = &this_cpu(tss_page); + idt_entry_t *idt = this_cpu(idt); + + /* The TSS may be live. Disuade any clever optimisations. */ + volatile struct tss64 *tss = &tss_page->tss; + seg_desc_t *gdt = + this_cpu(gdt) - FIRST_RESERVED_GDT_ENTRY; + + const struct desc_ptr gdtr = { + .base = (unsigned long)gdt, + .limit = LAST_RESERVED_GDT_BYTE, + }; + const struct desc_ptr idtr = { + .base = (unsigned long)idt, + .limit = sizeof(bsp_idt) - 1, + }; + + /* + * Set up the TSS. Warning - may be live, and the NMI/#MC must remain + * valid on every instruction boundary. (Note: these are all + * semantically ACCESS_ONCE() due to tss's volatile qualifier.) + * + * rsp0 refers to the primary stack. #MC, NMI, #DB and #DF handlers + * each get their own stacks. No IO Bitmap. + */ + tss->rsp0 = stack_bottom; + tss->ist[IST_MCE - 1] = stack_top + (1 + IST_MCE) * PAGE_SIZE; + tss->ist[IST_NMI - 1] = stack_top + (1 + IST_NMI) * PAGE_SIZE; + tss->ist[IST_DB - 1] = stack_top + (1 + IST_DB) * PAGE_SIZE; + tss->ist[IST_DF - 1] = stack_top + (1 + IST_DF) * PAGE_SIZE; + tss->bitmap = IOBMP_INVALID_OFFSET; + + /* All other stack pointers poisioned. */ + for ( i = IST_MAX; i < ARRAY_SIZE(tss->ist); ++i ) + tss->ist[i] = 0x8600111111111111UL; + tss->rsp1 = 0x8600111111111111UL; + tss->rsp2 = 0x8600111111111111UL; + + /* + * Set up the shadow stack IST. Used entries must point at the + * supervisor stack token. Unused entries are poisoned. + * + * This IST Table may be live, and the NMI/#MC entries must + * remain valid on every instruction boundary, hence the + * volatile qualifier. + */ + if ( cpu_has_xen_shstk ) + { + volatile uint64_t *ist_ssp = tss_page->ist_ssp; + unsigned long + mce_ssp = stack_top + (IST_MCE * IST_SHSTK_SIZE) - 8, + nmi_ssp = stack_top + (IST_NMI * IST_SHSTK_SIZE) - 8, + db_ssp = stack_top + (IST_DB * IST_SHSTK_SIZE) - 8, + df_ssp = stack_top + (IST_DF * IST_SHSTK_SIZE) - 8; + + ist_ssp[0] = 0x8600111111111111UL; + ist_ssp[IST_MCE] = mce_ssp; + ist_ssp[IST_NMI] = nmi_ssp; + ist_ssp[IST_DB] = db_ssp; + ist_ssp[IST_DF] = df_ssp; + for ( i = IST_DF + 1; i < ARRAY_SIZE(tss_page->ist_ssp); ++i ) + ist_ssp[i] = 0x8600111111111111UL; + + if ( IS_ENABLED(CONFIG_XEN_SHSTK) && rdssp() != SSP_NO_SHSTK ) + { + /* + * Rewrite supervisor tokens when shadow stacks are + * active. This resets any busy bits left across S3. + */ + wrss(mce_ssp, _p(mce_ssp)); + wrss(nmi_ssp, _p(nmi_ssp)); + wrss(db_ssp, _p(db_ssp)); + wrss(df_ssp, _p(df_ssp)); + } + + wrmsrns(MSR_ISST, (unsigned long)ist_ssp); + } + + _set_tssldt_desc(gdt + TSS_ENTRY, (unsigned long)tss, + sizeof(*tss) - 1, SYS_DESC_tss_avail); + if ( IS_ENABLED(CONFIG_PV32) ) + _set_tssldt_desc( + this_cpu(compat_gdt) - FIRST_RESERVED_GDT_ENTRY + TSS_ENTRY, + (unsigned long)tss, sizeof(*tss) - 1, SYS_DESC_tss_busy); + + per_cpu(full_gdt_loaded, cpu) = false; + lgdt(&gdtr); + lidt(&idtr); + ltr(TSS_SELECTOR); + lldt(0); + + enable_each_ist(idt); + + /* + * tss->rsp0 must be 16-byte aligned. + */ + BUG_ON(stack_bottom & 15); +} + static void __init init_ler(void) { unsigned int msr = 0; @@ -139,3 +252,16 @@ void asmlinkage percpu_early_traps_init(void) { load_system_tables(); } + +static void __init __maybe_unused build_assertions(void) +{ + /* + * This is best-effort (it doesn't cover some padding corner cases), but + * is preferable to hitting the check at boot time. + * + * tss->rsp0, pointing at the end of cpu_info.guest_cpu_user_regs, must be + * 16-byte aligned. + */ + BUILD_BUG_ON((sizeof(struct cpu_info) - + endof_field(struct cpu_info, guest_cpu_user_regs)) & 15); +} diff --git a/xen/include/xen/macros.h b/xen/include/xen/macros.h index f9ccde86fb..6b4a8dc8b7 100644 --- a/xen/include/xen/macros.h +++ b/xen/include/xen/macros.h @@ -94,6 +94,8 @@ */ #define sizeof_field(type, member) sizeof(((type *)NULL)->member) +#define endof_field(type, member) (offsetof(type, member) + sizeof_field(type, member)) + /* Cast an arbitrary integer to a pointer. */ #define _p(x) ((void *)(unsigned long)(x)) -- generated by git-patchbot for /home/xen/git/xen.git#staging
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |