1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2010, 2014, 2022 The Linux Foundation. All rights reserved. */
3
4 #include <linux/console.h>
5 #include <linux/cpu.h>
6 #include <linux/cpumask.h>
7 #include <linux/init.h>
8 #include <linux/kfifo.h>
9 #include <linux/moduleparam.h>
10 #include <linux/serial.h>
11 #include <linux/serial_core.h>
12 #include <linux/smp.h>
13 #include <linux/spinlock.h>
14
15 #include <asm/dcc.h>
16 #include <asm/processor.h>
17
18 #include "hvc_console.h"
19
20 /*
21 * Disable DCC driver at runtime. Want driver enabled for GKI, but some devices
22 * do not support the registers and crash when driver pokes the registers
23 */
24 static bool enable;
25 module_param(enable, bool, 0444);
26
27 /* DCC Status Bits */
28 #define DCC_STATUS_RX (1 << 30)
29 #define DCC_STATUS_TX (1 << 29)
30
31 #define DCC_INBUF_SIZE 128
32 #define DCC_OUTBUF_SIZE 1024
33
34 /* Lock to serialize access to DCC fifo */
35 static DEFINE_SPINLOCK(dcc_lock);
36
37 static DEFINE_KFIFO(inbuf, u8, DCC_INBUF_SIZE);
38 static DEFINE_KFIFO(outbuf, u8, DCC_OUTBUF_SIZE);
39
dcc_uart_console_putchar(struct uart_port * port,u8 ch)40 static void dcc_uart_console_putchar(struct uart_port *port, u8 ch)
41 {
42 while (__dcc_getstatus() & DCC_STATUS_TX)
43 cpu_relax();
44
45 __dcc_putchar(ch);
46 }
47
dcc_early_write(struct console * con,const char * s,unsigned n)48 static void dcc_early_write(struct console *con, const char *s, unsigned n)
49 {
50 struct earlycon_device *dev = con->data;
51
52 uart_console_write(&dev->port, s, n, dcc_uart_console_putchar);
53 }
54
dcc_early_console_setup(struct earlycon_device * device,const char * opt)55 static int __init dcc_early_console_setup(struct earlycon_device *device,
56 const char *opt)
57 {
58 unsigned int count = 0x4000000;
59
60 while (--count && (__dcc_getstatus() & DCC_STATUS_TX))
61 cpu_relax();
62
63 if (__dcc_getstatus() & DCC_STATUS_TX)
64 return -ENODEV;
65
66 device->con->write = dcc_early_write;
67
68 return 0;
69 }
70
71 EARLYCON_DECLARE(dcc, dcc_early_console_setup);
72
hvc_dcc_put_chars(uint32_t vt,const u8 * buf,size_t count)73 static ssize_t hvc_dcc_put_chars(uint32_t vt, const u8 *buf, size_t count)
74 {
75 size_t i;
76
77 for (i = 0; i < count; i++) {
78 while (__dcc_getstatus() & DCC_STATUS_TX)
79 cpu_relax();
80
81 __dcc_putchar(buf[i]);
82 }
83
84 return count;
85 }
86
hvc_dcc_get_chars(uint32_t vt,u8 * buf,size_t count)87 static ssize_t hvc_dcc_get_chars(uint32_t vt, u8 *buf, size_t count)
88 {
89 size_t i;
90
91 for (i = 0; i < count; ++i)
92 if (__dcc_getstatus() & DCC_STATUS_RX)
93 buf[i] = __dcc_getchar();
94 else
95 break;
96
97 return i;
98 }
99
100 /*
101 * Check if the DCC is enabled. If CONFIG_HVC_DCC_SERIALIZE_SMP is enabled,
102 * then we assume then this function will be called first on core0. That way,
103 * dcc_core0_available will be true only if it's available on core0.
104 */
hvc_dcc_check(void)105 static bool hvc_dcc_check(void)
106 {
107 unsigned long time = jiffies + (HZ / 10);
108 static bool dcc_core0_available;
109
110 /*
111 * If we're not on core 0, but we previously confirmed that DCC is
112 * active, then just return true.
113 */
114 int cpu = get_cpu();
115
116 if (IS_ENABLED(CONFIG_HVC_DCC_SERIALIZE_SMP) && cpu && dcc_core0_available) {
117 put_cpu();
118 return true;
119 }
120
121 put_cpu();
122
123 /* Write a test character to check if it is handled */
124 __dcc_putchar('\n');
125
126 while (time_is_after_jiffies(time)) {
127 if (!(__dcc_getstatus() & DCC_STATUS_TX)) {
128 dcc_core0_available = true;
129 return true;
130 }
131 }
132
133 return false;
134 }
135
136 /*
137 * Workqueue function that writes the output FIFO to the DCC on core 0.
138 */
dcc_put_work(struct work_struct * work)139 static void dcc_put_work(struct work_struct *work)
140 {
141 unsigned char ch;
142 unsigned long irqflags;
143
144 spin_lock_irqsave(&dcc_lock, irqflags);
145
146 /* While there's data in the output FIFO, write it to the DCC */
147 while (kfifo_get(&outbuf, &ch))
148 hvc_dcc_put_chars(0, &ch, 1);
149
150 /* While we're at it, check for any input characters */
151 while (!kfifo_is_full(&inbuf)) {
152 if (!hvc_dcc_get_chars(0, &ch, 1))
153 break;
154 kfifo_put(&inbuf, ch);
155 }
156
157 spin_unlock_irqrestore(&dcc_lock, irqflags);
158 }
159
160 static DECLARE_WORK(dcc_pwork, dcc_put_work);
161
162 /*
163 * Workqueue function that reads characters from DCC and puts them into the
164 * input FIFO.
165 */
dcc_get_work(struct work_struct * work)166 static void dcc_get_work(struct work_struct *work)
167 {
168 unsigned long irqflags;
169 u8 ch;
170
171 /*
172 * Read characters from DCC and put them into the input FIFO, as
173 * long as there is room and we have characters to read.
174 */
175 spin_lock_irqsave(&dcc_lock, irqflags);
176
177 while (!kfifo_is_full(&inbuf)) {
178 if (!hvc_dcc_get_chars(0, &ch, 1))
179 break;
180 kfifo_put(&inbuf, ch);
181 }
182 spin_unlock_irqrestore(&dcc_lock, irqflags);
183 }
184
185 static DECLARE_WORK(dcc_gwork, dcc_get_work);
186
187 /*
188 * Write characters directly to the DCC if we're on core 0 and the FIFO
189 * is empty, or write them to the FIFO if we're not.
190 */
hvc_dcc0_put_chars(u32 vt,const u8 * buf,size_t count)191 static ssize_t hvc_dcc0_put_chars(u32 vt, const u8 *buf, size_t count)
192 {
193 unsigned long irqflags;
194 ssize_t len;
195
196 if (!IS_ENABLED(CONFIG_HVC_DCC_SERIALIZE_SMP))
197 return hvc_dcc_put_chars(vt, buf, count);
198
199 spin_lock_irqsave(&dcc_lock, irqflags);
200 if (smp_processor_id() || (!kfifo_is_empty(&outbuf))) {
201 len = kfifo_in(&outbuf, buf, count);
202 spin_unlock_irqrestore(&dcc_lock, irqflags);
203
204 /*
205 * We just push data to the output FIFO, so schedule the
206 * workqueue that will actually write that data to DCC.
207 * CPU hotplug is disabled in dcc_init so CPU0 cannot be
208 * offlined after the cpu online check.
209 */
210 if (cpu_online(0))
211 schedule_work_on(0, &dcc_pwork);
212
213 return len;
214 }
215
216 /*
217 * If we're already on core 0, and the FIFO is empty, then just
218 * write the data to DCC.
219 */
220 len = hvc_dcc_put_chars(vt, buf, count);
221 spin_unlock_irqrestore(&dcc_lock, irqflags);
222
223 return len;
224 }
225
226 /*
227 * Read characters directly from the DCC if we're on core 0 and the FIFO
228 * is empty, or read them from the FIFO if we're not.
229 */
hvc_dcc0_get_chars(u32 vt,u8 * buf,size_t count)230 static ssize_t hvc_dcc0_get_chars(u32 vt, u8 *buf, size_t count)
231 {
232 unsigned long irqflags;
233 ssize_t len;
234
235 if (!IS_ENABLED(CONFIG_HVC_DCC_SERIALIZE_SMP))
236 return hvc_dcc_get_chars(vt, buf, count);
237
238 spin_lock_irqsave(&dcc_lock, irqflags);
239
240 if (smp_processor_id() || (!kfifo_is_empty(&inbuf))) {
241 len = kfifo_out(&inbuf, buf, count);
242 spin_unlock_irqrestore(&dcc_lock, irqflags);
243
244 /*
245 * If the FIFO was empty, there may be characters in the DCC
246 * that we haven't read yet. Schedule a workqueue to fill
247 * the input FIFO, so that the next time this function is
248 * called, we'll have data. CPU hotplug is disabled in dcc_init
249 * so CPU0 cannot be offlined after the cpu online check.
250 */
251 if (!len && cpu_online(0))
252 schedule_work_on(0, &dcc_gwork);
253
254 return len;
255 }
256
257 /*
258 * If we're already on core 0, and the FIFO is empty, then just
259 * read the data from DCC.
260 */
261 len = hvc_dcc_get_chars(vt, buf, count);
262 spin_unlock_irqrestore(&dcc_lock, irqflags);
263
264 return len;
265 }
266
267 static const struct hv_ops hvc_dcc_get_put_ops = {
268 .get_chars = hvc_dcc0_get_chars,
269 .put_chars = hvc_dcc0_put_chars,
270 };
271
hvc_dcc_console_init(void)272 static int __init hvc_dcc_console_init(void)
273 {
274 int ret;
275
276 if (!enable || !hvc_dcc_check())
277 return -ENODEV;
278
279 /* Returns -1 if error */
280 ret = hvc_instantiate(0, 0, &hvc_dcc_get_put_ops);
281
282 return ret < 0 ? -ENODEV : 0;
283 }
284 console_initcall(hvc_dcc_console_init);
285
hvc_dcc_init(void)286 static int __init hvc_dcc_init(void)
287 {
288 struct hvc_struct *p;
289
290 if (!enable || !hvc_dcc_check())
291 return -ENODEV;
292
293 if (IS_ENABLED(CONFIG_HVC_DCC_SERIALIZE_SMP)) {
294 pr_warn("\n");
295 pr_warn("********************************************************************\n");
296 pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
297 pr_warn("** **\n");
298 pr_warn("** HVC_DCC_SERIALIZE_SMP SUPPORT HAS BEEN ENABLED IN THIS KERNEL **\n");
299 pr_warn("** **\n");
300 pr_warn("** This means that this is a DEBUG kernel and unsafe for **\n");
301 pr_warn("** production use and has important feature like CPU hotplug **\n");
302 pr_warn("** disabled. **\n");
303 pr_warn("** **\n");
304 pr_warn("** If you see this message and you are not debugging the **\n");
305 pr_warn("** kernel, report this immediately to your vendor! **\n");
306 pr_warn("** **\n");
307 pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
308 pr_warn("********************************************************************\n");
309
310 cpu_hotplug_disable();
311 }
312
313 p = hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128);
314
315 return PTR_ERR_OR_ZERO(p);
316 }
317 device_initcall(hvc_dcc_init);
318