Skip to content

Commit 06b732e

Browse files
committed
smp: Add smp_stop_secondaries()
Doesn't work properly yet since we can't restart them... Signed-off-by: Hector Martin <marcan@marcan.st>
1 parent 3288548 commit 06b732e

File tree

5 files changed

+88
-8
lines changed

5 files changed

+88
-8
lines changed

proxyclient/m1n1/proxy.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@ class M1N1Proxy(Reloadable):
550550
P_SMP_WAIT = 0x503
551551
P_SMP_SET_WFE_MODE = 0x504
552552
P_SMP_IS_ALIVE = 0x505
553+
P_SMP_STOP_SECONDARIES = 0x506
553554

554555
P_HEAPBLOCK_ALLOC = 0x600
555556
P_MALLOC = 0x601
@@ -949,6 +950,8 @@ def smp_set_wfe_mode(self, mode):
949950
return self.request(self.P_SMP_SET_WFE_MODE, mode)
950951
def smp_is_alive(self, cpu):
951952
return self.request(self.P_SMP_IS_ALIVE, cpu)
953+
def smp_stop_secondaries(self, deep_sleep=False):
954+
self.request(self.P_SMP_STOP_SECONDARIES, deep_sleep)
952955

953956
def heapblock_alloc(self, size):
954957
return self.request(self.P_HEAPBLOCK_ALLOC, size)

src/proxy.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,9 @@ int proxy_process(ProxyRequest *request, ProxyReply *reply)
327327
case P_SMP_START_SECONDARIES:
328328
smp_start_secondaries();
329329
break;
330+
case P_SMP_STOP_SECONDARIES:
331+
smp_stop_secondaries(request->args[0]);
332+
break;
330333
case P_SMP_CALL:
331334
smp_call4(request->args[0], (void *)request->args[1], request->args[2],
332335
request->args[3], request->args[4], request->args[5]);

src/proxy.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ typedef enum {
8585
P_SMP_WAIT,
8686
P_SMP_SET_WFE_MODE,
8787
P_SMP_IS_ALIVE,
88+
P_SMP_STOP_SECONDARIES,
8889

8990
P_HEAPBLOCK_ALLOC = 0x600, // Heap and memory management ops
9091
P_MALLOC,

src/smp.c

Lines changed: 80 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ u8 *secondary_stacks[MAX_CPUS] = {dummy_stack};
3636
static bool wfe_mode = false;
3737

3838
static int target_cpu;
39+
static int cpu_nodes[MAX_CPUS];
3940
static struct spin_table spin_table[MAX_CPUS];
41+
static u64 pmgr_reg;
42+
static u64 cpu_start_off;
4043

4144
extern u8 _vectors_start[0];
4245

@@ -79,7 +82,7 @@ void smp_secondary_entry(void)
7982
}
8083
}
8184

