Introduction && Link:
It is a Note about The MIT course 6.S081. arranged by following it’s lab order
https://pdos.csail.mit.edu/6.S081/2021/index.html
https://pdos.csail.mit.edu/6.S081/2021/labs/util.html
Lab1 Utilities
Key Points
- The kernel uses the hardware protection mechanisms to ensure that each process executing user space can access only its own memory
- Fork creates a new process, called the child process, with exactly the same memory contents as the calling process
pingpong
what is the difference of two code block
1
2
3int fd[2];
pid=fork();
pipe(fd);1
2
3pid=fork();
int fd[2];
pipe(fd);all have 4 fd genereated
but the first one two process’s fd have no connection.
and the second one hasremember to exit at every child process, otherwise it will execute the code below
xargs
- what is char* a[10]?
format a = {char* char* …. char*}
- exec(command, argv)
the argv[0] should be not be filled with parameter but with command name
- there are two types format: “123\n456” and 123 456, how we deal with it.
we can devide with space of \n and treate “ as one of the char, delete it at the last step
- we should clear all the uninitial string otherwise we will get random value like “" which will cause a lot of confusion to us
- if you wanna pass char par[10][10] as a parameter in function you should write prototype like below
func(char * par[10][10]), that means you should write out the dimension of it
- what is the difference
char *par[] = {}; char * par[10] = {}; char *par[10], the former two are empty array, the last one is the right defination
- why we should fork and call exec
exec system call will replace the the calling process, that is why
- what is the difference between strlen and sizeof
pls Do use sizeof with memset - we can compare char with == but we should compare string by using strcmp
- “” is a string ‘’ is a char
- how to use pointer array properly
1
2
3
4
5char *pass_par[10];
char * test = "xargs";
pass_par[0] = test;
printf("%s\n", pass_par[0]);
Lab2 System calls
Mode
mode
Machine
mode is mostly intended for configuring a computer
supervisor mode is for executing privileged instructions: for example, enabling and disabling interrupts, reading and writing the register that holds the address of a page
table
CPUs provide a special instruction that switches the CPU from user mode
to supervisor mode. (RISC-V provides
the ecall)
xv6 is monolithic kernel, with all kernel in one mode
Kernel
the hardware only uses the low 39 bits when looking up virtual addresses in page tables; and
xv6 only uses 38 of those 39 bits. Thus, the maximum address is 2
38 − 1 = 0x3fffffffff
Each process has two stacks: a user stack and a kernel stack
In Entry.S it’s _entry set up a stack so that xv6 can run C code start.c
System call tracing
Preparation:
- read at least twice the instructions
- add print command to check the execute order of each function
- you can check how the kill pass all the argument
Note:
- The most important part is how to pass the argument to the system call
- To read the document, you will know the argument is stored in which Register, and you can use function argint
to “Fetch the nth 32-bit system call argument”
Sysinfo
Preparation:
- the trick part about the compilation is pls use sys_sysinfo instead of sys_info
- A process’s most important pieces of kernel state are its page table, its kernel
stack, and its run state. - sysinfotest -> kernel/sysproc.c -> kernel/kalloc*proc
Note:
- The most important part is to understand the function copyout
- for counting proc, we should caculate all the proc that not in UNUSED mode
- for counting mem, we should times the page size
Lab3 Page Table
Note:
- VA and PA is translated by map
- MMU won’t store any map
- kernel will write the map value into the satp register
- page is 4 KB in the Risk V, which required
- for satp, it is divided into three pieces 25+27+12, 12 is the byte within the page, index is for the map to translate to physical page
- every process keeps it’s own page table
- Kernel is using “direct mapping”
The Steps to translate the virtual to physical
- the virtual address is divided into PTE-selector and offset, for example 9+9+9(PTE-selector) + 12(Offset)
- for the first page table it is satp + value(first 9 bit), in it we can get the PPN of next page(it’s physical address)
concepts of each key defination
- pte = page table entries, it is actually an address
- ppn = physical table number
- pagetable is an array string like below
[*pte1, *pte2, *pte3 …. *pte512] - Each PTE contains a 44-bit physical page
number (PPN) and some flags - Sv39 Risc-V only uses bottom 27 bit for virtual address, that means 27 power of 2 is the max number of PTES
- each pte actually has 64 bit(8 byte), but it only uses the bottom 54 bits
- each page table has 512 ptes, in total it is 4096 byte
- *pte = ppn(44) + flag(12), pte is an address it is value is ppn+flag
- physical address is 56 bit
10 last physical address(56) = ppn(44) + Virtual offset(12) - the middle physical(56)= ppn(44)+ empty zero(12)
- every VA will has a unique three level pagetable chain
- walk function will create a link from VA to pte based on one certain first level pagetable
- mappages will store the pa to the last pagetable pte
rewrite Walk in non recursive way
1 | define BIT2OFFSET(level, va) ((va >> 12) >> level*9) & 0x1ff |
Free process’s memory
- it should free it’s page table and the physical memory it refers to
- Is only the leaf pagetable has the PTE_R PTE_W flag?
Print a page table(Task)
- pretty easy, we can just copy and modify freewalk to print
Speed up system calls(Task)
preparation
check the user side of ugetpid, to understand how the app gonna use the interface
script 1
2
3
4
5int ugetpid(void)
{
struct usyscall *u = (struct usyscall *)USYSCALL;
return u->pid;
}the function directly convert the USYSCALL Address to struct usyscall, and return the stored value of pid
To do this, we can kalloc a page and set it readable to userspace, Then in Kernel space we can directly store the pid into it
USYSCALL is a virtual address
mappages’s main purpose is to map va to pa, it use walk() to create a pte for the va, and store the pa into that pte
Each process has a separate page table(First Level), and when xv6 switches between processes, it also changes
page tableswe should create a new pagetable specify for this task, that means each process has two pagetable,
one is the original, other is the store pid one
Plan
- you know the Physical Address
- you know the VA address
- you can use mappages to map va to physical
- then you can init this value all done
A kernel page table per process(Task)
- modify struct proc add kernel field
- every User process will keep an extra identical kernel_pagetable
- at before, all the process share the same kernel page table
Simplify (HARD)
- this feature should use the User_kernel_page_table
when did it translated
copyout and copyin copy data to and from user virtual addresses provided as
system call arguments; they are in vm.c because they need to explicitly translate those addresses in order to find the corresponding physical memory
and after the user_kernel_page_table setup, it will translate by hardware
how this Virtual address range?
From 0 to bottom
Detecting which pages have been accessed (HARD)
how to determine PTE_A?
Inside riscv-privileged.pdf
where to set PTE_A
Risc-V done by itself: Each leaf PTE contains an accessed (A) and dirty (D) bit. The A bit indicates the virtual page has
been read, written, or fetched from since the last time the A bit was cleared. The D bit indicates
the virtual page has been written since the last time the D bit was cleared
Trap
Three main way to trigger Trap
1.System call, user executes the ecall
2.Exception
3.Device interrupt
Trap’s feature
1.transparent
2.Three distinct case trap: user space / kernel space /timer interrupt
Trap procedure
1.hardware action, Vector Assembly
2.C Trap handler
3.system call & drver
Kernel will do instead of CPU
- switch to kernel page table
2.switch to a stack in the kernel
- save register
What is stvec
The kernel writes the address of its trap handler here; the RISC-V jumps here to
handle a trap
Without stvec Then a trap could switch to supervisor mode while still running user instructions
What is trampoline
as the name it is, it is a trampline code for user process, it has all the important function such as uservec.
and it is stored at every pages