Xv6 traps and system calls
Traps and system calls
Learning xv6-riscv-book Chapter 4 Traps and system calls
[TOC]
Trap: CPU transfer to speical code to handle events
- system call: ecall into the kernel
- exception: something illegal
- interrupt: from device
xv6 kernel handles all traps.
code -> trap (handling in kernel) -> resume
trap handling proceeds:
- hardware actions by CPU
- vector prepares for kernel C code
- trap handler decides what to do
- do system call / device service
three cases of assembly vectors:
- traps from user space
- traps from kernel space
- timer interrupts
RISC-V trap machinery
Registers
A set of registers:
- kernel reads about a trap
- kernel writes to tell the CPU how to handle traps.
register | description | write by | when |
---|---|---|---|
stvec | address of trap handler | kernel | |
sepc | saved PC when a trap occurs | RISC-V | when a trap occurs |
scause | reason of trap | RISC-V | |
sscratch | places a value that comes in handy | kernel | at the very start of a traphandler |
sstatus | SIE bit: device interrupts are enabled? (defer until set) SPP bit: trap from user or supervisor mode?(ctrl what mode sret returns) |
These registers are in supervisor mode: cannot be r/w in user mode
Machine mode has an equivalent set of these regs: only for timer interrupts
Each CPU has its own set: can handling traps at a same time
hardware trap handling sequence
1 | trap_occurs: |
note: CPU does minimal work:
- kernel page table / stack are not switched
- registers other than PC are not saved
(kernel must do these tasks 👆)
Traps from user space
Traps from user space:
- trap occurs:
- uservec (trampoline.S:16)
- usertrap (trap.c:37)
- handle trap
- returing:
- usertrapret (trap.c:90)
- userret (trampoline.S:88))
Hardware doesn’t switch page tables during a trap:
- user page table includes a mapping for
uservec
uservec
switchsatp
to kernel page tableuservec
must be at the same address in k & u. (to continue pc after switch)
So, xv6 use a trampiline page (VA at TRAMPILINE
) to contains uservec. The contents of trampiline pages are set in trampiline.S
.
uservec
- starts: all registers -> values of interrupted code (
sscratch
points top->trapframe
);csrrw
instruction:swaps(a0, sscratch)
- save user registers to
trapframe
(ata0
) - save
a0
totrapframe
- switch
satp
to kernel page table (in trapframe) - calls
usertrap
usertrap
(usertrap
handle trap from user space, kernel traps are handled by kerneltrap
)
- determine the cause of the trap
- process trap:
- save
sepc
(the saved user program counter) - if trap is SystemCall: calls
syscall()
- if trap is DeviceIntrrupt: calls
devintr
- save
- return by
usertrapret
usertrapret
sets up the RISC-V control registers to prepare for a future trap from user space:
- stvec
- tramframe
- sepc
- calls
userret
userret
1 | userret(TRAPFRAME, userpagetable); |
- switches
satp
to user page table. - restores saved registers from trapframe.
sret
return to user space.
Calling system calls
e.g. (user/initcode.S:11) calling exec
:
1 | # exec(init, argv) |
a0
,a1
<- argumentsa7
<- system call numberecall
-> uservec -> usertrap -> syscallsyscall
:- retrieves syscall number from saved a7 in the trapframe
- use syscall number to index into
syscalls
- system call implementation function returns:
syscall
records return value inp->trapframe->a0
System call arguments
system call wrapper functions:
- places arguments in registers
- trap: registers are saved to trapframe
argint
,argaddr
,argfd
: retrieve arguments as integer, pointer or file descriptor.
pointer argument: (e.g. str):
- fetchstr -> copyinstr
- copyinstr: copies bytes from srcva (in user pagetable) to dst.
- use
walkaddr
to walk the page table (in software) to get pa for srcva
- use
Traps from kernel space
kernelvec
(kernelvec.S:10)kerneltrap
(trap.c:134)handle types of trap:
- devintr
- exception (kernel error => fatal): calls
panic
, stops executing - timer interrupt:
yield
to give up CPU.
return: restores control registers, return to kernelvec
Page-fault exceptions
Xv6: exception happens:
- exception from user space: kill the faulting process;
- exception from kernel: panic!
Real world: more interesting ways. e.g. use page faults to implement copy-on-write (COW) fork.
- Xv6 fork: calling
uvmcopy
to copy parent’s memory into child. (no share) - COW fork: safely share phyical memory
- share all physical pages (read-only)
- when child or patent store: raise a page-fault exception
- response to this exception:
- makes a copy of the page that contains the faulted address.
- both allow to read/write
- one for child, one for parent
- resumes the process caused the fault
page-fault exception: CPU cannot translate a virtual address to a physical address
- load page faults
- store page faults
- instruction page fault
A page-fault exception happen:
scause
<- PageFaultstval
<- address that couldn’t be translated
avoid complete copy & transparent
Other page faults feature:
- lazy allocation:
- sbrk => grows address space, but not marks valid in pgtbl
- page fault on new address => allocates physical memory, maps into the pgtbl
- paging from disk:
- app need more memory than physical RAM => write some pages to disk
- pg fault => if in disk: allocates a page of physical memory, read page from disk. (may evict another page to disk)
- automically extending stacks
- memory-mapped files
- …
EOF
1 | # By CDFMLR 2021-03-18 |
顶部图片来自于小歪API,系随机选取的图片,仅用于检测屏幕显示的机械、光电性能,与文章的任何内容及观点无关,也并不代表本人局部或全部同意、支持或者反对其中的任何内容及观点。如有侵权,联系删除。