]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.9.163/xtensa-smp-fix-secondary-cpu-initialization.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.9.163 / xtensa-smp-fix-secondary-cpu-initialization.patch
CommitLineData
d369aec6
SL
1From 389218e28ff521d3ce9e395b756b1b25ef73d914 Mon Sep 17 00:00:00 2001
2From: Max Filippov <jcmvbkbc@gmail.com>
3Date: Fri, 21 Dec 2018 08:26:20 -0800
4Subject: xtensa: SMP: fix secondary CPU initialization
5
6[ Upstream commit 32a7726c4f4aadfabdb82440d84f88a5a2c8fe13 ]
7
8- add missing memory barriers to the secondary CPU synchronization spin
9 loops; add comment to the matching memory barrier in the boot_secondary
10 and __cpu_die functions;
11- use READ_ONCE/WRITE_ONCE to access cpu_start_id/cpu_start_ccount
12 instead of reading/writing them directly;
13- re-initialize cpu_running every time before starting secondary CPU to
14 flush possible previous CPU startup results.
15
16Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
17Signed-off-by: Sasha Levin <sashal@kernel.org>
18---
19 arch/xtensa/kernel/head.S | 5 ++++-
20 arch/xtensa/kernel/smp.c | 34 +++++++++++++++++++++-------------
21 2 files changed, 25 insertions(+), 14 deletions(-)
22
23diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S
24index 27c8e07ace43..29f445b410b3 100644
25--- a/arch/xtensa/kernel/head.S
26+++ b/arch/xtensa/kernel/head.S
27@@ -281,12 +281,13 @@ should_never_return:
28
29 movi a2, cpu_start_ccount
30 1:
31+ memw
32 l32i a3, a2, 0
33 beqi a3, 0, 1b
34 movi a3, 0
35 s32i a3, a2, 0
36- memw
37 1:
38+ memw
39 l32i a3, a2, 0
40 beqi a3, 0, 1b
41 wsr a3, ccount
42@@ -323,11 +324,13 @@ ENTRY(cpu_restart)
43 rsr a0, prid
44 neg a2, a0
45 movi a3, cpu_start_id
46+ memw
47 s32i a2, a3, 0
48 #if XCHAL_DCACHE_IS_WRITEBACK
49 dhwbi a3, 0
50 #endif
51 1:
52+ memw
53 l32i a2, a3, 0
54 dhi a3, 0
55 bne a2, a0, 1b
56diff --git a/arch/xtensa/kernel/smp.c b/arch/xtensa/kernel/smp.c
57index fc4ad21a5ed4..fd0f0b50e021 100644
58--- a/arch/xtensa/kernel/smp.c
59+++ b/arch/xtensa/kernel/smp.c
60@@ -192,9 +192,11 @@ static int boot_secondary(unsigned int cpu, struct task_struct *ts)
61 int i;
62
63 #ifdef CONFIG_HOTPLUG_CPU
64- cpu_start_id = cpu;
65- system_flush_invalidate_dcache_range(
66- (unsigned long)&cpu_start_id, sizeof(cpu_start_id));
67+ WRITE_ONCE(cpu_start_id, cpu);
68+ /* Pairs with the third memw in the cpu_restart */
69+ mb();
70+ system_flush_invalidate_dcache_range((unsigned long)&cpu_start_id,
71+ sizeof(cpu_start_id));
72 #endif
73 smp_call_function_single(0, mx_cpu_start, (void *)cpu, 1);
74
75@@ -203,18 +205,21 @@ static int boot_secondary(unsigned int cpu, struct task_struct *ts)
76 ccount = get_ccount();
77 while (!ccount);
78
79- cpu_start_ccount = ccount;
80+ WRITE_ONCE(cpu_start_ccount, ccount);
81
82- while (time_before(jiffies, timeout)) {
83+ do {
84+ /*
85+ * Pairs with the first two memws in the
86+ * .Lboot_secondary.
87+ */
88 mb();
89- if (!cpu_start_ccount)
90- break;
91- }
92+ ccount = READ_ONCE(cpu_start_ccount);
93+ } while (ccount && time_before(jiffies, timeout));
94
95- if (cpu_start_ccount) {
96+ if (ccount) {
97 smp_call_function_single(0, mx_cpu_stop,
98- (void *)cpu, 1);
99- cpu_start_ccount = 0;
100+ (void *)cpu, 1);
101+ WRITE_ONCE(cpu_start_ccount, 0);
102 return -EIO;
103 }
104 }
105@@ -234,6 +239,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
106 pr_debug("%s: Calling wakeup_secondary(cpu:%d, idle:%p, sp: %08lx)\n",
107 __func__, cpu, idle, start_info.stack);
108
109+ init_completion(&cpu_running);
110 ret = boot_secondary(cpu, idle);
111 if (ret == 0) {
112 wait_for_completion_timeout(&cpu_running,
113@@ -295,8 +301,10 @@ void __cpu_die(unsigned int cpu)
114 unsigned long timeout = jiffies + msecs_to_jiffies(1000);
115 while (time_before(jiffies, timeout)) {
116 system_invalidate_dcache_range((unsigned long)&cpu_start_id,
117- sizeof(cpu_start_id));
118- if (cpu_start_id == -cpu) {
119+ sizeof(cpu_start_id));
120+ /* Pairs with the second memw in the cpu_restart */
121+ mb();
122+ if (READ_ONCE(cpu_start_id) == -cpu) {
123 platform_cpu_kill(cpu);
124 return;
125 }
126--
1272.19.1
128