Date: Thu, 12 Aug 2021 13:49:51 GMT From: Mark Johnston <markj@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: b8adacf39a5a - stable/13 - amd64: Set GS.base before calling init_secondary() on APs Message-ID: <202108121349.17CDnp0n052495@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=b8adacf39a5a968dabb36390bc51388553fb6ca9 commit b8adacf39a5a968dabb36390bc51388553fb6ca9 Author: Mark Johnston <markj@FreeBSD.org> AuthorDate: 2021-07-29 14:22:37 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2021-08-12 13:43:21 +0000 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 Sponsored by: The FreeBSD Foundation (cherry picked from commit 4b136ef259cefedc9b6404afc09138aeb8acbd91) --- sys/amd64/amd64/mp_machdep.c | 8 ++++---- sys/amd64/amd64/mpboot.S | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index 74f1af919b66..41c082ff40e9 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -103,6 +103,7 @@ char *doublefault_stack; char *mce_stack; char *nmi_stack; char *dbg_stack; +void *bootpcpu; extern u_int mptramp_la57; @@ -273,10 +274,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]; @@ -495,6 +494,7 @@ native_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; diff --git a/sys/amd64/amd64/mpboot.S b/sys/amd64/amd64/mpboot.S index e525102b5d3d..afdcffa573a4 100644 --- a/sys/amd64/amd64/mpboot.S +++ b/sys/amd64/amd64/mpboot.S @@ -270,4 +270,21 @@ entry_64: 2: movq KPML5phys, %rax 3: movq %rax, %cr3 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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202108121349.17CDnp0n052495>