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