pppac(4): destroy sessions the same way as pppx(4) does

2020-08-12 Thread Vitaliy Makkoveev
We destroy pppx(4) related sessions while we performing PIPEXDSESSION
command. But with pppac(4) we set session's state to
PIPEX_STATE_CLOSE_WAIT2 and we wait garbage collector to do destruction.

We removed `pipex{in,out}q'. So we can safe destroy session in any time.
I propose to make pppac(4) session destruction path the same as pppx(4)
does. Now we destroy them while performing PIPEXDSESSION commad too.
Also there is no in-kernel garbage collector for pppac(4) sessions.
yasuoka@ pointed me that npppd(8) should kill expired sessions.

This not only makes pppac(4) closer to pppx(4) but simplify code and
allow us to make safe pppx(4) session processing by pipex_timer().
So this is preparation step to restore in-kernel timeout for pppx(4)
too.


Index: sys/net/pipex.c
===
RCS file: /cvs/src/sys/net/pipex.c,v
retrieving revision 1.124
diff -u -p -r1.124 pipex.c
--- sys/net/pipex.c 12 Aug 2020 08:41:39 -  1.124
+++ sys/net/pipex.c 12 Aug 2020 09:07:12 -
@@ -536,29 +536,6 @@ out:
return error;
 }
 
-int
-pipex_notify_close_session(struct pipex_session *session)
-{
-   NET_ASSERT_LOCKED();
-   session->state = PIPEX_STATE_CLOSE_WAIT;
-   session->stat.idle_time = 0;
-   LIST_INSERT_HEAD(_close_wait_list, session, state_list);
-
-   return (0);
-}
-
-int
-pipex_notify_close_session_all(void)
-{
-   struct pipex_session *session;
-
-   NET_ASSERT_LOCKED();
-   LIST_FOREACH(session, _session_list, session_list)
-   if (session->state == PIPEX_STATE_OPENED)
-   pipex_notify_close_session(session);
-   return (0);
-}
-
 Static int
 pipex_close_session(struct pipex_session_close_req *req,
 struct pipex_iface_context *iface)
@@ -573,13 +550,9 @@ pipex_close_session(struct pipex_session
if (session->pipex_iface != iface)
return (EINVAL);
 
-   /* remove from close_wait list */
-   if (session->state == PIPEX_STATE_CLOSE_WAIT)
-   LIST_REMOVE(session, state_list);
-
/* get statistics before destroy the session */
req->pcr_stat = session->stat;
-   session->state = PIPEX_STATE_CLOSED;
+   pipex_destroy_session(session);
 
return (0);
 }
@@ -739,47 +712,25 @@ pipex_timer_stop(void)
 Static void
 pipex_timer(void *ignored_arg)
 {
-   struct pipex_session *session, *session_tmp;
+   struct pipex_session *session;
 
timeout_add_sec(_timer_ch, pipex_prune);
 
NET_LOCK();
/* walk through */
-   LIST_FOREACH_SAFE(session, _session_list, session_list,
-   session_tmp) {
-   switch (session->state) {
-   case PIPEX_STATE_OPENED:
-   if (session->timeout_sec == 0)
-   continue;
-
-   session->stat.idle_time++;
-   if (session->stat.idle_time < session->timeout_sec)
-   continue;
-
-   pipex_notify_close_session(session);
-   break;
-
-   case PIPEX_STATE_CLOSE_WAIT:
-   case PIPEX_STATE_CLOSE_WAIT2:
-   /* Wait PIPEXDSESSION from userland */
-   session->stat.idle_time++;
-   if (session->stat.idle_time < PIPEX_CLOSE_TIMEOUT)
-   continue;
-
-   if (session->state == PIPEX_STATE_CLOSE_WAIT)
-   LIST_REMOVE(session, state_list);
-   session->state = PIPEX_STATE_CLOSED;
-   /* FALLTHROUGH */
+   LIST_FOREACH(session, _session_list, session_list) {
+   if (session->state != PIPEX_STATE_OPENED)
+   continue;
+   if (session->timeout_sec == 0)
+   continue;
 
-   case PIPEX_STATE_CLOSED:
-   pipex_destroy_session(session);
-   break;
+   session->stat.idle_time++;
+   if (session->stat.idle_time < session->timeout_sec)
+   continue;
 
-   default:
-   break;
-   }
+   session->state = PIPEX_STATE_CLOSE_WAIT;
+   LIST_INSERT_HEAD(_close_wait_list, session, state_list);
}
-
NET_UNLOCK();
 }
 
Index: sys/net/pipex.h
===
RCS file: /cvs/src/sys/net/pipex.h,v
retrieving revision 1.27
diff -u -p -r1.27 pipex.h
--- sys/net/pipex.h 4 Aug 2020 09:32:05 -   1.27
+++ sys/net/pipex.h 12 Aug 2020 09:07:13 -
@@ -197,9 +197,6 @@ void  pipex_init (void);
 void  pipex_iface_init (struct pipex_iface_context *, u_int);
 void  pipex_iface_fini (struct pipex_iface_context *);
 
-int   

Re: wireguard listen in other rdomain?

2020-08-12 Thread Stefan Sperling
On Tue, Aug 11, 2020 at 05:46:05PM -0500, Abel Abraham Camarillo Ojeda wrote:
> Hi to all,
> 
> (unsure if this if for tech@ or misc@)
> 
> I'm using wireguard interfaces but I see that no matter what
> domain I put the interface:
> 
> # ifconfig wg0 rdomain X
> 
> It always listens in rdomain 0 (default),
> is this expected?, is there any way to listen in another rdomain?
> I want to expose several wg interfaces all listening in same port but
> there's not option to listen in another ip address:
> 
>  wgport port
>  Set the UDP port that the tunnel operates on.  The interface
> will
>  bind to INADDR_ANY and IN6ADDR_ANY_INIT.  If no port is
>  configured, one will be chosen automatically.
> 
> I tried creating several wg interfaces with different wgport and using
> pf udp redirections but source address selection gets very messy...
> 
> Ideas?

Did you try 'ifconfig wg0 wgrtable X' already?



Re: pppx(4): move ifnet out of KERNEL_LOCK()

2020-08-12 Thread Vitaliy Makkoveev
Updated to the recent source. The diff is OK'ed by yasuoka@. Also I did
what mpi@ requested. Should I still wait?


Index: sys/net/if_pppx.c
===
RCS file: /cvs/src/sys/net/if_pppx.c,v
retrieving revision 1.100
diff -u -p -r1.100 if_pppx.c
--- sys/net/if_pppx.c   12 Aug 2020 08:41:39 -  1.100
+++ sys/net/if_pppx.c   12 Aug 2020 11:08:12 -
@@ -191,7 +191,7 @@ int pppx_set_session_descr(struct pppx_
struct pipex_session_descr_req *);
 
 void   pppx_if_destroy(struct pppx_dev *, struct pppx_if *);
-void   pppx_if_start(struct ifnet *);
+void   pppx_if_qstart(struct ifqueue *);
 intpppx_if_output(struct ifnet *, struct mbuf *,
struct sockaddr *, struct rtentry *);
 intpppx_if_ioctl(struct ifnet *, u_long, caddr_t);
@@ -683,13 +683,12 @@ pppx_add_session(struct pppx_dev *pxd, s
snprintf(ifp->if_xname, sizeof(ifp->if_xname), "%s%d", "pppx", unit);
ifp->if_mtu = req->pr_peer_mru; /* XXX */
ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST | IFF_UP;
-   ifp->if_xflags = IFXF_CLONED;
-   ifp->if_start = pppx_if_start;
+   ifp->if_xflags = IFXF_CLONED | IFXF_MPSAFE;
+   ifp->if_qstart = pppx_if_qstart;
ifp->if_output = pppx_if_output;
ifp->if_ioctl = pppx_if_ioctl;
ifp->if_rtrequest = p2p_rtrequest;
ifp->if_type = IFT_PPP;
-   ifq_set_maxlen(>if_snd, 1);
ifp->if_softc = pxi;
/* ifp->if_rdomain = req->pr_rdomain; */
 
@@ -864,26 +863,21 @@ pppx_if_destroy(struct pppx_dev *pxd, st
 }
 
 void
-pppx_if_start(struct ifnet *ifp)
+pppx_if_qstart(struct ifqueue *ifq)
 {
+   struct ifnet *ifp = ifq->ifq_if;
struct pppx_if *pxi = (struct pppx_if *)ifp->if_softc;
struct mbuf *m;
int proto;
 
-   if (!ISSET(ifp->if_flags, IFF_RUNNING))
-   return;
-
-   for (;;) {
-   m = ifq_dequeue(>if_snd);
-
-   if (m == NULL)
-   break;
-
+   NET_LOCK();
+   while ((m = ifq_dequeue(ifq)) != NULL) {
proto = *mtod(m, int *);
m_adj(m, sizeof(proto));
 
pipex_ppp_output(m, pxi->pxi_session, proto);
}
+   NET_UNLOCK();
 }
 
 int



Re: pipex "idle-timeout" work with pppx(4).

2020-08-12 Thread Vitaliy Makkoveev
On Wed, Aug 12, 2020 at 11:17:29AM +0900, YASUOKA Masahiko wrote:
> On Tue, 11 Aug 2020 23:06:45 +0300
> Vitaliy Makkoveev  wrote:
> > We removed `pipex{in,out}q'. So now we can destroy pppac(4) session just
> > like we do in pppx(4) case. Also there is no reason to allow
> > pipex_timer() to destroy sessions - userland will do this by
> > PIPEXDSESSION. This permit us to use existing pipex_get_closed() for
> > both pppac(4) and pppx(4) without any modifications.
> > 
> > So, I propose pipex_close_session() and pipex_timer() be like below.
> 
> It doesn't seem to fix "idle-timeout".
> 

