Page MenuHomeFreeBSD

amd64: implement support for disabling splitlocks
Needs ReviewPublic

Authored by kib on Fri, Sep 18, 4:53 PM.
Tags
None
Referenced Files
F172574464: D59815.id187120.diff
Sat, Sep 19, 9:17 AM
F172521960: D59815.id187120.diff
Sat, Sep 19, 12:46 AM
F172515037: D59815.id187117.diff
Fri, Sep 18, 11:39 PM
F172514827: D59815.id187120.diff
Fri, Sep 18, 11:36 PM
F172514624: D59815.diff
Fri, Sep 18, 11:34 PM
F172513099: D59815.id187117.diff
Fri, Sep 18, 11:20 PM
F172511417: D59815.diff
Fri, Sep 18, 11:05 PM
Unknown Object (File)
Fri, Sep 18, 7:48 PM
Subscribers

Details

Reviewers
markj
jhb
Summary

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.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

kib requested review of this revision.Fri, Sep 18, 4:53 PM

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);
}

Fix reversed handling of the msr bit on context switch.

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.