blob: 0bc605d28df5cded9c64f4e887e66c07a1bc57d4 [file] [log] [blame]
Patrick Rudolph2f6f8d92024-10-23 15:20:13 +02001/* 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: