1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/pgtable.h>
4 #include <asm/abs_lowcore.h>
6 #define ABS_LOWCORE_UNMAPPED 1
7 #define ABS_LOWCORE_LAP_ON 2
8 #define ABS_LOWCORE_IRQS_ON 4
10 unsigned long __bootdata_preserved(__abs_lowcore);
11 bool __ro_after_init abs_lowcore_mapped;
13 int abs_lowcore_map(int cpu, struct lowcore *lc, bool alloc)
15 unsigned long addr = __abs_lowcore + (cpu * sizeof(struct lowcore));
16 unsigned long phys = __pa(lc);
19 for (i = 0; i < LC_PAGES; i++) {
20 rc = __vmem_map_4k_page(addr, phys, PAGE_KERNEL, alloc);
23 * Do not unmap allocated page tables in case the
24 * allocation was not requested. In such a case the
25 * request is expected coming from an atomic context,
26 * while the unmap attempt might sleep.
29 for (--i; i >= 0; i--) {
31 vmem_unmap_4k_page(addr);
42 void abs_lowcore_unmap(int cpu)
44 unsigned long addr = __abs_lowcore + (cpu * sizeof(struct lowcore));
47 for (i = 0; i < LC_PAGES; i++) {
48 vmem_unmap_4k_page(addr);
53 struct lowcore *get_abs_lowcore(unsigned long *flags)
55 unsigned long irq_flags;
61 if (abs_lowcore_mapped) {
62 return ((struct lowcore *)__abs_lowcore) + cpu;
65 panic("Invalid unmapped absolute lowcore access\n");
66 local_irq_save(irq_flags);
67 if (!irqs_disabled_flags(irq_flags))
68 *flags |= ABS_LOWCORE_IRQS_ON;
69 __ctl_store(cr0.val, 0, 0);
71 *flags |= ABS_LOWCORE_LAP_ON;
72 __ctl_clear_bit(0, 28);
74 *flags |= ABS_LOWCORE_UNMAPPED;
75 return lowcore_ptr[0];
79 void put_abs_lowcore(struct lowcore *lc, unsigned long flags)
81 if (abs_lowcore_mapped) {
83 panic("Invalid mapped absolute lowcore release\n");
85 if (smp_processor_id() != 0)
86 panic("Invalid mapped absolute lowcore access\n");
87 if (!(flags & ABS_LOWCORE_UNMAPPED))
88 panic("Invalid unmapped absolute lowcore release\n");
89 if (flags & ABS_LOWCORE_LAP_ON)
91 if (flags & ABS_LOWCORE_IRQS_ON)