1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
27
28#include <asm-generic/sections.h>
29#include <asm/cpu_device_id.h>
30#include <asm/imr.h>
31#include <asm/iosf_mbi.h>
32#include <asm/io.h>
33
34#include <linux/debugfs.h>
35#include <linux/init.h>
36#include <linux/mm.h>
37#include <linux/types.h>
38
39struct imr_device {
40 bool init;
41 struct mutex lock;
42 int max_imr;
43 int reg_base;
44};
45
46static struct imr_device imr_dev;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64#define IMR_LOCK BIT(31)
65
66struct imr_regs {
67 u32 addr_lo;
68 u32 addr_hi;
69 u32 rmask;
70 u32 wmask;
71};
72
73#define IMR_NUM_REGS (sizeof(struct imr_regs)/sizeof(u32))
74#define IMR_SHIFT 8
75#define imr_to_phys(x) ((x) << IMR_SHIFT)
76#define phys_to_imr(x) ((x) >> IMR_SHIFT)
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92static inline int imr_is_enabled(struct imr_regs *imr)
93{
94 return !(imr->rmask == IMR_READ_ACCESS_ALL &&
95 imr->wmask == IMR_WRITE_ACCESS_ALL &&
96 imr_to_phys(imr->addr_lo) == 0 &&
97 imr_to_phys(imr->addr_hi) == 0);
98}
99
100
101
102
103
104
105
106
107
108
109
110static int imr_read(struct imr_device *idev, u32 imr_id, struct imr_regs *imr)
111{
112 u32 reg = imr_id * IMR_NUM_REGS + idev->reg_base;
113 int ret;
114
115 ret = iosf_mbi_read(QRK_MBI_UNIT_MM, MBI_REG_READ, reg++, &imr->addr_lo);
116 if (ret)
117 return ret;
118
119 ret = iosf_mbi_read(QRK_MBI_UNIT_MM, MBI_REG_READ, reg++, &imr->addr_hi);
120 if (ret)
121 return ret;
122
123 ret = iosf_mbi_read(QRK_MBI_UNIT_MM, MBI_REG_READ, reg++, &imr->rmask);
124 if (ret)
125 return ret;
126
127 return iosf_mbi_read(QRK_MBI_UNIT_MM, MBI_REG_READ, reg++, &imr->wmask);
128}
129
130
131
132
133
134
135
136
137
138
139
140
141static int imr_write(struct imr_device *idev, u32 imr_id, struct imr_regs *imr)
142{
143 unsigned long flags;
144 u32 reg = imr_id * IMR_NUM_REGS + idev->reg_base;
145 int ret;
146
147 local_irq_save(flags);
148
149 ret = iosf_mbi_write(QRK_MBI_UNIT_MM, MBI_REG_WRITE, reg++, imr->addr_lo);
150 if (ret)
151 goto failed;
152
153 ret = iosf_mbi_write(QRK_MBI_UNIT_MM, MBI_REG_WRITE, reg++, imr->addr_hi);
154 if (ret)
155 goto failed;
156
157 ret = iosf_mbi_write(QRK_MBI_UNIT_MM, MBI_REG_WRITE, reg++, imr->rmask);
158 if (ret)
159 goto failed;
160
161 ret = iosf_mbi_write(QRK_MBI_UNIT_MM, MBI_REG_WRITE, reg++, imr->wmask);
162 if (ret)
163 goto failed;
164
165 local_irq_restore(flags);
166 return 0;
167failed:
168
169
170
171
172
173 local_irq_restore(flags);
174 WARN(ret, "IOSF-MBI write fail range 0x%08x-0x%08x unreliable\n",
175 imr_to_phys(imr->addr_lo), imr_to_phys(imr->addr_hi) + IMR_MASK);
176
177 return ret;
178}
179
180
181
182
183
184
185
186
187static int imr_dbgfs_state_show(struct seq_file *s, void *unused)
188{
189 phys_addr_t base;
190 phys_addr_t end;
191 int i;
192 struct imr_device *idev = s->private;
193 struct imr_regs imr;
194 size_t size;
195 int ret = -ENODEV;
196
197 mutex_lock(&idev->lock);
198
199 for (i = 0; i < idev->max_imr; i++) {
200
201 ret = imr_read(idev, i, &imr);
202 if (ret)
203 break;
204
205
206
207
208
209
210 if (imr_is_enabled(&imr)) {
211 base = imr_to_phys(imr.addr_lo);
212 end = imr_to_phys(imr.addr_hi) + IMR_MASK;
213 size = end - base + 1;
214 } else {
215 base = 0;
216 end = 0;
217 size = 0;
218 }
219 seq_printf(s, "imr%02i: base=%pa, end=%pa, size=0x%08zx "
220 "rmask=0x%08x, wmask=0x%08x, %s, %s\n", i,
221 &base, &end, size, imr.rmask, imr.wmask,
222 imr_is_enabled(&imr) ? "enabled " : "disabled",
223 imr.addr_lo & IMR_LOCK ? "locked" : "unlocked");
224 }
225
226 mutex_unlock(&idev->lock);
227 return ret;
228}
229DEFINE_SHOW_ATTRIBUTE(imr_dbgfs_state);
230
231
232
233
234
235
236static void imr_debugfs_register(struct imr_device *idev)
237{
238 debugfs_create_file("imr_state", 0444, NULL, idev,
239 &imr_dbgfs_state_fops);
240}
241
242
243
244
245
246
247
248
249static int imr_check_params(phys_addr_t base, size_t size)
250{
251 if ((base & IMR_MASK) || (size & IMR_MASK)) {
252 pr_err("base %pa size 0x%08zx must align to 1KiB\n",
253 &base, size);
254 return -EINVAL;
255 }
256 if (size == 0)
257 return -EINVAL;
258
259 return 0;
260}
261
262
263
264
265
266
267
268
269
270
271
272static inline size_t imr_raw_size(size_t size)
273{
274 return size - IMR_ALIGN;
275}
276
277
278
279
280
281
282
283
284static inline int imr_address_overlap(phys_addr_t addr, struct imr_regs *imr)
285{
286 return addr >= imr_to_phys(imr->addr_lo) && addr <= imr_to_phys(imr->addr_hi);
287}
288
289
290
291
292
293
294
295
296
297
298int imr_add_range(phys_addr_t base, size_t size,
299 unsigned int rmask, unsigned int wmask)
300{
301 phys_addr_t end;
302 unsigned int i;
303 struct imr_device *idev = &imr_dev;
304 struct imr_regs imr;
305 size_t raw_size;
306 int reg;
307 int ret;
308
309 if (WARN_ONCE(idev->init == false, "driver not initialized"))
310 return -ENODEV;
311
312 ret = imr_check_params(base, size);
313 if (ret)
314 return ret;
315
316
317 raw_size = imr_raw_size(size);
318 end = base + raw_size;
319
320
321
322
323
324 imr.addr_lo = phys_to_imr(base);
325 imr.addr_hi = phys_to_imr(end);
326 imr.rmask = rmask;
327 imr.wmask = wmask;
328 if (!imr_is_enabled(&imr))
329 return -ENOTSUPP;
330
331 mutex_lock(&idev->lock);
332
333
334
335
336
337
338
339 reg = -1;
340 for (i = 0; i < idev->max_imr; i++) {
341 ret = imr_read(idev, i, &imr);
342 if (ret)
343 goto failed;
344
345
346 ret = -EINVAL;
347 if (imr_is_enabled(&imr)) {
348 if (imr_address_overlap(base, &imr))
349 goto failed;
350 if (imr_address_overlap(end, &imr))
351 goto failed;
352 } else {
353 reg = i;
354 }
355 }
356
357
358 if (reg == -1) {
359 ret = -ENOMEM;
360 goto failed;
361 }
362
363 pr_debug("add %d phys %pa-%pa size %zx mask 0x%08x wmask 0x%08x\n",
364 reg, &base, &end, raw_size, rmask, wmask);
365
366
367 imr.addr_lo = phys_to_imr(base);
368 imr.addr_hi = phys_to_imr(end);
369 imr.rmask = rmask;
370 imr.wmask = wmask;
371
372 ret = imr_write(idev, reg, &imr);
373 if (ret < 0) {
374
375
376
377
378
379 imr.addr_lo = 0;
380 imr.addr_hi = 0;
381 imr.rmask = IMR_READ_ACCESS_ALL;
382 imr.wmask = IMR_WRITE_ACCESS_ALL;
383 imr_write(idev, reg, &imr);
384 }
385failed:
386 mutex_unlock(&idev->lock);
387 return ret;
388}
389EXPORT_SYMBOL_GPL(imr_add_range);
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407static int __imr_remove_range(int reg, phys_addr_t base, size_t size)
408{
409 phys_addr_t end;
410 bool found = false;
411 unsigned int i;
412 struct imr_device *idev = &imr_dev;
413 struct imr_regs imr;
414 size_t raw_size;
415 int ret = 0;
416
417 if (WARN_ONCE(idev->init == false, "driver not initialized"))
418 return -ENODEV;
419
420
421
422
423
424 if (reg == -1) {
425 ret = imr_check_params(base, size);
426 if (ret)
427 return ret;
428 }
429
430
431 raw_size = imr_raw_size(size);
432 end = base + raw_size;
433
434 mutex_lock(&idev->lock);
435
436 if (reg >= 0) {
437
438 ret = imr_read(idev, reg, &imr);
439 if (ret)
440 goto failed;
441
442 if (!imr_is_enabled(&imr) || imr.addr_lo & IMR_LOCK) {
443 ret = -ENODEV;
444 goto failed;
445 }
446 found = true;
447 } else {
448
449 for (i = 0; i < idev->max_imr; i++) {
450 ret = imr_read(idev, i, &imr);
451 if (ret)
452 goto failed;
453
454 if (!imr_is_enabled(&imr) || imr.addr_lo & IMR_LOCK)
455 continue;
456
457 if ((imr_to_phys(imr.addr_lo) == base) &&
458 (imr_to_phys(imr.addr_hi) == end)) {
459 found = true;
460 reg = i;
461 break;
462 }
463 }
464 }
465
466 if (!found) {
467 ret = -ENODEV;
468 goto failed;
469 }
470
471 pr_debug("remove %d phys %pa-%pa size %zx\n", reg, &base, &end, raw_size);
472
473
474 imr.addr_lo = 0;
475 imr.addr_hi = 0;
476 imr.rmask = IMR_READ_ACCESS_ALL;
477 imr.wmask = IMR_WRITE_ACCESS_ALL;
478
479 ret = imr_write(idev, reg, &imr);
480
481failed:
482 mutex_unlock(&idev->lock);
483 return ret;
484}
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499int imr_remove_range(phys_addr_t base, size_t size)
500{
501 return __imr_remove_range(-1, base, size);
502}
503EXPORT_SYMBOL_GPL(imr_remove_range);
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518static inline int imr_clear(int reg)
519{
520 return __imr_remove_range(reg, 0, 0);
521}
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537static void __init imr_fixup_memmap(struct imr_device *idev)
538{
539 phys_addr_t base = virt_to_phys(&_text);
540 size_t size = virt_to_phys(&__end_rodata) - base;
541 unsigned long start, end;
542 int i;
543 int ret;
544
545
546 for (i = 0; i < idev->max_imr; i++)
547 imr_clear(i);
548
549 start = (unsigned long)_text;
550 end = (unsigned long)__end_rodata - 1;
551
552
553
554
555
556
557
558
559
560 ret = imr_add_range(base, size, IMR_CPU, IMR_CPU);
561 if (ret < 0) {
562 pr_err("unable to setup IMR for kernel: %zu KiB (%lx - %lx)\n",
563 size / 1024, start, end);
564 } else {
565 pr_info("protecting kernel .text - .rodata: %zu KiB (%lx - %lx)\n",
566 size / 1024, start, end);
567 }
568
569}
570
571static const struct x86_cpu_id imr_ids[] __initconst = {
572 X86_MATCH_VENDOR_FAM_MODEL(INTEL, 5, INTEL_FAM5_QUARK_X1000, NULL),
573 {}
574};
575
576
577
578
579
580
581static int __init imr_init(void)
582{
583 struct imr_device *idev = &imr_dev;
584
585 if (!x86_match_cpu(imr_ids) || !iosf_mbi_available())
586 return -ENODEV;
587
588 idev->max_imr = QUARK_X1000_IMR_MAX;
589 idev->reg_base = QUARK_X1000_IMR_REGBASE;
590 idev->init = true;
591
592 mutex_init(&idev->lock);
593 imr_debugfs_register(idev);
594 imr_fixup_memmap(idev);
595 return 0;
596}
597device_initcall(imr_init);
598