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