1*4cbb6682Sriastradh /* $NetBSD: cpu_subr.c,v 1.5 2021/11/14 16:56:32 riastradh Exp $ */
2483c6a3dSskrll
3483c6a3dSskrll /*-
4483c6a3dSskrll * Copyright (c) 2020 The NetBSD Foundation, Inc.
5483c6a3dSskrll * All rights reserved.
6483c6a3dSskrll *
7483c6a3dSskrll * This code is derived from software contributed to The NetBSD Foundation
8483c6a3dSskrll * by Nick Hudson
9483c6a3dSskrll *
10483c6a3dSskrll * Redistribution and use in source and binary forms, with or without
11483c6a3dSskrll * modification, are permitted provided that the following conditions
12483c6a3dSskrll * are met:
13483c6a3dSskrll * 1. Redistributions of source code must retain the above copyright
14483c6a3dSskrll * notice, this list of conditions and the following disclaimer.
15483c6a3dSskrll * 2. Redistributions in binary form must reproduce the above copyright
16483c6a3dSskrll * notice, this list of conditions and the following disclaimer in the
17483c6a3dSskrll * documentation and/or other materials provided with the distribution.
18483c6a3dSskrll *
19483c6a3dSskrll * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20483c6a3dSskrll * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21483c6a3dSskrll * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22483c6a3dSskrll * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23483c6a3dSskrll * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24483c6a3dSskrll * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25483c6a3dSskrll * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26483c6a3dSskrll * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27483c6a3dSskrll * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28483c6a3dSskrll * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29483c6a3dSskrll * POSSIBILITY OF SUCH DAMAGE.
30483c6a3dSskrll */
31483c6a3dSskrll
32483c6a3dSskrll #include "opt_cputypes.h"
33483c6a3dSskrll #include "opt_multiprocessor.h"
34483c6a3dSskrll
35483c6a3dSskrll #include <sys/cdefs.h>
36*4cbb6682Sriastradh __KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.5 2021/11/14 16:56:32 riastradh Exp $");
37483c6a3dSskrll
38483c6a3dSskrll #include <sys/param.h>
39483c6a3dSskrll #include <sys/atomic.h>
40483c6a3dSskrll #include <sys/cpu.h>
41483c6a3dSskrll #include <sys/reboot.h>
42483c6a3dSskrll
43a15683c1Sskrll #include <arm/cpufunc.h>
44a15683c1Sskrll
45483c6a3dSskrll #ifdef VERBOSE_INIT_ARM
46483c6a3dSskrll #define VPRINTF(...) printf(__VA_ARGS__)
47483c6a3dSskrll #else
48483c6a3dSskrll #define VPRINTF(...) __nothing
49483c6a3dSskrll #endif
50483c6a3dSskrll
51483c6a3dSskrll #ifdef MULTIPROCESSOR
52483c6a3dSskrll #define NCPUINFO MAXCPUS
53483c6a3dSskrll #else
54483c6a3dSskrll #define NCPUINFO 1
55483c6a3dSskrll #endif /* MULTIPROCESSOR */
56483c6a3dSskrll
57483c6a3dSskrll mpidr_t cpu_mpidr[NCPUINFO] = {
58483c6a3dSskrll [0 ... NCPUINFO - 1] = ~0,
59483c6a3dSskrll };
60483c6a3dSskrll
61483c6a3dSskrll struct cpu_info *cpu_info[NCPUINFO] __read_mostly = {
62483c6a3dSskrll [0] = &cpu_info_store[0]
63483c6a3dSskrll };
64483c6a3dSskrll
65483c6a3dSskrll #ifdef MULTIPROCESSOR
66483c6a3dSskrll
67483c6a3dSskrll #define CPUINDEX_DIVISOR (sizeof(u_long) * NBBY)
68483c6a3dSskrll
69483c6a3dSskrll volatile u_long arm_cpu_hatched[howmany(MAXCPUS, CPUINDEX_DIVISOR)] __cacheline_aligned = { 0 };
70483c6a3dSskrll volatile u_long arm_cpu_mbox[howmany(MAXCPUS, CPUINDEX_DIVISOR)] __cacheline_aligned = { 0 };
71483c6a3dSskrll u_int arm_cpu_max = 1;
72483c6a3dSskrll
73483c6a3dSskrll void
cpu_boot_secondary_processors(void)74483c6a3dSskrll cpu_boot_secondary_processors(void)
75483c6a3dSskrll {
76483c6a3dSskrll u_int cpuno;
77483c6a3dSskrll
78483c6a3dSskrll if ((boothowto & RB_MD1) != 0)
79483c6a3dSskrll return;
80483c6a3dSskrll
81483c6a3dSskrll VPRINTF("%s: starting secondary processors\n", __func__);
82483c6a3dSskrll
83483c6a3dSskrll /* send mbox to have secondary processors do cpu_hatch() */
84*4cbb6682Sriastradh dmb(ish); /* store-release matches locore.S/armv6_start.S */
85483c6a3dSskrll for (size_t n = 0; n < __arraycount(arm_cpu_mbox); n++)
86483c6a3dSskrll atomic_or_ulong(&arm_cpu_mbox[n], arm_cpu_hatched[n]);
87483c6a3dSskrll
88a15683c1Sskrll dsb(ishst);
890ef099a7Sskrll sev();
90483c6a3dSskrll
91483c6a3dSskrll /* wait all cpus have done cpu_hatch() */
92483c6a3dSskrll for (cpuno = 1; cpuno < ncpu; cpuno++) {
93483c6a3dSskrll if (!cpu_hatched_p(cpuno))
94483c6a3dSskrll continue;
95483c6a3dSskrll
96483c6a3dSskrll const size_t off = cpuno / CPUINDEX_DIVISOR;
97483c6a3dSskrll const u_long bit = __BIT(cpuno % CPUINDEX_DIVISOR);
98483c6a3dSskrll
99*4cbb6682Sriastradh /* load-acquire matches cpu_clr_mbox */
100*4cbb6682Sriastradh while (atomic_load_acquire(&arm_cpu_mbox[off]) & bit) {
101483c6a3dSskrll __asm __volatile ("wfe");
102483c6a3dSskrll }
103483c6a3dSskrll /* Add processor to kcpuset */
104483c6a3dSskrll kcpuset_set(kcpuset_attached, cpuno);
105483c6a3dSskrll }
106483c6a3dSskrll
107483c6a3dSskrll VPRINTF("%s: secondary processors hatched\n", __func__);
108483c6a3dSskrll }
109483c6a3dSskrll
110483c6a3dSskrll bool
cpu_hatched_p(u_int cpuindex)111483c6a3dSskrll cpu_hatched_p(u_int cpuindex)
112483c6a3dSskrll {
113483c6a3dSskrll const u_int off = cpuindex / CPUINDEX_DIVISOR;
114483c6a3dSskrll const u_int bit = cpuindex % CPUINDEX_DIVISOR;
115483c6a3dSskrll
116*4cbb6682Sriastradh /* load-acquire matches cpu_set_hatched */
117*4cbb6682Sriastradh return (atomic_load_acquire(&arm_cpu_hatched[off]) & __BIT(bit)) != 0;
118483c6a3dSskrll }
119483c6a3dSskrll
120483c6a3dSskrll void
cpu_set_hatched(int cpuindex)121483c6a3dSskrll cpu_set_hatched(int cpuindex)
122483c6a3dSskrll {
123483c6a3dSskrll
124483c6a3dSskrll const size_t off = cpuindex / CPUINDEX_DIVISOR;
125483c6a3dSskrll const u_long bit = __BIT(cpuindex % CPUINDEX_DIVISOR);
126483c6a3dSskrll
127*4cbb6682Sriastradh dmb(ish); /* store-release matches cpu_hatched_p */
128483c6a3dSskrll atomic_or_ulong(&arm_cpu_hatched[off], bit);
1290ab152a3Sskrll dsb(ishst);
1300ab152a3Sskrll sev();
131483c6a3dSskrll }
132483c6a3dSskrll
133483c6a3dSskrll void
cpu_clr_mbox(int cpuindex)134483c6a3dSskrll cpu_clr_mbox(int cpuindex)
135483c6a3dSskrll {
136483c6a3dSskrll
137483c6a3dSskrll const size_t off = cpuindex / CPUINDEX_DIVISOR;
138483c6a3dSskrll const u_long bit = __BIT(cpuindex % CPUINDEX_DIVISOR);
139483c6a3dSskrll
140483c6a3dSskrll /* Notify cpu_boot_secondary_processors that we're done */
141*4cbb6682Sriastradh dmb(ish); /* store-release */
142483c6a3dSskrll atomic_and_ulong(&arm_cpu_mbox[off], ~bit);
143a15683c1Sskrll dsb(ishst);
1440ef099a7Sskrll sev();
145483c6a3dSskrll }
146483c6a3dSskrll
147483c6a3dSskrll #endif
148