If hw supports it, on atomic operation that requires exclusive ownership of more than one cache line, #AC is generated.
Thread can control it with sysarch(I386_SET_SPLITLOCK). The global default is set with hw.splitlock_force.
Details
Details
Diff Detail
Diff Detail
- Repository
- rG FreeBSD src repository
- Lint
Lint Skipped - Unit
Tests Skipped
Event Timeline
Comment Actions
Test program I used with simics:
/* $Id: splitlock.c,v 1.5 2026/09/18 16:39:53 kostik Exp kostik $ */
#include <sys/param.h>
#include <sys/mman.h>
#include <machine/atomic.h>
#include <machine/sysarch.h>
#include <err.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifndef I386_SET_SPLITLOCK
#define I386_SET_SPLITLOCK 14
#define I386_GET_SPLITLOCK 15
#endif
static void
sigbus_handler(int signo, siginfo_t *si, void *mc)
{
printf("sig%d si_code %d addr %p\n", signo, si->si_code, si->si_addr);
exit(0);
}
int
main(void)
{
char *m;
struct sigaction sa;
int error, val;
val = 1;
error = sysarch(I386_SET_SPLITLOCK, &val);
if (error == -1)
err(1, "I386_SET_SPLITLOCK");
error = sysarch(I386_GET_SPLITLOCK, &val);
if (error == -1)
err(1, "I386_GET_SPLITLOCK");
printf("setlock: %d\n", val);
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = sigbus_handler;
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGBUS, &sa, NULL) == -1)
err(1, "sigaction");
m = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (m == MAP_FAILED)
err(1, "mmap");
m += 256 - 1;
atomic_fetchadd_long((unsigned long *)m, 1);
}Comment Actions
Fix splitlock control on exec for non-native ABIs.
Cache MSR_MEMORY_CTL, avoiding msr read on the context switch.
Use non-seializing immediate form for WRMSR when available.