xref: /linux/arch/s390/kernel/skey.c (revision bc46b7cbc58c4cb562b6a45a1fbc7b8e7b23df58)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #include <asm/rwonce.h>
4 #include <asm/page.h>
5 #include <asm/skey.h>
6 
7 int skey_regions_initialized;
8 
load_real_address(unsigned long address)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])\n"
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  */
__skey_regions_initialize(void)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 }
49