|
30 | 30 | #define ARCH_GET_UNTAG_MASK 0x4001 |
31 | 31 | #define ARCH_ENABLE_TAGGED_ADDR 0x4002 |
32 | 32 | #define ARCH_GET_MAX_TAG_BITS 0x4003 |
| 33 | +#define ARCH_FORCE_TAGGED_SVA 0x4004 |
33 | 34 |
|
34 | 35 | /* Specified test function bits */ |
35 | 36 | #define FUNC_MALLOC 0x1 |
|
38 | 39 | #define FUNC_SYSCALL 0x8 |
39 | 40 | #define FUNC_URING 0x10 |
40 | 41 | #define FUNC_INHERITE 0x20 |
| 42 | +#define FUNC_PASID 0x40 |
41 | 43 |
|
42 | | -#define TEST_MASK 0x3f |
| 44 | +#define TEST_MASK 0x7f |
43 | 45 |
|
44 | 46 | #define LOW_ADDR (0x1UL << 30) |
45 | 47 | #define HIGH_ADDR (0x3UL << 48) |
|
55 | 57 | #define URING_QUEUE_SZ 1 |
56 | 58 | #define URING_BLOCK_SZ 2048 |
57 | 59 |
|
| 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 | + |
58 | 67 | struct testcases { |
59 | 68 | unsigned int later; |
60 | 69 | int expected; /* 2: SIGSEGV Error; 1: other errors */ |
61 | 70 | unsigned long lam; |
62 | 71 | uint64_t addr; |
| 72 | + uint64_t cmd; |
63 | 73 | int (*test_func)(struct testcases *test); |
64 | 74 | const char *msg; |
65 | 75 | }; |
@@ -556,7 +566,7 @@ int do_uring(unsigned long lam) |
556 | 566 | struct file_io *fi; |
557 | 567 | struct stat st; |
558 | 568 | int ret = 1; |
559 | | - char path[PATH_MAX]; |
| 569 | + char path[PATH_MAX] = {0}; |
560 | 570 |
|
561 | 571 | /* get current process path */ |
562 | 572 | if (readlink("/proc/self/exe", path, PATH_MAX) <= 0) |
@@ -852,6 +862,226 @@ static void cmd_help(void) |
852 | 862 | printf("\t-h: help\n"); |
853 | 863 | } |
854 | 864 |
|
| 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 | + |
855 | 1085 | int main(int argc, char **argv) |
856 | 1086 | { |
857 | 1087 | int c = 0; |
@@ -910,6 +1140,9 @@ int main(int argc, char **argv) |
910 | 1140 | if (tests & FUNC_INHERITE) |
911 | 1141 | run_test(inheritance_cases, ARRAY_SIZE(inheritance_cases)); |
912 | 1142 |
|
| 1143 | + if (tests & FUNC_PASID) |
| 1144 | + run_test(pasid_cases, ARRAY_SIZE(pasid_cases)); |
| 1145 | + |
913 | 1146 | ksft_set_plan(tests_cnt); |
914 | 1147 |
|
915 | 1148 | return ksft_exit_pass(); |
|
0 commit comments