Skip to content

Commit 3482147

Browse files
weihongzhansendc
authored andcommitted
selftests/x86/lam: Add ARCH_FORCE_TAGGED_SVA test cases for linear-address masking
By default do not allow to enable both LAM and use SVA in the same process. The new ARCH_FORCE_TAGGED_SVA arch_prctl() overrides the limitation. Add new test cases for the new arch_prctl: Before using ARCH_FORCE_TAGGED_SVA, should not allow to enable LAM/SVA coexisting. the test cases should be negative. The test depands on idxd driver and iommu. before test, need add "intel_iommu=on,sm_on" in kernel command line and insmod idxd driver. Signed-off-by: Weihong Zhang <weihong.zhang@intel.com> Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/all/20230312112612.31869-17-kirill.shutemov%40linux.intel.com
1 parent 833c12c commit 3482147

1 file changed

Lines changed: 235 additions & 2 deletions

File tree

  • tools/testing/selftests/x86

tools/testing/selftests/x86/lam.c

Lines changed: 235 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#define ARCH_GET_UNTAG_MASK 0x4001
3131
#define ARCH_ENABLE_TAGGED_ADDR 0x4002
3232
#define ARCH_GET_MAX_TAG_BITS 0x4003
33+
#define ARCH_FORCE_TAGGED_SVA 0x4004
3334

3435
/* Specified test function bits */
3536
#define FUNC_MALLOC 0x1
@@ -38,8 +39,9 @@
3839
#define FUNC_SYSCALL 0x8
3940
#define FUNC_URING 0x10
4041
#define FUNC_INHERITE 0x20
42+
#define FUNC_PASID 0x40
4143

42-
#define TEST_MASK 0x3f
44+
#define TEST_MASK 0x7f
4345

4446
#define LOW_ADDR (0x1UL << 30)
4547
#define HIGH_ADDR (0x3UL << 48)
@@ -55,11 +57,19 @@
5557
#define URING_QUEUE_SZ 1
5658
#define URING_BLOCK_SZ 2048
5759

60+
/* Pasid test define */
61+
#define LAM_CMD_BIT 0x1
62+
#define PAS_CMD_BIT 0x2
63+
#define SVA_CMD_BIT 0x4
64+
65+
#define PAS_CMD(cmd1, cmd2, cmd3) (((cmd3) << 8) | ((cmd2) << 4) | ((cmd1) << 0))
66+
5867
struct testcases {
5968
unsigned int later;
6069
int expected; /* 2: SIGSEGV Error; 1: other errors */
6170
unsigned long lam;
6271
uint64_t addr;
72+
uint64_t cmd;
6373
int (*test_func)(struct testcases *test);
6474
const char *msg;
6575
};
@@ -556,7 +566,7 @@ int do_uring(unsigned long lam)
556566
struct file_io *fi;
557567
struct stat st;
558568
int ret = 1;
559-
char path[PATH_MAX];
569+
char path[PATH_MAX] = {0};
560570

561571
/* get current process path */
562572
if (readlink("/proc/self/exe", path, PATH_MAX) <= 0)
@@ -852,6 +862,226 @@ static void cmd_help(void)
852862
printf("\t-h: help\n");
853863
}
854864

