Linear mapping does not work on raspi3 real machine
equation314 opened this issue · comments
Yuekai Jia commented
Commit: e63f11d
Build command:
make arch=aarch64 LOG=info graphic=on
Serial port log (with some debug info):
Hello Raspberry Pi!
[ INFO][-] FrameAllocator init end
[ INFO][-] heap init end
[ INFO][-] memory: init end
[ INFO][-] framebuffer: init end
Framebuffer {
fb_info: FramebufferInfo {
xres: 0x500,
yres: 0x2d0,
xres_virtual: 0x500,
yres_virtual: 0x2d0,
xoffset: 0x0,
yoffset: 0x0,
depth: 0x10,
pitch: 0xa00,
bus_addr: 0xfea38000,
screen_size: 0x1c2000
},
color_depth: ColorDepth16,
color_config: RGB565,
base_addr: 0xffff00003ea38000
}
[ INFO][-] timer: init end
[ INFO][-] console: init end
____ __ ____ _____
/ __ \ __ __ _____ / /_ / __ \/ ___/
/ /_/ // / / // ___// __// / / /\__ \
/ _, _// /_/ /(__ )/ /_ / /_/ /___/ /
/_/ |_| \__,_//____/ \__/ \____//____/
[ INFO][-] SFS linked to kernel, from ffff000000158088 to ffff000001fee290
[ERROR][-] MAP BEGIN 0 126cec
[ERROR][-] MAP END
[ERROR][-] MAP BEGIN 137780 5648
[ERROR][-] MAP END
[ERROR][-] MAP BEGIN 7ffffff00000 fc000
[ERROR][-] MAP END
[ERROR][-] MAP BEGIN 7fffffffc000 4000
[ERROR][-] MAP END
[ INFO][-] process: init end
[ERROR][0] ESR: 0x8200000e, Syndrome: InstructionAbort { kind: Permission, level: 2 }, elr: 84dc
[ WARN][0]
handle_page_fault OK @ 0x84dc elr 0x84dc
[ERROR][0] ESR: 0x92000007, Syndrome: DataAbort { kind: Translation, level: 3 }, elr: 8588
[ WARN][0]
handle_page_fault OK @ 0x13ac38 elr 0x8588
[ERROR][0] ESR: 0x92000007, Syndrome: DataAbort { kind: Translation, level: 3 }, elr: 85a4
[ WARN][0]
handle_page_fault OK @ 0x40 elr 0x85a4
[ERROR][0] ESR: 0x92000047, Syndrome: DataAbort { kind: Translation, level: 3 }, elr: 867c
[ WARN][0]
handle_page_fault OK @ 0x137780 elr 0x867c
[ERROR][0] ESR: 0x8200000e, Syndrome: InstructionAbort { kind: Permission, level: 2 }, elr: 867c
[ERROR][0]
EXCEPTION: Page Fault @ 0x867c elr 0x867c
[ERROR][0] TrapFrame {
elr: 0x867c,
spsr: 0x60000340,
sp: 0x7ffffffffd70,
tpidr: 0x0,
x1to29: [
0x1c8,
0x84a8,
0x875c,
0x7fffffffff70,
0x137780,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0
],
__reserved: 0x0,
x30: 0x0,
x0: 0x0
}
[ERROR][0] On CPU0 Thread 0
[ERROR][-] UNMAP BEGIN 0 126cec
[ERROR][-] UNMAP END
[ERROR][-] UNMAP BEGIN 137780 5648
[ERROR][-] UNMAP END
[ERROR][-] UNMAP BEGIN 7ffffff00000 fc000
[ERROR][-] UNMAP END
[ERROR][-] UNMAP BEGIN 7fffffffc000 4000
[ERROR][-] UNMAP END
[ INFO][-] PageTable dropping: PhysFrame[4KiB](0x3b3ff000)
Chen commented
可以复现
gjz010 commented
在trap handler里把四级页表打出来,没看出问题
(感觉是玄学)
Yuekai Jia commented
发生此问题的主要原因是:上下文切换到内核线程时,往 TLB 中加入了 gloabl 属性的某项,导致切换为用户线程后访问同一虚拟地址时,根据 TLB 中错误的该项,将该虚拟地址映射为了错误的物理地址。
具体地,对于位于低地址空间的 0x8000
的虚拟地址,内核线程的页表会将其映射为相同的物理地址 0x8000
。当上下文切换到内核线程时,由于某些原因(可能是对 [0~0x20000]
这 2MB 大页内的地址进行了访存,暂未查明)将 0x8000
到 0x8000
的映射加入了 TLB,并且属性为 global。切换为用户线程后,用户程序对 0x8000
页内的某一虚拟地址进行了取指,此时虽有 ASID 机制,但 TLB 中的那项属性为 global,仍然可以匹配成功,于是仍将该虚拟页映射到了 0x8000
的错误物理页帧,从而取出了错误的数据,将其作为了非法的指令,导致了 page fault。
d56a889 的解决方法:将内核线程的 ttbr0_el1
设为空,使得内核线程无法访问低地址空间。