Yes it's not. It's "pre-" step which makes following fix easier.

We don't need to mark pppx(4) sessions because there is no special cases
for them. We just need to kill pppx(4) related "pr_timeout_sec != 0"
checks and call pipex_get_closed() by pppx_get_closed().

> > We simplify pppac(4) session destruction. We unify behavior with pppx(4)
> > - we killing session just now. There is no reason to modify
> > pipex_get_closed() and pipex_link_session(). pppx(4) related sessions
> > can be processed by pipex_timer(). There is no performance impact.
> 
> We need to modify pppx_get_closed() to implement idle-timeout.
> 
> > Do you like this? We can do two diffs. The first to unify destruction
> > and the second to re-enable in-kernel timeout for pppx(4) and revert man
> > pages modifications.
> 
> I have no objection to your "unify destruction".
> 
> I'll rebase my diff after that work.

Thanks. I posted "unify destruction" here [1].

1. https://marc.info/?l=openbsd-tech=159722447900893=2



Re: ldapd: adding bsd.schema

2020-08-12 Thread Aisha Tammy
On 8/2/20 9:34 AM, Aisha Tammy wrote:
> On 7/26/20 5:25 PM, Aisha Tammy wrote:
>> On 7/26/20 5:21 PM, Aisha Tammy wrote:
>>> Hi,
>>>   Am reviving an old thread from 
>>> https://marc.info/?l=openbsd-tech=152663835315469=4
>>> (i did cc reyk@ sorry if it is noise)
>>>
>>> For some reason seems like the patch didn't go through...
>>>
>>> I am reattaching it here, maybe someone can take a look and 
>>> see if it can be merged ?
>>> Getting sshPublicKey would be really nice!
>>>
>>> Aisha
>>>  
>>
>>
>> reattaching it because thunderbird
>>
> 
> Bump, can anyone see if this is fine ?
> 
> Thanks,
> Aisha
> 

