blob: 0bc605d28df5cded9c64f4e887e66c07a1bc57d4 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2024 9elements GmbH
* Author: Patrick Rudolph <patrick.rudolph@9elements.com>
*
* This file provides ARMv8 specific code for the generic part of the
* ACPI parking protocol implementation. It contains the spinning code
* that will be installed into the parking protocol and it points the
* secondary CPUs to their own parking protocol page once it has been
* set up by the generic part.
*/
#include <asm/acpi_table.h>
#include <linux/linkage.h>
/* Filled by C code */
.global acpi_pp_tables
acpi_pp_tables:
.quad 0
.global acpi_pp_etables
acpi_pp_etables:
.quad 0
/* Read by C code */
.global acpi_pp_code_size
acpi_pp_code_size:
.word __secondary_pp_code_end - __secondary_pp_code_start
.global acpi_pp_secondary_jump
ENTRY(acpi_pp_secondary_jump)
0:
/*
* Cannot use atomic operations since the MMU and D-cache
* might be off. Use the MPIDR instead to find the spintable.
*/
/* Check if parking protocol table is ready */
ldr x1, =acpi_pp_tables
ldr x0, [x1]
cbnz x0, 0f
wfe
b 0b
0: /* Get end of page tables in x3 */
ldr x1, =acpi_pp_etables
ldr x3, [x1]
/* Get own CPU ID in w2 */
mrs x2, mpidr_el1
lsr x9, x2, #32
bfi x2, x9, #24, #8 /* w2 is aff3:aff2:aff1:aff0 */
0: /* Loop over all parking protocol pages */
cmp x0, x3
b.ge hlt
/* Fetch CPU_ID from current page */
ldr x1, [x0, #ACPI_PP_CPU_ID_OFFSET]
lsr x9, x1, #32
bfi x1, x9, #24, #8 /* w1 is aff3:aff2:aff1:aff0 */
/* Compare CPU_IDs */
cmp w1, w2
b.eq 0f
add x0, x0, #ACPI_PP_PAGE_SIZE
b 0b
hlt: wfi
b hlt /* Should never happen. */
0: /* x0 points to the 4K-aligned, parking protocol page */
add x2, x0, #ACPI_PP_CPU_CODE_OFFSET
/* Jump to spin code in own parking protocol page */
br x2
ENDPROC(acpi_pp_secondary_jump)
.align 8
__secondary_pp_code_start:
.global acpi_pp_code_start
ENTRY(acpi_pp_code_start)
/* x0 points to the 4K-aligned, parking protocol page */
/* Prepare defines for spinning code */
mov w3, #ACPI_PP_CPU_ID_INVALID
mov x2, #ACPI_PP_JMP_ADR_INVALID
/* Mark parking protocol page as ready */
str w3, [x0, #ACPI_PP_CPU_ID_OFFSET]
dsb sy
0: wfe
ldr w1, [x0, #ACPI_PP_CPU_ID_OFFSET]
/* Check CPU ID is valid */
cmp w1, w3
b.eq 0b
/* Check jump address valid */
ldr x1, [x0, #ACPI_PP_CPU_JMP_OFFSET]
cmp x1, x2
b.eq 0b
/* Clear jump address before jump */
str x2, [x0, #ACPI_PP_CPU_JMP_OFFSET]
dsb sy
br x1
ENDPROC(acpi_pp_code_start)
/* Secondary Boot Code ends here */
__secondary_pp_code_end: