Now that the rnd(9) API guarantees serial callbacks, we can simplify
everything a bit more.
(Some drivers like hifn(4) and sun8icrypto(4) still use locks to
coordinate with other parts of the driver to submit requests to and
process responses from the device.)
This simplifies the rndsource API -- no need to lock, unless you're
also coordinating with other driver logic like concurrent
opencrypto(4) requests that share device requests.
It looks like the original motivation for deferring to
config_interrupts was to wait until softint_establish worked. But
this no longer needs to use softints to deliver the entropy, so
that's moot.
Doing this synchronously gives us a better chance for more entropy
earlier.
These no longer ever run from hard interrupt context or with a spin
lock held, so there is no longer any need to have them at IPL_VM to
block hard interrupts. Instead, lower them to IPL_SOFTSERIAL.
This only ever reads from a single device register, so no need to
serialize access.
XXX This should really have a hardware-specific health test, but I
can't find any documentation on the underlying physical entropy
source.
We only ever read a single register at a time; no exclusive access or
serialization needed.
XXX This driver should have some kind of hardware-specific health
test -- is there documentation anywhere for what this RNG actually
is?
This incorrectly rejected the configuration as invalid if any
descriptor is not large enough to be interface descriptors.
Instead, it should reject the configuration only if any descriptor is
not large enough to be a _descriptor_, or if any interface-type
descriptor is not large enough to be an interface descriptor, but
skip over descriptors of other types even if they're smaller than
interface descriptors.
Candidate fix for PR kern/56762.
Just need to wait until softint_establish and high-priority xcalls
will work, no later than that. Doing this earlier gives us slightly
more of a chance to ensure cprng_fast and ssp get entropy from
hardware RNG devices that rely on interrupts.
If the self-test fails, disable everything else at boot -- don't just
leave it to the operator to notice and do something.
This way we get entropy earlier at boot, before threads start and
before the first things in the kernel that draw from it (cprng fast
init, ssp init).
Previously this was attached as RND_TYPE_UNKNOWN, at a time when the
kernel assumed _any_ RNG-type rndsource produced independent uniform
random bits and subjected it to automatic tests that would fail with
high probability for many other distributions. But sun8icrypto(4) is
very nonuniform (probably yields consecutive samples of a ring
oscillator, which are very much not independent).
Now the kernel no longer makes this assumption, so it is valid to
label this as what it is -- a hardware RNG. We should ideally still
have better information from the vendor about what's going on under
the hood before enabling nonzero entropy for it. But at least we can
label its type accurately.
No need to block interrupts while we're going through all the data
structures -- only need to block interrupts for the handoff from
interrupt handler to lower-priority logic.
The syscall only guarantees up to 256 bytes in a single go -- if
interrupted, it might return short, but if the caller requested at
least 256 bytes it will definitely return 256 bytes.
This is no longer ever taken in hard interrupt context, so there's no
longer any need to block interrupts while doing crypto operations on
the global entropy pool.
Otherwise, there is a window during which interrupts are running, but
the softint is not, so if many interrupts queue (low-entropy) samples
early at boot, they might get dropped on the floor. This could
happen, for instance, with a PCI RNG like ubsec(4) or hifn(4) which
requests entropy and processes it in its own hard interrupt handler.
This way, we never take the global entropy lock from interrupt
handlers (no interrupts while cold), so the global entropy lock need
not block interrupts.
There's an annoying ordering issue here: softint_establish doesn't
work until after CPUs have been detected, which happens inside
configure(), which is also what enables interrupts. So we have no
opportunity to softint_establish the entropy softint _before_
interrupts are enabled.
To work around this, we have to put a conditional into the interrupt
path, and go out of our way to process any queued samples after
establishing the softint. If we just made softint_establish work
early, like percpu_create does now, this problem would go away and we
could delete a bit of logic here.
Candidate fix for PR kern/56730.
This way we get a full lockdebug dump when LOCKDEBUG is enabled,
instead of just the panic message (which includes the lock address
you could pass to `show lock' in ddb, but let's get the dump by
default even if you don't enter ddb).
Also in the KASSERT print the mutex.
The standard says:
4.1.3.1 Driver Requirements: PCI Device Layout
For device configuration access, the driver MUST use ... 32-bit
wide and aligned accesses for ... 64-bit wide fields. For 64-bit
fields, the driver MAY access each of the high and low 32-bit parts
of the field independently.
NB: "MAY" in this text refers to "independently" (i.e. the order of
accesses) not "32-bit" (which is restricted by the earlier "MUST").
Note also that virtio_{read,write}_device_config_8 in virtio.c already
uses two 32-bit accesses.
The attribution in userret is good enough as is, because the stack
trace on panic shows the syscall number in the trap frame, so no need
to put extra cost in the syscall entry logic even under DIAGNOSTIC.
May need access to the global entropy pool (infrequently). This way
the global entropy pool lock can be lowered to IPL_SOFTSERIAL too,
with a little additional work.