Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
X
xv6-public
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
问题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
银宸时代
OS Lab Group
奖励实验
xv6-public
提交
e096f2f8
提交
e096f2f8
10月 27, 2011
创建
作者:
Silas Boyd-Wickizer
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Separate paging code from vmap code so it's easier to explore vm.c.
上级
561b41ed
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
197 行增加
和
182 行删除
+197
-182
Makefile
Makefile
+1
-0
hwvm.c
hwvm.c
+191
-0
kernel.h
kernel.h
+5
-0
vm.c
vm.c
+0
-182
没有找到文件。
Makefile
浏览文件 @
e096f2f8
...
@@ -32,6 +32,7 @@ OBJS = \
...
@@ -32,6 +32,7 @@ OBJS = \
fs.o
\
fs.o
\
ioapic.o
\
ioapic.o
\
lapic.o
\
lapic.o
\
hwvm.o
\
hz.o
\
hz.o
\
kalloc.o
\
kalloc.o
\
kbd.o
\
kbd.o
\
...
...
hwvm.c
0 → 100644
浏览文件 @
e096f2f8
#include "param.h"
#include "types.h"
#include "amd64.h"
#include "mmu.h"
#include "cpu.h"
#include "kernel.h"
#include "bits.h"
#include "spinlock.h"
#include "kalloc.h"
#include "queue.h"
#include "condvar.h"
#include "proc.h"
#include <stddef.h>
extern
pml4e_t
kpml4
[];
static
pme_t
*
descend
(
pme_t
*
dir
,
const
void
*
va
,
u64
flags
,
int
create
,
int
level
)
{
pme_t
entry
;
pme_t
*
next
;
retry:
dir
=
&
dir
[
PX
(
level
,
va
)];
entry
=
*
dir
;
if
(
entry
&
PTE_P
)
{
next
=
p2v
(
PTE_ADDR
(
entry
));
}
else
{
if
(
!
create
)
return
NULL
;
next
=
(
pme_t
*
)
kalloc
();
if
(
!
next
)
return
NULL
;
memset
(
next
,
0
,
PGSIZE
);
if
(
!
cmpswap
(
dir
,
entry
,
v2p
(
next
)
|
PTE_P
|
PTE_W
|
flags
))
{
kfree
((
void
*
)
next
);
goto
retry
;
}
}
return
next
;
}
// Return the address of the PTE in page table pgdir
// that corresponds to linear address va. If create!=0,
// create any required page table pages.
pme_t
*
walkpgdir
(
pml4e_t
*
pml4
,
const
void
*
va
,
int
create
)
{
pme_t
*
pdp
;
pme_t
*
pd
;
pme_t
*
pt
;
pdp
=
descend
(
pml4
,
va
,
PTE_U
,
create
,
3
);
if
(
pdp
==
NULL
)
return
NULL
;
pd
=
descend
(
pdp
,
va
,
PTE_U
,
create
,
2
);
if
(
pd
==
NULL
)
return
NULL
;
pt
=
descend
(
pd
,
va
,
PTE_U
,
create
,
1
);
if
(
pt
==
NULL
)
return
NULL
;
return
&
pt
[
PX
(
0
,
va
)];
}
void
updatepages
(
pme_t
*
pml4
,
void
*
begin
,
void
*
end
,
int
perm
)
{
char
*
a
,
*
last
;
pme_t
*
pte
;
a
=
PGROUNDDOWN
(
begin
);
last
=
PGROUNDDOWN
(
end
);
for
(;;)
{
pte
=
walkpgdir
(
pml4
,
a
,
1
);
if
(
pte
!=
0
)
{
if
(
perm
==
0
)
*
pte
=
0
;
else
*
pte
=
PTE_ADDR
(
*
pte
)
|
perm
|
PTE_P
;
}
if
(
a
==
last
)
break
;
a
+=
PGSIZE
;
}
}
static
void
pgmap
(
void
*
va
,
void
*
last
,
paddr
pa
)
{
pme_t
*
pdp
;
pme_t
*
pd
;
pme_t
*
pt
;
for
(;;)
{
pdp
=
descend
(
kpml4
,
va
,
0
,
1
,
3
);
pd
=
descend
(
pdp
,
va
,
0
,
1
,
2
);
pt
=
descend
(
pd
,
va
,
0
,
1
,
1
);
pt
=
&
pt
[
PX
(
0
,
va
)];
*
pt
=
pa
|
PTE_W
|
PTE_P
;
if
(
va
==
last
)
break
;
va
+=
PGSIZE
;
pa
+=
PGSIZE
;
}
}
// set up a page table to get off the ground
void
initpg
(
char
*
(
*
alloc
)(
void
))
{
// Map first 4GB to PBASE
pgmap
((
void
*
)
PBASE
,
(
void
*
)
(
PBASE
+
(
1UL
<<
32
)),
0
);
// boot.S maps first 1GB to KBASE and gets us running with kpml4
}
// Set up kernel part of a page table.
pml4e_t
*
setupkvm
(
void
)
{
pml4e_t
*
pml4
;
int
k
;
if
((
pml4
=
(
pml4e_t
*
)
kalloc
())
==
0
)
return
0
;
k
=
PX
(
3
,
PBASE
);
memset
(
&
pml4
[
0
],
0
,
8
*
k
);
memmove
(
&
pml4
[
k
],
&
kpml4
[
k
],
8
*
(
512
-
k
));
return
pml4
;
}
// Switch h/w page table register to the kernel-only page table,
// for when no process is running.
void
switchkvm
(
void
)
{
lcr3
(
v2p
(
kpml4
));
// switch to the kernel page table
}
// Switch TSS and h/w page table to correspond to process p.
void
switchuvm
(
struct
proc
*
p
)
{
u64
base
=
(
u64
)
&
mycpu
()
->
ts
;
pushcli
();
mycpu
()
->
gdt
[
TSSSEG
>>
3
]
=
(
struct
segdesc
)
SEGDESC
(
base
,
(
sizeof
(
mycpu
()
->
ts
)
-
1
),
SEG_P
|
SEG_TSS64A
);
mycpu
()
->
gdt
[(
TSSSEG
>>
3
)
+
1
]
=
(
struct
segdesc
)
SEGDESCHI
(
base
);
mycpu
()
->
ts
.
rsp
[
0
]
=
(
u64
)
myproc
()
->
kstack
+
KSTACKSIZE
;
mycpu
()
->
ts
.
iomba
=
(
u16
)
offsetof
(
struct
taskstate
,
iopb
);
ltr
(
TSSSEG
);
if
(
p
->
vmap
==
0
||
p
->
vmap
->
pml4
==
0
)
panic
(
"switchuvm: no vmap/pml4"
);
lcr3
(
v2p
(
p
->
vmap
->
pml4
));
// switch to new address space
popcli
();
}
static
void
freepm
(
pme_t
*
pm
,
int
level
)
{
int
i
;
if
(
level
!=
0
)
{
for
(
i
=
0
;
i
<
512
;
i
++
)
{
if
(
pm
[
i
]
&
PTE_P
)
freepm
(
p2v
(
PTE_ADDR
(
pm
[
i
])),
level
-
1
);
}
}
kfree
(
pm
);
}
// Free a page table and all the physical memory pages
// in the user part.
void
freevm
(
pml4e_t
*
pml4
)
{
int
k
;
int
i
;
if
(
pml4
==
0
)
panic
(
"freevm: no pgdir"
);
// Don't free kernel portion of the pml4
k
=
PX
(
3
,
PBASE
);
for
(
i
=
0
;
i
<
k
;
i
++
)
{
if
(
pml4
[
i
]
&
PTE_P
)
{
freepm
(
p2v
(
PTE_ADDR
(
pml4
[
i
])),
2
);
}
}
kfree
(
pml4
);
}
kernel.h
浏览文件 @
e096f2f8
...
@@ -81,6 +81,11 @@ int dirlink(struct inode*, char*, u32);
...
@@ -81,6 +81,11 @@ int dirlink(struct inode*, char*, u32);
void
dir_init
(
struct
inode
*
dp
);
void
dir_init
(
struct
inode
*
dp
);
void
dir_flush
(
struct
inode
*
dp
);
void
dir_flush
(
struct
inode
*
dp
);
// hwvm.c
void
freevm
(
pml4e_t
*
);
pml4e_t
*
setupkvm
(
void
);
pme_t
*
walkpgdir
(
pml4e_t
*
,
const
void
*
,
int
);
// hz.c
// hz.c
void
microdelay
(
u64
);
void
microdelay
(
u64
);
...
...
vm.c
浏览文件 @
e096f2f8
...
@@ -12,68 +12,6 @@
...
@@ -12,68 +12,6 @@
#include "proc.h"
#include "proc.h"
#include <stddef.h>
#include <stddef.h>
extern
char
data
[];
// defined in data.S
extern
pml4e_t
kpml4
[];
extern
char
*
pgalloc
(
void
);
static
pme_t
*
descend
(
pme_t
*
dir
,
const
void
*
va
,
u64
flags
,
int
create
,
int
level
)
{
pme_t
entry
;
pme_t
*
next
;
retry:
dir
=
&
dir
[
PX
(
level
,
va
)];
entry
=
*
dir
;
if
(
entry
&
PTE_P
)
{
next
=
p2v
(
PTE_ADDR
(
entry
));
}
else
{
if
(
!
create
)
return
NULL
;
next
=
(
pme_t
*
)
pgalloc
();
if
(
!
next
)
return
NULL
;
memset
(
next
,
0
,
PGSIZE
);
if
(
!
cmpswap
(
dir
,
entry
,
v2p
(
next
)
|
PTE_P
|
PTE_W
|
flags
))
{
kfree
((
void
*
)
next
);
goto
retry
;
}
}
return
next
;
}
static
void
pgmap
(
void
*
va
,
void
*
last
,
paddr
pa
)
{
pme_t
*
pdp
;
pme_t
*
pd
;
pme_t
*
pt
;
for
(;;)
{
pdp
=
descend
(
kpml4
,
va
,
0
,
1
,
3
);
pd
=
descend
(
pdp
,
va
,
0
,
1
,
2
);
pt
=
descend
(
pd
,
va
,
0
,
1
,
1
);
pt
=
&
pt
[
PX
(
0
,
va
)];
*
pt
=
pa
|
PTE_W
|
PTE_P
;
if
(
va
==
last
)
break
;
va
+=
PGSIZE
;
pa
+=
PGSIZE
;
}
}
// set up a page table to get off the ground
void
initpg
(
char
*
(
*
alloc
)(
void
))
{
// Map first 4GB to PBASE
pgmap
((
void
*
)
PBASE
,
(
void
*
)
(
PBASE
+
(
1UL
<<
32
)),
0
);
// boot.S maps first 1GB to KBASE and gets us running with kpml4
}
// Set up CPU's kernel segment descriptors.
// Set up CPU's kernel segment descriptors.
// Run once at boot time on each CPU.
// Run once at boot time on each CPU.
void
void
...
@@ -90,47 +28,6 @@ inittls(void)
...
@@ -90,47 +28,6 @@ inittls(void)
c
->
kmem
=
&
kmems
[
cpunum
()];
c
->
kmem
=
&
kmems
[
cpunum
()];
}
}
// Set up kernel part of a page table.
static
pml4e_t
*
setupkvm
(
void
)
{
pml4e_t
*
pml4
;
int
k
;
if
((
pml4
=
(
pml4e_t
*
)
kalloc
())
==
0
)
return
0
;
k
=
PX
(
3
,
PBASE
);
memset
(
&
pml4
[
0
],
0
,
8
*
k
);
memmove
(
&
pml4
[
k
],
&
kpml4
[
k
],
8
*
(
512
-
k
));
return
pml4
;
}
// Switch h/w page table register to the kernel-only page table,
// for when no process is running.
void
switchkvm
(
void
)
{
lcr3
(
v2p
(
kpml4
));
// switch to the kernel page table
}
// Switch TSS and h/w page table to correspond to process p.
void
switchuvm
(
struct
proc
*
p
)
{
u64
base
=
(
u64
)
&
mycpu
()
->
ts
;
pushcli
();
mycpu
()
->
gdt
[
TSSSEG
>>
3
]
=
(
struct
segdesc
)
SEGDESC
(
base
,
(
sizeof
(
mycpu
()
->
ts
)
-
1
),
SEG_P
|
SEG_TSS64A
);
mycpu
()
->
gdt
[(
TSSSEG
>>
3
)
+
1
]
=
(
struct
segdesc
)
SEGDESCHI
(
base
);
mycpu
()
->
ts
.
rsp
[
0
]
=
(
u64
)
myproc
()
->
kstack
+
KSTACKSIZE
;
mycpu
()
->
ts
.
iomba
=
(
u16
)
offsetof
(
struct
taskstate
,
iopb
);
ltr
(
TSSSEG
);
if
(
p
->
vmap
==
0
||
p
->
vmap
->
pml4
==
0
)
panic
(
"switchuvm: no vmap/pml4"
);
lcr3
(
v2p
(
p
->
vmap
->
pml4
));
// switch to new address space
popcli
();
}
static
struct
vma
*
static
struct
vma
*
vma_alloc
(
void
)
vma_alloc
(
void
)
{
{
...
@@ -160,43 +57,6 @@ vma_free(void *p)
...
@@ -160,43 +57,6 @@ vma_free(void *p)
kmfree
(
e
);
kmfree
(
e
);
}
}
static
void
freepm
(
pme_t
*
pm
,
int
level
)
{
int
i
;
if
(
level
!=
0
)
{
for
(
i
=
0
;
i
<
512
;
i
++
)
{
if
(
pm
[
i
]
&
PTE_P
)
freepm
(
p2v
(
PTE_ADDR
(
pm
[
i
])),
level
-
1
);
}
}
kfree
(
pm
);
}
// Free a page table and all the physical memory pages
// in the user part.
static
void
freevm
(
pml4e_t
*
pml4
)
{
int
k
;
int
i
;
if
(
pml4
==
0
)
panic
(
"freevm: no pgdir"
);
// Don't free kernel portion of the pml4
k
=
PX
(
3
,
PBASE
);
for
(
i
=
0
;
i
<
k
;
i
++
)
{
if
(
pml4
[
i
]
&
PTE_P
)
{
freepm
(
p2v
(
PTE_ADDR
(
pml4
[
i
])),
2
);
}
}
kfree
(
pml4
);
}
#ifdef TREE
#ifdef TREE
struct
state
{
struct
state
{
int
share
;
int
share
;
...
@@ -441,48 +301,6 @@ copyout(struct vmap *vmap, uptr va, void *p, u64 len)
...
@@ -441,48 +301,6 @@ copyout(struct vmap *vmap, uptr va, void *p, u64 len)
return
0
;
return
0
;
}
}
// Return the address of the PTE in page table pgdir
// that corresponds to linear address va. If create!=0,
// create any required page table pages.
static
pme_t
*
walkpgdir
(
pml4e_t
*
pml4
,
const
void
*
va
,
int
create
)
{
pme_t
*
pdp
;
pme_t
*
pd
;
pme_t
*
pt
;
pdp
=
descend
(
pml4
,
va
,
PTE_U
,
create
,
3
);
if
(
pdp
==
NULL
)
return
NULL
;
pd
=
descend
(
pdp
,
va
,
PTE_U
,
create
,
2
);
if
(
pd
==
NULL
)
return
NULL
;
pt
=
descend
(
pd
,
va
,
PTE_U
,
create
,
1
);
if
(
pt
==
NULL
)
return
NULL
;
return
&
pt
[
PX
(
0
,
va
)];
}
void
updatepages
(
pme_t
*
pml4
,
void
*
begin
,
void
*
end
,
int
perm
)
{
char
*
a
,
*
last
;
pme_t
*
pte
;
a
=
PGROUNDDOWN
(
begin
);
last
=
PGROUNDDOWN
(
end
);
for
(;;)
{
pte
=
walkpgdir
(
pml4
,
a
,
1
);
if
(
pte
!=
0
)
{
if
(
perm
==
0
)
*
pte
=
0
;
else
*
pte
=
PTE_ADDR
(
*
pte
)
|
perm
|
PTE_P
;
}
if
(
a
==
last
)
break
;
a
+=
PGSIZE
;
}
}
struct
vmnode
*
struct
vmnode
*
vmn_copy
(
struct
vmnode
*
n
)
vmn_copy
(
struct
vmnode
*
n
)
{
{
...
...
编写
预览
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论