1- /* $OpenBSD: ns8250.c,v 1.28 2020/06/21 20:36:07 pd Exp $ */
1+ /* $OpenBSD: ns8250.c,v 1.29 2020/06/28 16:52:45 pd Exp $ */
22/*
33 * Copyright (c) 2016 Mike Larkin <mlarkin@openbsd.org>
44 *
3737extern char * __progname ;
3838struct ns8250_dev com1_dev ;
3939
40+ /* Flags to distinguish calling threads to com_rcv */
41+ #define NS8250_DEV_THREAD 0
42+ #define NS8250_CPU_THREAD 1
43+
44+ static struct vm_dev_pipe dev_pipe ;
45+
4046static void com_rcv_event (int , short , void * );
41- static void com_rcv (struct ns8250_dev * , uint32_t , uint32_t );
47+ static void com_rcv (struct ns8250_dev * , uint32_t , uint32_t , int );
48+
49+ /*
50+ * ns8250_pipe_dispatch
51+ *
52+ * Reads a message off the pipe, expecting a reguest to reset events after a
53+ * zero-byte read from the com device.
54+ */
55+ static void
56+ ns8250_pipe_dispatch (int fd , short event , void * arg )
57+ {
58+ enum pipe_msg_type msg ;
59+
60+ msg = vm_pipe_recv (& dev_pipe );
61+ switch (msg ) {
62+ case NS8250_ZERO_READ :
63+ log_debug ("%s: resetting events after zero byte read" , __func__ );
64+ event_del (& com1_dev .event );
65+ event_add (& com1_dev .wake , NULL );
66+ break ;
67+ case NS8250_RATELIMIT :
68+ evtimer_add (& com1_dev .rate , & com1_dev .rate_tv );
69+ break ;
70+ default :
71+ fatalx ("%s: unexpected pipe message %d" , __func__ , msg );
72+ }
73+ }
4274
4375/*
4476 * ratelimit
@@ -75,6 +107,7 @@ ns8250_init(int fd, uint32_t vmid)
75107 errno = ret ;
76108 fatal ("could not initialize com1 mutex" );
77109 }
110+
78111 com1_dev .fd = fd ;
79112 com1_dev .irq = 4 ;
80113 com1_dev .portid = NS8250_COM1 ;
@@ -115,6 +148,9 @@ ns8250_init(int fd, uint32_t vmid)
115148 timerclear (& com1_dev .rate_tv );
116149 com1_dev .rate_tv .tv_usec = 10000 ;
117150 evtimer_set (& com1_dev .rate , ratelimit , NULL );
151+
152+ vm_pipe_init (& dev_pipe , ns8250_pipe_dispatch );
153+ event_add (& dev_pipe .read_ev , NULL );
118154}
119155
120156static void
@@ -137,7 +173,7 @@ com_rcv_event(int fd, short kind, void *arg)
137173 if (com1_dev .regs .lsr & LSR_RXRDY )
138174 com1_dev .rcv_pending = 1 ;
139175 else
140- com_rcv (& com1_dev , (uintptr_t )arg , 0 );
176+ com_rcv (& com1_dev , (uintptr_t )arg , 0 , NS8250_DEV_THREAD );
141177 }
142178
143179 /* If pending interrupt, inject */
@@ -181,7 +217,7 @@ com_rcv_handle_break(struct ns8250_dev *com, uint8_t cmd)
181217 * Must be called with the mutex of the com device acquired
182218 */
183219static void
184- com_rcv (struct ns8250_dev * com , uint32_t vm_id , uint32_t vcpu_id )
220+ com_rcv (struct ns8250_dev * com , uint32_t vm_id , uint32_t vcpu_id , int thread )
185221{
186222 char buf [2 ];
187223 ssize_t sz ;
@@ -201,8 +237,13 @@ com_rcv(struct ns8250_dev *com, uint32_t vm_id, uint32_t vcpu_id)
201237 if (errno != EAGAIN )
202238 log_warn ("unexpected read error on com device" );
203239 } else if (sz == 0 ) {
204- event_del (& com -> event );
205- event_add (& com -> wake , NULL );
240+ if (thread == NS8250_DEV_THREAD ) {
241+ event_del (& com -> event );
242+ event_add (& com -> wake , NULL );
243+ } else {
244+ /* Called by vcpu thread, use pipe for event changes */
245+ vm_pipe_send (& dev_pipe , NS8250_ZERO_READ );
246+ }
206247 return ;
207248 } else if (sz != 1 && sz != 2 )
208249 log_warnx ("unexpected read return value %zd on com device" , sz );
@@ -258,8 +299,7 @@ vcpu_process_com_data(struct vm_exit *vei, uint32_t vm_id, uint32_t vcpu_id)
258299 /* Limit output rate if needed */
259300 if (com1_dev .pause_ct > 0 &&
260301 com1_dev .byte_out % com1_dev .pause_ct == 0 ) {
261- evtimer_add (& com1_dev .rate ,
262- & com1_dev .rate_tv );
302+ vm_pipe_send (& dev_pipe , NS8250_RATELIMIT );
263303 } else {
264304 /* Set TXRDY and clear "no pending interrupt" */
265305 com1_dev .regs .iir |= IIR_TXRDY ;
@@ -300,7 +340,7 @@ vcpu_process_com_data(struct vm_exit *vei, uint32_t vm_id, uint32_t vcpu_id)
300340 com1_dev .regs .iir = 0x1 ;
301341
302342 if (com1_dev .rcv_pending )
303- com_rcv (& com1_dev , vm_id , vcpu_id );
343+ com_rcv (& com1_dev , vm_id , vcpu_id , NS8250_CPU_THREAD );
304344 }
305345
306346 /* If pending interrupt, make sure it gets injected */
0 commit comments