[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 14/22] x86/traps: Extend struct cpu_user_regs/cpu_info with FRED fields
The FRED on-stack format is larger than the IDT format, but is by and large compatible. FRED reuses space above cs and ss for extra metadata, some of which is purely informational, and some of which causes additional effects in ERET{U,S}. Follow Linux's choice of naming for fred_{c,s}s structures, to make it very clear at the point of use that it's dependent on FRED. There is also the event data field and reserved fields, but we cannot include these in struct cpu_user_regs without reintroducing OoB structure accesses in the non-FRED case. See commit 6065a05adf15 ("x86/traps: 'Fix' safety of read_registers() in #DF path"). for more details. Instead, use a new struct fred_info and position it suitably in struct cpu_info. This boundary will be loaded into MSR_FRED_RSP_SL0, and must be 64-byte aligned. This does add 16 bytes back into struct cpu_info, undoing the saving we made by dropping the vm86 data segment selectors. No functional change. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- CC: Jan Beulich <JBeulich@xxxxxxxx> CC: Roger Pau Monné <roger.pau@xxxxxxxxxx> --- xen/arch/x86/include/asm/cpu-user-regs.h | 71 ++++++++++++++++++++++-- xen/arch/x86/include/asm/current.h | 2 + xen/arch/x86/traps-setup.c | 5 ++ 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/xen/arch/x86/include/asm/cpu-user-regs.h b/xen/arch/x86/include/asm/cpu-user-regs.h index d700a3ef3447..06d9cbfbe6ba 100644 --- a/xen/arch/x86/include/asm/cpu-user-regs.h +++ b/xen/arch/x86/include/asm/cpu-user-regs.h @@ -30,6 +30,10 @@ struct cpu_user_regs /* * During IDT delivery for exceptions with an error code, hardware pushes * to this point. Entry_vector is filled in by software. + * + * During FRED delivery, hardware always pushes to this point. Software + * copies fred_ss.vector into entry_vector so most interrupt/exception + * handling can be FRED-agnostic. */ uint32_t error_code; @@ -42,17 +46,76 @@ struct cpu_user_regs */ union { uint64_t rip; uint32_t eip; uint16_t ip; }; - uint16_t cs, _pad0[1]; - uint8_t saved_upcall_mask; /* PV (v)rflags.IF == !saved_upcall_mask */ - uint8_t _pad1[3]; + union { + struct { + uint16_t cs; + unsigned long :16; + uint8_t saved_upcall_mask; /* PV (v)rflags.IF == !saved_upcall_mask */ + }; + unsigned long csx; + struct { + /* + * Bits 0 thru 31 control ERET{U,S} behaviour, and is state of the + * interrupted context. + */ + uint16_t cs; + unsigned int sl:2; /* Stack Level */ + bool wfe:1; /* Wait-for-ENDBRANCH state */ + } fred_cs; + }; union { uint64_t rflags; uint32_t eflags; uint16_t flags; }; union { uint64_t rsp; uint32_t esp; uint16_t sp; uint8_t spl; }; - uint16_t ss, _pad2[3]; + union { + uint16_t ss; + unsigned long ssx; + struct { + /* + * Bits 0 thru 31 control ERET{U,S} behaviour, and is state about + * the event which occured. + */ + uint16_t ss; + bool sti:1; /* Was blocked-by-STI, and not cancelled */ + bool swint:1; /* Was a SYSCALL/SYSENTER/INT $N */ + bool nmi:1; /* Was an NMI. */ + unsigned long :13; + + /* + * Bits 32 thru 63 are ignored by ERET{U,S} and are informative + * only. + */ + uint8_t vector; + unsigned long :8; + unsigned int type:4; /* X86_ET_* */ + unsigned long :4; + bool enclave:1; /* Event taken in SGX mode */ + bool lm:1; /* Was in Long Mode */ + bool nested:1; /* Exception during event delivery, clear for #DF */ + unsigned long :1; + unsigned int insnlen:4; /* .type >= SW_INT */ + } fred_ss; + }; /* * For IDT delivery, tss->rsp0 points to this boundary as embedded within * struct cpu_info. It must be 16-byte aligned. */ }; +struct fred_info +{ + /* + * Event Data. For: + * #DB: PENDING_DBG (%dr6 with positive polarity) + * NMI: NMI-Source Bitmap (on capable hardware) + * #PF: %cr2 + * #NM: MSR_XFD_ERR (only XFD-induced #NMs) + */ + uint64_t edata; + uint64_t _rsvd; + + /* + * For FRED delivery, MSR_FRED_RSP_SL0 points to this boundary as embedded + * within struct cpu_info. It must be 64-byte aligned. + */ +}; #endif /* X86_CPU_USER_REGS_H */ diff --git a/xen/arch/x86/include/asm/current.h b/xen/arch/x86/include/asm/current.h index a7c9473428b2..962eb76a82b3 100644 --- a/xen/arch/x86/include/asm/current.h +++ b/xen/arch/x86/include/asm/current.h @@ -38,6 +38,8 @@ struct vcpu; struct cpu_info { struct cpu_user_regs guest_cpu_user_regs; + struct fred_info _fred; /* Only used when FRED is active. */ + unsigned int processor_id; unsigned int verw_sel; struct vcpu *current_vcpu; diff --git a/xen/arch/x86/traps-setup.c b/xen/arch/x86/traps-setup.c index fbae7072c292..37202c17fcea 100644 --- a/xen/arch/x86/traps-setup.c +++ b/xen/arch/x86/traps-setup.c @@ -360,7 +360,12 @@ static void __init __maybe_unused build_assertions(void) * * tss->rsp0, pointing at the end of cpu_info.guest_cpu_user_regs, must be * 16-byte aligned. + * + * MSR_FRED_RSP_SL0, pointing to the end of cpu_info._fred must be 64-byte + * aligned. */ BUILD_BUG_ON((sizeof(struct cpu_info) - endof_field(struct cpu_info, guest_cpu_user_regs)) & 15); + BUILD_BUG_ON((sizeof(struct cpu_info) - + endof_field(struct cpu_info, _fred)) & 63); } -- 2.39.5
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |