Physical devices
The benefit of using virtual addresses is that it allows management software, such as a kernel, to control the view of memory that is presented to software. The kernel can control what memory is visible, the virtual address at which that memory is visible, and what accesses are permitted to that memory. This allows the kernel to sandbox applications (hiding the resources of one application from another application) and to provide abstraction from the underlying hardware [1, Ch. 3].
*----------* *----------* +- devices interface -+
| | | | ___ I/O 0 'boot' regfile |
| 64 KiB | | 64 KiB | ___ I/O 1 'csrs' regfile | ___
| | per-process | | ___ I/O ... regfile | |
| virtual | ___ MMU ___ | physical | ___ I/O 23 regfile | |
| memory | mapping | memory | | |c
| | | | ___ main memory | *------------*
| | | | ___ (I/O references) ___ | _ | persistent |
| | | | | d | storage |
*----------* *----------* +- -+ *------------*
1 Address alignment
16 bit
15 7 0
|------------------|------------------|
| physical address | page offset |
8 bit 8 bit
256 byte page size
A resolved address is the combination of a physical address and an offset [1, Ch. 5]. In this case, there’s an 8 bit physical address and an 8 bit offset, which means the minimum amount of space per physical page is 256 bytes. An offset is left out when passing around physical addresses. Memory is allocated in 256 byte blocks. Section 2 explains strategies for small allocations.
16 bit
15 7 0
|------------------|------------------|
| physical address | page offset |
|-------------------------------------|
| virtual address offset |
A translation of the upper virtual address byte is done to resolve to a 16 bit physical address. The lower byte of the virtual address, the offset, is the same offset in the resolved address in order to perform byte-specific operations on the designated memory page.
Contrary to physical resolved addresses, the 16 bit virtual address is passed around userland in its entirety.
2 MMU: memory management unit
A kernel can only map segments of 256 bytes to a process’ virtual memory. In order to handle multiple smaller allocations efficiently, like 24 byte arrays and a couple of small objects, an allocator layer in userland may be used. A system call is only done when more physical space is necessary for the allocation rather than with every single allocation [2].
The MMU holds a table of virtual segments and their physical address for the userspace. It also holds the flags belonging to the segment [3, Ch. 4] [1, Ch. 4].
- Flags
- Cacheable
- Readonly
- Copy-on-write
- Executable
- Reserved
- Reserved
- Reserved
- Dirty
- Physical address
Currently, the two-byte MMU stride is for a 16 bit physical address.
- Cacheable: an indication that the data doesn’t change outside of write instructions, and can therefore be cached, unlike ever-changing dynamic data provided by I/O regfiles;
- Readonly: a write operation will signal a segmentation fault to the processor;
- Copy-on-write: a write operation will signal a copy-on-write to the processor;
- Executable: a read operation through an execution mode will signal a segmentation fault to the processor;
- Dirty: a read or write triggers a new lookup in physical memory.
A four-byte MMU stride is experimental, with ptr (2 byte), len (1 byte), flags (1 byte) fields
3 I/O: input and output
There are 24 total pages mapped to I/O devices. Each page is a 256 byte register file to communicate with the device, and the rest is managed by the main memory port [1, Ch. 3]. Every one of the I/O devices has 4 interrupt pins each, resulting in 96 total external interrupts. There are 32 system calls for a grand total of 128 interrupts. It means exactly one page of 256 bytes are allocated for the interrupt map with a 16 bit address per interrupt. The I/O device address range is from 0x0000
to 0x1700
(6.144 bytes).
Two built-in I/O devices are present in the QCPU microcontroller:
- ‘Boot’ sector ROM device [
0
], - ‘CSRs’ (Control & Status Registers) device [
1
].
3.1 Control & Status Registers
- User stack-frame register [
0, 1
] - User stack-pointer register [
2, 3
] - Kernel stack-frame register [
4, 5
] - Kernel stack-pointer register [
6, 7
] - Flag register [
8
] - Interrupt identifier [
9
] - Address of generated exception [
10, 11
] - Write to clear interrupt/critical interrupt section [
12
] - Reserved [
13
] - Timer prescaler [
14, 15
] - Storage control block reserved [
16 - 31
] - Reserved [
32 - 255
]
identifier | name | description |
---|---|---|
0x00 |
timer |
system timer for preemptive multitasking) (lowest priority) |
0x01 |
syscall |
system call interface |
0x02 |
cow |
a memory page is being written to with copy-on-write active |
0x03 |
segv |
on unmapped or unprivileged virtual memory access |