git: d8c1abb0e340 - main - amd64: calculate if hardware supports disabling splitlocks

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Tue, 22 Sep 2026 15:41:49 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=d8c1abb0e3409314fb89400bc85b5051649e91ab

commit d8c1abb0e3409314fb89400bc85b5051649e91ab
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-09-18 14:33:54 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-09-22 15:40:40 +0000

    amd64: calculate if hardware supports disabling splitlocks
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D59815
---
 sys/amd64/amd64/initcpu.c  | 18 ++++++++++++++++++
 sys/amd64/amd64/machdep.c  | 11 +++++++++++
 sys/amd64/include/md_var.h |  3 +++
 3 files changed, 32 insertions(+)

diff --git a/sys/amd64/amd64/initcpu.c b/sys/amd64/amd64/initcpu.c
index 5b615be4b8dc..4ae79693addf 100644
--- a/sys/amd64/amd64/initcpu.c
+++ b/sys/amd64/amd64/initcpu.c
@@ -440,3 +440,21 @@ amd64_cpu_init_fred(void)
 		printf("FRED enabled\n");
 
 }
+
+void
+amd64_init_splitlock(void)
+{
+	uint64_t msr;
+
+	if ((cpu_stdext_feature3 & CPUID_STDEXT3_CORE_CAP) != 0) {
+		if (rdmsr_safe(MSR_IA32_CORE_CAP, &msr) == 0)
+			ia32_splitlock = (msr & IA32_CORE_CAP_SPLITLOCK) != 0;
+	}
+	if (ia32_splitlock) {
+		TUNABLE_INT_FETCH("hw.splitlock_force", &ia32_splitlock_force);
+		if (ia32_splitlock_force != 0)
+			ia32_splitlock_force = 1;
+	} else {
+		ia32_splitlock_force = 0;
+	}
+}
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index c6a77c5ef852..c34dd7818b8c 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -206,6 +206,15 @@ long realmem = 0;
 int late_console = 1;
 int lass_enabled = 0;
 
+int ia32_splitlock = 0;
+SYSCTL_INT(_hw, OID_AUTO, splitlock, CTLFLAG_RD,
+    &ia32_splitlock, 0,
+    "splitlock prevention supported");
+int ia32_splitlock_force = 1;
+SYSCTL_INT(_hw, OID_AUTO, splitlock_force, CTLFLAG_RDTUN | CTLFLAG_NOFETCH,
+    &ia32_splitlock_force, 0,
+    "splitlock prevention enabled by default");
+
 int __read_frequently fred = 0;
 SYSCTL_INT(_hw, OID_AUTO, fred, CTLFLAG_RDTUN | CTLFLAG_NOFETCH,
     &fred, 0,
@@ -1648,6 +1657,8 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
 	/* setup proc 0's pcb */
 	thread0.td_pcb->pcb_flags = 0;
 
+	amd64_init_splitlock();
+
         env = kern_getenv("kernelname");
 	if (env != NULL)
 		strlcpy(kernelname, env, sizeof(kernelname));
diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h
index d51cfae510e7..a46ae8dfe794 100644
--- a/sys/amd64/include/md_var.h
+++ b/sys/amd64/include/md_var.h
@@ -46,6 +46,8 @@ extern int	hw_ssb_disable;
 extern int	nmi_flush_l1d_sw;
 extern int	syscall_ret_l1d_flush_mode;
 extern int	lass_enabled;
+extern int	ia32_splitlock;
+extern int	ia32_splitlock_force;
 
 extern vm_paddr_t intel_graphics_stolen_base;
 extern vm_paddr_t intel_graphics_stolen_size;
@@ -67,6 +69,7 @@ struct trapframe;
 void	amd64_conf_fast_syscall(void);
 void	amd64_cpu_init_fred(void);
 void	amd64_db_resume_dbreg(void);
+void	amd64_init_splitlock(void);
 vm_paddr_t amd64_loadaddr(void);
 void	amd64_lower_shared_page(struct sysentvec *);
 void	amd64_bsp_pcpu_init1(struct pcpu *pc);