xref: /linux/arch/s390/kernel/abs_lowcore.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #include <linux/pgtable.h>
4 #include <asm/abs_lowcore.h>
5 
6 unsigned long __bootdata_preserved(__abs_lowcore);
7 int __bootdata_preserved(relocate_lowcore);
8 
9 int abs_lowcore_map(int cpu, struct lowcore *lc, bool alloc)
10 {
11 	unsigned long addr = __abs_lowcore + (cpu * sizeof(struct lowcore));
12 	unsigned long phys = __pa(lc);
13 	int rc, i;
14 
15 	for (i = 0; i < LC_PAGES; i++) {
16 		rc = __vmem_map_4k_page(addr, phys, PAGE_KERNEL, alloc);
17 		if (rc) {
18 			/*
19 			 * Do not unmap allocated page tables in case the
20 			 * allocation was not requested. In such a case the
21 			 * request is expected coming from an atomic context,
22 			 * while the unmap attempt might sleep.
23 			 */
24 			if (alloc) {
25 				for (--i; i >= 0; i--) {
26 					addr -= PAGE_SIZE;
27 					vmem_unmap_4k_page(addr);
28 				}
29 			}
30 			return rc;
31 		}
32 		addr += PAGE_SIZE;
33 		phys += PAGE_SIZE;
34 	}
35 	return 0;
36 }
37 
38 void abs_lowcore_unmap(int cpu)
39 {
40 	unsigned long addr = __abs_lowcore + (cpu * sizeof(struct lowcore));
41 	int i;
42 
43 	for (i = 0; i < LC_PAGES; i++) {
44 		vmem_unmap_4k_page(addr);
45 		addr += PAGE_SIZE;
46 	}
47 }
48