0.9.0 —— armv7a 后端,以及它回答的那个宽度问题 - #9
Merged
Merged
Conversation
THE FIRST MACHINE HERE WHOSE PAGE-TABLE ENTRY IS NOT EIGHT BYTES. openarch was designed on three application-class 64-bit machines, and its page table interface carries an entry in an `arch_u64` while saying nothing about how one is STORED. `pte_encode.h` recorded the assumption as a statement of fact: "a page-table entry is 64 bits on every machine here". ARMv7-A's short-descriptor entry is 32 bits. The VALUE fits, so the carrier did not have to change; what was missing is a way to ASK. A kernel sizing a table from `sizeof(arch::pte)` builds one twice as large as the hardware walks, and the walker then reads every second word as an entry. Nothing diagnoses that — the table is well formed, the entries are correct, and the machine reads the gaps. `arch_pte_entry_bytes()` is the answer, and every backend implements it: 8 on riscv64, aarch64 and x86_64, 4 on armv7a, 0 on Cortex-M, where the refusal is already carried by `provides` withholding `openarch:address-space`. CORTEX-M COULD NOT SETTLE THIS, AND IT IS WORTH SAYING WHY. It is a 32-bit machine, which is what the plan expected to surface the assumption — but it has an MPU and no page table, so its pte group exists and refuses. A 32-bit machine WITHOUT paging leaves the question exactly where it was. The machine that settles it is 32-bit AND paged. ## The backend All four groups: cpu (TPIDRPRW/TPIDRURW, which unlike riscv's `tp` do not compete), pte (short-descriptor small pages), context (r4-r11, SP, LR — ten words, the smallest saved context here), trap (an eight-entry vector table of one instruction each). `srsdb`/`rfeia` RATHER THAN FOUR MODE STACKS. Each ARMv7-A exception is taken in its own processor mode with its own banked SP, so the obvious implementation requires a board to allocate and install four stacks before the first exception can be reported — four more things to get wrong in the code that runs before anything can report a fault. `srsdb` writes the return state onto the SVC stack from whichever mode is current, so the kernel's one stack serves every exception. THE RETURN OFFSET IS WRITTEN OUT PER EXCEPTION rather than folded into a macro parameter: 4 for IRQ, FIQ and prefetch abort, 8 for data abort, 0 for SVC and undefined. One wrong value resumes into the middle of an instruction. `openarch:preemption` IS WITHHELD. `arch_trap_switch` asks a trap to resume a different context; here the resumption address is on the SVC stack rather than in a register, so switching stacks mid-trap changes which frame `rfeia` pops and is well defined only if the resumed context was suspended through the same path. That is a real design and not one this backend has measured, so a consumer that needs it is refused by name at resolution. The Cortex-M backend already withholds `openarch:address-space` by the same mechanism. ## What is asserted `tests/pte_encoding` gains the armv7a bit patterns, read off the architecture manual rather than produced by the code under test, and the width property itself: the whole entry must lie in the low 32 bits. A new CI job boots a program on qemu `-M virt -cpu cortex-a15` that reads the width back THROUGH THE ABI and exits 0 only if it is 4 — the half a host test cannot reach. Measured before commit: `armv7a pte width 4, entry fits 32 bits`, exit 0. A second step asks whether the one-line usage REACHES the backend, for both armv7a triples. That is the check 0.8.0 shipped without: it carried a Cortex-M backend `backend-auto` never bound, and everything was green because nothing asked. The job's two fixtures are base64 rather than heredocs. A heredoc inside a YAML block scalar needs its terminator at column zero, which ends the block, and indenting it stops bash recognising it — both spellings fail, and the second fails at run time.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
这个后端是为了回答一个问题而存在的:32 位页表项能不能通过一个把返回值定为
arch_u64的接口表达。答案是「值可以,存储不行」。ARMv7-A 短描述符是 32 位;
pte_encode.h原文写着「a page-table entry is 64 bits on every machine here」。用sizeof(arch::pte)给页表定尺寸的内核会建出两倍大的表,硬件把每隔一个字读成条目 —— 没有任何东西会诊断它:表是良构的,条目是对的,机器读的是空隙。新增
arch_pte_entry_bytes(),五个后端各自实现(riscv64/aarch64/x86_64 为 8,armv7a 为 4,Cortex-M 为 0)。Cortex-M 没能settle 这个问题:它确实是 32 位,但有 MPU 没有页表,pte 组是「存在并拒绝」。32 位而不分页的机器把问题留在原地。
后端四组齐全。
openarch:preemption被扣住——ARMv7-A 的恢复地址在 SVC 栈上而不在寄存器里,trap 中途换栈会改变rfeia弹出的帧,只有当被恢复的上下文也经同一路径挂起时才良定义。这是个真实设计,不是本后端测过的,所以在解析期按名字拒绝,与 Cortex-M 扣住openarch:address-space同一机制。判据:
tests/pte_encoding加了照架构手册手写的位模式与「整条目落在低 32 位」;新 CI job 在 qemu-M virt -cpu cortex-a15上启动程序,通过 ABI 读回宽度,只有为 4 才退 0(提交前实测:armv7a pte width 4, entry fits 32 bits,退 0);再加一条「一行写法够不够得到后端」——那正是 0.8.0 缺的那条。