Another bump.

Aisha



Re: ldapd: adding bsd.schema

2020-08-12 Thread Theo Buehler
On Tue, Aug 11, 2020 at 10:22:51PM -0400, Aisha Tammy wrote:
> Another bump.

I think this is useful and am ok with this.

Are there any concerns? If not, I'm going to commit it tomorrow.

Index: etc/examples/ldapd.conf
===
RCS file: /cvs/src/etc/examples/ldapd.conf,v
retrieving revision 1.1
diff -u -p -u -p -r1.1 ldapd.conf
--- etc/examples/ldapd.conf 11 Jul 2014 21:20:10 -  1.1
+++ etc/examples/ldapd.conf 18 May 2018 10:09:45 -
@@ -3,6 +3,7 @@
 schema "/etc/ldap/core.schema"
 schema "/etc/ldap/inetorgperson.schema"
 schema "/etc/ldap/nis.schema"
+schema "/etc/ldap/bsd.schema"
 
 listen on lo0
 listen on "/var/run/ldapi"
Index: usr.sbin/ldapd/Makefile
===
RCS file: /cvs/src/usr.sbin/ldapd/Makefile,v
retrieving revision 1.15
diff -u -p -u -p -r1.15 Makefile
--- usr.sbin/ldapd/Makefile 20 Jan 2017 11:55:08 -  1.15
+++ usr.sbin/ldapd/Makefile 18 May 2018 10:09:45 -
@@ -17,7 +17,8 @@ CFLAGS+=  -Wshadow -Wpointer-arith -Wcast
 CFLAGS+=   -Wsign-compare
 CLEANFILES+=   y.tab.h parse.c
 
