mirror of
https://github.com/opnsense/src.git
synced 2026-02-20 00:11:07 -05:00
amd64: Set GS.base before calling init_secondary() on APs
KMSAN instrumentation requires thread-local storage to track initialization state for function parameters and return values. This buffer is accessed as part of each function prologue. It is provided by the KMSAN runtime, which looks up a pointer in the current thread's structure. When KMSAN is configured, init_secondary() is instrumented, but this means that GS.base must be initialized first, otherwise the runtime cannot safely access curthread. Work around this by loading GS.base before calling init_secondary(), so that the runtime can at least check curthread == NULL and return a pointer to some dummy storage. Note that init_secondary() still must reload GS.base after calling lgdt(), which loads a selector into %gs, which in turn clears the base register. Reviewed by: kib MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D31336
This commit is contained in:
parent
e153745083
commit
4b136ef259
2 changed files with 21 additions and 4 deletions
|
|
@ -103,6 +103,7 @@ static char *doublefault_stack;
|
|||
static char *mce_stack;
|
||||
static char *nmi_stack;
|
||||
static char *dbg_stack;
|
||||
void *bootpcpu;
|
||||
|
||||
extern u_int mptramp_la57;
|
||||
extern u_int mptramp_nx;
|
||||
|
|
@ -197,10 +198,8 @@ init_secondary(void)
|
|||
/* Update microcode before doing anything else. */
|
||||
ucode_load_ap(cpu);
|
||||
|
||||
/* Get per-cpu data and save */
|
||||
pc = &__pcpu[cpu];
|
||||
|
||||
/* prime data page for it to use */
|
||||
/* Initialize the PCPU area. */
|
||||
pc = bootpcpu;
|
||||
pcpu_init(pc, cpu, sizeof(struct pcpu));
|
||||
dpcpu_init(dpcpu, cpu);
|
||||
pc->pc_apic_id = cpu_apic_ids[cpu];
|
||||
|
|
@ -431,6 +430,7 @@ start_all_aps(void)
|
|||
dpcpu = (void *)kmem_malloc_domainset(DOMAINSET_PREF(domain),
|
||||
DPCPU_SIZE, M_WAITOK | M_ZERO);
|
||||
|
||||
bootpcpu = &__pcpu[cpu];
|
||||
bootSTK = (char *)bootstacks[cpu] +
|
||||
kstack_pages * PAGE_SIZE - 8;
|
||||
bootAP = cpu;
|
||||
|
|
|
|||
|
|
@ -260,4 +260,21 @@ bootMP_size:
|
|||
.p2align 4,0
|
||||
entry_64:
|
||||
movq bootSTK, %rsp
|
||||
|
||||
/*
|
||||
* Initialize the segment register used for the PCPU area. The PCPU
|
||||
* area will be initialized by init_secondary(), but it should be
|
||||
* accessible before that to support sanitizer instrumentation which
|
||||
* accesses per-CPU variables.
|
||||
*
|
||||
* Note that GS.base is loaded again in init_secondary(). This is not
|
||||
* redundant: lgdt() loads a selector into %gs and this has the side
|
||||
* effect of clearing GS.base.
|
||||
*/
|
||||
movl $MSR_GSBASE, %ecx
|
||||
movq bootpcpu, %rax
|
||||
movq %rax, %rdx
|
||||
shrq $32, %rdx
|
||||
wrmsr
|
||||
|
||||
jmp init_secondary
|
||||
|
|
|
|||
Loading…
Reference in a new issue