82-
static void smp_start_cpu(int index, int die, int cluster, int core, u64 rvbar, u64 cpu_start_base)
85+
static void smp_start_cpu(int index, int die, int cluster, int core, u64 impl, u64 cpu_start_base)
8386
{
8487
int i;
8588

@@ -99,7 +102,7 @@ static void smp_start_cpu(int index, int die, int cluster, int core, u64 rvbar,
99102

100103
sysop("dmb sy");
101104

102-
write64(rvbar, (u64)_vectors_start);
105+
write64(impl, (u64)_vectors_start);
103106

104107
cpu_start_base += die * PMGR_DIE_OFFSET;
105108

@@ -110,27 +113,73 @@ static void smp_start_cpu(int index, int die, int cluster, int core, u64 rvbar,
110113
// Actually start the core
111114
write32(cpu_start_base + 0x8 + 4 * cluster, 1 << core);
112115

113-
for (i = 0; i < 500; i++) {
116+
for (i = 0; i < 100; i++) {
114117
sysop("dmb ld");
115118
if (spin_table[index].flag)
116119
break;
117120
udelay(1000);
118121
}
119122

120-
if (i >= 500)
123+
if (i >= 100)
121124
printf("Failed!\n");
122125
else
123126
printf(" Started.\n");
124127

125128
_reset_stack = dummy_stack + DUMMY_STACK_SIZE;
126129
}
127130

131+
static void smp_stop_cpu(int index, int die, int cluster, int core, u64 impl, u64 cpu_start_base,
132+
bool deep_sleep)
133+
{
134+
int i;
135+
136+
if (index >= MAX_CPUS)
137+
return;
138+
139+
if (!spin_table[index].flag)
140+
return;
141+
142+
printf("Stopping CPU %d (%d:%d:%d)... ", index, die, cluster, core);
143+
144+
cpu_start_base += die * PMGR_DIE_OFFSET;
145+
146+
// Request CPU stop
147+
write32(cpu_start_base + 0x0, 1 << (4 * cluster + core));
148+
149+
// Put the CPU to sleep
150+
smp_call1(index, cpu_sleep, deep_sleep);
151+
152+
// If going into deep sleep, powering off the last core in a cluster kills our register
153+
// access, so just wait a bit.
154+
if (deep_sleep) {
155+
udelay(10000);
156+
printf(" Presumed stopped.\n");
157+
memset(&spin_table[index], 0, sizeof(struct spin_table));
158+
return;
159+
}
160+
161+
// Check that it actually shut down
162+
for (i = 0; i < 50; i++) {
163+
sysop("dmb ld");
164+
if (!(read64(impl + 0x100) & 0xff))
165+
break;
166+
udelay(1000);
167+
}
168+
169+
if (i >= 50) {
170+
printf("Failed!\n");
171+
} else {
172+
printf(" Stopped.\n");
173+
174+
memset(&spin_table[index], 0, sizeof(struct spin_table));
175+
}
176+
}
177+
128178
void smp_start_secondaries(void)
129179
{
130180
printf("Starting secondary CPUs...\n");
131181

132182
int pmgr_path[8];
133-
u64 pmgr_reg;
134183

135184
if (adt_path_offset_trace(adt, "/arm-io/pmgr", pmgr_path) < 0) {
136185
printf("Error getting /arm-io/pmgr node\n");
@@ -147,9 +196,6 @@ void smp_start_secondaries(void)
147196
return;
148197
}
149198

150-
int cpu_nodes[MAX_CPUS];
151-
u64 cpu_start_off;
152-
153199
memset(cpu_nodes, 0, sizeof(cpu_nodes));
154200

155201
switch (chip_id) {
@@ -208,6 +254,32 @@ void smp_start_secondaries(void)
208254
spin_table[0].mpidr = mrs(MPIDR_EL1) & 0xFFFFFF;
209255
}
210256

257+
void smp_stop_secondaries(bool deep_sleep)
258+
{
259+
printf("Stopping secondary CPUs...\n");
260+
smp_set_wfe_mode(true);
261+
262+
for (int i = 1; i < MAX_CPUS; i++) {
263+
int node = cpu_nodes[i];
264+
265+
if (!node)
266+
continue;
267+
268+
u32 reg;
269+
u64 cpu_impl_reg[2];
270+
if (ADT_GETPROP(adt, node, "reg", &reg) < 0)
271+
continue;
272+
if (ADT_GETPROP_ARRAY(adt, node, "cpu-impl-reg", cpu_impl_reg) < 0)
273+
continue;
274+
275+
u8 core = FIELD_GET(CPU_REG_CORE, reg);
276+
u8 cluster = FIELD_GET(CPU_REG_CLUSTER, reg);
277+
u8 die = FIELD_GET(CPU_REG_DIE, reg);
278+
279+
smp_stop_cpu(i, die, cluster, core, cpu_impl_reg[0], pmgr_reg + cpu_start_off, deep_sleep);
280+
}
281+
}
282+
211283
void smp_send_ipi(int cpu)
212284
{
213285
if (cpu >= MAX_CPUS)

src/smp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ extern u8 *secondary_stacks[MAX_CPUS];
1414
void smp_secondary_entry(void);
1515

1616
void smp_start_secondaries(void);
17+
void smp_stop_secondaries(bool deep_sleep);
1718

1819
#define smp_call0(i, f) smp_call4(i, f, 0, 0, 0, 0)
1920
#define smp_call1(i, f, a) smp_call4(i, f, a, 0, 0, 0)

0 commit comments

Comments
 (0)