git: 6d6a82416b88 - stable/15 - amd64: support for tracking per-thread 'disable splitlocks' state
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 29 Sep 2026 00:31:57 UTC
The branch stable/15 has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=6d6a82416b88183036577b824068a26919797791
commit 6d6a82416b88183036577b824068a26919797791
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-09-18 14:33:54 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-09-29 00:27:15 +0000
amd64: support for tracking per-thread 'disable splitlocks' state
(cherry picked from commit e318f24c0f53b52bd280b827509ad752db0497bf)
---
sys/amd64/amd64/exec_machdep.c | 10 ++++++++++
sys/amd64/amd64/machdep.c | 36 ++++++++++++++++++++++++++++++++++++
sys/amd64/amd64/pmap.c | 14 ++++++++++++++
sys/amd64/amd64/vm_machdep.c | 2 ++
sys/amd64/ia32/ia32_signal.c | 1 +
sys/amd64/include/md_var.h | 5 +++++
sys/amd64/include/proc.h | 2 ++
sys/amd64/linux/linux_sysvec.c | 1 +
sys/amd64/linux32/linux32_sysvec.c | 1 +
9 files changed, 72 insertions(+)
diff --git a/sys/amd64/amd64/exec_machdep.c b/sys/amd64/amd64/exec_machdep.c
index 12562968a4e3..698a81911e14 100644
--- a/sys/amd64/amd64/exec_machdep.c
+++ b/sys/amd64/amd64/exec_machdep.c
@@ -406,6 +406,15 @@ x86_clear_dbregs(struct pcb *pcb)
clear_pcb_flags(pcb, PCB_DBREGS);
}
+void
+exec_splitlock(struct thread *td)
+{
+ if (ia32_splitlock_force)
+ enable_splitlock(td);
+ else if (ia32_splitlock)
+ disable_splitlock(td);
+}
+
/*
* Reset registers to default values on exec.
*/
@@ -443,6 +452,7 @@ exec_setregs(struct thread *td, struct image_params *imgp, uintptr_t stack)
regs->tf_flags = TF_HASSEGS;
x86_clear_dbregs(pcb);
+ exec_splitlock(td);
/*
* Drop the FP state if we hold it, so that the process gets a
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 1d823650a737..0b72a1043b40 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -1929,6 +1929,42 @@ safe_read(vm_offset_t addr, char *valp)
return (uiomove_mem(UIO_MEM_KMEM, &uio));
}
+void
+enable_splitlock_ac(void)
+{
+ MPASS(ia32_splitlock);
+ wrmsr(MSR_MEMORY_CTL, rdmsr(MSR_MEMORY_CTL) |
+ MSR_MEMORY_CTL_SPLITLOCK);
+}
+
+void
+enable_splitlock(struct thread *td)
+{
+ MPASS(td == curthread);
+ td->td_md.md_td_flags |= TDF_MD_SPLITLOCK_AC;
+ critical_enter();
+ enable_splitlock_ac();
+ critical_exit();
+}
+
+void
+disable_splitlock_ac(void)
+{
+ MPASS(ia32_splitlock);
+ wrmsr(MSR_MEMORY_CTL, rdmsr(MSR_MEMORY_CTL) &
+ ~MSR_MEMORY_CTL_SPLITLOCK);
+}
+
+void
+disable_splitlock(struct thread *td)
+{
+ MPASS(td == curthread);
+ td->td_md.md_td_flags &= ~TDF_MD_SPLITLOCK_AC;
+ critical_enter();
+ disable_splitlock_ac();
+ critical_exit();
+}
+
#ifdef KDB
/*
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 63ff6269119b..b3f8c2d60468 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -10235,8 +10235,22 @@ DEFINE_IFUNC(static, void, pmap_activate_sw_mode, (struct thread *, pmap_t,
void
pmap_activate_sw(struct thread *td)
{
+ struct thread *oldtd;
pmap_t oldpmap, pmap;
u_int cpuid;
+ bool oldtd_sl, td_sl;
+
+ oldtd = curthread;
+ if (ia32_splitlock && oldtd != td) {
+ oldtd_sl = (atomic_load_int(&oldtd->td_md.md_td_flags) &
+ TDF_MD_SPLITLOCK_AC) != 0;
+ td_sl = (atomic_load_int(&td->td_md.md_td_flags) &
+ TDF_MD_SPLITLOCK_AC) != 0;
+ if (oldtd_sl && !td_sl)
+ disable_splitlock_ac();
+ else if (!oldtd_sl && td_sl)
+ enable_splitlock_ac();
+ }
oldpmap = PCPU_GET(curpmap);
pmap = vmspace_pmap(td->td_proc->p_vmspace);
diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c
index 200a63add3d8..2fd3c2443118 100644
--- a/sys/amd64/amd64/vm_machdep.c
+++ b/sys/amd64/amd64/vm_machdep.c
@@ -199,6 +199,8 @@ copy_thread(struct thread *td1, struct thread *td2)
/* Setup to release spin count in fork_exit(). */
td2->td_md.md_spinlock_count = 1;
td2->td_md.md_saved_flags = PSL_KERNEL | PSL_I;
+ td2->td_md.md_td_flags = td1->td_md.md_td_flags &
+ TDF_MD_SPLITLOCK_AC;
pmap_thread_init_invl_gen(td2);
/*
diff --git a/sys/amd64/ia32/ia32_signal.c b/sys/amd64/ia32/ia32_signal.c
index 3b26244932b4..84912b292861 100644
--- a/sys/amd64/ia32/ia32_signal.c
+++ b/sys/amd64/ia32/ia32_signal.c
@@ -981,6 +981,7 @@ ia32_setregs(struct thread *td, struct image_params *imgp, uintptr_t stack)
regs->tf_flags = TF_HASSEGS;
x86_clear_dbregs(pcb);
+ exec_splitlock(td);
fpstate_drop(td);
diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h
index ae5f0b3a5850..f73cb916d53a 100644
--- a/sys/amd64/include/md_var.h
+++ b/sys/amd64/include/md_var.h
@@ -106,6 +106,11 @@ void get_fpcontext(struct thread *td, struct __mcontext *mcp,
char **xfpusave, size_t *xfpusave_len);
int set_fpcontext(struct thread *td, struct __mcontext *mcp,
char *xfpustate, size_t xfpustate_len);
+void enable_splitlock_ac(void);
+void enable_splitlock(struct thread *td);
+void disable_splitlock_ac(void);
+void disable_splitlock(struct thread *td);
+void exec_splitlock(struct thread *td);
void wrmsr_early_safe_start(void);
void wrmsr_early_safe_end(void);
diff --git a/sys/amd64/include/proc.h b/sys/amd64/include/proc.h
index 10b79128b0f5..6c75c7c1c021 100644
--- a/sys/amd64/include/proc.h
+++ b/sys/amd64/include/proc.h
@@ -80,6 +80,8 @@ struct mdthread {
void *md_usr_fpu_save;
};
+#define TDF_MD_SPLITLOCK_AC 0x00000001 /* Disable split cache lines */
+
struct mdproc {
struct proc_ldt *md_ldt; /* (t) per-process ldt */
struct system_segment_descriptor md_ldt_sd;
diff --git a/sys/amd64/linux/linux_sysvec.c b/sys/amd64/linux/linux_sysvec.c
index 890cf01c46a0..210c3e127de3 100644
--- a/sys/amd64/linux/linux_sysvec.c
+++ b/sys/amd64/linux/linux_sysvec.c
@@ -265,6 +265,7 @@ linux_exec_setregs(struct thread *td, struct image_params *imgp,
regs->tf_flags = TF_HASSEGS;
x86_clear_dbregs(pcb);
+ exec_splitlock(td);
/*
* Drop the FP state if we hold it, so that the process gets a
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index 735ebb151017..a61039a2dc16 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -607,6 +607,7 @@ linux_exec_setregs(struct thread *td, struct image_params *imgp,
regs->tf_rbx = (register_t)imgp->ps_strings;
x86_clear_dbregs(pcb);
+ exec_splitlock(td);
fpstate_drop(td);
}