865+
/* Check for file existence */
866+
uint8_t file_Exists(const char *fileName)
867+
{
868+
struct stat buffer;
869+
870+
uint8_t ret = (stat(fileName, &buffer) == 0);
871+
872+
return ret;
873+
}
874+
875+
/* Sysfs idxd files */
876+
const char *dsa_configs[] = {
877+
"echo 1 > /sys/bus/dsa/devices/dsa0/wq0.1/group_id",
878+
"echo shared > /sys/bus/dsa/devices/dsa0/wq0.1/mode",
879+
"echo 10 > /sys/bus/dsa/devices/dsa0/wq0.1/priority",
880+
"echo 16 > /sys/bus/dsa/devices/dsa0/wq0.1/size",
881+
"echo 15 > /sys/bus/dsa/devices/dsa0/wq0.1/threshold",
882+
"echo user > /sys/bus/dsa/devices/dsa0/wq0.1/type",
883+
"echo MyApp1 > /sys/bus/dsa/devices/dsa0/wq0.1/name",
884+
"echo 1 > /sys/bus/dsa/devices/dsa0/engine0.1/group_id",
885+
"echo dsa0 > /sys/bus/dsa/drivers/idxd/bind",
886+
/* bind files and devices, generated a device file in /dev */
887+
"echo wq0.1 > /sys/bus/dsa/drivers/user/bind",
888+
};
889+
890+
/* DSA device file */
891+
const char *dsaDeviceFile = "/dev/dsa/wq0.1";
892+
/* file for io*/
893+
const char *dsaPasidEnable = "/sys/bus/dsa/devices/dsa0/pasid_enabled";
894+
895+
/*
896+
* DSA depends on kernel cmdline "intel_iommu=on,sm_on"
897+
* return pasid_enabled (0: disable 1:enable)
898+
*/
899+
int Check_DSA_Kernel_Setting(void)
900+
{
901+
char command[256] = "";
902+
char buf[256] = "";
903+
char *ptr;
904+
int rv = -1;
905+
906+
snprintf(command, sizeof(command) - 1, "cat %s", dsaPasidEnable);
907+
908+
FILE *cmd = popen(command, "r");
909+
910+
if (cmd) {
911+
while (fgets(buf, sizeof(buf) - 1, cmd) != NULL);
912+
913+
pclose(cmd);
914+
rv = strtol(buf, &ptr, 16);
915+
}
916+
917+
return rv;
918+
}
919+
920+
/*
921+
* Config DSA's sysfs files as shared DSA's WQ.
922+
* Generated a device file /dev/dsa/wq0.1
923+
* Return: 0 OK; 1 Failed; 3 Skip(SVA disabled).
924+
*/
925+
int Dsa_Init_Sysfs(void)
926+
{
927+
uint len = ARRAY_SIZE(dsa_configs);
928+
const char **p = dsa_configs;
929+
930+
if (file_Exists(dsaDeviceFile) == 1)
931+
return 0;
932+
933+
/* check the idxd driver */
934+
if (file_Exists(dsaPasidEnable) != 1) {
935+
printf("Please make sure idxd driver was loaded\n");
936+
return 3;
937+
}
938+
939+
/* Check SVA feature */
940+
if (Check_DSA_Kernel_Setting() != 1) {
941+
printf("Please enable SVA.(Add intel_iommu=on,sm_on in kernel cmdline)\n");
942+
return 3;
943+
}
944+
945+
/* Check the idxd device file on /dev/dsa/ */
946+
for (int i = 0; i < len; i++) {
947+
if (system(p[i]))
948+
return 1;
949+
}
950+
951+
/* After config, /dev/dsa/wq0.1 should be generated */
952+
return (file_Exists(dsaDeviceFile) != 1);
953+
}
954+
955+
/*
956+
* Open DSA device file, triger API: iommu_sva_alloc_pasid
957+
*/
958+
void *allocate_dsa_pasid(void)
959+
{
960+
int fd;
961+
void *wq;
962+
963+
fd = open(dsaDeviceFile, O_RDWR);
964+
if (fd < 0) {
965+
perror("open");
966+
return MAP_FAILED;
967+
}
968+
969+
wq = mmap(NULL, 0x1000, PROT_WRITE,
970+
MAP_SHARED | MAP_POPULATE, fd, 0);
971+
if (wq == MAP_FAILED)
972+
perror("mmap");
973+
974+
return wq;
975+
}
976+
977+
int set_force_svm(void)
978+
{
979+
int ret = 0;
980+
981+
ret = syscall(SYS_arch_prctl, ARCH_FORCE_TAGGED_SVA);
982+
983+
return ret;
984+
}
985+
986+
int handle_pasid(struct testcases *test)
987+
{
988+
uint tmp = test->cmd;
989+
uint runed = 0x0;
990+
int ret = 0;
991+
void *wq = NULL;
992+
993+
ret = Dsa_Init_Sysfs();
994+
if (ret != 0)
995+
return ret;
996+
997+
for (int i = 0; i < 3; i++) {
998+
int err = 0;
999+
1000+
if (tmp & 0x1) {
1001+
/* run set lam mode*/
1002+
if ((runed & 0x1) == 0) {
1003+
err = set_lam(LAM_U57_BITS);
1004+
runed = runed | 0x1;
1005+
} else
1006+
err = 1;
1007+
} else if (tmp & 0x4) {
1008+
/* run force svm */
1009+
if ((runed & 0x4) == 0) {
1010+
err = set_force_svm();
1011+
runed = runed | 0x4;
1012+
} else
1013+
err = 1;
1014+
} else if (tmp & 0x2) {
1015+
/* run allocate pasid */
1016+
if ((runed & 0x2) == 0) {
1017+
runed = runed | 0x2;
1018+
wq = allocate_dsa_pasid();
1019+
if (wq == MAP_FAILED)
1020+
err = 1;
1021+
} else
1022+
err = 1;
1023+
}
1024+
1025+
ret = ret + err;
1026+
if (ret > 0)
1027+
break;
1028+
1029+
tmp = tmp >> 4;
1030+
}
1031+
1032+
if (wq != MAP_FAILED && wq != NULL)
1033+
if (munmap(wq, 0x1000))
1034+
printf("munmap failed %d\n", errno);
1035+
1036+
if (runed != 0x7)
1037+
ret = 1;
1038+
1039+
return (ret != 0);
1040+
}
1041+
1042+
/*
1043+
* Pasid test depends on idxd and SVA, kernel should enable iommu and sm.
1044+
* command line(intel_iommu=on,sm_on)
1045+
*/
1046+
static struct testcases pasid_cases[] = {
1047+
{
1048+
.expected = 1,
1049+
.cmd = PAS_CMD(LAM_CMD_BIT, PAS_CMD_BIT, SVA_CMD_BIT),
1050+
.test_func = handle_pasid,
1051+
.msg = "PASID: [Negative] Execute LAM, PASID, SVA in sequence\n",
1052+
},
1053+
{
1054+
.expected = 0,
1055+
.cmd = PAS_CMD(LAM_CMD_BIT, SVA_CMD_BIT, PAS_CMD_BIT),
1056+
.test_func = handle_pasid,
1057+
.msg = "PASID: Execute LAM, SVA, PASID in sequence\n",
1058+
},
1059+
{
1060+
.expected = 1,
1061+
.cmd = PAS_CMD(PAS_CMD_BIT, LAM_CMD_BIT, SVA_CMD_BIT),
1062+
.test_func = handle_pasid,
1063+
.msg = "PASID: [Negative] Execute PASID, LAM, SVA in sequence\n",
1064+
},
1065+
{
1066+
.expected = 0,
1067+
.cmd = PAS_CMD(PAS_CMD_BIT, SVA_CMD_BIT, LAM_CMD_BIT),
1068+
.test_func = handle_pasid,
1069+
.msg = "PASID: Execute PASID, SVA, LAM in sequence\n",
1070+
},
1071+
{
1072+
.expected = 0,
1073+
.cmd = PAS_CMD(SVA_CMD_BIT, LAM_CMD_BIT, PAS_CMD_BIT),
1074+
.test_func = handle_pasid,
1075+
.msg = "PASID: Execute SVA, LAM, PASID in sequence\n",
1076+
},
1077+
{
1078+
.expected = 0,
1079+
.cmd = PAS_CMD(SVA_CMD_BIT, PAS_CMD_BIT, LAM_CMD_BIT),
1080+
.test_func = handle_pasid,
1081+
.msg = "PASID: Execute SVA, PASID, LAM in sequence\n",
1082+
},
1083+
};
1084+
8551085
int main(int argc, char **argv)
8561086
{
8571087
int c = 0;
@@ -910,6 +1140,9 @@ int main(int argc, char **argv)
9101140
if (tests & FUNC_INHERITE)
9111141
run_test(inheritance_cases, ARRAY_SIZE(inheritance_cases));
9121142

1143+
if (tests & FUNC_PASID)
1144+
run_test(pasid_cases, ARRAY_SIZE(pasid_cases));
1145+
9131146
ksft_set_plan(tests_cnt);
9141147

9151148
return ksft_exit_pass();

0 commit comments

Comments
 (0)