| 1 | |
| 2 |
|
| 3 | #include <asm/rwonce.h>
|
| 4 | #include <asm/page.h>
|
| 5 | #include <asm/skey.h>
|
| 6 |
|
| 7 | int skey_regions_initialized;
|
| 8 |
|
| 9 | static inline unsigned long load_real_address(unsigned long address)
|
| 10 | {
|
| 11 | unsigned long real;
|
| 12 |
|
| 13 | asm volatile(
|
| 14 | " lra %[real],0(%[address])"
|
| 15 | : [real] "=d" (real)
|
| 16 | : [address] "a" (address)
|
| 17 | : "cc");
|
| 18 | return real;
|
| 19 | }
|
| 20 |
|
| 21 | |
| 22 | * Initialize storage keys of registered memory regions with the
|
| 23 | * default key. This is useful for code which is executed with a
|
| 24 | * non-default access key.
|
| 25 |
|
| 26 | void __skey_regions_initialize(void)
|
| 27 | {
|
| 28 | unsigned long address, real;
|
| 29 | struct skey_region *r, *end;
|
| 30 |
|
| 31 | r = __skey_region_start;
|
| 32 | end = __skey_region_end;
|
| 33 | while (r < end) {
|
| 34 | address = r->start & PAGE_MASK;
|
| 35 | do {
|
| 36 | real = load_real_address(address);
|
| 37 | page_set_storage_key(real, PAGE_DEFAULT_KEY, 1);
|
| 38 | address += PAGE_SIZE;
|
| 39 | } while (address < r->end);
|
| 40 | r++;
|
| 41 | }
|
| 42 | |
| 43 | * Make sure storage keys are initialized before
|
| 44 | * skey_regions_initialized is changed.
|
| 45 |
|
| 46 | barrier();
|
| 47 | WRITE_ONCE(skey_regions_initialized, 1);
|
| 48 | }
|