forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/tools/testing/selftests/x86/iopl.c
....@@ -35,6 +35,16 @@
3535
3636 }
3737
38
+static void clearhandler(int sig)
39
+{
40
+ struct sigaction sa;
41
+ memset(&sa, 0, sizeof(sa));
42
+ sa.sa_handler = SIG_DFL;
43
+ sigemptyset(&sa.sa_mask);
44
+ if (sigaction(sig, &sa, 0))
45
+ err(1, "sigaction");
46
+}
47
+
3848 static jmp_buf jmpbuf;
3949
4050 static void sigsegv(int sig, siginfo_t *si, void *ctx_void)
....@@ -42,24 +52,166 @@
4252 siglongjmp(jmpbuf, 1);
4353 }
4454
55
+static bool try_outb(unsigned short port)
56
+{
57
+ sethandler(SIGSEGV, sigsegv, SA_RESETHAND);
58
+ if (sigsetjmp(jmpbuf, 1) != 0) {
59
+ return false;
60
+ } else {
61
+ asm volatile ("outb %%al, %w[port]"
62
+ : : [port] "Nd" (port), "a" (0));
63
+ return true;
64
+ }
65
+ clearhandler(SIGSEGV);
66
+}
67
+
68
+static void expect_ok_outb(unsigned short port)
69
+{
70
+ if (!try_outb(port)) {
71
+ printf("[FAIL]\toutb to 0x%02hx failed\n", port);
72
+ exit(1);
73
+ }
74
+
75
+ printf("[OK]\toutb to 0x%02hx worked\n", port);
76
+}
77
+
78
+static void expect_gp_outb(unsigned short port)
79
+{
80
+ if (try_outb(port)) {
81
+ printf("[FAIL]\toutb to 0x%02hx worked\n", port);
82
+ nerrs++;
83
+ }
84
+
85
+ printf("[OK]\toutb to 0x%02hx failed\n", port);
86
+}
87
+
88
+#define RET_FAULTED 0
89
+#define RET_FAIL 1
90
+#define RET_EMUL 2
91
+
92
+static int try_cli(void)
93
+{
94
+ unsigned long flags;
95
+
96
+ sethandler(SIGSEGV, sigsegv, SA_RESETHAND);
97
+ if (sigsetjmp(jmpbuf, 1) != 0) {
98
+ return RET_FAULTED;
99
+ } else {
100
+ asm volatile("cli; pushf; pop %[flags]"
101
+ : [flags] "=rm" (flags));
102
+
103
+ /* X86_FLAGS_IF */
104
+ if (!(flags & (1 << 9)))
105
+ return RET_FAIL;
106
+ else
107
+ return RET_EMUL;
108
+ }
109
+ clearhandler(SIGSEGV);
110
+}
111
+
112
+static int try_sti(bool irqs_off)
113
+{
114
+ unsigned long flags;
115
+
116
+ sethandler(SIGSEGV, sigsegv, SA_RESETHAND);
117
+ if (sigsetjmp(jmpbuf, 1) != 0) {
118
+ return RET_FAULTED;
119
+ } else {
120
+ asm volatile("sti; pushf; pop %[flags]"
121
+ : [flags] "=rm" (flags));
122
+
123
+ /* X86_FLAGS_IF */
124
+ if (irqs_off && (flags & (1 << 9)))
125
+ return RET_FAIL;
126
+ else
127
+ return RET_EMUL;
128
+ }
129
+ clearhandler(SIGSEGV);
130
+}
131
+
132
+static void expect_gp_sti(bool irqs_off)
133
+{
134
+ int ret = try_sti(irqs_off);
135
+
136
+ switch (ret) {
137
+ case RET_FAULTED:
138
+ printf("[OK]\tSTI faulted\n");
139
+ break;
140
+ case RET_EMUL:
141
+ printf("[OK]\tSTI NOPped\n");
142
+ break;
143
+ default:
144
+ printf("[FAIL]\tSTI worked\n");
145
+ nerrs++;
146
+ }
147
+}
148
+
149
+/*
150
+ * Returns whether it managed to disable interrupts.
151
+ */
152
+static bool test_cli(void)
153
+{
154
+ int ret = try_cli();
155
+
156
+ switch (ret) {
157
+ case RET_FAULTED:
158
+ printf("[OK]\tCLI faulted\n");
159
+ break;
160
+ case RET_EMUL:
161
+ printf("[OK]\tCLI NOPped\n");
162
+ break;
163
+ default:
164
+ printf("[FAIL]\tCLI worked\n");
165
+ nerrs++;
166
+ return true;
167
+ }
168
+
169
+ return false;
170
+}
171
+
45172 int main(void)
46173 {
47174 cpu_set_t cpuset;
175
+
48176 CPU_ZERO(&cpuset);
49177 CPU_SET(0, &cpuset);
50178 if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0)
51179 err(1, "sched_setaffinity to CPU 0");
52180
53181 /* Probe for iopl support. Note that iopl(0) works even as nonroot. */
54
- if (iopl(3) != 0) {
182
+ switch(iopl(3)) {
183
+ case 0:
184
+ break;
185
+ case -ENOSYS:
186
+ printf("[OK]\tiopl() nor supported\n");
187
+ return 0;
188
+ default:
55189 printf("[OK]\tiopl(3) failed (%d) -- try running as root\n",
56190 errno);
57191 return 0;
58192 }
59193
60
- /* Restore our original state prior to starting the test. */
194
+ /* Make sure that CLI/STI are blocked even with IOPL level 3 */
195
+ expect_gp_sti(test_cli());
196
+ expect_ok_outb(0x80);
197
+
198
+ /* Establish an I/O bitmap to test the restore */
199
+ if (ioperm(0x80, 1, 1) != 0)
200
+ err(1, "ioperm(0x80, 1, 1) failed\n");
201
+
202
+ /* Restore our original state prior to starting the fork test. */
61203 if (iopl(0) != 0)
62204 err(1, "iopl(0)");
205
+
206
+ /*
207
+ * Verify that IOPL emulation is disabled and the I/O bitmap still
208
+ * works.
209
+ */
210
+ expect_ok_outb(0x80);
211
+ expect_gp_outb(0xed);
212
+ /* Drop the I/O bitmap */
213
+ if (ioperm(0x80, 1, 0) != 0)
214
+ err(1, "ioperm(0x80, 1, 0) failed\n");
63215
64216 pid_t child = fork();
65217 if (child == -1)
....@@ -90,14 +242,8 @@
90242
91243 printf("[RUN]\tparent: write to 0x80 (should fail)\n");
92244
93
- sethandler(SIGSEGV, sigsegv, 0);
94
- if (sigsetjmp(jmpbuf, 1) != 0) {
95
- printf("[OK]\twrite was denied\n");
96
- } else {
97
- asm volatile ("outb %%al, $0x80" : : "a" (0));
98
- printf("[FAIL]\twrite was allowed\n");
99
- nerrs++;
100
- }
245
+ expect_gp_outb(0x80);
246
+ expect_gp_sti(test_cli());
101247
102248 /* Test the capability checks. */
103249 printf("\tiopl(3)\n");
....@@ -133,4 +279,3 @@
133279 done:
134280 return nerrs ? 1 : 0;
135281 }
136
-