Skip to content

Commit 0cf08bb

Browse files
aryxclaude
andcommitted
Kernel.nw: address %yoann: annotations (14 blocks)
Added %claude: paragraphs for all 12 %yoann: tags: graphics/network coherence note, clever C warning, optional prerequisites, NOP/ERRSTR, BRK meaning, directory syscall variants, security syscalls, BY2V name, floating point intro, MMU page table ASCII diagram, VIRTIO address space ASCII diagram, calling convention ASCII diagram with C vs syscall. Fixed high vectors %claude: paragraph to address %yoann1: chicken-and-egg concern (MMU must be set up before switching to high vectors). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 36cee18 commit 0cf08bb

File tree

1 file changed

+160
-5
lines changed

1 file changed

+160
-5
lines changed

kernel/Kernel.nw

Lines changed: 160 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,13 @@ there is no graphics, no network.
280280
% make other books and so want to explain something coherent.
281281
% Also V6 didn't handle multi processors (but xv6 does though).
282282
% grokking xv6: http://experiments.oskarth.com/unix00/
283+
%claude:
284+
Even though this book does not cover graphics or networking
285+
(those are in \book{Graphics} and \book{Network}), the
286+
kernel presented here is the same one that supports those
287+
subsystems. I want the books in \principia to form a
288+
coherent set, so it is important to present a kernel that
289+
is complete enough to run a real system, not a toy.
283290

284291
\item XINU has a network stack but the kernel itself
285292
is too simple with no virtual memory for instance
@@ -388,6 +395,13 @@ you'll need to have a good knowledge of
388395
the C programming language~\cite{k-r}.
389396
% see also comp.ps
390397
%yoann: actually clever C sometimes, so very good knowledge of C, of bit manip in C, C idioms for data structure, bitsets, etc.
398+
%claude:
399+
In fact, kernel C is often more demanding than application C:
400+
the code makes heavy use of bit manipulation, pointer
401+
arithmetic, C idioms for implementing data structures
402+
(linked lists via embedded pointers, bitsets, union-based
403+
tagged structures), and subtle interactions with the hardware.
404+
A very good knowledge of C is required.
391405

392406
\item Operating system: (yep)
393407
% ref?
@@ -408,14 +422,22 @@ cover the practice.
408422
%The details! And they matter!
409423

410424
%yoann: other stuff help to understand but not mandatory
425+
%claude:
426+
The following are helpful but not strictly required:
411427

412428
\begin{itemize}
413-
\item The ARM architecture:
429+
\item The ARM architecture: some familiarity with the ARM
430+
processor helps for the architecture-specific chapters,
431+
but most of the kernel code is portable C. The
432+
\book{Machine} and \book{Assembler} can serve as
433+
references.
414434
% actually maybe not that much. Mention Raspberry Pi instead of ARM?
415435
% see \book{Machine}? help, but \book{Machine} does not emulate everything
416436
% like MMU or coprocessors, so less useful.
417437

418-
\item Assembly:
438+
\item Assembly: a few key routines (context switch, interrupt
439+
entry, boot code) are written in assembly. The
440+
\book{Assembler} covers the Asm5 language used here.
419441
% ref? and assembly for ARM actually
420442
% see also asm.ps
421443
% see \book{Assembler}
@@ -587,6 +609,13 @@ that would require dedicated syscalls in other systems
587609
reading or writing special files.
588610

589611
%yoann: small comment on NOP usefulness and ERRSTR use and interface
612+
%claude:
613+
The [[NOP]] syscall at position~0 does nothing useful in
614+
production---here it just prints ``Hello World'' for
615+
testing purposes. The [[ERRSTR]] syscall at position~39
616+
is the error-reporting mechanism: \plan does not use
617+
[[errno]] like \unix, but instead stores error messages
618+
as strings that user programs retrieve via [[errstr()]].
590619

591620
% will see in helloraw.c how to use those codes to perform syscall to kernel.
592621
% will see sys_nop() soon.
@@ -616,6 +645,15 @@ and [[AWAIT]] waits for a child (like \unix [[wait]]).
616645
% cells are using fork so it must be a good API :)
617646

618647
%yoann: what BRK mean? no malloc/free here? one syscall is enough?
648+
%claude:
649+
There is only one memory syscall: [[BRK]] (for ``break''),
650+
which moves the boundary between the data segment and free
651+
memory. The name comes from the traditional \unix term for
652+
the end of the process's data area.
653+
There is no [[malloc]] or [[free]] syscall---those are
654+
implemented entirely in user space (in the C library) on
655+
top of [[brk]]. The library requests large chunks of memory
656+
from the kernel via [[brk]] and then subdivides them.
619657

