mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
Documentation: um: document nommu UML
Add a description of nommu UML, a bit about how it works and some notes on how to use it. Partially based on Hajime's documentation. Link: https://patch.msgid.link/20260723113633.19c6669dc151.Ibd7a532eef856a1ea39699a263dfa8a9ded9dc20@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
626ff2b34d
commit
92dae5e08d
|
|
@ -9,6 +9,7 @@ Virtualization Support
|
|||
|
||||
kvm/index
|
||||
uml/user_mode_linux_howto_v2
|
||||
uml/nommu-uml
|
||||
paravirt_ops
|
||||
guest-halt-polling
|
||||
ne_overview
|
||||
|
|
|
|||
54
Documentation/virt/uml/nommu-uml.rst
Normal file
54
Documentation/virt/uml/nommu-uml.rst
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
Execution model
|
||||
===============
|
||||
|
||||
When emulating a system with an MMU, UML gives every ``mm_struct`` its own
|
||||
host process with its own host address space, and keeps that address space
|
||||
in sync with the kernel's page tables by issuing ``mmap()``/``munmap()``
|
||||
into it.
|
||||
|
||||
NOMMU has no per-process address spaces: there is a single "physical" address
|
||||
space that the kernel and every userspace process share. UML models this with
|
||||
a **userspace runner** - an ordinary uml-userspace stub host process, started
|
||||
exactly like an MMU userspace process, but with the whole of "physical" memory
|
||||
(the physmem file) mapped into it at the kernel's addresses:
|
||||
|
||||
- The runner ``exec()``'s the stub just like the MMU case. The only extra step
|
||||
is that, once it is up, the kernel maps the entire physmem file into it in one
|
||||
go, at the same addresses the kernel uses.
|
||||
- Because NOMMU never remaps, that single mapping is all a runner ever needs:
|
||||
there is no per-mm host process, no TLB sync and no ``mmap()`` of individual
|
||||
page-table entries into a child. Userspace code and data - placed in memory
|
||||
by the loader - are directly executable and accessible.
|
||||
- The runner processes hold no per-task state: the kernel loads a task's state
|
||||
on every entry, so there's just one process per CPU.
|
||||
|
||||
Running a task's userspace therefore only means pointing a runner at that
|
||||
task's code and letting it run until the next syscall or signal
|
||||
|
||||
Building and running
|
||||
====================
|
||||
|
||||
Configure and build the ARCH=um kernel normally, but deselect CONFIG_MMU.
|
||||
|
||||
KUnit tests can be run in NOMMU mode with::
|
||||
|
||||
./tools/testing/kunit/kunit.py run \
|
||||
--kconfig_add CONFIG_MMU=n --kconfig_add CONFIG_KUNIT_UML_PCI=n
|
||||
|
||||
Running a normal userspace requires NOMMU-aware binaries. There is no stock
|
||||
x86_64 NOMMU distribution, but a prebuilt Alpine image with musl-libc and
|
||||
busybox built for NOMMU is available and can be turned into a root image::
|
||||
|
||||
cid=$(docker create ghcr.io/thehajime/alpine:3.20.3-um-nommu)
|
||||
docker export "$cid" > alpine.tar
|
||||
docker rm "$cid"
|
||||
mkdir alpine-root && tar xf alpine.tar -C alpine-root
|
||||
mke2fs -q -F -t ext4 -d alpine-root alpine.ext4 1200M
|
||||
|
||||
Then boot it::
|
||||
|
||||
./linux ubd0=./alpine.ext4 root=/dev/ubda rw mem=1024m init=/sbin/init
|
||||
Loading…
Reference in New Issue
Block a user