-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SPLITLOCK test: add split lock test for cpu
This test app will use "lock addl" instruction to trigger #AC in hardware and kernel. Signed-off-by: Tony Zhu <[email protected]>
- Loading branch information
Showing
3 changed files
with
135 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
*.o | ||
sl_test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# SPDX-License-Identifier: GPL-2.0-only | ||
# Copyright (c) 2022 Intel Corporation. | ||
|
||
BIN := sl_test | ||
|
||
all: $(BIN) | ||
|
||
sl_test: sl_test.c | ||
gcc $^ -o $@ | ||
|
||
clean: | ||
rm -rf $(BIN) *.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
// SPDX-License-Identifier: GPL-2.0-only | ||
// Copyright (c) 2022 Intel Corporation. | ||
|
||
/* | ||
* Split lock test app to check if the locked instruction will trigger #AC | ||
*/ | ||
|
||
#define _GNU_SOURCE | ||
#include <sys/types.h> | ||
#include <sys/stat.h> | ||
#include <sys/wait.h> | ||
#include <fcntl.h> | ||
#include <stdlib.h> | ||
#include <signal.h> | ||
#include <stdio.h> | ||
#include <unistd.h> | ||
#include <string.h> | ||
#include <time.h> | ||
#include <sys/time.h> | ||
#include <stdio.h> | ||
|
||
void catch_sigbus(int sig) | ||
{ | ||
printf("Caught SIGBUS/#AC due to split locked access\n"); | ||
|
||
exit(-1); | ||
} | ||
|
||
/* | ||
* Atomically add 1 to *iptr using "lock addl" instruction. | ||
* Since *iptr crosses two cache lines, #AC is generated by the split lock. | ||
*/ | ||
void do_split_locked_inst(int *iptr) | ||
{ | ||
/* | ||
* The distance between iptr and next cache line is 3 bytes. | ||
* Operand size in "addl" is 4 bytes. So iptr will span two cache | ||
* lines. "lock addl" instruction will trigger #AC in hardware | ||
* and kernel either delivers SIGBUS to this process or re-execute | ||
* the instruction depending on | ||
* /sys/kernel/debug/x86/split_lock/user_mode setting. | ||
*/ | ||
asm volatile ("lock addl $1, %0\n\t" | ||
: "=m" (*iptr)); | ||
} | ||
|
||
/* | ||
* Test SIGBUS delivered after a lock instruction generates #AC for split lock | ||
* operand *iptr. | ||
*/ | ||
void test_sigbus(int *iptr) | ||
{ | ||
pid_t pid; | ||
|
||
pid = fork(); | ||
if (pid) | ||
return; | ||
|
||
/* | ||
* The locked instruction will trigger #AC and kernel will deliver | ||
* SIGBUS to this process. The SIGBUS handler in this process will | ||
* verify that the signal is delivered and the process is killed then. | ||
*/ | ||
do_split_locked_inst(iptr); | ||
} | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
int *iptr; | ||
char *cptr; | ||
char *line = NULL; | ||
int ret = 0; | ||
size_t len; | ||
FILE *fp; | ||
|
||
fp = fopen("/proc/cpuinfo", "r"); | ||
if (!fp) | ||
return 1; | ||
|
||
while (getline(&line, &len, fp) != -1) { | ||
if (!strncmp(line, "flags", 5)) { | ||
if (strstr(line, "split_lock_detect")) | ||
ret = 1; | ||
break; | ||
} | ||
} | ||
|
||
free(line); | ||
fclose(fp); | ||
if (!ret) { | ||
printf("split_lock_dect: [FAIL]\n"); | ||
return !ret; | ||
} | ||
|
||
signal(SIGBUS, catch_sigbus); | ||
|
||
/* | ||
* Enable Alignment Checking on x86_64. | ||
* This will generate alignment check on not only split lock but also | ||
* on any misalignment. | ||
* Turn on this for reference only. | ||
*/ | ||
/* __asm__("pushf\norl $0x40000,(%rsp)\npopf"); */ | ||
|
||
/* aligned_alloc() provides 64-byte aligned memory */ | ||
cptr = (char *)aligned_alloc(64, 128); | ||
|
||
/* | ||
* Increment the pointer by 61, making it 3 bytes away from the next | ||
* cache line and 4-byte *iptr across two cache line. | ||
*/ | ||
iptr = (int *)(cptr + 61); | ||
|
||
test_sigbus(iptr); | ||
|
||
free(cptr); | ||
|
||
printf("Split Lock test - exits normally\n"); | ||
|
||
return 0; | ||
} |