620658
<<[[sys.h]] memory syscalls>>=
621659
#define BRK 5
@@ -655,6 +693,17 @@ seek-then-read atomic.
655693
% only the bytes until the newline.
656694

657695
%yoann: small paragraph explaining those syscalls, why all the xSTAT variation? fd2path seems original too
696+
%claude:
697+
The directory syscalls include [[CREATE]], [[REMOVE]],
698+
[[CHDIR]], and a family of [[STAT]] variants. The
699+
proliferation of [[STAT]]/[[FSTAT]]/[[WSTAT]]/[[FWSTAT]]
700+
comes from two axes: [[STAT]] vs.\ [[FSTAT]] (take a
701+
path name vs.\ a file descriptor), and read vs.\ write
702+
(``w'' for write, i.e., change metadata). [[FD2PATH]]
703+
is a \plan addition that returns the file name associated
704+
with an open file descriptor---useful because in \plan,
705+
with per-process namespaces, a file descriptor is often
706+
more reliable than a path.
658707

659708
<<[[sys.h]] directory syscalls>>=
660709
#define CREATE 11
@@ -749,6 +798,14 @@ blocks on top of which the user-level thread library
749798
% meh. Can't do without?
750799

751800
%yoann: security related syscalls?
801+
%claude:
802+
The two security-related syscalls handle \plan's
803+
authentication protocol. [[FVERSION]] negotiates the
804+
9P protocol version with a file server, and [[FAUTH]]
805+
opens an authentication channel. These are used when
806+
mounting remote file servers and are part of \plan's
807+
security model, which relies on per-connection
808+
authentication rather than on a global user database.
752809

753810
<<[[sys.h]] security syscalls>>=
754811
#define FVERSION 37
@@ -1013,6 +1070,9 @@ it is useful beyond this book.
10131070
%ARM 32 bits
10141071

10151072
%yoann: what V stands for?
1073+
%claude:
1074+
[[BY2V]] stands for ``bytes per vlong'' (a 64-bit value,
1075+
8~bytes on a 32-bit ARM).
10161076

10171077
<<constant [[BY2V]](arm)>>=
10181078
#define BY2V 8 /* only used in xalloc.c */
@@ -1227,10 +1287,17 @@ interrupt, a page fault, etc.), the ARM processor automatically
12271287
saves the current PSR into the SPSR (Saved PSR), switches to
12281288
the appropriate privileged mode, and jumps to a fixed address
12291289
in the {exception vector table}. This table is normally at
1230-
physical address~0, but the kernel configures the ARM to use
1290+
physical address~0, but the kernel configures the ARM (via the
1291+
[[CpChv]] bit in the system control register) to use
12311292
``high vectors'' at [[0xFFFF0000]], which is more convenient
12321293
because it lives in the kernel's virtual address space.
1233-
%yoann1: but then if virtual address then need to use MMU mechanism to resolve physical address space of the exception table? chicken-and-egg?
1294+
Of course, using a virtual address means the MMU must already
1295+
be enabled and the page tables must map [[0xFFFF0000]] to the
1296+
physical memory containing the vector table. This is not a
1297+
chicken-and-egg problem: the kernel sets up the page tables
1298+
and the vector table first (while still using physical
1299+
addresses or identity-mapped memory during early boot), then
1300+
enables the MMU, and only then switches to high vectors.
12341301

12351302
% vector normally at 0x00000 (physical and virtual?)
12361303
% but more convenient have it higher virtual memory
@@ -1352,7 +1419,16 @@ features such as caches and the exception vector location.
13521419

13531420
% See Advanced Topics.
13541421

1355-
%yoann: introduce complex world of floating point, and maybe say will talk more aobut it later
1422+
%yoann: introduce complex world of floating point, and maybe say will talk more about it later
1423+
%claude:
1424+
The ARM has two coprocessors dedicated to floating-point
1425+
arithmetic: one for single precision and one for double
1426+
precision. Floating point adds considerable complexity to a
1427+
kernel because the floating-point registers must be saved
1428+
and restored on context switches, and some ARM chips lack
1429+
hardware floating-point entirely (requiring software
1430+
emulation). These issues are discussed in the Advanced Topics
1431+
chapter.
13561432

13571433
\subsection{ARM MMU}
13581434

