From 5eb256fe165c6037cc5a8564ef05b24836d97ffb Mon Sep 17 00:00:00 2001 From: Luiz Souza Date: Fri, 23 Feb 2018 19:43:41 -0300 Subject: Revert "Revert "MFC r321899"" This reverts commit 364d23417fdf8cd90b896af94c6857c6ba13be8c. --- sys/amd64/amd64/elf_machdep.c | 19 +++++++++++++++++++ sys/amd64/amd64/initcpu.c | 27 +++++++++++++++++++++++++++ sys/amd64/include/md_var.h | 5 ++++- sys/amd64/linux/linux_sysvec.c | 2 ++ 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/sys/amd64/amd64/elf_machdep.c b/sys/amd64/amd64/elf_machdep.c index ca07adc..4e9476a 100644 --- a/sys/amd64/amd64/elf_machdep.c +++ b/sys/amd64/amd64/elf_machdep.c @@ -84,6 +84,25 @@ struct sysentvec elf64_freebsd_sysvec = { }; INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec); +void +amd64_lower_shared_page(struct sysentvec *sv) +{ + if (hw_lower_amd64_sharedpage != 0) { + sv->sv_maxuser -= PAGE_SIZE; + sv->sv_shared_page_base -= PAGE_SIZE; + sv->sv_usrstack -= PAGE_SIZE; + sv->sv_psstrings -= PAGE_SIZE; + } +} + +/* + * Do this fixup before INIT_SYSENTVEC (SI_ORDER_ANY) because the latter + * uses the value of sv_shared_page_base. + */ +SYSINIT(elf64_sysvec_fixup, SI_SUB_EXEC, SI_ORDER_FIRST, + (sysinit_cfunc_t) amd64_lower_shared_page, + &elf64_freebsd_sysvec); + static Elf64_Brandinfo freebsd_brand_info = { .brand = ELFOSABI_FREEBSD, .machine = EM_X86_64, diff --git a/sys/amd64/amd64/initcpu.c b/sys/amd64/amd64/initcpu.c index 63c0f20..ff3b6be 100644 --- a/sys/amd64/amd64/initcpu.c +++ b/sys/amd64/amd64/initcpu.c @@ -48,6 +48,11 @@ __FBSDID("$FreeBSD$"); static int hw_instruction_sse; SYSCTL_INT(_hw, OID_AUTO, instruction_sse, CTLFLAG_RD, &hw_instruction_sse, 0, "SIMD/MMX2 instructions available in CPU"); +static int lower_sharedpage_init; +int hw_lower_amd64_sharedpage; +SYSCTL_INT(_hw, OID_AUTO, lower_amd64_sharedpage, CTLFLAG_RDTUN, + &hw_lower_amd64_sharedpage, 0, + "Lower sharedpage to work around Ryzen issue with executing code near the top of user memory"); /* * -1: automatic (default) * 0: keep enable CLFLUSH @@ -122,6 +127,28 @@ init_amd(void) wrmsr(0xc0011020, msr); } } + + /* + * Work around a problem on Ryzen that is triggered by executing + * code near the top of user memory, in our case the signal + * trampoline code in the shared page on amd64. + * + * This function is executed once for the BSP before tunables take + * effect so the value determined here can be overridden by the + * tunable. This function is then executed again for each AP and + * also on resume. Set a flag the first time so that value set by + * the tunable is not overwritten. + * + * The stepping and/or microcode versions should be checked after + * this issue is fixed by AMD so that we don't use this mode if not + * needed. + */ + if (lower_sharedpage_init == 0) { + lower_sharedpage_init = 1; + if (CPUID_TO_FAMILY(cpu_id) == 0x17) { + hw_lower_amd64_sharedpage = 1; + } + } } /* diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h index 706ffc6..7a84631 100644 --- a/sys/amd64/include/md_var.h +++ b/sys/amd64/include/md_var.h @@ -34,12 +34,15 @@ #include -extern uint64_t *vm_page_dump; +extern uint64_t *vm_page_dump; +extern int hw_lower_amd64_sharedpage; struct savefpu; +struct sysentvec; void amd64_conf_fast_syscall(void); void amd64_db_resume_dbreg(void); +void amd64_lower_shared_page(struct sysentvec *); void amd64_syscall(struct thread *td, int traced); void doreti_iret(void) __asm(__STRING(doreti_iret)); void doreti_iret_fault(void) __asm(__STRING(doreti_iret_fault)); diff --git a/sys/amd64/linux/linux_sysvec.c b/sys/amd64/linux/linux_sysvec.c index f77c2c9..942819b 100644 --- a/sys/amd64/linux/linux_sysvec.c +++ b/sys/amd64/linux/linux_sysvec.c @@ -833,6 +833,8 @@ static void linux_vdso_install(void *param) { + amd64_lower_shared_page(&elf_linux_sysvec); + linux_szsigcode = (&_binary_linux_locore_o_end - &_binary_linux_locore_o_start); -- cgit v1.1