-SCHEMA_FILES=  core.schema \
+SCHEMA_FILES=  bsd.schema \
+   core.schema \
inetorgperson.schema \
nis.schema
 
Index: usr.sbin/ldapd/schema/bsd.schema
===
RCS file: usr.sbin/ldapd/schema/bsd.schema
diff -N usr.sbin/ldapd/schema/bsd.schema
--- /dev/null   1 Jan 1970 00:00:00 -
+++ usr.sbin/ldapd/schema/bsd.schema18 May 2018 10:09:45 -
@@ -0,0 +1,17 @@
+attributetype ( 1.3.6.1.4.1.30155.115.2 NAME 'shadowPassword'
+   DESC 'POSIX hashed password'
+   EQUALITY caseExactIA5Match
+   SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.4.1.30155.115.3 NAME 'sshPublicKey'
+   DESC 'SSH public key'
+   EQUALITY caseExactIA5Match
+   SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+objectclass ( 1.3.6.1.4.1.30155.115.1 NAME 'bsdAccount'
+   SUP top
+   AUXILIARY
+   DESC 'Abstraction of an account with OpenBSD attributes'
+   MUST ( uid )
+   MAY ( shadowPassword $ shadowExpire $ modifyTimestamp $ userClass $
+   sshPublicKey ))



Re: pipex "idle-timeout" work with pppx(4).

2020-08-12 Thread YASUOKA Masahiko
Hi,

On Wed, 12 Aug 2020 12:38:39 +0300
Vitaliy Makkoveev  wrote:
> We don't need to mark pppx(4) sessions because there is no special cases
> for them. We just need to kill pppx(4) related "pr_timeout_sec != 0"
> checks and call pipex_get_closed() by pppx_get_closed().

How do you implement that by calling pipex_get_closed() by
pppx_get_closed()?


PIPEXGCLOSED is to pick up expired sessions which is associated with
the character device (/dev/{pppx,pppac}0).  In pppac(4) case, the
character device is the same object of the interface pppac.  But
pppx(4) is not the same.  pipex_session has no direct referece to the
device.  This is why my diff was modifying pipex_get_closed().



Re: pipex "idle-timeout" work with pppx(4).

2020-08-12 Thread Vitaliy Makkoveev
On Wed, Aug 12, 2020 at 09:07:15PM +0900, YASUOKA Masahiko wrote:
> Hi,
> 
> On Wed, 12 Aug 2020 12:38:39 +0300
> Vitaliy Makkoveev  wrote:
> > We don't need to mark pppx(4) sessions because there is no special cases
> > for them. We just need to kill pppx(4) related "pr_timeout_sec != 0"
> > checks and call pipex_get_closed() by pppx_get_closed().
> 
> How do you implement that by calling pipex_get_closed() by
> pppx_get_closed()?
> 
> 
> PIPEXGCLOSED is to pick up expired sessions which is associated with
> the character device (/dev/{pppx,pppac}0).  In pppac(4) case, the
> character device is the same object of the interface pppac.  But
> pppx(4) is not the same.  pipex_session has no direct referece to the
> device.  This is why my diff was modifying pipex_get_closed().
> 

You are right. I have my own tree where I divided pppx(4) sessions and
iface_context. So in my tree I have one `pipex_iface_context' in `struct
pppx_dev' and the usage of most pppx(4) is identical to pppac(4). Sorry,
I forgot that it's not shared yet :(

You are right, pppx_get_closed() still needs to do it's own
`pipex_close_wait_list' walkthrough.



Re: ldapd: adding bsd.schema

2020-08-12 Thread Robert Klein
Hi,

On Wed, 12 Aug 2020 09:00:18 +0200
Theo Buehler  wrote:

> On Tue, Aug 11, 2020 at 10:22:51PM -0400, Aisha Tammy wrote:
> > Another bump.  
> 
> I think this is useful and am ok with this.
> 
> Are there any concerns? If not, I'm going to commit it tomorrow.

for an sshPublicKey attribute, there's a “openssh-lpk” schema which
seems to be in common use.  It's defined as

# octetString SYNTAX
attributetype ( 1.3.6.1.4.1.24552.500.1.1.1.13 NAME 'sshPublicKey'
DESC 'OpenSSH Public key'
EQUALITY octetStringMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )

# printableString SYNTAX yes|no
objectclass ( 1.3.6.1.4.1.24552.500.1.1.2.0 NAME 'ldapPublicKey' SUP
top AUXILIARY DESC 'OpenSSH LPK objectclass'
MUST uid
MAY sshPublicKey
)

though there are versions of the “ldapPublicKey” definitions with both
uid and sshPublicKye in the MUST  and both in the MAY clause.  The
“both MAY” version is imho more flexible.


The original mail proposing bsd.schema seems to have added both
“shadowPassword” and “bsdaccount” more as an afterthought, it seems.


Best regards
Robert


> 
> Index: etc/examples/ldapd.conf
> ===
> RCS file: /cvs/src/etc/examples/ldapd.conf,v
> retrieving revision 1.1
> diff -u -p -u -p -r1.1 ldapd.conf
> --- etc/examples/ldapd.conf   11 Jul 2014 21:20:10 -
> 1.1 +++ etc/examples/ldapd.conf   18 May 2018 10:09:45 -
> @@ -3,6 +3,7 @@
>  schema "/etc/ldap/core.schema"
>  schema "/etc/ldap/inetorgperson.schema"
>  schema "/etc/ldap/nis.schema"
> +schema "/etc/ldap/bsd.schema"
>  
>  listen on lo0
>  listen on "/var/run/ldapi"
> Index: usr.sbin/ldapd/Makefile
> ===
> RCS file: /cvs/src/usr.sbin/ldapd/Makefile,v
> retrieving revision 1.15
> diff -u -p -u -p -r1.15 Makefile
> --- usr.sbin/ldapd/Makefile   20 Jan 2017 11:55:08 -
> 1.15 +++ usr.sbin/ldapd/Makefile  18 May 2018 10:09:45 -
> @@ -17,7 +17,8 @@ CFLAGS+=-Wshadow -Wpointer-arith -Wcast
>  CFLAGS+= -Wsign-compare
>  CLEANFILES+= y.tab.h parse.c
>  
> -SCHEMA_FILES=core.schema \
> +SCHEMA_FILES=bsd.schema \
> + core.schema \
>   inetorgperson.schema \
>   nis.schema
>  
> Index: usr.sbin/ldapd/schema/bsd.schema
> ===
> RCS file: usr.sbin/ldapd/schema/bsd.schema
> diff -N usr.sbin/ldapd/schema/bsd.schema
> --- /dev/null 1 Jan 1970 00:00:00 -
> +++ usr.sbin/ldapd/schema/bsd.schema  18 May 2018 10:09:45 -
> @@ -0,0 +1,17 @@
> +attributetype ( 1.3.6.1.4.1.30155.115.2 NAME 'shadowPassword'
> + DESC 'POSIX hashed password'
> + EQUALITY caseExactIA5Match
> + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
> +
> +attributetype ( 1.3.6.1.4.1.30155.115.3 NAME 'sshPublicKey'
> + DESC 'SSH public key'
> + EQUALITY caseExactIA5Match
> + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
> +
> +objectclass ( 1.3.6.1.4.1.30155.115.1 NAME 'bsdAccount'
> + SUP top
> + AUXILIARY
> + DESC 'Abstraction of an account with OpenBSD attributes'
> + MUST ( uid )
> + MAY ( shadowPassword $ shadowExpire $ modifyTimestamp $
> userClass $
> + sshPublicKey ))
> 



getitimer(2), setitimer(2): merge critical sections

2020-08-12 Thread Scott Cheloha
Hi,

Things in getitimer(2) and setitimer(2) have been rearranged
adequately.  Their critical sections are ready to be combined.

Merging these critical sections is necessary to make getitimer(2) and
setitimer(2) MP-safe.  They are not ready to run without the kernel
lock just yet, but this diff is a prerequisite.  Everything up until
now was done to make this patch less painful.

So, this patch:

We introduce a new kernel subroutine, "setitimer()", that does all of
the common, error-free work for both getitimer(2) and setitimer(2).
The high-level steps are as follows:

 - convert input from itimerval to itimerspec
 - enter the critical section
 - read the timer's current value
 - (ITIMER_REAL) do timeout_add(9)/timeout_del(9)
 - (ITIMER_REAL) convert input from relative to absolute time
 - write the timer's new value
 - leave the critical section
 - (ITIMER_REAL) convert output from absolute to relative time
 - convert output from itimerspec to itimerval

All of this code has been moved more-or-less verbatim from
sys_getitimer() and sys_setitimer() and interleaved within the
new subroutine around a single critical section.

Meanwhile, sys_getitimer() and sys_setitimer() are left to handle all
of the error-prone work: copyin(9), input validation, and copyout(9).

The changes in sys_getitimer() are straightforward.  All of its common
code folds neatly into the new subroutine without any changes to the
surrounding code.

sys_setitimer() is trickier because it doesn't use SCARG directly.
I've introduced additional itimerval pointers to keep changes minimal
here.  However, I think it would benefit from the direct use of SCARG
to distinguish userspace addresses from kernel stack addresses.  That
can wait until later, though.

sys_setitimer() now performs its own copyout(9) instead of relying on
sys_getitimer() to do it implicitly.  This adds a bit of additional
code but I would rather see the syscall do copyout(9) explicitly.

There is one behavior change: in the setitimer(2) swap case it is now
possible to EFAULT on copyout(9) *after* you have written the new
timer value and (possibly) started the ITIMER_REAL timeout.

For example, the following code now yields EFAULT even though a new
oneshot timer has been started successfully.

struct itimerval new;
int error;

new.it_value.tv_sec = 1;
new.it_value.tv_usec = 0;
timerclear(_interval);
error = setitimer(ITIMER_REAL, , 0xdeadbeef);
if (error)
warn("setitimer");

I don't think there is a way to avoid this without introducing a bunch
of extra complexity.  The critical section is protected by a mutex and
copyout(9) can sleep, so we have to wait until we leave the critical
section to copyout(9).  If we leave the mutex to do the copyout(9)
before writing the new timer value then the swap is no longer atomic.
Of course, this is not an issue *now*, but when the syscalls are
unlocked you will lose atomicity.

Personally I don't think this is a huge deal.  If you're getting
EFAULT there is a bigger problem in your code.

Thoughts?  ok?

Index: kern_time.c
===
RCS file: /cvs/src/sys/kern/kern_time.c,v
retrieving revision 1.140
diff -u -p -r1.140 kern_time.c
--- kern_time.c 12 Aug 2020 15:31:27 -  1.140
+++ kern_time.c 12 Aug 2020 18:44:08 -
@@ -491,7 +491,7 @@ out:
 struct mutex itimer_mtx = MUTEX_INITIALIZER(IPL_CLOCK);
 
 /*
- * Get value of an interval timer.  The process virtual and
+ * Get and/or set value of an interval timer.  The process virtual and
  * profiling virtual time timers are kept internally in the
  * way they are specified externally: in time until they expire.
  *
@@ -509,6 +509,63 @@ struct mutex itimer_mtx = MUTEX_INITIALI
  * real time timers .it_interval.  Rather, we compute the next time in
  * absolute time the timer should go off.
  */
+void
+setitimer(int which, struct itimerval *itv, struct itimerval *olditv)
+{
+   struct itimerspec its, oldits;
+   struct itimerspec *itimer;
+   struct process *pr;
+   int timo;
+
+   KASSERT(which >= ITIMER_REAL && which <= ITIMER_PROF);
+
+   pr = curproc->p_p;
+   itimer = >ps_timer[which];
+
+   if (itv != NULL) {
+   TIMEVAL_TO_TIMESPEC(>it_value, _value);
+   TIMEVAL_TO_TIMESPEC(>it_interval, _interval);
+   }
+
+   if (which != ITIMER_REAL)
+   mtx_enter(_mtx);
+
+   if (olditv != NULL)
+   oldits = *itimer;
+   if (itv != NULL) {
+   if (which == ITIMER_REAL) {
+   struct timespec cts;
+   getnanouptime();
+   if (timespecisset(_value)) {
+   timo = tstohz(_value);
+   timeout_add(>ps_realit_to, timo);
+   timespecadd(_value, , _value);
+   } else
+   

sdmmc(4) HS200 support

2020-08-12 Thread Mark Kettenis
This diff lays the groundwork for HS200 mode for eMMC.  This mode
supports data transfer modes of up to 200 MB/s.  The crucial bit here
is that using this mode requires tuning which is done by calling a
chip-specific execute_tuning function.  I have an implementation for
amlmmc(4) that seems to work which I'll send in a separate diff.

The diff also adds some bits to support higher speed modes for SD
cards, but those aren't hooked up yet.  I'll leave that for a future
diff.  I'll probably look into adding support for sdhc(4) in the near
future as well.

Don't expect enormous speed increases from this; most eMMC chips I've
seen are not actually limited by the tramsfer speed.  But for
amlmmc(4) this makes a difference since the DDR52 mode isn't reliable.

Tested on the Odroid-N2, Odroid-C4 and an amd64 netbook that uses eMMC.

ok?


Index: dev/sdmmc/sdhc.c
===
RCS file: /cvs/src/sys/dev/sdmmc/sdhc.c,v
retrieving revision 1.68
diff -u -p -r1.68 sdhc.c
--- dev/sdmmc/sdhc.c14 Jun 2020 18:37:16 -  1.68
+++ dev/sdmmc/sdhc.c12 Aug 2020 18:52:05 -
@@ -121,26 +121,18 @@ void  sdhc_dump_regs(struct sdhc_host *);
 #endif
 
 struct sdmmc_chip_functions sdhc_functions = {
-   /* host controller reset */
-   sdhc_host_reset,
-   /* host controller capabilities */
-   sdhc_host_ocr,
-   sdhc_host_maxblklen,
-   /* card detection */
-   sdhc_card_detect,
-   /* bus power and clock frequency */
-   sdhc_bus_power,
-   sdhc_bus_clock,
-   sdhc_bus_width,
-   /* command execution */
-   sdhc_exec_command,
-   /* card interrupt */
-   sdhc_card_intr_mask,
-   sdhc_card_intr_ack,
-   /* UHS functions */
-   sdhc_signal_voltage,
-   /* hibernate */
-   sdhc_hibernate_init,
+   .host_reset = sdhc_host_reset,
+   .host_ocr = sdhc_host_ocr,
+   .host_maxblklen = sdhc_host_maxblklen,
+   .card_detect = sdhc_card_detect,
+   .bus_power = sdhc_bus_power,
+   .bus_clock = sdhc_bus_clock,
+   .bus_width = sdhc_bus_width,
+   .exec_command = sdhc_exec_command,
+   .card_intr_mask = sdhc_card_intr_mask,
+   .card_intr_ack = sdhc_card_intr_ack,
+   .signal_voltage = sdhc_signal_voltage,
+   .hibernate_init = sdhc_hibernate_init,
 };
 
 struct cfdriver sdhc_cd = {
Index: dev/sdmmc/sdmmc_mem.c
===
RCS file: /cvs/src/sys/dev/sdmmc/sdmmc_mem.c,v
retrieving revision 1.33
diff -u -p -r1.33 sdmmc_mem.c
--- dev/sdmmc/sdmmc_mem.c   4 Jun 2018 13:33:10 -   1.33
+++ dev/sdmmc/sdmmc_mem.c   12 Aug 2020 18:52:05 -
@@ -70,6 +70,34 @@ int  sdmmc_mem_write_block_subr(struct sd
 #define DPRINTF(s) /**/
 #endif
 
+const struct {
+   const char *name;
+   int v;
+   int freq;
+} switch_group0_functions[] = {
+   /* Default/SDR12 */
+   { "Default/SDR12",   0,  25000 },
+
+   /* High-Speed/SDR25 */
+   { "High-Speed/SDR25",   SMC_CAPS_SD_HIGHSPEED,   5 },
+
+   /* SDR50 */
+   { "SDR50",  SMC_CAPS_UHS_SDR50, 10 },
+
+   /* SDR104 */
+   { "SDR104", SMC_CAPS_UHS_SDR104,208000 },
+
+   /* DDR50 */
+   { "DDR50",  SMC_CAPS_UHS_DDR50,  5 },
+};
+
+const int sdmmc_mmc_timings[] = {
+   [SDMMC_TIMING_LEGACY]   = 26000,
+   [SDMMC_TIMING_HIGHSPEED]= 52000,
+   [SDMMC_TIMING_MMC_DDR52]= 52000,
+   [SDMMC_TIMING_MMC_HS200]= 20
+};
+
 /*
  * Initialize SD/MMC memory cards and memory in SDIO "combo" cards.
  */
@@ -581,6 +609,41 @@ sdmmc_be512_to_bitfield512(sdmmc_bitfiel
 }
 
 int
+sdmmc_mem_execute_tuning(struct sdmmc_softc *sc, struct sdmmc_function *sf)
+{
+   int timing = -1;
+
+   if (ISSET(sc->sc_flags, SMF_SD_MODE)) {
+   if (!ISSET(sc->sc_flags, SMF_UHS_MODE))
+   return 0;
+
+   switch (sf->csd.tran_speed) {
+   case 10:
+   timing = SDMMC_TIMING_UHS_SDR50;
+   break;
+   case 208000:
+   timing = SDMMC_TIMING_UHS_SDR104;
+   break;
+   default:
+   return 0;
+   }
+   } else {
+   switch (sf->csd.tran_speed) {
+   case 20:
+   timing = SDMMC_TIMING_MMC_HS200;
+   break;
+   default:
+   return 0;
+   }
+   }
+
+   DPRINTF(("%s: execute tuning for timing %d\n", SDMMCDEVNAME(sc),
+   timing));
+
+   return sdmmc_chip_execute_tuning(sc->sct, sc->sch, timing);
+}
+
+int
 sdmmc_mem_sd_init(struct sdmmc_softc *sc, struct sdmmc_function *sf)
 {
int support_func, best_func, error;
@@ -647,6 +710,8 @@ sdmmc_mem_sd_init(struct sdmmc_softc *sc