kqueue_scan() should not return EWOULDBLOCK

2020-12-22 Thread Visa Hankala
This fixes a recent regression in kqueue_scan() where the function can
mistakenly return EWOULDBLOCK.

Currently, kqueue_scan() does one more scan attempt after a timeout.
Usually, this gives no new events and the function bails out through
the following code. Note that it clears `error'.

if (kq->kq_count == 0) {
/*
 * Successive loops are only necessary if there are more
 * ready events to gather, so they don't need to block.
 */
if ((tsp != NULL && !timespecisset(tsp)) ||
scan->kqs_nevent != 0) {
splx(s);
error = 0;
goto done;
}

However, there can be a last-minute event activation, in which case the
function processes the event queue. Unfortunately, the error variable
preserves its value EWOULDBLOCK/EAGAIN that gets returned to the caller.
kevent(2), or select(2) or poll(2), is not supposed to return this error.

The issue emerged in r1.146 of kern_event.c when the final copyout() was
moved outside kqueue_scan(). The copyout()'s return value used to
override the EWOULDBLOCK.

The following patch fixes the regression by clearing `error' at the
start of each scan round. The clearing could be done conditionally after
kqueue_sleep(). However, that does not seem as robust.

OK?

Index: kern/kern_event.c
===
RCS file: src/sys/kern/kern_event.c,v
retrieving revision 1.153
diff -u -p -r1.153 kern_event.c
--- kern/kern_event.c   20 Dec 2020 12:54:05 -  1.153
+++ kern/kern_event.c   23 Dec 2020 07:10:24 -
@@ -977,6 +977,8 @@ kqueue_scan(struct kqueue_scan_state *sc
 retry:
KASSERT(nkev == 0);
 
+   error = 0;
+
if (kq->kq_state & KQ_DYING) {
error = EBADF;
goto done;



Wake on LAN support for rge(4)

2020-12-22 Thread Kevin Lo
Hi,

This diff implements WoL support in rge(4).  I can wakeup the machine with WoL
after suspending it through `zzz` or powering off it through `halt -p`.

Index: share/man/man4/rge.4
===
RCS file: /cvs/src/share/man/man4/rge.4,v
retrieving revision 1.4
diff -u -p -u -p -r1.4 rge.4
--- share/man/man4/rge.412 Oct 2020 02:11:10 -  1.4
+++ share/man/man4/rge.423 Dec 2020 04:33:26 -
@@ -37,6 +37,15 @@ Rivet Networks Killer E3000 Adapter (250
 .It
 TP-LINK TL-NG421 Adapter (2500baseT)
 .El
+.Pp
+The
+.Nm
+driver additionally supports Wake on LAN (WoL).
+See
+.Xr arp 8
+and
+.Xr ifconfig 8
+for more details.
 .Sh SEE ALSO
 .Xr arp 4 ,
 .Xr ifmedia 4 ,
Index: sys/dev/pci/if_rge.c
===
RCS file: /cvs/src/sys/dev/pci/if_rge.c,v
retrieving revision 1.9
diff -u -p -u -p -r1.9 if_rge.c
--- sys/dev/pci/if_rge.c12 Dec 2020 11:48:53 -  1.9
+++ sys/dev/pci/if_rge.c23 Dec 2020 04:33:27 -
@@ -59,6 +59,7 @@ int rge_debug = 0;
 
 intrge_match(struct device *, void *, void *);
 void   rge_attach(struct device *, struct device *, void *);
+intrge_activate(struct device *, int);
 intrge_intr(void *);
 intrge_encap(struct rge_softc *, struct mbuf *, int);
 intrge_ioctl(struct ifnet *, u_long, caddr_t);
@@ -111,6 +112,10 @@ intrge_get_link_status(struct rge_soft
 void   rge_txstart(void *);
 void   rge_tick(void *);
 void   rge_link_state(struct rge_softc *);
+#ifndef SMALL_KERNEL
+intrge_wol(struct ifnet *, int);
+void   rge_wol_power(struct rge_softc *);
+#endif
 
 static const struct {
uint16_t reg;
@@ -126,7 +131,7 @@ static const struct {
 };
 
 struct cfattach rge_ca = {
-   sizeof(struct rge_softc), rge_match, rge_attach
+   sizeof(struct rge_softc), rge_match, rge_attach, NULL, rge_activate
 };
 
 struct cfdriver rge_cd = {
@@ -272,6 +277,11 @@ rge_attach(struct device *parent, struct
ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
 #endif
 
+#ifndef SMALL_KERNEL
+   ifp->if_capabilities |= IFCAP_WOL;
+   ifp->if_wol = rge_wol;
+   rge_wol(ifp, 0);
+#endif
timeout_set(>sc_timeout, rge_tick, sc);
task_set(>sc_task, rge_txstart, sc);
 
@@ -288,6 +298,25 @@ rge_attach(struct device *parent, struct
 }
 
 int
+rge_activate(struct device *self, int act)
+{
+   struct rge_softc *sc = (struct rge_softc *)self;
+   int rv = 0;
+
+   switch (act) {
+   case DVACT_POWERDOWN:
+   rv = config_activate_children(self, act);
+#ifndef SMALL_KERNEL
+   rge_wol_power(sc);
+#endif
+   default:
+   rv = config_activate_children(self, act);
+   break;
+   }
+   return (rv);
+}
+
+int
 rge_intr(void *arg)
 {
struct rge_softc *sc = arg;
@@ -2025,6 +2054,7 @@ rge_hw_init(struct rge_softc *sc)
/* Set PCIe uncorrectable error status. */
rge_write_csi(sc, 0x108,
rge_read_csi(sc, 0x108) | 0x0010);
+
 }
 
 void
@@ -2391,3 +2421,48 @@ rge_link_state(struct rge_softc *sc)
if_link_state_change(ifp);
}
 }
+
+#ifndef SMALL_KERNEL
+int
+rge_wol(struct ifnet *ifp, int enable)
+{
+   struct rge_softc *sc = ifp->if_softc;
+
+   if (enable) {
+   if (!(RGE_READ_1(sc, RGE_CFG1) & RGE_CFG1_PM_EN)) {
+   printf("%s: power management is disabled, "
+   "cannot do WOL\n", sc->sc_dev.dv_xname);
+   return (ENOTSUP);
+   }
+
+   }
+
+   rge_iff(sc);
+
+   if (enable)
+   RGE_MAC_SETBIT(sc, 0xc0b6, 0x0001);
+   else
+   RGE_MAC_CLRBIT(sc, 0xc0b6, 0x0001);
+
+   RGE_SETBIT_1(sc, RGE_EECMD, RGE_EECMD_WRITECFG);
+   RGE_CLRBIT_1(sc, RGE_CFG5, RGE_CFG5_WOL_LANWAKE | RGE_CFG5_WOL_UCAST |
+   RGE_CFG5_WOL_MCAST | RGE_CFG5_WOL_BCAST);
+   RGE_CLRBIT_1(sc, RGE_CFG3, RGE_CFG3_WOL_LINK | RGE_CFG3_WOL_MAGIC);
+   if (enable)
+   RGE_SETBIT_1(sc, RGE_CFG5, RGE_CFG5_WOL_LANWAKE);
+   RGE_CLRBIT_1(sc, RGE_EECMD, RGE_EECMD_WRITECFG);
+
+   return (0);
+}
+
+void
+rge_wol_power(struct rge_softc *sc)
+{
+   /* Disable RXDV gate. */
+   RGE_CLRBIT_1(sc, RGE_PPSW, 0x08);
+   DELAY(2000);
+
+   RGE_SETBIT_1(sc, RGE_CFG1, RGE_CFG1_PM_EN);
+   RGE_SETBIT_1(sc, RGE_CFG2, RGE_CFG2_PMSTS_EN);
+}
+#endif
Index: sys/dev/pci/if_rgereg.h
===
RCS file: /cvs/src/sys/dev/pci/if_rgereg.h,v
retrieving revision 1.5
diff -u -p -u -p -r1.5 if_rgereg.h
--- sys/dev/pci/if_rgereg.h 22 Nov 2020 14:06:22 -  1.5
+++ sys/dev/pci/if_rgereg.h 23 Dec 2020 04:33:27 -
@@ -111,16 +111,24 @@
 #define RGE_EECMD_WRITECFG 0xc0
 
 /* Flags for 

Re: uvmexp & per-CPU counters

2020-12-22 Thread Mark Kettenis
> Date: Mon, 21 Dec 2020 16:46:32 -0300
> From: Martin Pieuchot 
> 
> During a page fault multiples counters are updated.  They fall into two
> categories "fault counters" and "global statistics" both of which are
> currently represented by int-sized fields inside a global: `uvmexp'.
> 
> Diff below makes use of the per-CPU counters_inc(9) API to make sure no
> update is lost with an unlocked fault handler.  I only converted the
> fields touched by uvm_fault() to have a working solution and start a
> discussion.
> 
> - Should we keep a single enum for all fields inside `uvmexp' or do we
>   want to separate "statistics counters" which are mostly used sys/arch
>   from "fault counters" which are only used in uvm/uvm_fault.c?
> 
> - The counter_add(9) API deals with uint64_t and currently uvmexp uses
>   int.  Should we truncate or change the size of uvmexp fields or do
>   something else?
> 
> Comments?

I think this breaks "show uvmexp" in ddb.

You fear that using atomic operations for these counters would lead to
too much bus contention on systems with a large number of CPUs?

> Index: kern/init_main.c
> ===
> RCS file: /cvs/src/sys/kern/init_main.c,v
> retrieving revision 1.302
> diff -u -p -r1.302 init_main.c
> --- kern/init_main.c  7 Dec 2020 16:55:28 -   1.302
> +++ kern/init_main.c  21 Dec 2020 19:37:13 -
> @@ -432,6 +432,7 @@ main(void *framep)
>  #endif
>  
>   mbcpuinit();/* enable per cpu mbuf data */
> + uvm_init_percpu();
>  
>   /* init exec and emul */
>   init_exec();
> Index: uvm/uvm_extern.h
> ===
> RCS file: /cvs/src/sys/uvm/uvm_extern.h,v
> retrieving revision 1.155
> diff -u -p -r1.155 uvm_extern.h
> --- uvm/uvm_extern.h  1 Dec 2020 13:56:22 -   1.155
> +++ uvm/uvm_extern.h  21 Dec 2020 19:37:13 -
> @@ -289,6 +289,7 @@ void  uvm_vsunlock_device(struct proc 
> *
>   void *);
>  void uvm_pause(void);
>  void uvm_init(void); 
> +void uvm_init_percpu(void);
>  int  uvm_io(vm_map_t, struct uio *, int);
>  
>  #define  UVM_IO_FIXPROT  0x01
> Index: uvm/uvm_fault.c
> ===
> RCS file: /cvs/src/sys/uvm/uvm_fault.c,v
> retrieving revision 1.109
> diff -u -p -r1.109 uvm_fault.c
> --- uvm/uvm_fault.c   8 Dec 2020 12:26:31 -   1.109
> +++ uvm/uvm_fault.c   21 Dec 2020 19:37:13 -
> @@ -35,6 +35,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -271,7 +272,7 @@ uvmfault_anonget(struct uvm_faultinfo *u
>   int result;
>  
>   result = 0; /* XXX shut up gcc */
> - uvmexp.fltanget++;
> + counters_inc(uvmexp_counters, flt_anget);
>  /* bump rusage counters */
>   if (anon->an_page)
>   curproc->p_ru.ru_minflt++;
> @@ -295,7 +296,7 @@ uvmfault_anonget(struct uvm_faultinfo *u
>   if ((pg->pg_flags & (PG_BUSY|PG_RELEASED)) == 0)
>   return (VM_PAGER_OK);
>   atomic_setbits_int(>pg_flags, PG_WANTED);
> - uvmexp.fltpgwait++;
> + counters_inc(uvmexp_counters, flt_pgwait);
>  
>   /*
>* the last unlock must be an atomic unlock+wait on
> @@ -310,7 +311,7 @@ uvmfault_anonget(struct uvm_faultinfo *u
>  
>   if (pg == NULL) {   /* out of RAM.  */
>   uvmfault_unlockall(ufi, amap, NULL);
> - uvmexp.fltnoram++;
> + counters_inc(uvmexp_counters, flt_noram);
>   uvm_wait("flt_noram1");
>   /* ready to relock and try again */
>   } else {
> @@ -325,7 +326,7 @@ uvmfault_anonget(struct uvm_faultinfo *u
>* it is ok to read an_swslot here because
>* we hold PG_BUSY on the page.
>*/
> - uvmexp.pageins++;
> + counters_inc(uvmexp_counters, pageins);
>   result = uvm_swap_get(pg, anon->an_swslot,
>   PGO_SYNCIO);
>  
> @@ -369,7 +370,7 @@ uvmfault_anonget(struct uvm_faultinfo *u
>   uvm_anfree(anon);   /* frees page for us */
>   if (locked)
>   uvmfault_unlockall(ufi, amap, NULL);
> - uvmexp.fltpgrele++;
> + counters_inc(uvmexp_counters, flt_pgrele);
>   return (VM_PAGER_REFAULT);  /* refault! */
>   }
>  
> @@ -426,7 +427,7 @@ 

Re: xhci zero length transfers 'leak' one transfer buffer count

2020-12-22 Thread Marcus Glocker
> > Did you consider incrementing xx->ntrb instead?

>That doesn't work either, because the status completion code needs
>xx->ntrb to be correct for the data TD to be handled correctly.
>Incrementing xx->ntrb means the number of TRBs for the data TD is
>incorrect, since it includes the (optional) zero TD's TRB.
>
>In this case the zero TD allocates a TRB but doesn't do proper
>accounting, and currently there's no place where this could be
>accounted properly.
>
>In the end it's all software, so I guess the diff will simply have
>to be bigger than just a one-liner.

> > With the diff below the produced TRB isn't accounted which might
> > lead
> > to and off-by-one.

Sorry, I missed this thread and had to re-grab the last mail from MARC.

Can't we just take account of the zero trb separately?


Index: dev/usb/xhci.c
===
RCS file: /cvs/src/sys/dev/usb/xhci.c,v
retrieving revision 1.119
diff -u -p -u -p -r1.119 xhci.c
--- dev/usb/xhci.c  31 Jul 2020 19:27:57 -  1.119
+++ dev/usb/xhci.c  22 Dec 2020 19:41:01 -
@@ -1135,6 +1135,7 @@ xhci_xfer_done(struct usbd_xfer *xfer)
i = (xp->ring.ntrb - 1);
}
xp->free_trbs += xx->ntrb;
+   xp->free_trbs += xx->zerotrb;
xx->index = -1;
xx->ntrb = 0;
 
@@ -1842,6 +1843,7 @@ xhci_xfer_get_trb(struct xhci_softc *sc,
switch (last) {
case -1:/* This will be a zero-length TD. */
xp->pending_xfers[xp->ring.index] = NULL;
+   xx->zerotrb = 1; /* There can only be one zero TRB per xfer. */
break;
case 0: /* This will be in a chain. */
xp->pending_xfers[xp->ring.index] = xfer;
Index: dev/usb/xhcivar.h
===
RCS file: /cvs/src/sys/dev/usb/xhcivar.h,v
retrieving revision 1.11
diff -u -p -u -p -r1.11 xhcivar.h
--- dev/usb/xhcivar.h   6 Oct 2019 17:30:00 -   1.11
+++ dev/usb/xhcivar.h   22 Dec 2020 19:41:01 -
@@ -40,6 +40,7 @@ struct xhci_xfer {
struct usbd_xfer xfer;
int  index; /* Index of the last TRB */
size_t   ntrb;  /* Number of associated TRBs */
+   size_t   zerotrb;   /* Is zero len TRB required? */
 };
 
 struct xhci_ring {



Re: Wireguard - VPN up after reboot

2020-12-22 Thread Solene Rapenne
On Tue, 22 Dec 2020 09:50:04 +
"Salvatore Cuzzilla" :

> Hi Everyone,
> 
> I'm happily using 'Wireguard' to setup few VPNs.
> I store the required configuration within /etc/hostname.wg0 & I startup the 
> tunnel with 'doas sh
> /etc/netstart wg0'.
> 
> Everything is working like expected. 
> However, upon system reload the connectivity is lost.
> The wg0 interface comes up but the tunnel stays in a sort of 'waiting'
> state.
> 
> The only way I figure out to bring it up is either re-launching 'doas sh 
> /etc/netstart wg0' or
> pinging the tunnel default gateway.
> 
> Is there any decent/clean way to avoid manual intervention?
> 
> ---
> :wq,
> Salvatore.
> 

I had the same issue, you must avoid using hostname for
the remote address of the wireguard peer, because at this
stage you can't resolve hostnames.



Re: Force knote state update in klist_invalidate()

2020-12-22 Thread Visa Hankala
On Mon, Dec 21, 2020 at 04:51:45PM -0300, Martin Pieuchot wrote:
> On 21/12/20(Mon) 16:45, Visa Hankala wrote:
> > There is a slight inconsistency in klist_invalidate(). If the knote is
> > already in the event queue and has flag EV_ONESHOT, kqueue_scan() will
> > not invoke the newly set f_event. In this case, the kevent(2) system
> > call will return the knote's original event state that no longer
> > reflects the state that is reachable through the file descriptor
> > (the caller of klist_invalidate() has already revoked access to the
> > file or device).
> 
> I don't understand the problem.  Why should filt_dead() be called?  Is
> it a race between two threads?  Would you mind giving a scenario or some
> code example?

klist_invalidate() often is asynchronous relative to the thread that
registered the knote, so yes, sort of a race is involved.

filt_dead() sets the knote's event flags and data. Without the added
call, filt_dead() might not be invoked and the knote's fields may
retain old state that then gets reported to the caller of kqueue_scan().
In fact, this applies to any knote that has EV_ONESHOT set because the
scan loop skips f_event when the flag is present.

The kn->kn_fop->f_event(kn, 0) followed by knote_activate(kn) is
actually similar to activation through knote().

> 
> > I think a proper fix is to invoke f_event manually to force the state
> > update.
> > 
> > OK?
> > 
> > Index: kern/kern_event.c
> > ===
> > RCS file: src/sys/kern/kern_event.c,v
> > retrieving revision 1.153
> > diff -u -p -r1.153 kern_event.c
> > --- kern/kern_event.c   20 Dec 2020 12:54:05 -  1.153
> > +++ kern/kern_event.c   21 Dec 2020 16:19:30 -
> > @@ -1618,6 +1618,7 @@ klist_invalidate(struct klist *list)
> > kn->kn_fop->f_detach(kn);
> > if (kn->kn_fop->f_flags & FILTEROP_ISFD) {
> > kn->kn_fop = _filtops;
> > +   kn->kn_fop->f_event(kn, 0);
> > knote_activate(kn);
> > s = splhigh();
> > knote_release(kn);
> > 
> 



Re: [diff] usr.sbin/smtpd: fix event handling upon exit

2020-12-22 Thread Todd C . Miller
OK millert@

 - todd



Re: Wireguard - VPN up after reboot

2020-12-22 Thread Olivia Mackintosh
AFAIK, rc(8) should run netstart on boot. This is executed at /etc/rc:447. Can 
you post the contents of /etc/hostname.wg0 (of course redacting sensitive 
fields) ?

Olivia

On 22 December 2020 09:50:04 GMT, Salvatore Cuzzilla  
wrote:
>Hi Everyone,
>
>I'm happily using 'Wireguard' to setup few VPNs.
>I store the required configuration within /etc/hostname.wg0 & I startup the 
>tunnel with 'doas sh
>/etc/netstart wg0'.
>
>Everything is working like expected. 
>However, upon system reload the connectivity is lost.
>The wg0 interface comes up but the tunnel stays in a sort of 'waiting'
>state.
>
>The only way I figure out to bring it up is either re-launching 'doas sh 
>/etc/netstart wg0' or
>pinging the tunnel default gateway.
>
>Is there any decent/clean way to avoid manual intervention?
>
>---
>:wq,
>Salvatore.
>

-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.

Re: IPv6 pf_test EACCES

2020-12-22 Thread Alexandr Nedvedicky
On Mon, Dec 21, 2020 at 11:34:04PM +0100, Alexander Bluhm wrote:
> Hi,
> 
> A while ago we decided to pass EACCES to uerland if pf blocks a
> packet.  IPv6 still has the old EHOSTUNREACH code.
> 
> Use the same errno for dropped IPv6 packets as in IPv4.
> 
> ok?
> 

looks good to me.

OK sashan



Wireguard - VPN up after reboot

2020-12-22 Thread Salvatore Cuzzilla
Hi Everyone,

I'm happily using 'Wireguard' to setup few VPNs.
I store the required configuration within /etc/hostname.wg0 & I startup the 
tunnel with 'doas sh
/etc/netstart wg0'.

Everything is working like expected. 
However, upon system reload the connectivity is lost.
The wg0 interface comes up but the tunnel stays in a sort of 'waiting'
state.

The only way I figure out to bring it up is either re-launching 'doas sh 
/etc/netstart wg0' or
pinging the tunnel default gateway.

Is there any decent/clean way to avoid manual intervention?

---
:wq,
Salvatore.



Re: IPv6 pf_test EACCES

2020-12-22 Thread Florian Obser
Yes please.
OK florian

On 21 December 2020 23:34:04 CET, Alexander Bluhm  
wrote:
>Hi,
>
>A while ago we decided to pass EACCES to uerland if pf blocks a
>packet.  IPv6 still has the old EHOSTUNREACH code.
>
>Use the same errno for dropped IPv6 packets as in IPv4.
>
>ok?
>
>bluhm
>
>Index: netinet6/ip6_output.c
>===
>RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_output.c,v
>retrieving revision 1.247
>diff -u -p -r1.247 ip6_output.c
>--- netinet6/ip6_output.c  17 Jul 2020 15:21:36 -  1.247
>+++ netinet6/ip6_output.c  21 Dec 2020 22:27:24 -
>@@ -616,7 +616,7 @@ reroute:
> 
> #if NPF > 0
>   if (pf_test(AF_INET6, PF_OUT, ifp, ) != PF_PASS) {
>-  error = EHOSTUNREACH;
>+  error = EACCES;
>   m_freem(m);
>   goto done;
>   }
>@@ -2773,7 +2773,7 @@ ip6_output_ipsec_send(struct tdb *tdb, s
>   if ((encif = enc_getif(tdb->tdb_rdomain, tdb->tdb_tap)) == NULL ||
>   pf_test(AF_INET6, fwd ? PF_FWD : PF_OUT, encif, ) != PF_PASS) {
>   m_freem(m);
>-  return EHOSTUNREACH;
>+  return EACCES;
>   }
>   if (m == NULL)
>   return 0;

-- 
Sent from a mobile device. Please excuse poor formating.