Skip to content
GitLab
Explore
Projects
Groups
Topics
Snippets
Projects
Groups
Topics
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
今天也要好好吃饭
OSKernel2024-章雨薏
Commits
cf4069b5
Commit
cf4069b5
authored
7 months ago
by
zhangyuyi
Browse files
Options
Download
Patches
Plain Diff
lab4 finish
parent
3243a481
pgtbl
No related merge requests found
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
grade-lab-pgtbl
+1
-1
grade-lab-pgtbl
kernel/defs.h
+6
-0
kernel/defs.h
kernel/exec.c
+2
-0
kernel/exec.c
kernel/proc.c
+23
-1
kernel/proc.c
kernel/proc.h
+2
-0
kernel/proc.h
kernel/vm.c
+152
-6
kernel/vm.c
user/sh.c
+1
-0
user/sh.c
with
187 additions
and
8 deletions
+187
-8
grade-lab-pgtbl
+
1
−
1
View file @
cf4069b5
#!/usr/bin/env python
#!/usr/bin/env python
3
import
re
from
gradelib
import
*
...
...
This diff is collapsed.
Click to expand it.
kernel/defs.h
+
6
−
0
View file @
cf4069b5
...
...
@@ -179,6 +179,12 @@ int copyout(pagetable_t, uint64, char *, uint64);
int
copyin
(
pagetable_t
,
char
*
,
uint64
,
uint64
);
int
copyinstr
(
pagetable_t
,
char
*
,
uint64
,
uint64
);
int
test_pagetable
();
void
vmprint
(
pagetable_t
);
pagetable_t
proc_kpt_init
();
void
proc_kvmmmap
(
pagetable_t
,
uint64
,
uint64
,
uint64
,
int
);
void
proc_kvminithart
(
pagetable_t
);
void
free_proc_kpt
(
pagetable_t
pagetable
);
// plic.c
void
plicinit
(
void
);
...
...
This diff is collapsed.
Click to expand it.
kernel/exec.c
+
2
−
0
View file @
cf4069b5
...
...
@@ -97,6 +97,7 @@ int exec(char *path, char **argv) {
p
->
trapframe
->
sp
=
sp
;
// initial stack pointer
proc_freepagetable
(
oldpagetable
,
oldsz
);
if
(
p
->
pid
==
1
)
vmprint
(
p
->
pagetable
);
return
argc
;
// this ends up in a0, the first argument to main(argc, argv)
bad:
...
...
@@ -105,6 +106,7 @@ bad:
iunlockput
(
ip
);
end_op
();
}
if
(
p
->
pid
==
1
)
vmprint
(
p
->
pagetable
);
return
-
1
;
}
...
...
This diff is collapsed.
Click to expand it.
kernel/proc.c
+
23
−
1
View file @
cf4069b5
...
...
@@ -110,6 +110,17 @@ found:
release
(
&
p
->
lock
);
return
0
;
}
// ljg add
// An empty kernel page table.
p
->
k_pagetable
=
proc_kpt_init
();
// 申请内核栈,确保每一个进程的内核页表都关于该进程的内核栈有一个映射
char
*
pa
=
kalloc
();
if
(
pa
==
0
)
panic
(
"kalloc"
);
uint64
va
=
KSTACK
((
int
)
(
p
-
proc
));
proc_kvmmmap
(
p
->
k_pagetable
,
va
,
(
uint64
)
pa
,
PGSIZE
,
PTE_R
|
PTE_W
);
p
->
kstack
=
va
;
// Set up new context to start executing at forkret,
// which returns to user space.
...
...
@@ -128,6 +139,14 @@ static void freeproc(struct proc *p) {
p
->
trapframe
=
0
;
if
(
p
->
pagetable
)
proc_freepagetable
(
p
->
pagetable
,
p
->
sz
);
p
->
pagetable
=
0
;
// 释放一个进程的内核栈
if
(
p
->
kstack
){
uvmunmap
(
p
->
k_pagetable
,
p
->
kstack
,
1
,
1
);
}
p
->
kstack
=
0
;
// 释放内核页表
free_proc_kpt
(
p
->
k_pagetable
);
p
->
k_pagetable
=
0
;
p
->
sz
=
0
;
p
->
pid
=
0
;
p
->
parent
=
0
;
...
...
@@ -430,8 +449,11 @@ void scheduler(void) {
// before jumping back to us.
p
->
state
=
RUNNING
;
c
->
proc
=
p
;
// 加载进程的内核页表到核心的satp寄存器
proc_kvminithart
(
p
->
k_pagetable
);
swtch
(
&
c
->
context
,
&
p
->
context
);
// ljg add Come back to the global kernel page table
kvminithart
();
// Process is done running for now.
// It should have changed its p->state before coming back.
c
->
proc
=
0
;
...
...
This diff is collapsed.
Click to expand it.
kernel/proc.h
+
2
−
0
View file @
cf4069b5
...
...
@@ -98,6 +98,8 @@ struct proc {
uint64
kstack
;
// Virtual address of kernel stack
uint64
sz
;
// Size of process memory (bytes)
pagetable_t
pagetable
;
// User page table
// TODO
pagetable_t
k_pagetable
;
// kernel page table
struct
trapframe
*
trapframe
;
// data page for trampoline.S
struct
context
context
;
// swtch() here to run process
struct
file
*
ofile
[
NOFILE
];
// Open files
...
...
This diff is collapsed.
Click to expand it.
kernel/vm.c
+
152
−
6
View file @
cf4069b5
...
...
@@ -5,6 +5,9 @@
#include
"riscv.h"
#include
"defs.h"
#include
"fs.h"
#include
"spinlock.h"
#include
"proc.h"
/*
* the kernel's page table.
...
...
@@ -45,12 +48,58 @@ void kvminit() {
kvmmap
(
TRAMPOLINE
,
(
uint64
)
trampoline
,
PGSIZE
,
PTE_R
|
PTE_X
);
}
// 为进程的内核页表新建一个初始化函数
pagetable_t
proc_kpt_init
(){
pagetable_t
k_pagetable
=
(
pagetable_t
)
kalloc
();
memset
(
k_pagetable
,
0
,
PGSIZE
);
// uart registers
proc_kvmmmap
(
k_pagetable
,
UART0
,
UART0
,
PGSIZE
,
PTE_R
|
PTE_W
);
// virtio mmio disk interface
proc_kvmmmap
(
k_pagetable
,
VIRTIO0
,
VIRTIO0
,
PGSIZE
,
PTE_R
|
PTE_W
);
// CLINT
proc_kvmmmap
(
k_pagetable
,
CLINT
,
CLINT
,
0x10000
,
PTE_R
|
PTE_W
);
// PLIC
proc_kvmmmap
(
k_pagetable
,
PLIC
,
PLIC
,
0x400000
,
PTE_R
|
PTE_W
);
// map kernel text executable and read-only.
proc_kvmmmap
(
k_pagetable
,
KERNBASE
,
KERNBASE
,
(
uint64
)
etext
-
KERNBASE
,
PTE_R
|
PTE_X
);
// map kernel data and the physical RAM we'll make use of.
proc_kvmmmap
(
k_pagetable
,
(
uint64
)
etext
,
(
uint64
)
etext
,
PHYSTOP
-
(
uint64
)
etext
,
PTE_R
|
PTE_W
);
// map the trampoline for trap entry/exit to
// the highest virtual address in the kernel.
proc_kvmmmap
(
k_pagetable
,
TRAMPOLINE
,
(
uint64
)
trampoline
,
PGSIZE
,
PTE_R
|
PTE_X
);
return
k_pagetable
;
}
// kvmmap是为内核页表的虚拟地址与物理地址做映射,这里需要重新添加一个类似的函数
void
proc_kvmmmap
(
pagetable_t
k_pagetable
,
uint64
va
,
uint64
pa
,
uint64
sz
,
int
perm
){
if
(
mappages
(
k_pagetable
,
va
,
sz
,
pa
,
perm
)
!=
0
)
panic
(
"proc_kvmmap"
);
}
// Switch h/w page table register to the kernel's page table,
// and enable paging.
void
kvminithart
()
{
w_satp
(
MAKE_SATP
(
kernel_pagetable
));
sfence_vma
();
}
void
proc_kvminithart
(
pagetable_t
k_pagetable
){
w_satp
(
MAKE_SATP
(
k_pagetable
));
sfence_vma
();
}
// Return the address of the PTE in page table pagetable
// that corresponds to virtual address va. If alloc!=0,
...
...
@@ -113,7 +162,7 @@ uint64 kvmpa(uint64 va) {
pte_t
*
pte
;
uint64
pa
;
pte
=
walk
(
kernel
_pagetable
,
va
,
0
);
pte
=
walk
(
myproc
()
->
k
_pagetable
,
va
,
0
);
if
(
pte
==
0
)
panic
(
"kvmpa"
);
if
((
*
pte
&
PTE_V
)
==
0
)
panic
(
"kvmpa"
);
pa
=
PTE2PA
(
*
pte
);
...
...
@@ -229,20 +278,45 @@ uint64 uvmdealloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz) {
// All leaf mappings must already have been removed.
void
freewalk
(
pagetable_t
pagetable
)
{
// there are 2^9 = 512 PTEs in a page table.
// 遍历一个页表页的PTE表项
for
(
int
i
=
0
;
i
<
512
;
i
++
)
{
pte_t
pte
=
pagetable
[
i
];
/* 判断PTE的Flag位,如果还有下一级页表(即当前是根页表或次页表),
则递归调用freewalk释放页表项,并将对应的PTE清零 */
if
((
pte
&
PTE_V
)
&&
(
pte
&
(
PTE_R
|
PTE_W
|
PTE_X
))
==
0
)
{
// this PTE points to a lower-level page table.
uint64
child
=
PTE2PA
(
pte
);
freewalk
((
pagetable_t
)
child
);
pagetable
[
i
]
=
0
;
uint64
child
=
PTE2PA
(
pte
);
// 将PTE转为为物理地址
freewalk
((
pagetable_t
)
child
);
// 递归调用freewalk
pagetable
[
i
]
=
0
;
// 清零
}
else
if
(
pte
&
PTE_V
)
{
/* 如果叶子页表的虚拟地址还有映射到物理地址,报错panic。
因为调用freewalk之前应该会先uvmunmap释放物理内存 */
panic
(
"freewalk: leaf"
);
}
}
kfree
((
void
*
)
pagetable
);
kfree
((
void
*
)
pagetable
);
// 释放pagetable指向的物理页
}
// 释放进程的内核页表
void
free_proc_kpt
(
pagetable_t
pagetable
)
{
// there are 2^9 = 512 PTEs in a page table.
for
(
int
i
=
0
;
i
<
512
;
i
++
){
pte_t
pte
=
pagetable
[
i
];
if
(
pte
&
PTE_V
){
// this PTE points to a lower-level page table.
uint64
child
=
PTE2PA
(
pte
);
pagetable
[
i
]
=
0
;
if
((
pte
&
(
PTE_R
|
PTE_W
|
PTE_X
))
==
0
){
// 说明不是第三级,进行递归
free_proc_kpt
((
pagetable_t
)
child
);
}
}
}
kfree
((
void
*
)
pagetable
);
}
// Free user memory pages,
// then free page-table pages.
void
uvmfree
(
pagetable_t
pagetable
,
uint64
sz
)
{
...
...
@@ -281,6 +355,33 @@ err:
return
-
1
;
}
// 仿照uvmcopy()函数,实现将用户空间的映射添加到每个进程的内核页表
void
u2k_vmcopy
(
pagetable_t
pagetable
,
pagetable_t
k_pagetable
,
uint64
oldsz
,
uint64
newsz
){
pte_t
*
pte_from
;
pte_t
*
pte_to
;
oldsz
=
PGROUNDUP
(
oldsz
);
for
(
uint64
i
=
oldsz
;
i
<
newsz
;
i
+=
PGSIZE
){
// 对页表pagetable中虚拟地址为i进行检查,检查pte是否存在
if
((
pte_from
=
walk
(
pagetable
,
i
,
0
))
==
0
)
panic
(
"u2k_vmcopy: pte should exist"
);
// 对内核页表k_pagetable中虚拟地址为i进行检查,检查pte是否存在,若不存在则申请物理内存并映射。
if
((
pte_to
=
walk
(
k_pagetable
,
i
,
1
))
==
0
){
panic
(
"u2k_vmcopy: pte walk fail"
);
}
// 在内核模式下,无法访问设置了PTE_U的页面,
// 所以接下来要获得pagetable中虚拟地址为i的pte的标志位
// uint64 pa = PTE2PA(*pte_from);
// uint flags = (PTE_FLAGS(*pte_from)) & (~PTE_U);
// *pte_to = PA2PTE(pa) | flags;
// 感觉上面三句有点多,改成一句
*
pte_to
=
(
*
pte_from
)
&
(
~
PTE_U
);
}
}
// mark a PTE invalid for user access.
// used by exec for the user stack guard page.
void
uvmclear
(
pagetable_t
pagetable
,
uint64
va
)
{
...
...
@@ -378,4 +479,49 @@ int test_pagetable() {
uint64
gsatp
=
MAKE_SATP
(
kernel_pagetable
);
printf
(
"test_pagetable: %d
\n
"
,
satp
!=
gsatp
);
return
satp
!=
gsatp
;
}
\ No newline at end of file
}
// 辅助函数,用于递归打印页表
void
_vmprint
(
pagetable_t
pagetable
,
int
level
)
{
// there are 2^9 = 512 PTEs in a page table.
// 遍历一个页表页的PTE表项
for
(
int
i
=
0
;
i
<
512
;
i
++
)
{
pte_t
pte
=
pagetable
[
i
];
//获取第i条PTE
//虚拟地址有映射到物理地址 即有效pte
if
(
pte
&
PTE_V
)
{
// 根据level打印层级标识
for
(
int
j
=
0
;
j
<
level
;
j
++
)
{
if
(
j
==
0
)
printf
(
"||"
);
else
printf
(
" ||"
);
}
// 打印当前索引和页表项信息
if
((
pte
&
(
PTE_R
|
PTE_W
|
PTE_X
))
==
0
)
{
// 非叶子节点
printf
(
"idx: %d: pa: %p, flags: ----
\n
"
,
i
,
PTE2PA
(
pte
));
_vmprint
((
pagetable_t
)
PTE2PA
(
pte
),
level
+
1
);
// 递归调用
}
else
{
// 叶子节点 打印虚拟地址va
// uint64 va = ((uint64)pagetable) + (i << 12);
uint64
va
=
(
i
<<
12
)
;
// 计算虚拟地址
printf
(
"idx: %d: va: %p -> pa: %p, flags: %s%s%s%s
\n
"
,
i
,
va
,
PTE2PA
(
pte
),
(
pte
&
PTE_R
?
"r"
:
"-"
),
(
pte
&
PTE_W
?
"w"
:
"-"
),
(
pte
&
PTE_X
?
"x"
:
"-"
),
(
pte
&
PTE_U
?
"u"
:
"-"
));
}
}
}
}
// 外部调用的 vmprint 函数
void
vmprint
(
pagetable_t
pagetable
)
{
// 打印根页表
printf
(
"page table %p
\n
"
,
pagetable
);
// 传递level级和递归
_vmprint
(
pagetable
,
1
);
}
This diff is collapsed.
Click to expand it.
user/sh.c
+
1
−
0
View file @
cf4069b5
...
...
@@ -54,6 +54,7 @@ void panic(char *);
struct
cmd
*
parsecmd
(
char
*
);
// Execute cmd. Never returns.
__attribute__
((
noreturn
))
void
runcmd
(
struct
cmd
*
cmd
)
{
int
p
[
2
];
struct
backcmd
*
bcmd
;
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment
Menu
Explore
Projects
Groups
Topics
Snippets