xref: /kvmtool/hw/serial.c (revision 04d76d8673ae0a1ebf4f0b917dc843079d0237d3)
1 #include "kvm/8250-serial.h"
2 
3 #include "kvm/read-write.h"
4 #include "kvm/ioport.h"
5 #include "kvm/util.h"
6 #include "kvm/term.h"
7 #include "kvm/kvm.h"
8 
9 #include <linux/serial_reg.h>
10 
11 #include <pthread.h>
12 
13 struct serial8250_device {
14 	pthread_mutex_t		mutex;
15 
16 	uint16_t		iobase;
17 	uint8_t			irq;
18 
19 	uint8_t			rbr;		/* receive buffer */
20 	uint8_t			dll;
21 	uint8_t			dlm;
22 	uint8_t			iir;
23 	uint8_t			ier;
24 	uint8_t			fcr;
25 	uint8_t			lcr;
26 	uint8_t			mcr;
27 	uint8_t			lsr;
28 	uint8_t			msr;
29 	uint8_t			scr;
30 };
31 
32 static struct serial8250_device devices[] = {
33 	/* ttyS0 */
34 	[0]	= {
35 		.mutex			= PTHREAD_MUTEX_INITIALIZER,
36 
37 		.iobase			= 0x3f8,
38 		.irq			= 4,
39 
40 		.iir			= UART_IIR_NO_INT,
41 		.lsr			= UART_LSR_TEMT | UART_LSR_THRE,
42 		.msr			= UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS,
43 		.mcr			= UART_MCR_OUT2,
44 	},
45 	/* ttyS1 */
46 	[1]	= {
47 		.mutex			= PTHREAD_MUTEX_INITIALIZER,
48 
49 		.iobase			= 0x2f8,
50 		.irq			= 3,
51 
52 		.iir			= UART_IIR_NO_INT,
53 	},
54 	/* ttyS2 */
55 	[2]	= {
56 		.mutex			= PTHREAD_MUTEX_INITIALIZER,
57 
58 		.iobase			= 0x3e8,
59 		.irq			= 4,
60 
61 		.iir			= UART_IIR_NO_INT,
62 	},
63 };
64 
65 #define SYSRQ_PENDING_NONE		0
66 #define SYSRQ_PENDING_BREAK		1
67 #define SYSRQ_PENDING_CMD		2
68 
69 static int sysrq_pending;
70 
71 static void serial8250__sysrq(struct kvm *self, struct serial8250_device *dev)
72 {
73 	switch (sysrq_pending) {
74 	case SYSRQ_PENDING_BREAK:
75 		dev->lsr	|= UART_LSR_DR | UART_LSR_BI;
76 
77 		sysrq_pending	= SYSRQ_PENDING_CMD;
78 		break;
79 	case SYSRQ_PENDING_CMD:
80 		dev->rbr	= 'p';
81 		dev->lsr	|= UART_LSR_DR;
82 
83 		sysrq_pending	= SYSRQ_PENDING_NONE;
84 		break;
85 	}
86 }
87 
88 static void serial8250__receive(struct kvm *self, struct serial8250_device *dev)
89 {
90 	int c;
91 
92 	if (dev->lsr & UART_LSR_DR)
93 		return;
94 
95 	if (sysrq_pending) {
96 		serial8250__sysrq(self, dev);
97 		return;
98 	}
99 
100 	if (!term_readable(CONSOLE_8250))
101 		return;
102 
103 	c		= term_getc(CONSOLE_8250);
104 
105 	if (c < 0)
106 		return;
107 
108 	dev->rbr	= c;
109 	dev->lsr	|= UART_LSR_DR;
110 }
111 
112 /*
113  * Interrupts are injected for ttyS0 only.
114  */
115 void serial8250__inject_interrupt(struct kvm *self)
116 {
117 	struct serial8250_device *dev = &devices[0];
118 
119 	if (pthread_mutex_lock(&dev->mutex) != 0)
120 		die("pthread_mutex_lock");
121 
122 	serial8250__receive(self, dev);
123 
124 	if (dev->ier & UART_IER_RDI && dev->lsr & UART_LSR_DR)
125 		dev->iir		= UART_IIR_RDI;
126 	else if (dev->ier & UART_IER_THRI)
127 		dev->iir		= UART_IIR_THRI;
128 	else
129 		dev->iir		= UART_IIR_NO_INT;
130 
131 	if (dev->iir != UART_IIR_NO_INT) {
132 		kvm__irq_line(self, dev->irq, 0);
133 		kvm__irq_line(self, dev->irq, 1);
134 	}
135 
136 	if (pthread_mutex_unlock(&dev->mutex) != 0)
137 		die("pthread_mutex_unlock");
138 }
139 
140 void serial8250__inject_sysrq(struct kvm *self)
141 {
142 	sysrq_pending	= SYSRQ_PENDING_BREAK;
143 }
144 
145 static struct serial8250_device *find_device(uint16_t port)
146 {
147 	unsigned int i;
148 
149 	for (i = 0; i < ARRAY_SIZE(devices); i++) {
150 		struct serial8250_device *dev = &devices[i];
151 
152 		if (dev->iobase == (port & ~0x7))
153 			return dev;
154 	}
155 	return NULL;
156 }
157 
158 static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
159 {
160 	struct serial8250_device *dev;
161 	uint16_t offset;
162 	bool ret = true;
163 
164 	dev		= find_device(port);
165 	if (!dev)
166 		return false;
167 
168 	if (pthread_mutex_lock(&dev->mutex) != 0)
169 		die("pthread_mutex_lock");
170 
171 	offset		= port - dev->iobase;
172 
173 	if (dev->lcr & UART_LCR_DLAB) {
174 		switch (offset) {
175 		case UART_DLL:
176 			dev->dll	= ioport__read8(data);
177 			break;
178 		case UART_DLM:
179 			dev->dlm	= ioport__read8(data);
180 			break;
181 		case UART_FCR:
182 			dev->fcr	= ioport__read8(data);
183 			break;
184 		case UART_LCR:
185 			dev->lcr	= ioport__read8(data);
186 			break;
187 		case UART_MCR:
188 			dev->mcr	= ioport__read8(data);
189 			break;
190 		case UART_LSR:
191 			/* Factory test */
192 			break;
193 		case UART_MSR:
194 			/* Not used */
195 			break;
196 		case UART_SCR:
197 			dev->scr	= ioport__read8(data);
198 			break;
199 		default:
200 			ret		= false;
201 			goto out_unlock;
202 		}
203 	} else {
204 		switch (offset) {
205 		case UART_TX: {
206 			char *addr = data;
207 
208 			if (!(dev->mcr & UART_MCR_LOOP))
209 				term_putc(CONSOLE_8250, addr, size * count);
210 
211 			dev->iir		= UART_IIR_NO_INT;
212 			break;
213 		}
214 		case UART_FCR:
215 			dev->fcr	= ioport__read8(data);
216 			break;
217 		case UART_IER:
218 			dev->ier	= ioport__read8(data) & 0x3f;
219 			break;
220 		case UART_LCR:
221 			dev->lcr	= ioport__read8(data);
222 			break;
223 		case UART_MCR:
224 			dev->mcr	= ioport__read8(data);
225 			break;
226 		case UART_LSR:
227 			/* Factory test */
228 			break;
229 		case UART_MSR:
230 			/* Not used */
231 			break;
232 		case UART_SCR:
233 			dev->scr	= ioport__read8(data);
234 			break;
235 		default:
236 			ret		= false;
237 			goto out_unlock;
238 		}
239 	}
240 
241 out_unlock:
242 	if (pthread_mutex_unlock(&dev->mutex) != 0)
243 		die("pthread_mutex_unlock");
244 
245 	return ret;
246 }
247 
248 static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
249 {
250 	struct serial8250_device *dev;
251 	uint16_t offset;
252 	bool ret = true;
253 
254 	dev		= find_device(port);
255 	if (!dev)
256 		return false;
257 
258 	if (pthread_mutex_lock(&dev->mutex) != 0)
259 		die("pthread_mutex_lock");
260 
261 	offset		= port - dev->iobase;
262 
263 	if (dev->lcr & UART_LCR_DLAB) {
264 		switch (offset) {
265 		case UART_DLL:
266 			ioport__write8(data, dev->dll);
267 			goto out_unlock;
268 
269 		case UART_DLM:
270 			ioport__write8(data, dev->dlm);
271 			goto out_unlock;
272 
273 		default:
274 			break;
275 		}
276 	} else {
277 		switch (offset) {
278 		case UART_RX:
279 			ioport__write8(data, dev->rbr);
280 			dev->lsr		&= ~UART_LSR_DR;
281 			dev->iir		= UART_IIR_NO_INT;
282 			goto out_unlock;
283 
284 		case UART_IER:
285 			ioport__write8(data, dev->ier);
286 			goto out_unlock;
287 
288 		default:
289 			break;
290 		}
291 	}
292 
293 	switch (offset) {
294 	case UART_IIR: {
295 		uint8_t iir = dev->iir;
296 
297 		if (dev->fcr & UART_FCR_ENABLE_FIFO)
298 			iir		|= 0xc0;
299 
300 		ioport__write8(data, iir);
301 		break;
302 	}
303 	case UART_LCR:
304 		ioport__write8(data, dev->lcr);
305 		break;
306 	case UART_MCR:
307 		ioport__write8(data, dev->mcr);
308 		break;
309 	case UART_LSR:
310 		ioport__write8(data, dev->lsr);
311 		dev->lsr		&= ~(UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI);
312 		break;
313 	case UART_MSR:
314 		ioport__write8(data, dev->msr);
315 		break;
316 	case UART_SCR:
317 		ioport__write8(data, dev->scr);
318 		break;
319 	default:
320 		ret		= false;
321 		goto out_unlock;
322 	}
323 out_unlock:
324 	if (pthread_mutex_unlock(&dev->mutex) != 0)
325 		die("pthread_mutex_unlock");
326 
327 	return ret;
328 }
329 
330 static struct ioport_operations serial8250_ops = {
331 	.io_in		= serial8250_in,
332 	.io_out		= serial8250_out,
333 };
334 
335 static void serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev)
336 {
337 	ioport__register(dev->iobase, &serial8250_ops, 8);
338 	kvm__irq_line(kvm, dev->irq, 0);
339 }
340 
341 void serial8250__init(struct kvm *kvm)
342 {
343 	unsigned int i;
344 
345 	for (i = 0; i < ARRAY_SIZE(devices); i++) {
346 		struct serial8250_device *dev = &devices[i];
347 
348 		serial8250__device_init(kvm, dev);
349 	}
350 }
351