tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

amd64: svs



Here is an implementation that isolates the user and kernel virtual
spaces on amd64 [1] - SVS, for Separate Virtual Space. It is incomplete,
but it's a functional first shot.

The goal is to unmap the kernel when running in usermode. To achieve that,
we create a per-cpu L4 page, which contains the same slots as the current
thread's pmap, minus what we don't want to have mapped in userland.

We keep two PAs: ci_svs_kpdirpa which is the address of the pmap L4 page,
and ci_svs_updirpa which is the address of the per-cpu L4 page.

When a kernel->user transition occurs, we load ci_svs_updirpa in %cr3. When
a user->kernel transition occurs, we load ci_svs_kpdirpa in %cr3. When a
kernel->kernel transition occurs, we don't do anything.

PG_G is dropped from the kernel pages, because during a kernel->user
transition a reload of %cr3 does not flush pages with PG_G, and here, we
really want to flush them. (There is a possible optimization that consists
in setting PG_G on _user_ pages, but that will be investigated later.)

ci_svs_kpdirpa and ci_svs_updirpa must be synchronized in two places:

(a) When context-switching, we set ci_svs_kpdirpa to the new pmap, and copy
into ci_svs_updirpa the pmap L4 slots we want mapped in userland.
(b) When a user thread allocates memory that requires an additional L4
slot, the CPU that is adding this slot iterates over all the other CPUs
that have the process' pmap loaded and adds said slot in their
ci_svs_updirpa.

Right now, only the PTE area is unmapped from userland. But as I said, it's
a first shot. The next easy steps are: unmapping the direct map, moving the
kernel entry points in a dedicated .text.user section and unmapping all the
kernel sections except this one. Later, it will get a bit more complicated.

Regarding the performance impact, it depends on what the system is doing.
If it performs a lot of syscalls (eg during a ./build.sh), there will be
a lot of kernel<->user transitions, and the regression will be seeable.
Otherwise, we get only kernel<->kernel transitions, and there is no
regression there. So typically I don't think NetBSD routers will be slower.

Finally, SVS is compatible with KASLR.

I would like to commit this patch, with the option disabled by default for
now.

Maxime

[1] http://m00nbsd.net/garbage/svs/svs.diff


Home | Main Index | Thread Index | Old Index