Early file mmaps are pinned and populated

for memory, pinning is currently irrelevant, since the kernel never
revokes memory.  populating is just a performance tradeoff: soft-page
faults at the first access, vs wasting large blobs of RAM (like if Go
decides to mmap a huge contig region, but doesn't use it) and greater
initial mmap costs.  both of these might change in the future.

for files, we run into correctness issues with blocking in vcore context
(which we don't allow).  for code and data that are touched from vcore
context, we need them to be both pinned and populated.  pinning prevents
further removal, and population ensures we never take a hard page fault.

since there is a lot of libc magic at startup and no good way (yet) to
identify the file segments needed by vcore context, i just pin/populate
any file mmap that happens before uthread or application code takes
over.

the question is what to do about all of the other mmaps out there,
memory and file alike.  the current default *flags* are unpinned,
unpopulated. it's up to userspace to change this if they want.

for memory, that means that mallocs are not populated/pinned.  as
mentioned above, we don't revoke anonymous mmaps, so in essence the
default already is pinned, but unpopulated, even though the MAP_LOCKED
flag isn't set.  i'm okay with this, but we'll need to look at all sorts
of mallocs (like uthread structs, syscall structs, etc) if this ever
changes.

for files mmapped later, including dlopens, userspace will need to pin
and populate.  populating from blocking media is going to be pretty
expensive, so either way we want userspace to be in control.  but since
the existing norm is to use MAP_LOCKED, and MAP_POPULATE, it makes sense
to stick with those.
Fault reflection and blocking page faults (XCC)

Unhandled traps/faults will now be reflected back to userspace for MCPs
in uthread context.  SCPs and MCPs in vcore context retain the existing
behavior (death).

Hard page faults (that can't be serviced without blocking) for
file-backed VMRs will be reflected as unhandled PFs.  Userspace can tell
if the PF is on a valid VMR or not by checking the error code.

The RISCV stuff is all just stubs.  If I made any x86-like assumptions
that are unreasonable, let me know.

You need to reinstall your kernel headers.  Easiest way is to rebuild
your toolchain.
MM populate cleanup

The main thing is the use of a history counter, which allows us to
detect changes in the VMRs, whether that change is just some prot
settings, or the existence of VMRs, etc.  While we can't reinspect the
vmr memory across an unlock-and-block, the history tells us it is safe
to keep following our previous instructions (keep mmaping a range of
pages).
SYS_populate_va (XCC)

Syscall for populating a range of virtual addresses.  This will usually
be used by PF handlers on file-backed VMRs, but it can be done for any
sort of user-controlled read-ahead that is desired.

If people want more control, like an FD interface that doesn't bother
with PTEs, let me know.

You need to reinstall your kernel headers.
Async syscall helper
2LS op for handling reflected faults

The pthread one knows how to handle page faults on file-backed virtual
addresses.

I'm using the existing pthread syscall handling, so this sits in
pthread.c for now.  Most other 2LSs will do the same thing.  In the
future, we could have a uthread helper for it, but only if we redo some
of the other syscall stuff.  Due to the ev_q and how we track syscalls,
which is a 2LS decision, most of this will probably stay in the specific
2LS.