Skip to content

Commit 775d37d

Browse files
kirylIngo Molnar
authored andcommitted
x86/acpi: Replace manual page table initialization with kernel_ident_mapping_init()
The init_transition_pgtable() functions maps the page with asm_acpi_mp_play_dead() into an identity mapping. Replace open-coded manual page table initialization with kernel_ident_mapping_init() to avoid code duplication. Use x86_mapping_info::offset to get the page mapped at the correct location. Signed-off-by: Kirill A. Shutemov <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Reviewed-by: Kai Huang <[email protected]> Reviewed-by: Tom Lendacky <[email protected]> Acked-by: Rafael J. Wysocki <[email protected]> Cc: Andy Lutomirski <[email protected]> Cc: Linus Torvalds <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 634ab76 commit 775d37d

File tree

1 file changed

+15
-58
lines changed

1 file changed

+15
-58
lines changed

arch/x86/kernel/acpi/madt_wakeup.c

Lines changed: 15 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -70,58 +70,6 @@ static void __init free_pgt_page(void *pgt, void *dummy)
7070
return memblock_free(pgt, PAGE_SIZE);
7171
}
7272

73-
/*
74-
* Make sure asm_acpi_mp_play_dead() is present in the identity mapping at
75-
* the same place as in the kernel page tables. asm_acpi_mp_play_dead() switches
76-
* to the identity mapping and the function has be present at the same spot in
77-
* the virtual address space before and after switching page tables.
78-
*/
79-
static int __init init_transition_pgtable(pgd_t *pgd)
80-
{
81-
pgprot_t prot = PAGE_KERNEL_EXEC_NOENC;
82-
unsigned long vaddr, paddr;
83-
p4d_t *p4d;
84-
pud_t *pud;
85-
pmd_t *pmd;
86-
pte_t *pte;
87-
88-
vaddr = (unsigned long)asm_acpi_mp_play_dead;
89-
pgd += pgd_index(vaddr);
90-
if (!pgd_present(*pgd)) {
91-
p4d = (p4d_t *)alloc_pgt_page(NULL);
92-
if (!p4d)
93-
return -ENOMEM;
94-
set_pgd(pgd, __pgd(__pa(p4d) | _KERNPG_TABLE));
95-
}
96-
p4d = p4d_offset(pgd, vaddr);
97-
if (!p4d_present(*p4d)) {
98-
pud = (pud_t *)alloc_pgt_page(NULL);
99-
if (!pud)
100-
return -ENOMEM;
101-
set_p4d(p4d, __p4d(__pa(pud) | _KERNPG_TABLE));
102-
}
103-
pud = pud_offset(p4d, vaddr);
104-
if (!pud_present(*pud)) {
105-
pmd = (pmd_t *)alloc_pgt_page(NULL);
106-
if (!pmd)
107-
return -ENOMEM;
108-
set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
109-
}
110-
pmd = pmd_offset(pud, vaddr);
111-
if (!pmd_present(*pmd)) {
112-
pte = (pte_t *)alloc_pgt_page(NULL);
113-
if (!pte)
114-
return -ENOMEM;
115-
set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE));
116-
}
117-
pte = pte_offset_kernel(pmd, vaddr);
118-
119-
paddr = __pa(vaddr);
120-
set_pte(pte, pfn_pte(paddr >> PAGE_SHIFT, prot));
121-
122-
return 0;
123-
}
124-
12573
static int __init acpi_mp_setup_reset(u64 reset_vector)
12674
{
12775
struct x86_mapping_info info = {
@@ -130,15 +78,14 @@ static int __init acpi_mp_setup_reset(u64 reset_vector)
13078
.page_flag = __PAGE_KERNEL_LARGE_EXEC,
13179
.kernpg_flag = _KERNPG_TABLE_NOENC,
13280
};
81+
unsigned long mstart, mend;
13382
pgd_t *pgd;
13483

13584
pgd = alloc_pgt_page(NULL);
13685
if (!pgd)
13786
return -ENOMEM;
13887

13988
for (int i = 0; i < nr_pfn_mapped; i++) {
140-
unsigned long mstart, mend;
141-
14289
mstart = pfn_mapped[i].start << PAGE_SHIFT;
14390
mend = pfn_mapped[i].end << PAGE_SHIFT;
14491
if (kernel_ident_mapping_init(&info, pgd, mstart, mend)) {
@@ -147,14 +94,24 @@ static int __init acpi_mp_setup_reset(u64 reset_vector)
14794
}
14895
}
14996

150-
if (kernel_ident_mapping_init(&info, pgd,
151-
PAGE_ALIGN_DOWN(reset_vector),
152-
PAGE_ALIGN(reset_vector + 1))) {
97+
mstart = PAGE_ALIGN_DOWN(reset_vector);
98+
mend = mstart + PAGE_SIZE;
99+
if (kernel_ident_mapping_init(&info, pgd, mstart, mend)) {
153100
kernel_ident_mapping_free(&info, pgd);
154101
return -ENOMEM;
155102
}
156103

157-
if (init_transition_pgtable(pgd)) {
104+
/*
105+
* Make sure asm_acpi_mp_play_dead() is present in the identity mapping
106+
* at the same place as in the kernel page tables.
107+
* asm_acpi_mp_play_dead() switches to the identity mapping and the
108+
* function must be present at the same spot in the virtual address space
109+
* before and after switching page tables.
110+
*/
111+
info.offset = __START_KERNEL_map - phys_base;
112+
mstart = PAGE_ALIGN_DOWN(__pa(asm_acpi_mp_play_dead));
113+
mend = mstart + PAGE_SIZE;
114+
if (kernel_ident_mapping_init(&info, pgd, mstart, mend)) {
158115
kernel_ident_mapping_free(&info, pgd);
159116
return -ENOMEM;
160117
}

0 commit comments

Comments
 (0)