Re: vmd(8): simplify vcpu logic, removing uart & net reads

2021-07-16 Thread Dave Voutila


Mike Larkin writes:

> On Sun, Jul 11, 2021 at 08:10:42AM -0400, Dave Voutila wrote:
>>
>> Ping...looking for OK. Would like to get this committed this week.
>>
>
> Sorry this took so long. ok mlarkin.
>
> Thanks to the numerous testers who ran with this for the past few
> weeks.
>

Committed. Thanks again, testers!

-dv



Re: vmd(8): simplify vcpu logic, removing uart & net reads

2021-07-15 Thread Mike Larkin
On Sun, Jul 11, 2021 at 08:10:42AM -0400, Dave Voutila wrote:
>
> Ping...looking for OK. Would like to get this committed this week.
>

Sorry this took so long. ok mlarkin.

Thanks to the numerous testers who ran with this for the past few
weeks.

> Dave Voutila writes:
>
> > Looking for an OK for this one now. Anyone?
> >
> > Dave Voutila  writes:
> >
> >> Dave Voutila writes:
> >>
> >>> Looking for some broader testing of the following diff. It cleans up
> >>> some complicated logic predominantly left over from the early days of
> >>> vmd prior to its having a dedicated device thread.
> >>
> >> Still looking for tester feedback. I've been running this diff while
> >> hosting multiple guests continously (OpenBSD-current, Alpine 3.14,
> >> Debian 10.10, Ubuntu 20.04) with no issues.
> >>
> >> I know a few folks have told me they've applied the diff and have not
> >> seen issues.
> >
> > I've had positive reports from 4 people. Thanks everyone that tested and
> > provided feedback!
> >
> >>
> >> I'll prod for OK next week, so if you've tested the diff please let me
> >> know!
> >
> > OK to commit?
> >
> >>
> >>>
> >>> In summary, this diff:
> >>>
> >>> - Removes vionet "rx pending" state handling and removes the code path
> >>>   for the vcpu thread to possibly take control of the virtio net device
> >>>   and attempt a read of the underlying tap(4). (virtio.{c,h}, vm.c)
> >>>
> >>> - Removes ns8250 "rcv pending" state handling and removes the code path
> >>>   for the vcpu thread to read the pty via com_rcv(). (ns8250.{c,h})
> >>>
> >>> In both of the above cases, the event handling thread will be notified
> >>> of readable data and deal with it.
> >>>
> >>> Why remove them? The logic is overly complicated and hard to reason
> >>> about for zero gain. (This diff results in no intended functional
> >>> change.) Plus, some of the above logic I helped add to deal with the
> >>> race conditions and state corruption over a year ago. The logic was
> >>> needed once upon a time, but shouldn't be needed at present.
> >>>
> >>> I've had positive testing feedback from abieber@ so far with at least
> >>> the ns8250/uart diff, but want to cast a broader net here with both
> >>> before either part is committed. I debated splitting these up, but
> >>> they're thematically related.
> >>>
> >>> -dv
> >>>
> >>> Index: virtio.c
> >>> ===
> >>> RCS file: /cvs/src/usr.sbin/vmd/virtio.c,v
> >>> retrieving revision 1.91
> >>> diff -u -p -r1.91 virtio.c
> >>> --- virtio.c  21 Jun 2021 02:38:18 -  1.91
> >>> +++ virtio.c  23 Jun 2021 11:28:03 -
> >>> @@ -1254,12 +1254,12 @@ static int
> >>>  vionet_rx(struct vionet_dev *dev)
> >>>  {
> >>>   char buf[PAGE_SIZE];
> >>> - int hasdata, num_enq = 0, spc = 0;
> >>> + int num_enq = 0, spc = 0;
> >>>   struct ether_header *eh;
> >>>   ssize_t sz;
> >>>
> >>>   do {
> >>> - sz = read(dev->fd, buf, sizeof buf);
> >>> + sz = read(dev->fd, buf, sizeof(buf));
> >>>   if (sz == -1) {
> >>>   /*
> >>>* If we get EAGAIN, No data is currently available.
> >>> @@ -1270,21 +1270,17 @@ vionet_rx(struct vionet_dev *dev)
> >>>   "device");
> >>>   } else if (sz > 0) {
> >>>   eh = (struct ether_header *)buf;
> >>> - if (!dev->lockedmac || sz < ETHER_HDR_LEN ||
> >>> + if (!dev->lockedmac ||
> >>>   ETHER_IS_MULTICAST(eh->ether_dhost) ||
> >>>   memcmp(eh->ether_dhost, dev->mac,
> >>>   sizeof(eh->ether_dhost)) == 0)
> >>>   num_enq += vionet_enq_rx(dev, buf, sz, &spc);
> >>>   } else if (sz == 0) {
> >>>   log_debug("process_rx: no data");
> >>> - hasdata = 0;
> >>>   break;
> >>>   }
> >>> + } while (spc > 0 && sz > 0);
> >>>
> >>> - hasdata = fd_hasdata(dev->fd);
> >>> - } while (spc && hasdata);
> >>> -
> >>> - dev->rx_pending = hasdata;
> >>>   return (num_enq);
> >>>  }
> >>>
> >>> @@ -1301,16 +1297,6 @@ vionet_rx_event(int fd, short kind, void
> >>>
> >>>   mutex_lock(&dev->mutex);
> >>>
> >>> - /*
> >>> -  * We already have other data pending to be received. The data that
> >>> -  * has become available now will be enqueued to the vionet_dev
> >>> -  * later.
> >>> -  */
> >>> - if (dev->rx_pending) {
> >>> - mutex_unlock(&dev->mutex);
> >>> - return;
> >>> - }
> >>> -
> >>>   if (vionet_rx(dev) > 0) {
> >>>   /* XXX: vcpu_id */
> >>>   vcpu_assert_pic_irq(dev->vm_id, 0, dev->irq);
> >>> @@ -1320,40 +1306,6 @@ vionet_rx_event(int fd, short kind, void
> >>>  }
> >>>
> >>>  /*
> >>> - * vionet_process_rx
> >>> - *
> >>> - * Processes any remaining pending receivable data for a vionet device.
> >>> - * Called on VCPU exit. Although we poll on the tap file descriptor of
> >>> - * a vionet_

Re: vmd(8): simplify vcpu logic, removing uart & net reads

2021-07-11 Thread Dave Voutila


Ping...looking for OK. Would like to get this committed this week.

Dave Voutila writes:

> Looking for an OK for this one now. Anyone?
>
> Dave Voutila  writes:
>
>> Dave Voutila writes:
>>
>>> Looking for some broader testing of the following diff. It cleans up
>>> some complicated logic predominantly left over from the early days of
>>> vmd prior to its having a dedicated device thread.
>>
>> Still looking for tester feedback. I've been running this diff while
>> hosting multiple guests continously (OpenBSD-current, Alpine 3.14,
>> Debian 10.10, Ubuntu 20.04) with no issues.
>>
>> I know a few folks have told me they've applied the diff and have not
>> seen issues.
>
> I've had positive reports from 4 people. Thanks everyone that tested and
> provided feedback!
>
>>
>> I'll prod for OK next week, so if you've tested the diff please let me
>> know!
>
> OK to commit?
>
>>
>>>
>>> In summary, this diff:
>>>
>>> - Removes vionet "rx pending" state handling and removes the code path
>>>   for the vcpu thread to possibly take control of the virtio net device
>>>   and attempt a read of the underlying tap(4). (virtio.{c,h}, vm.c)
>>>
>>> - Removes ns8250 "rcv pending" state handling and removes the code path
>>>   for the vcpu thread to read the pty via com_rcv(). (ns8250.{c,h})
>>>
>>> In both of the above cases, the event handling thread will be notified
>>> of readable data and deal with it.
>>>
>>> Why remove them? The logic is overly complicated and hard to reason
>>> about for zero gain. (This diff results in no intended functional
>>> change.) Plus, some of the above logic I helped add to deal with the
>>> race conditions and state corruption over a year ago. The logic was
>>> needed once upon a time, but shouldn't be needed at present.
>>>
>>> I've had positive testing feedback from abieber@ so far with at least
>>> the ns8250/uart diff, but want to cast a broader net here with both
>>> before either part is committed. I debated splitting these up, but
>>> they're thematically related.
>>>
>>> -dv
>>>
>>> Index: virtio.c
>>> ===
>>> RCS file: /cvs/src/usr.sbin/vmd/virtio.c,v
>>> retrieving revision 1.91
>>> diff -u -p -r1.91 virtio.c
>>> --- virtio.c21 Jun 2021 02:38:18 -  1.91
>>> +++ virtio.c23 Jun 2021 11:28:03 -
>>> @@ -1254,12 +1254,12 @@ static int
>>>  vionet_rx(struct vionet_dev *dev)
>>>  {
>>> char buf[PAGE_SIZE];
>>> -   int hasdata, num_enq = 0, spc = 0;
>>> +   int num_enq = 0, spc = 0;
>>> struct ether_header *eh;
>>> ssize_t sz;
>>>
>>> do {
>>> -   sz = read(dev->fd, buf, sizeof buf);
>>> +   sz = read(dev->fd, buf, sizeof(buf));
>>> if (sz == -1) {
>>> /*
>>>  * If we get EAGAIN, No data is currently available.
>>> @@ -1270,21 +1270,17 @@ vionet_rx(struct vionet_dev *dev)
>>> "device");
>>> } else if (sz > 0) {
>>> eh = (struct ether_header *)buf;
>>> -   if (!dev->lockedmac || sz < ETHER_HDR_LEN ||
>>> +   if (!dev->lockedmac ||
>>> ETHER_IS_MULTICAST(eh->ether_dhost) ||
>>> memcmp(eh->ether_dhost, dev->mac,
>>> sizeof(eh->ether_dhost)) == 0)
>>> num_enq += vionet_enq_rx(dev, buf, sz, &spc);
>>> } else if (sz == 0) {
>>> log_debug("process_rx: no data");
>>> -   hasdata = 0;
>>> break;
>>> }
>>> +   } while (spc > 0 && sz > 0);
>>>
>>> -   hasdata = fd_hasdata(dev->fd);
>>> -   } while (spc && hasdata);
>>> -
>>> -   dev->rx_pending = hasdata;
>>> return (num_enq);
>>>  }
>>>
>>> @@ -1301,16 +1297,6 @@ vionet_rx_event(int fd, short kind, void
>>>
>>> mutex_lock(&dev->mutex);
>>>
>>> -   /*
>>> -* We already have other data pending to be received. The data that
>>> -* has become available now will be enqueued to the vionet_dev
>>> -* later.
>>> -*/
>>> -   if (dev->rx_pending) {
>>> -   mutex_unlock(&dev->mutex);
>>> -   return;
>>> -   }
>>> -
>>> if (vionet_rx(dev) > 0) {
>>> /* XXX: vcpu_id */
>>> vcpu_assert_pic_irq(dev->vm_id, 0, dev->irq);
>>> @@ -1320,40 +1306,6 @@ vionet_rx_event(int fd, short kind, void
>>>  }
>>>
>>>  /*
>>> - * vionet_process_rx
>>> - *
>>> - * Processes any remaining pending receivable data for a vionet device.
>>> - * Called on VCPU exit. Although we poll on the tap file descriptor of
>>> - * a vionet_dev in a separate thread, this function still needs to be
>>> - * called on VCPU exit: it can happen that not all data fits into the
>>> - * receive queue of the vionet_dev immediately. So any outstanding data
>>> - * is handled here.
>>> - *
>>> - * Parameters:
>>> - *  vm_id: VM ID of the VM for which to process vionet events
>>> - */
>>

Re: vmd(8): simplify vcpu logic, removing uart & net reads

2021-07-06 Thread Dave Voutila


Looking for an OK for this one now. Anyone?

Dave Voutila  writes:

> Dave Voutila writes:
>
>> Looking for some broader testing of the following diff. It cleans up
>> some complicated logic predominantly left over from the early days of
>> vmd prior to its having a dedicated device thread.
>
> Still looking for tester feedback. I've been running this diff while
> hosting multiple guests continously (OpenBSD-current, Alpine 3.14,
> Debian 10.10, Ubuntu 20.04) with no issues.
>
> I know a few folks have told me they've applied the diff and have not
> seen issues.

I've had positive reports from 4 people. Thanks everyone that tested and
provided feedback!

>
> I'll prod for OK next week, so if you've tested the diff please let me
> know!

OK to commit?

>
>>
>> In summary, this diff:
>>
>> - Removes vionet "rx pending" state handling and removes the code path
>>   for the vcpu thread to possibly take control of the virtio net device
>>   and attempt a read of the underlying tap(4). (virtio.{c,h}, vm.c)
>>
>> - Removes ns8250 "rcv pending" state handling and removes the code path
>>   for the vcpu thread to read the pty via com_rcv(). (ns8250.{c,h})
>>
>> In both of the above cases, the event handling thread will be notified
>> of readable data and deal with it.
>>
>> Why remove them? The logic is overly complicated and hard to reason
>> about for zero gain. (This diff results in no intended functional
>> change.) Plus, some of the above logic I helped add to deal with the
>> race conditions and state corruption over a year ago. The logic was
>> needed once upon a time, but shouldn't be needed at present.
>>
>> I've had positive testing feedback from abieber@ so far with at least
>> the ns8250/uart diff, but want to cast a broader net here with both
>> before either part is committed. I debated splitting these up, but
>> they're thematically related.
>>
>> -dv
>>
>> Index: virtio.c
>> ===
>> RCS file: /cvs/src/usr.sbin/vmd/virtio.c,v
>> retrieving revision 1.91
>> diff -u -p -r1.91 virtio.c
>> --- virtio.c 21 Jun 2021 02:38:18 -  1.91
>> +++ virtio.c 23 Jun 2021 11:28:03 -
>> @@ -1254,12 +1254,12 @@ static int
>>  vionet_rx(struct vionet_dev *dev)
>>  {
>>  char buf[PAGE_SIZE];
>> -int hasdata, num_enq = 0, spc = 0;
>> +int num_enq = 0, spc = 0;
>>  struct ether_header *eh;
>>  ssize_t sz;
>>
>>  do {
>> -sz = read(dev->fd, buf, sizeof buf);
>> +sz = read(dev->fd, buf, sizeof(buf));
>>  if (sz == -1) {
>>  /*
>>   * If we get EAGAIN, No data is currently available.
>> @@ -1270,21 +1270,17 @@ vionet_rx(struct vionet_dev *dev)
>>  "device");
>>  } else if (sz > 0) {
>>  eh = (struct ether_header *)buf;
>> -if (!dev->lockedmac || sz < ETHER_HDR_LEN ||
>> +if (!dev->lockedmac ||
>>  ETHER_IS_MULTICAST(eh->ether_dhost) ||
>>  memcmp(eh->ether_dhost, dev->mac,
>>  sizeof(eh->ether_dhost)) == 0)
>>  num_enq += vionet_enq_rx(dev, buf, sz, &spc);
>>  } else if (sz == 0) {
>>  log_debug("process_rx: no data");
>> -hasdata = 0;
>>  break;
>>  }
>> +} while (spc > 0 && sz > 0);
>>
>> -hasdata = fd_hasdata(dev->fd);
>> -} while (spc && hasdata);
>> -
>> -dev->rx_pending = hasdata;
>>  return (num_enq);
>>  }
>>
>> @@ -1301,16 +1297,6 @@ vionet_rx_event(int fd, short kind, void
>>
>>  mutex_lock(&dev->mutex);
>>
>> -/*
>> - * We already have other data pending to be received. The data that
>> - * has become available now will be enqueued to the vionet_dev
>> - * later.
>> - */
>> -if (dev->rx_pending) {
>> -mutex_unlock(&dev->mutex);
>> -return;
>> -}
>> -
>>  if (vionet_rx(dev) > 0) {
>>  /* XXX: vcpu_id */
>>  vcpu_assert_pic_irq(dev->vm_id, 0, dev->irq);
>> @@ -1320,40 +1306,6 @@ vionet_rx_event(int fd, short kind, void
>>  }
>>
>>  /*
>> - * vionet_process_rx
>> - *
>> - * Processes any remaining pending receivable data for a vionet device.
>> - * Called on VCPU exit. Although we poll on the tap file descriptor of
>> - * a vionet_dev in a separate thread, this function still needs to be
>> - * called on VCPU exit: it can happen that not all data fits into the
>> - * receive queue of the vionet_dev immediately. So any outstanding data
>> - * is handled here.
>> - *
>> - * Parameters:
>> - *  vm_id: VM ID of the VM for which to process vionet events
>> - */
>> -void
>> -vionet_process_rx(uint32_t vm_id)
>> -{
>> -int i;
>> -
>> -for (i = 0 ; i < nr_vionet; i++) {
>> -mutex_lock(&vionet[i].mutex);
>> -if (!vionet[i].rx_adde

Re: vmd(8): simplify vcpu logic, removing uart & net reads

2021-07-05 Thread Mischa
Hi Dave,

> On 3 Jul 2021, at 19:08, Matthias Schmidt  wrote:
> 
> Hi Dave,
> 
> * Dave Voutila wrote:
>> Looking for some broader testing of the following diff. It cleans up
>> some complicated logic predominantly left over from the early days of
>> vmd prior to its having a dedicated device thread.
>> 
>> In summary, this diff:
>> 
>> - Removes vionet "rx pending" state handling and removes the code path
>>  for the vcpu thread to possibly take control of the virtio net device
>>  and attempt a read of the underlying tap(4). (virtio.{c,h}, vm.c)
>> 
>> - Removes ns8250 "rcv pending" state handling and removes the code path
>>  for the vcpu thread to read the pty via com_rcv(). (ns8250.{c,h})
>> 
>> In both of the above cases, the event handling thread will be notified
>> of readable data and deal with it.
>> 
>> Why remove them? The logic is overly complicated and hard to reason
>> about for zero gain. (This diff results in no intended functional
>> change.) Plus, some of the above logic I helped add to deal with the
>> race conditions and state corruption over a year ago. The logic was
>> needed once upon a time, but shouldn't be needed at present.
>> 
>> I've had positive testing feedback from abieber@ so far with at least
>> the ns8250/uart diff, but want to cast a broader net here with both
>> before either part is committed. I debated splitting these up, but
>> they're thematically related.
> 
> I have the diff running since one week on -current with stable/current
> and an Archlinux guest and have noticed no regression so far.
> 
> Cheers
> 
>   Matthias

No issues on my side as well.

Mischa



Re: vmd(8): simplify vcpu logic, removing uart & net reads

2021-07-03 Thread Matthias Schmidt
Hi Dave,

* Dave Voutila wrote:
> Looking for some broader testing of the following diff. It cleans up
> some complicated logic predominantly left over from the early days of
> vmd prior to its having a dedicated device thread.
> 
> In summary, this diff:
> 
> - Removes vionet "rx pending" state handling and removes the code path
>   for the vcpu thread to possibly take control of the virtio net device
>   and attempt a read of the underlying tap(4). (virtio.{c,h}, vm.c)
> 
> - Removes ns8250 "rcv pending" state handling and removes the code path
>   for the vcpu thread to read the pty via com_rcv(). (ns8250.{c,h})
> 
> In both of the above cases, the event handling thread will be notified
> of readable data and deal with it.
> 
> Why remove them? The logic is overly complicated and hard to reason
> about for zero gain. (This diff results in no intended functional
> change.) Plus, some of the above logic I helped add to deal with the
> race conditions and state corruption over a year ago. The logic was
> needed once upon a time, but shouldn't be needed at present.
> 
> I've had positive testing feedback from abieber@ so far with at least
> the ns8250/uart diff, but want to cast a broader net here with both
> before either part is committed. I debated splitting these up, but
> they're thematically related.

I have the diff running since one week on -current with stable/current
and an Archlinux guest and have noticed no regression so far.

Cheers

Matthias



Re: vmd(8): simplify vcpu logic, removing uart & net reads

2021-07-02 Thread Dave Voutila


Dave Voutila writes:

> Looking for some broader testing of the following diff. It cleans up
> some complicated logic predominantly left over from the early days of
> vmd prior to its having a dedicated device thread.

Still looking for tester feedback. I've been running this diff while
hosting multiple guests continously (OpenBSD-current, Alpine 3.14,
Debian 10.10, Ubuntu 20.04) with no issues.

I know a few folks have told me they've applied the diff and have not
seen issues.

I'll prod for OK next week, so if you've tested the diff please let me
know!

>
> In summary, this diff:
>
> - Removes vionet "rx pending" state handling and removes the code path
>   for the vcpu thread to possibly take control of the virtio net device
>   and attempt a read of the underlying tap(4). (virtio.{c,h}, vm.c)
>
> - Removes ns8250 "rcv pending" state handling and removes the code path
>   for the vcpu thread to read the pty via com_rcv(). (ns8250.{c,h})
>
> In both of the above cases, the event handling thread will be notified
> of readable data and deal with it.
>
> Why remove them? The logic is overly complicated and hard to reason
> about for zero gain. (This diff results in no intended functional
> change.) Plus, some of the above logic I helped add to deal with the
> race conditions and state corruption over a year ago. The logic was
> needed once upon a time, but shouldn't be needed at present.
>
> I've had positive testing feedback from abieber@ so far with at least
> the ns8250/uart diff, but want to cast a broader net here with both
> before either part is committed. I debated splitting these up, but
> they're thematically related.
>
> -dv
>
> Index: virtio.c
> ===
> RCS file: /cvs/src/usr.sbin/vmd/virtio.c,v
> retrieving revision 1.91
> diff -u -p -r1.91 virtio.c
> --- virtio.c  21 Jun 2021 02:38:18 -  1.91
> +++ virtio.c  23 Jun 2021 11:28:03 -
> @@ -1254,12 +1254,12 @@ static int
>  vionet_rx(struct vionet_dev *dev)
>  {
>   char buf[PAGE_SIZE];
> - int hasdata, num_enq = 0, spc = 0;
> + int num_enq = 0, spc = 0;
>   struct ether_header *eh;
>   ssize_t sz;
>
>   do {
> - sz = read(dev->fd, buf, sizeof buf);
> + sz = read(dev->fd, buf, sizeof(buf));
>   if (sz == -1) {
>   /*
>* If we get EAGAIN, No data is currently available.
> @@ -1270,21 +1270,17 @@ vionet_rx(struct vionet_dev *dev)
>   "device");
>   } else if (sz > 0) {
>   eh = (struct ether_header *)buf;
> - if (!dev->lockedmac || sz < ETHER_HDR_LEN ||
> + if (!dev->lockedmac ||
>   ETHER_IS_MULTICAST(eh->ether_dhost) ||
>   memcmp(eh->ether_dhost, dev->mac,
>   sizeof(eh->ether_dhost)) == 0)
>   num_enq += vionet_enq_rx(dev, buf, sz, &spc);
>   } else if (sz == 0) {
>   log_debug("process_rx: no data");
> - hasdata = 0;
>   break;
>   }
> + } while (spc > 0 && sz > 0);
>
> - hasdata = fd_hasdata(dev->fd);
> - } while (spc && hasdata);
> -
> - dev->rx_pending = hasdata;
>   return (num_enq);
>  }
>
> @@ -1301,16 +1297,6 @@ vionet_rx_event(int fd, short kind, void
>
>   mutex_lock(&dev->mutex);
>
> - /*
> -  * We already have other data pending to be received. The data that
> -  * has become available now will be enqueued to the vionet_dev
> -  * later.
> -  */
> - if (dev->rx_pending) {
> - mutex_unlock(&dev->mutex);
> - return;
> - }
> -
>   if (vionet_rx(dev) > 0) {
>   /* XXX: vcpu_id */
>   vcpu_assert_pic_irq(dev->vm_id, 0, dev->irq);
> @@ -1320,40 +1306,6 @@ vionet_rx_event(int fd, short kind, void
>  }
>
>  /*
> - * vionet_process_rx
> - *
> - * Processes any remaining pending receivable data for a vionet device.
> - * Called on VCPU exit. Although we poll on the tap file descriptor of
> - * a vionet_dev in a separate thread, this function still needs to be
> - * called on VCPU exit: it can happen that not all data fits into the
> - * receive queue of the vionet_dev immediately. So any outstanding data
> - * is handled here.
> - *
> - * Parameters:
> - *  vm_id: VM ID of the VM for which to process vionet events
> - */
> -void
> -vionet_process_rx(uint32_t vm_id)
> -{
> - int i;
> -
> - for (i = 0 ; i < nr_vionet; i++) {
> - mutex_lock(&vionet[i].mutex);
> - if (!vionet[i].rx_added) {
> - mutex_unlock(&vionet[i].mutex);
> - continue;
> - }
> -
> - if (vionet[i].rx_pending) {
> - if (vionet_rx(&vionet[i])) {
> - vcpu_assert_pic_irq(

vmd(8): simplify vcpu logic, removing uart & net reads

2021-06-27 Thread Dave Voutila
Looking for some broader testing of the following diff. It cleans up
some complicated logic predominantly left over from the early days of
vmd prior to its having a dedicated device thread.

In summary, this diff:

- Removes vionet "rx pending" state handling and removes the code path
  for the vcpu thread to possibly take control of the virtio net device
  and attempt a read of the underlying tap(4). (virtio.{c,h}, vm.c)

- Removes ns8250 "rcv pending" state handling and removes the code path
  for the vcpu thread to read the pty via com_rcv(). (ns8250.{c,h})

In both of the above cases, the event handling thread will be notified
of readable data and deal with it.

Why remove them? The logic is overly complicated and hard to reason
about for zero gain. (This diff results in no intended functional
change.) Plus, some of the above logic I helped add to deal with the
race conditions and state corruption over a year ago. The logic was
needed once upon a time, but shouldn't be needed at present.

I've had positive testing feedback from abieber@ so far with at least
the ns8250/uart diff, but want to cast a broader net here with both
before either part is committed. I debated splitting these up, but
they're thematically related.

-dv

Index: virtio.c
===
RCS file: /cvs/src/usr.sbin/vmd/virtio.c,v
retrieving revision 1.91
diff -u -p -r1.91 virtio.c
--- virtio.c21 Jun 2021 02:38:18 -  1.91
+++ virtio.c23 Jun 2021 11:28:03 -
@@ -1254,12 +1254,12 @@ static int
 vionet_rx(struct vionet_dev *dev)
 {
char buf[PAGE_SIZE];
-   int hasdata, num_enq = 0, spc = 0;
+   int num_enq = 0, spc = 0;
struct ether_header *eh;
ssize_t sz;

do {
-   sz = read(dev->fd, buf, sizeof buf);
+   sz = read(dev->fd, buf, sizeof(buf));
if (sz == -1) {
/*
 * If we get EAGAIN, No data is currently available.
@@ -1270,21 +1270,17 @@ vionet_rx(struct vionet_dev *dev)
"device");
} else if (sz > 0) {
eh = (struct ether_header *)buf;
-   if (!dev->lockedmac || sz < ETHER_HDR_LEN ||
+   if (!dev->lockedmac ||
ETHER_IS_MULTICAST(eh->ether_dhost) ||
memcmp(eh->ether_dhost, dev->mac,
sizeof(eh->ether_dhost)) == 0)
num_enq += vionet_enq_rx(dev, buf, sz, &spc);
} else if (sz == 0) {
log_debug("process_rx: no data");
-   hasdata = 0;
break;
}
+   } while (spc > 0 && sz > 0);

-   hasdata = fd_hasdata(dev->fd);
-   } while (spc && hasdata);
-
-   dev->rx_pending = hasdata;
return (num_enq);
 }

@@ -1301,16 +1297,6 @@ vionet_rx_event(int fd, short kind, void

mutex_lock(&dev->mutex);

-   /*
-* We already have other data pending to be received. The data that
-* has become available now will be enqueued to the vionet_dev
-* later.
-*/
-   if (dev->rx_pending) {
-   mutex_unlock(&dev->mutex);
-   return;
-   }
-
if (vionet_rx(dev) > 0) {
/* XXX: vcpu_id */
vcpu_assert_pic_irq(dev->vm_id, 0, dev->irq);
@@ -1320,40 +1306,6 @@ vionet_rx_event(int fd, short kind, void
 }

 /*
- * vionet_process_rx
- *
- * Processes any remaining pending receivable data for a vionet device.
- * Called on VCPU exit. Although we poll on the tap file descriptor of
- * a vionet_dev in a separate thread, this function still needs to be
- * called on VCPU exit: it can happen that not all data fits into the
- * receive queue of the vionet_dev immediately. So any outstanding data
- * is handled here.
- *
- * Parameters:
- *  vm_id: VM ID of the VM for which to process vionet events
- */
-void
-vionet_process_rx(uint32_t vm_id)
-{
-   int i;
-
-   for (i = 0 ; i < nr_vionet; i++) {
-   mutex_lock(&vionet[i].mutex);
-   if (!vionet[i].rx_added) {
-   mutex_unlock(&vionet[i].mutex);
-   continue;
-   }
-
-   if (vionet[i].rx_pending) {
-   if (vionet_rx(&vionet[i])) {
-   vcpu_assert_pic_irq(vm_id, 0, vionet[i].irq);
-   }
-   }
-   mutex_unlock(&vionet[i].mutex);
-   }
-}
-
-/*
  * Must be called with dev->mutex acquired.
  */
 void
@@ -1383,7 +1335,6 @@ vionet_notify_rx(struct vionet_dev *dev)
/* Compute offset into avail ring */
avail = (struct vring_avail *)(vr + dev->vq[RXQ].vq_availoffset);

-   dev->rx_added = 1;
dev->vq[RXQ].notified_avail = avail->idx - 1;

free(vr);
@@ -1937,7 +18