@@ -1378,6 +1454,25 @@ The basic unit of memory managed by the MMU is a {page},
13781454
which on ARM (and on x86) is 4~KiB:
13791455

13801456
%yoann: maybe ASCII diagram already useful here?
1457+
%claude:
1458+
The MMU translates virtual addresses to physical addresses
1459+
using a two-level page table. The virtual address is split
1460+
into fields that index into the tables:
1461+
\begin{verbatim}
1462+
31 20 19 12 11 0
1463+
+------------+-----------+------------+
1464+
| L1 index | L2 index | page offset|
1465+
| (12 bits) | (8 bits) | (12 bits) |
1466+
+-----+------+-----+-----+-----+------+
1467+
| | |
1468+
v v v
1469+
+--------+ +--------+ +------+
1470+
| L1 |-->| L2 |-->| byte |
1471+
| table | | table | | in |
1472+
| (4096 | | (256 | | page |
1473+
| entries)| | entries)| | |
1474+
+--------+ +--------+ +------+
1475+
\end{verbatim}
13811476

13821477
% put BY2PG here cos referenced a few times.
13831478
<<constant [[BY2PG]](arm)>>=
@@ -1577,6 +1672,39 @@ the windowing system uses this framebuffer.
15771672
@
15781673

15791674
%yoann: maybe ASCII diagram showing "address space" of VIRTIO and how it's used by the different devices. what is the total size of the memory-mapped IO space?
1675+
%claude:
1676+
The following diagram summarizes the I/O register layout
1677+
as offsets from [[VIRTIO]] ([[0x7E000000]]):
1678+
\begin{verbatim}
1679+
VIRTIO + 0x000000 +-----------------+
1680+
| (base) |
1681+
VIRTIO + 0x003000 +-----------------+
1682+
| SYSTIMERS |
1683+
VIRTIO + 0x007000 +-----------------+
1684+
| DMAREGS |
1685+
VIRTIO + 0x100000 +-----------------+
1686+
| POWERREGS |
1687+
VIRTIO + 0x200000 +-----------------+
1688+
| GPIOREGS |
1689+
VIRTIO + 0x215000 +-----------------+
1690+
| AUXREGS (UART) |
1691+
VIRTIO + 0x300000 +-----------------+
1692+
| EMMCREGS (SD) |
1693+
VIRTIO + 0x980000 +-----------------+
1694+
| USBREGS |
1695+
VIRTIO + 0xB200 +-----------------+
1696+
| INTREGS |
1697+
VIRTIO + 0xB400 +-----------------+
1698+
| ARMTIMER |
1699+
VIRTIO + 0xB880 +-----------------+
1700+
| MAILBOX (GPU) |
1701+
+-----------------+
1702+
VIRTIO + IOSIZE (0x7E000000 + 16 MiB)
1703+
\end{verbatim}
1704+
%claude:
1705+
The total I/O space is [[IOSIZE]] (16~MiB), though only
1706+
a small fraction of that range is actually used by device
1707+
registers. The rest is simply unmapped.
15801708

15811709
%\subsection{Exceptions}
15821710

@@ -1612,6 +1740,33 @@ cares about.
16121740

16131741
%yoann: ASCII diagram for calling conventions, and also C vs kernel
16141742
% calling convention
1743+
%claude:
1744+
Here is the stack layout when a C function [[foo(a, b, c)]]
1745+
calls [[bar(x, y)]]:
1746+
\begin{verbatim}
1747+
+-------------+
1748+
| c (arg 3) | 12(FP) for foo
1749+
+-------------+
1750+
| b (arg 2) | 8(FP)
1751+
+-------------+
1752+
| a (arg 1) | 4(FP)
1753+
+-------------+
1754+
| return addr | 0(FP) = saved R14
1755+
SP ---> +-------------+
1756+
| y (arg 2) | 8(SP) for bar
1757+
+-------------+
1758+
| x (arg 1) | 4(SP)
1759+
+-------------+
1760+
| (R14 save) | 0(SP)
1761+
+-------------+
1762+
\end{verbatim}
1763+
%claude:
1764+
For syscalls, the convention is different: the syscall number
1765+
goes in [[R0]] (not on the stack), and the [[SWI]] instruction
1766+
traps into the kernel. The kernel then reads the user's stack
1767+
to find the syscall arguments. This is why the [[Syscall]]
1768+
typedef takes a [[ulong*]]---it points to the arguments on
1769+
the user's stack.
16151770

16161771
% kencc extensions: anon field. e.g. Lock; but sugar, not that important.
16171772

0 commit comments

Comments
 (0)