1/* SPDX-License-Identifier: GPL-2.0+ */ 2/* 3 * Copyright (C) 2024 9elements GmbH 4 * Author: Patrick Rudolph <patrick.rudolph@9elements.com> 5 * 6 * This file provides ARMv8 specific code for the generic part of the 7 * ACPI parking protocol implementation. It contains the spinning code 8 * that will be installed into the parking protocol and it points the 9 * secondary CPUs to their own parking protocol page once it has been 10 * set up by the generic part. 11 */ 12 13#include <asm/acpi_table.h> 14#include <linux/linkage.h> 15 16/* Filled by C code */ 17.global acpi_pp_tables 18acpi_pp_tables: 19 .quad 0 20 21.global acpi_pp_etables 22acpi_pp_etables: 23 .quad 0 24 25/* Read by C code */ 26.global acpi_pp_code_size 27acpi_pp_code_size: 28 .word __secondary_pp_code_end - __secondary_pp_code_start 29 30.global acpi_pp_secondary_jump 31ENTRY(acpi_pp_secondary_jump) 320: 33 /* 34 * Cannot use atomic operations since the MMU and D-cache 35 * might be off. Use the MPIDR instead to find the spintable. 36 */ 37 38 /* Check if parking protocol table is ready */ 39 ldr x1, =acpi_pp_tables 40 ldr x0, [x1] 41 cbnz x0, 0f 42 wfe 43 b 0b 44 450: /* Get end of page tables in x3 */ 46 ldr x1, =acpi_pp_etables 47 ldr x3, [x1] 48 49 /* Get own CPU ID in w2 */ 50 mrs x2, mpidr_el1 51 lsr x9, x2, #32 52 bfi x2, x9, #24, #8 /* w2 is aff3:aff2:aff1:aff0 */ 53 540: /* Loop over all parking protocol pages */ 55 cmp x0, x3 56 b.ge hlt 57 58 /* Fetch CPU_ID from current page */ 59 ldr x1, [x0, #ACPI_PP_CPU_ID_OFFSET] 60 lsr x9, x1, #32 61 bfi x1, x9, #24, #8 /* w1 is aff3:aff2:aff1:aff0 */ 62 63 /* Compare CPU_IDs */ 64 cmp w1, w2 65 b.eq 0f 66 67 add x0, x0, #ACPI_PP_PAGE_SIZE 68 b 0b 69 70hlt: wfi 71 b hlt /* Should never happen. */ 72 730: /* x0 points to the 4K-aligned, parking protocol page */ 74 add x2, x0, #ACPI_PP_CPU_CODE_OFFSET 75 76 /* Jump to spin code in own parking protocol page */ 77 br x2 78ENDPROC(acpi_pp_secondary_jump) 79 80.align 8 81__secondary_pp_code_start: 82.global acpi_pp_code_start 83ENTRY(acpi_pp_code_start) 84 /* x0 points to the 4K-aligned, parking protocol page */ 85 86 /* Prepare defines for spinning code */ 87 mov w3, #ACPI_PP_CPU_ID_INVALID 88 mov x2, #ACPI_PP_JMP_ADR_INVALID 89 90 /* Mark parking protocol page as ready */ 91 str w3, [x0, #ACPI_PP_CPU_ID_OFFSET] 92 dsb sy 93 940: wfe 95 ldr w1, [x0, #ACPI_PP_CPU_ID_OFFSET] 96 97 /* Check CPU ID is valid */ 98 cmp w1, w3 99 b.eq 0b 100 101 /* Check jump address valid */ 102 ldr x1, [x0, #ACPI_PP_CPU_JMP_OFFSET] 103 cmp x1, x2 104 b.eq 0b 105 106 /* Clear jump address before jump */ 107 str x2, [x0, #ACPI_PP_CPU_JMP_OFFSET] 108 dsb sy 109 110 br x1 111ENDPROC(acpi_pp_code_start) 112 /* Secondary Boot Code ends here */ 113__secondary_pp_code_end: 114