Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
X
xv6-public
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
问题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
银宸时代
OS Lab Group
奖励实验
xv6-public
提交
649c423f
提交
649c423f
6月 07, 2011
创建
作者:
Frans Kaashoek
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
new mem layout: kernel at KERNBASE, i.e., kernel va's are not equal to pa's
上级
7a560836
隐藏空白字符变更
内嵌
并排
正在显示
22 个修改的文件
包含
243 行增加
和
92 行删除
+243
-92
Makefile
Makefile
+2
-2
bootmain.c
bootmain.c
+6
-5
bootother.S
bootother.S
+16
-8
console.c
console.c
+2
-1
defs.h
defs.h
+3
-0
exec.c
exec.c
+1
-0
fs.c
fs.c
+1
-1
ide.c
ide.c
+2
-1
kalloc.c
kalloc.c
+23
-5
main.c
main.c
+19
-9
mmu.h
mmu.h
+1
-8
mp.c
mp.c
+3
-1
multiboot.S
multiboot.S
+7
-4
param.h
param.h
+0
-2
proc.c
proc.c
+4
-1
proc.h
proc.h
+3
-3
spinlock.c
spinlock.c
+2
-1
syscall.c
syscall.c
+1
-0
sysproc.c
sysproc.c
+2
-1
trap.c
trap.c
+2
-2
vm.c
vm.c
+119
-37
x86.h
x86.h
+24
-0
没有找到文件。
Makefile
浏览文件 @
649c423f
...
...
@@ -114,7 +114,7 @@ bootother: bootother.S
$(CC)
$(CFLAGS)
-nostdinc
-I
.
-c
bootother.S
$(LD)
$(LDFLAGS)
-N
-e
start
-Ttext
0x7000
-o
bootother.out bootother.o
$(OBJCOPY)
-S
-O
binary bootother.out bootother
$(OBJDUMP)
-S
bootother.o
>
bootother.asm
$(OBJDUMP)
-S
bootother.o
ut
>
bootother.asm
initcode
:
initcode.S
$(CC)
$(CFLAGS)
-nostdinc
-I
.
-c
initcode.S
...
...
@@ -123,7 +123,7 @@ initcode: initcode.S
$(OBJDUMP)
-S
initcode.o
>
initcode.asm
kernel
:
$(OBJS) multiboot.o data.o bootother initcode
$(LD)
$(LDFLAGS)
-T
text
0x100000
-e
main
-o
kernel multiboot.o data.o
$(OBJS)
-b
binary initcode bootother
$(LD)
$(LDFLAGS)
-T
kernel.ld
-e
multiboot_entry
-o
kernel multiboot.o data.o
$(OBJS)
-b
binary initcode bootother
$(OBJDUMP)
-S
kernel
>
kernel.asm
$(OBJDUMP)
-t
kernel |
sed
'1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d'
>
kernel.sym
...
...
bootmain.c
浏览文件 @
649c423f
...
...
@@ -8,6 +8,7 @@
#include "types.h"
#include "elf.h"
#include "x86.h"
#include "memlayout.h"
#define SECTSIZE 512
...
...
@@ -19,7 +20,7 @@ bootmain(void)
struct
elfhdr
*
elf
;
struct
proghdr
*
ph
,
*
eph
;
void
(
*
entry
)(
void
);
uchar
*
v
a
;
uchar
*
p
a
;
elf
=
(
struct
elfhdr
*
)
0x10000
;
// scratch space
...
...
@@ -34,15 +35,15 @@ bootmain(void)
ph
=
(
struct
proghdr
*
)((
uchar
*
)
elf
+
elf
->
phoff
);
eph
=
ph
+
elf
->
phnum
;
for
(;
ph
<
eph
;
ph
++
){
va
=
(
uchar
*
)
ph
->
v
a
;
readseg
(
v
a
,
ph
->
filesz
,
ph
->
offset
);
pa
=
(
uchar
*
)
ph
->
p
a
;
readseg
(
p
a
,
ph
->
filesz
,
ph
->
offset
);
if
(
ph
->
memsz
>
ph
->
filesz
)
stosb
(
v
a
+
ph
->
filesz
,
0
,
ph
->
memsz
-
ph
->
filesz
);
stosb
(
p
a
+
ph
->
filesz
,
0
,
ph
->
memsz
-
ph
->
filesz
);
}
// Call the entry point from the ELF header.
// Does not return!
entry
=
(
void
(
*
)(
void
))(
elf
->
entry
);
entry
=
(
void
(
*
)(
void
))(
elf
->
entry
&
0xFFFFFF
);
// XXX get ridd off 0xFFFFF
entry
();
}
...
...
bootother.S
浏览文件 @
649c423f
#include "asm.h"
#include "memlayout.h"
# Each non-boot CPU ("AP") is started up in response to a STARTUP
# IPI from the boot CPU. Section B.4.2 of the Multi-Processor
...
...
@@ -24,10 +25,16 @@
#define CR0_PE 1
#define RELOC1(x) ((x) + KERNBASE) // same as V2P, but without casts
.code16
.globl start
start:
cli
cli
## movw $0xb800, %ax
## movw %ax, %es
## movw $65, %es:(0x0)
xorw %ax,%ax
movw %ax,%ds
...
...
@@ -38,13 +45,14 @@ start:
movl %cr0, %eax
orl $CR0_PE, %eax
movl %eax, %cr0
//PAGEBREAK!
ljmp $(SEG_KCODE<<3), $start32
ljmpl $(SEG_KCODE<< 3), $(start32+KERNBASE)
.code32
start32:
# movw $65, 0xb8002
movw $(SEG_KDATA<<3), %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
...
...
@@ -53,10 +61,10 @@ start32:
movw %ax, %gs
# switch to the stack allocated by bootothers()
movl
start-4
, %esp
movl
RELOC1(start-4)
, %esp
# call mpmain()
call *(
start
-8)
call *(
RELOC1(start)
-8)
movw $0x8a00, %ax
movw %ax, %dx
...
...
@@ -69,8 +77,8 @@ spin:
.p2align 2
gdt:
SEG_NULLASM
SEG_ASM(STA_X|STA_R,
0x0
, 0xffffffff)
SEG_ASM(STA_W,
0x0
, 0xffffffff)
SEG_ASM(STA_X|STA_R,
-KERNBASE
, 0xffffffff)
SEG_ASM(STA_W,
-KERNBASE
, 0xffffffff)
gdtdesc:
.word (gdtdesc - gdt - 1)
...
...
console.c
浏览文件 @
649c423f
...
...
@@ -10,6 +10,7 @@
#include "condvar.h"
#include "fs.h"
#include "file.h"
#include "memlayout.h"
#include "mmu.h"
#include "queue.h"
#include "proc.h"
...
...
@@ -177,7 +178,7 @@ panic(char *s)
//PAGEBREAK: 50
#define BACKSPACE 0x100
#define CRTPORT 0x3d4
static
ushort
*
crt
=
(
ushort
*
)
0xb8000
;
// CGA memory
static
ushort
*
crt
=
(
ushort
*
)
P2V
(
0xb8000
)
;
// CGA memory
static
void
cgaputc
(
int
c
)
...
...
defs.h
浏览文件 @
649c423f
...
...
@@ -73,6 +73,7 @@ extern uchar ioapicid;
void
ioapicinit
(
void
);
// kalloc.c
char
*
pgalloc
(
void
);
void
kinit
(
void
);
char
*
kalloc
(
void
);
void
kfree
(
char
*
);
...
...
@@ -187,6 +188,8 @@ void uartintr(void);
void
uartputc
(
int
);
// vm.c
void
printpgdir
(
pde_t
*
);
void
pginit
(
char
*
(
*
alloc
)());
void
seginit
(
void
);
void
kvmalloc
(
void
);
void
vmenable
(
void
);
...
...
exec.c
浏览文件 @
649c423f
#include "types.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
...
...
fs.c
浏览文件 @
649c423f
...
...
@@ -605,7 +605,7 @@ namex(char *path, int nameiparent, char *name)
{
struct
inode
*
ip
,
*
next
;
if
(
*
path
==
'/'
)
if
(
*
path
==
'/'
)
ip
=
iget
(
ROOTDEV
,
ROOTINO
);
else
ip
=
idup
(
proc
->
cwd
);
...
...
ide.c
浏览文件 @
649c423f
...
...
@@ -3,6 +3,7 @@
#include "types.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
...
...
@@ -94,7 +95,7 @@ void
ideintr
(
void
)
{
struct
buf
*
b
;
// Take first buffer off queue.
acquire
(
&
idelock
);
if
((
b
=
idequeue
)
==
0
){
...
...
kalloc.c
浏览文件 @
649c423f
...
...
@@ -5,6 +5,7 @@
#include "types.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
...
...
@@ -17,9 +18,24 @@ void kminit(void);
struct
kmem
kmems
[
NCPU
];
extern
char
end
[];
// first address after kernel loaded from ELF file
char
*
newend
;
static
int
kinited
__attribute__
((
aligned
(
CACHELINE
)));
// simple page allocator to get off the ground during boot
char
*
pgalloc
(
void
)
{
if
(
newend
==
0
)
newend
=
end
;
void
*
p
=
(
void
*
)
PGROUNDUP
((
uint
)
newend
);
memset
(
p
,
0
,
PGSIZE
);
newend
=
newend
+
PGSIZE
;
return
p
;
}
static
void
__attribute__
((
unused
))
kmemprint
(
void
)
{
...
...
@@ -42,8 +58,9 @@ kfree_pool(struct kmem *m, char *v)
{
struct
run
*
r
;
if
((
uint
)
v
%
PGSIZE
||
v
<
end
||
(
uint
)
v
>=
PHYSTOP
)
panic
(
"kfree"
);
if
((
uint
)
v
%
PGSIZE
||
v
<
end
||
v2p
(
v
)
>=
PHYSTOP
)
{
panic
(
"kfree_pool"
);
}
// Fill with junk to catch dangling refs.
if
(
kinited
)
...
...
@@ -83,9 +100,10 @@ kinit(void)
initlock
(
&
kmems
[
c
].
lock
,
kmems
[
c
].
name
);
}
p
=
(
char
*
)
PGROUNDUP
((
uint
)
end
);
for
(;
p
+
PGSIZE
<=
(
char
*
)
PHYSTOP
;
p
+=
PGSIZE
)
kfree_pool
(
&
kmems
[((
uintptr_t
)
p
)
/
(
PHYSTOP
/
NCPU
)],
p
);
p
=
(
char
*
)
PGROUNDUP
((
uint
)
newend
);
for
(;
p
+
PGSIZE
<=
(
char
*
)
p2v
(
PHYSTOP
);
p
+=
PGSIZE
)
{
kfree_pool
(
&
kmems
[((
uintptr_t
)
v2p
(
p
))
/
(
PHYSTOP
/
NCPU
)],
p
);
}
kminit
();
kinited
=
1
;
}
...
...
main.c
浏览文件 @
649c423f
#include "types.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
...
...
@@ -12,6 +13,7 @@ static void bootothers(void);
static
void
mpmain
(
void
);
void
jmpkstack
(
void
)
__attribute__
((
noreturn
));
void
mainc
(
void
);
static
volatile
int
newpgdir
;
// Bootstrap processor starts running C code here.
// Allocate a real stack and switch to it, first
...
...
@@ -19,6 +21,7 @@ void mainc(void);
int
main
(
void
)
{
pginit
(
pgalloc
);
mpinit
();
// collect info about this machine
lapicinit
(
mpbcpu
());
seginit
();
// set up segments
...
...
@@ -49,7 +52,6 @@ mainc(void)
ioapicinit
();
// another interrupt controller
consoleinit
();
// I/O devices & their interrupts
uartinit
();
// serial port
kvmalloc
();
// initialize the kernel page table
rcuinit
();
// initialize rcu module
nsinit
();
// initialize name space module
pinit
();
// process table
...
...
@@ -62,6 +64,8 @@ mainc(void)
timerinit
();
// uniprocessor timer
userinit
();
// first user process
bootothers
();
// start other processors
kvmalloc
();
// new kernel page table wo. bottom mapped
newpgdir
=
1
;
// Finish setting up this processor in mpmain.
mpmain
();
}
...
...
@@ -70,16 +74,22 @@ mainc(void)
// Bootstrap CPU comes here from mainc().
// Other CPUs jump here from bootother.S.
static
void
mp
main
(
void
)
mp
boot
(
void
)
{
if
(
cpunum
()
!=
mpbcpu
()){
seginit
();
lapicinit
(
cpunum
());
}
vmenable
();
// turn on paging
seginit
();
lapicinit
(
cpunum
());
mpmain
();
}
static
void
mpmain
(
void
)
{
cprintf
(
"cpu%d: starting
\n
"
,
cpu
->
id
);
idtinit
();
// load idt register
xchg
(
&
cpu
->
booted
,
1
);
// tell bootothers() we're up
while
(
!
newpgdir
)
;
// wait until we have new page dir
switchkvm
();
// switch to new page dir
scheduler
();
// start running processes
}
...
...
@@ -95,7 +105,7 @@ bootothers(void)
// Write bootstrap code to unused memory at 0x7000.
// The linker has placed the image of bootother.S in
// _binary_bootother_start.
code
=
(
uchar
*
)
0x7000
;
code
=
p2v
(
0x7000
)
;
memmove
(
code
,
_binary_bootother_start
,
(
uint
)
_binary_bootother_size
);
for
(
c
=
cpus
;
c
<
cpus
+
ncpu
;
c
++
){
...
...
@@ -107,9 +117,9 @@ bootothers(void)
// its first instruction.
stack
=
kalloc
();
*
(
void
**
)(
code
-
4
)
=
stack
+
KSTACKSIZE
;
*
(
void
**
)(
code
-
8
)
=
mp
main
;
*
(
void
**
)(
code
-
8
)
=
mp
boot
;
lapicstartap
(
c
->
id
,
(
uint
)
code
);
lapicstartap
(
c
->
id
,
v2p
(
code
)
);
// Wait for cpu to finish mpmain()
while
(
c
->
booted
==
0
)
...
...
mmu.h
浏览文件 @
649c423f
...
...
@@ -42,6 +42,7 @@
#define CR0_CD 0x40000000 // Cache Disable
#define CR0_PG 0x80000000 // Paging
//PAGEBREAK!
// Segment Descriptor
struct
segdesc
{
...
...
@@ -111,18 +112,10 @@ struct segdesc {
// construct linear address from indexes and offset
#define PGADDR(d, t, o) ((uint)((d) << PDXSHIFT | (t) << PTXSHIFT | (o)))
// turn a kernel linear address into a physical address.
// all of the kernel data structures have linear and
// physical addresses that are equal.
#define PADDR(a) ((uint)(a))
// Page directory and page table constants.
#define NPDENTRIES 1024 // page directory entries per page directory
#define NPTENTRIES 1024 // page table entries per page table
#define PGSIZE 4096 // bytes mapped by a page
#define PGSHIFT 12 // log2(PGSIZE)
#define PTXSHIFT 12 // offset of PTX in a linear address
#define PDXSHIFT 22 // offset of PDX in a linear address
...
...
mp.c
浏览文件 @
649c423f
...
...
@@ -5,6 +5,7 @@
#include "types.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mp.h"
#include "x86.h"
#include "mmu.h"
...
...
@@ -42,6 +43,7 @@ mpsearch1(uchar *addr, int len)
{
uchar
*
e
,
*
p
;
addr
=
p2v
((
uint
)
addr
);
e
=
addr
+
len
;
for
(
p
=
addr
;
p
<
e
;
p
+=
sizeof
(
struct
mp
))
if
(
memcmp
(
p
,
"_MP_"
,
4
)
==
0
&&
sum
(
p
,
sizeof
(
struct
mp
))
==
0
)
...
...
@@ -86,7 +88,7 @@ mpconfig(struct mp **pmp)
if
((
mp
=
mpsearch
())
==
0
||
mp
->
physaddr
==
0
)
return
0
;
conf
=
(
struct
mpconf
*
)
mp
->
physaddr
;
conf
=
(
struct
mpconf
*
)
p2v
((
uint
)
mp
->
physaddr
)
;
if
(
memcmp
(
conf
,
"PCMP"
,
4
)
!=
0
)
return
0
;
if
(
conf
->
version
!=
1
&&
conf
->
version
!=
4
)
...
...
multiboot.S
浏览文件 @
649c423f
...
...
@@ -15,6 +15,9 @@
# }
#include "asm.h"
#include "memlayout.h"
#define RELOC(x) ((x) - KERNBASE) // same as V2P, but without casts
#define STACK 4096
...
...
@@ -42,7 +45,7 @@ multiboot_header:
# boot loader - bootasm.S - sets up.
.globl multiboot_entry
multiboot_entry:
lgdt
gdtdesc
lgdt
RELOC(gdtdesc)
ljmp $(SEG_KCODE<<3), $mbstart32
mbstart32:
...
...
@@ -65,11 +68,11 @@ spin:
.p2align 2 # force 4 byte alignment
gdt:
SEG_NULLASM # null seg
SEG_ASM(STA_X|STA_R,
0x0
, 0xffffffff) # code seg
SEG_ASM(STA_W,
0x0
, 0xffffffff) # data seg
SEG_ASM(STA_X|STA_R,
-KERNBASE
, 0xffffffff) # code seg
SEG_ASM(STA_W,
-KERNBASE
, 0xffffffff) # data seg
gdtdesc:
.word (gdtdesc - gdt - 1) # sizeof(gdt) - 1
.long
gdt
# address gdt
.long
RELOC(gdt)
# address gdt
.comm stack, STACK
param.h
浏览文件 @
649c423f
...
...
@@ -7,8 +7,6 @@
#define NINODE 50 // maximum number of active i-nodes
#define NDEV 10 // maximum major device number
#define ROOTDEV 1 // device number of file system root disk
#define USERTOP 0xA0000 // end of user address space
#define PHYSTOP 0x10000000 // use phys mem up to here as free pool
#define MAXARG 32 // max exec arguments
#define MAXNAME 16 // max string names
#define MINCYCTHRESH 1000000 // min cycles a proc executes on a core before allowed to be stolen
...
...
proc.c
浏览文件 @
649c423f
#include "types.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "x86.h"
#include "spinlock.h"
...
...
@@ -506,6 +507,7 @@ scheduler(void)
// cprintf("%d: no longer idle, running %d\n", cpu->id, p->pid);
idle
[
cpu
->
id
]
=
0
;
}
release
(
&
runq
->
lock
);
// Switch to chosen process. It is the process's job
...
...
@@ -560,6 +562,7 @@ sched(void)
proc
->
curcycles
+=
rdtsc
()
-
proc
->
tsc
;
mtrace_fcall_register
(
proc
->
pid
,
0
,
0
,
mtrace_pause
);
mtrace_call_set
(
0
,
cpunum
());
swtch
(
&
proc
->
context
,
cpu
->
scheduler
);
cpu
->
intena
=
intena
;
}
...
...
@@ -587,7 +590,7 @@ forkret(void)
// in which to call cv_sleep().
if
(
proc
->
cwd
==
0
)
proc
->
cwd
=
namei
(
"/"
);
// Return to "caller", actually trapret (see allocproc).
}
...
...
proc.h
浏览文件 @
649c423f
...
...
@@ -143,7 +143,7 @@ extern struct ns *nspid;
// holding those two variables in the local cpu's struct cpu.
// This is similar to how thread-local variables are implemented
// in thread libraries such as Linux pthreads.
extern
struct
cpu
*
cpu
__asm
(
"%gs:0"
);
// &cpus[cpunum()]
extern
struct
cpu
*
cpu
__asm
(
"%gs:0"
);
// &cpus[cpunum()]
.cpu
extern
struct
proc
*
proc
__asm
(
"%gs:4"
);
// cpus[cpunum()].proc
extern
struct
kmem
*
kmem
__asm
(
"%gs:8"
);
// &
kmems[cpunum()]
extern
struct
runq
*
runq
__asm
(
"%gs:12"
);
// &
runqs[cpunum()]
extern
struct
kmem
*
kmem
__asm
(
"%gs:8"
);
// &
cpu[cpunum()].kmem
extern
struct
runq
*
runq
__asm
(
"%gs:12"
);
// &
cpu[cpunum()].runq
spinlock.c
浏览文件 @
649c423f
...
...
@@ -4,6 +4,7 @@
#include "defs.h"
#include "param.h"
#include "x86.h"
#include "memlayout.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
...
...
@@ -94,7 +95,7 @@ getcallerpcs(void *v, uint pcs[])
ebp
=
(
uint
*
)
v
-
2
;
for
(
i
=
0
;
i
<
10
;
i
++
){
if
(
ebp
==
0
||
ebp
<
(
uint
*
)
0x100000
||
ebp
==
(
uint
*
)
0xffffffff
)
if
(
ebp
==
0
||
ebp
<
(
uint
*
)
KERNBASE
||
ebp
==
(
uint
*
)
0xffffffff
)
break
;
pcs
[
i
]
=
ebp
[
1
];
// saved %eip
ebp
=
(
uint
*
)
ebp
[
0
];
// saved %ebp
...
...
syscall.c
浏览文件 @
649c423f
#include "types.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
...
...
sysproc.c
浏览文件 @
649c423f
...
...
@@ -2,6 +2,7 @@
#include "x86.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
...
...
@@ -135,7 +136,7 @@ sys_unmap(void)
(
void
*
)
(
PGROUNDDOWN
(
addr
)),
(
void
*
)
(
PGROUNDDOWN
(
addr
)
+
PGROUNDUP
(
len
)));
cli
();
lcr3
(
PADDR
(
proc
->
vmap
->
pgdir
));
lcr3
(
v2p
(
proc
->
vmap
->
pgdir
));
for
(
uint
i
=
0
;
i
<
ncpu
;
i
++
)
if
(
i
!=
cpu
->
id
)
lapic_tlbflush
(
i
);
...
...
trap.c
浏览文件 @
649c423f
#include "types.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
...
...
@@ -32,7 +33,7 @@ tvinit(void)
void
idtinit
(
void
)
{
lidt
(
idt
,
sizeof
(
idt
));
lidt
(
idt
,
sizeof
(
idt
));
}
//PAGEBREAK: 41
...
...
@@ -48,7 +49,6 @@ trap(struct trapframe *tf)
exit
();
return
;
}
switch
(
tf
->
trapno
){
case
T_IRQ0
+
IRQ_TIMER
:
if
(
cpu
->
id
==
0
){
...
...
vm.c
浏览文件 @
649c423f
...
...
@@ -2,6 +2,7 @@
#include "types.h"
#include "defs.h"
#include "x86.h"
#include "memlayout.h"
#include "mmu.h"
#include "spinlock.h"
#include "condvar.h"
...
...
@@ -14,6 +15,64 @@ extern char data[]; // defined in data.S
static
pde_t
*
kpgdir
__attribute__
((
aligned
(
CACHELINE
)));
// for use in scheduler()
struct
segdesc
gdt
[
NSEGS
];
// page map for during boot
static
void
pgmap
(
void
*
va
,
void
*
last
,
uint
pa
)
{
pde_t
*
pde
;
pte_t
*
pgtab
;
pte_t
*
pte
;
for
(;;){
pde
=
&
kpgdir
[
PDX
(
va
)];
pde_t
pdev
=
*
pde
;
if
(
pdev
==
0
)
{
pgtab
=
(
pte_t
*
)
pgalloc
();
*
pde
=
v2p
(
pgtab
)
|
PTE_P
|
PTE_W
;
}
else
{
pgtab
=
(
pte_t
*
)
p2v
(
PTE_ADDR
(
pdev
));
}
pte
=
&
pgtab
[
PTX
(
va
)];
*
pte
=
pa
|
PTE_W
|
PTE_P
;
if
(
va
==
last
)
break
;
va
+=
PGSIZE
;
pa
+=
PGSIZE
;
}
}
// set up a page table to get off the ground
void
pginit
(
char
*
(
*
alloc
)(
void
))
{
uint
cr0
;
kpgdir
=
(
pde_t
*
)
alloc
();
pgmap
((
void
*
)
0
,
(
void
*
)
PHYSTOP
,
0
);
pgmap
((
void
*
)
KERNBASE
,
(
void
*
)
(
KERNBASE
+
PHYSTOP
),
0
);
pgmap
((
void
*
)
0xFE000000
,
0
,
0xFE000000
);
switchkvm
();
// load kpgdir into cr3
cr0
=
rcr0
();
cr0
|=
CR0_PG
;
lcr0
(
cr0
);
// paging on
// new gdt
gdt
[
SEG_KCODE
]
=
SEG
(
STA_X
|
STA_R
,
0
,
0xffffffff
,
0
);
gdt
[
SEG_KDATA
]
=
SEG
(
STA_W
,
0
,
0xffffffff
,
0
);
lgdt
((
void
*
)
v2p
(
gdt
),
sizeof
(
gdt
));
loadgs
(
SEG_KDATA
<<
3
);
loadfs
(
SEG_KDATA
<<
3
);
loades
(
SEG_KDATA
<<
3
);
loadds
(
SEG_KDATA
<<
3
);
loadss
(
SEG_KDATA
<<
3
);
__asm
volatile
(
"ljmp %0,$1f
\n
1:
\n
"
::
"i"
(
SEG_KCODE
<<
3
));
// reload cs
}
// Set up CPU's kernel segment descriptors.
// Run once at boot time on each CPU.
void
...
...
@@ -34,7 +93,8 @@ seginit(void)
// Map cpu, curproc, kmem, runq
c
->
gdt
[
SEG_KCPU
]
=
SEG
(
STA_W
,
&
c
->
cpu
,
16
,
0
);
lgdt
(
c
->
gdt
,
sizeof
(
c
->
gdt
));
// lgt((void *) v2p((void*)(c->gdt)), sizeof(c->gdt));
lgdt
((
void
*
)(
c
->
gdt
),
sizeof
(
c
->
gdt
));
loadgs
(
SEG_KCPU
<<
3
);
// Initialize cpu-local storage.
...
...
@@ -44,6 +104,31 @@ seginit(void)
runq
=
&
runqs
[
cpunum
()];
}
void
printpgdir
(
pde_t
*
pgdir
)
{
pde_t
*
pde
;
pte_t
*
pgtab
;
pte_t
pte
;
for
(
uint
i
=
0
;
i
<
NPDENTRIES
;
i
++
)
{
pde
=
&
pgdir
[
i
];
pde_t
pdev
=
*
pde
;
if
(
pdev
&
PTE_P
)
{
pgtab
=
(
pte_t
*
)
p2v
(
PTE_ADDR
(
pdev
));
cprintf
(
"%d: p 0x%x v 0x%x
\n
"
,
i
,
PTE_ADDR
(
pdev
),
pgtab
);
for
(
uint
j
=
0
;
j
<
NPTENTRIES
;
j
++
)
{
pte
=
pgtab
[
j
];
if
(
pte
&
PTE_P
)
{
void
*
pg
=
p2v
(
PTE_ADDR
(
pte
));
if
(
pg
!=
0
)
;
// cprintf(" %d: 0x%x v 0x%x\n", j, pte, pg);
}
}
}
}
}
// 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.
...
...
@@ -57,7 +142,7 @@ walkpgdir(pde_t *pgdir, const void *va, int create)
pde
=
&
pgdir
[
PDX
(
va
)];
pde_t
pdev
=
*
pde
;
if
(
pdev
&
PTE_P
){
pgtab
=
(
pte_t
*
)
PTE_ADDR
(
pdev
);
pgtab
=
(
pte_t
*
)
p2v
(
PTE_ADDR
(
pdev
)
);
}
else
{
if
(
!
create
||
(
pgtab
=
(
pte_t
*
)
kalloc
())
==
0
)
return
0
;
...
...
@@ -66,7 +151,7 @@ walkpgdir(pde_t *pgdir, const void *va, int create)
// The permissions here are overly generous, but they can
// be further restricted by the permissions in the page table
// entries, if necessary.
if
(
!
__sync_bool_compare_and_swap
(
pde
,
pdev
,
PADDR
(
pgtab
)
|
PTE_P
|
PTE_W
|
PTE_U
))
{
if
(
!
__sync_bool_compare_and_swap
(
pde
,
pdev
,
v2p
(
pgtab
)
|
PTE_P
|
PTE_W
|
PTE_U
))
{
kfree
((
void
*
)
pgtab
);
goto
retry
;
}
...
...
@@ -82,7 +167,7 @@ mappages(pde_t *pgdir, void *la, uint size, uint pa, int perm)
{
char
*
a
,
*
last
;
pte_t
*
pte
;
a
=
PGROUNDDOWN
(
la
);
last
=
PGROUNDDOWN
(
la
+
size
-
1
);
for
(;;){
...
...
@@ -136,8 +221,6 @@ clearpages(pde_t *pgdir, void *begin, void *end)
}
}
// The mappings from logical to linear are one to one (i.e.,
// segmentation doesn't do anything).
// There is one page table per process, plus one that's used
// when a CPU is not running any process (kpgdir).
// A user process uses the same page table as the kernel; the
...
...
@@ -159,14 +242,16 @@ clearpages(pde_t *pgdir, void *begin, void *end)
// (both in physical memory and in the kernel's virtual address
// space).
static
struct
kmap
{
void
*
p
;
void
*
e
;
void
*
l
;
uint
p
;
uint
e
;
int
perm
;
}
kmap
[]
=
{
{(
void
*
)
USERTOP
,
(
void
*
)
0x100000
,
PTE_W
},
// I/O space
{(
void
*
)
0x100000
,
data
,
0
},
// kernel text, rodata
{
data
,
(
void
*
)
PHYSTOP
,
PTE_W
},
// kernel data, memory
{(
void
*
)
0xFE000000
,
0
,
PTE_W
},
// device mappings
{
(
void
*
)
IOSPACEB
,
IOSPACEB
,
IOSPACEE
,
PTE_W
},
// I/O space
{
P2V
(
IOSPACEB
),
IOSPACEB
,
IOSPACEE
,
PTE_W
},
// I/O space
{
(
void
*
)
KERNLINK
,
V2P
(
KERNLINK
),
V2P
(
data
),
0
},
// kernel text, rodata
{
data
,
V2P
(
data
),
PHYSTOP
,
PTE_W
},
// kernel data, memory
{
(
void
*
)
0xFE000000
,
0xFE000000
,
0
,
PTE_W
},
// device mappings
};
// Set up kernel part of a page table.
...
...
@@ -181,7 +266,7 @@ setupkvm(void)
memset
(
pgdir
,
0
,
PGSIZE
);
k
=
kmap
;
for
(
k
=
kmap
;
k
<
&
kmap
[
NELEM
(
kmap
)];
k
++
)
if
(
mappages
(
pgdir
,
k
->
p
,
k
->
e
-
k
->
p
,
(
uint
)
k
->
p
,
k
->
perm
)
<
0
)
if
(
mappages
(
pgdir
,
k
->
l
,
k
->
e
-
k
->
p
,
(
uint
)
k
->
p
,
k
->
perm
)
<
0
)
return
0
;
return
pgdir
;
...
...
@@ -193,6 +278,7 @@ void
kvmalloc
(
void
)
{
kpgdir
=
setupkvm
();
switchkvm
();
}
// Turn on paging.
...
...
@@ -202,9 +288,20 @@ vmenable(void)
uint
cr0
;
switchkvm
();
// load kpgdir into cr3
cr0
=
rcr0
();
cr0
|=
CR0_PG
;
lcr0
(
cr0
);
struct
cpu
*
c
=
&
cpus
[
0
];
lgdt
((
void
*
)
v2p
((
void
*
)(
c
->
gdt
)),
sizeof
(
c
->
gdt
));
loadgs
(
SEG_KCPU
<<
3
);
loadfs
(
SEG_KDATA
<<
3
);
loades
(
SEG_KDATA
<<
3
);
loadds
(
SEG_KDATA
<<
3
);
loadss
(
SEG_KDATA
<<
3
);
__asm
volatile
(
"ljmp %0,$1f
\n
1:
\n
"
::
"i"
(
SEG_KCODE
<<
3
));
// reload cs
}
// Switch h/w page table register to the kernel-only page table,
...
...
@@ -212,7 +309,7 @@ vmenable(void)
void
switchkvm
(
void
)
{
lcr3
(
PADDR
(
kpgdir
));
// switch to the kernel page table
lcr3
(
v2p
(
kpgdir
));
// switch to the kernel page table
}
// Switch TSS and h/w page table to correspond to process p.
...
...
@@ -223,11 +320,11 @@ switchuvm(struct proc *p)
cpu
->
gdt
[
SEG_TSS
]
=
SEG16
(
STS_T32A
,
&
cpu
->
ts
,
sizeof
(
cpu
->
ts
)
-
1
,
0
);
cpu
->
gdt
[
SEG_TSS
].
s
=
0
;
cpu
->
ts
.
ss0
=
SEG_KDATA
<<
3
;
cpu
->
ts
.
esp0
=
(
uint
)
proc
->
kstack
+
KSTACKSIZE
;
cpu
->
ts
.
esp0
=
(
uint
)
proc
->
kstack
+
KSTACKSIZE
;
ltr
(
SEG_TSS
<<
3
);
if
(
p
->
vmap
==
0
||
p
->
vmap
->
pgdir
==
0
)
panic
(
"switchuvm: no vmap/pgdir"
);
lcr3
(
PADDR
(
p
->
vmap
->
pgdir
));
// switch to new address space
lcr3
(
v2p
(
p
->
vmap
->
pgdir
));
// switch to new address space
popcli
();
}
...
...
@@ -242,7 +339,7 @@ freevm(pde_t *pgdir)
panic
(
"freevm: no pgdir"
);
for
(
i
=
0
;
i
<
NPDENTRIES
;
i
++
){
if
(
pgdir
[
i
]
&
PTE_P
)
kfree
(
(
char
*
)
PTE_ADDR
(
pgdir
[
i
]
));
kfree
(
p2v
(
PTE_ADDR
(
pgdir
[
i
])
));
}
kfree
((
char
*
)
pgdir
);
}
...
...
@@ -498,7 +595,7 @@ vmap_copy(struct vmap *m, int share)
__sync_fetch_and_add
(
&
c
->
e
[
i
].
n
->
ref
,
1
);
}
if
(
share
)
lcr3
(
PADDR
(
m
->
pgdir
));
// Reload hardware page table
lcr3
(
v2p
(
m
->
pgdir
));
// Reload hardware page table
release
(
&
m
->
lock
);
return
c
;
...
...
@@ -534,21 +631,6 @@ vmn_load(struct vmnode *vmn, struct inode *ip, uint offset, uint sz)
}
}
//PAGEBREAK!
// Map user virtual address to kernel physical address.
char
*
uva2ka
(
pde_t
*
pgdir
,
char
*
uva
)
{
pte_t
*
pte
;
pte
=
walkpgdir
(
pgdir
,
uva
,
0
);
if
((
*
pte
&
PTE_P
)
==
0
)
return
0
;
if
((
*
pte
&
PTE_U
)
==
0
)
return
0
;
return
(
char
*
)
PTE_ADDR
(
*
pte
);
}
// Copy len bytes from p to user address va in vmap.
// Most useful when vmap is not the current page table.
int
...
...
@@ -634,7 +716,7 @@ pagefault_wcow(struct vmap *vmap, uint va, pte_t *pte, struct vma *m, uint npg)
// Update the hardware page tables to reflect the change to the vma
clearpages
(
vmap
->
pgdir
,
(
void
*
)
m
->
va_start
,
(
void
*
)
m
->
va_end
);
pte
=
walkpgdir
(
vmap
->
pgdir
,
(
const
void
*
)
va
,
0
);
*
pte
=
PADDR
(
m
->
n
->
page
[
npg
])
|
PTE_P
|
PTE_U
|
PTE_W
;
*
pte
=
v2p
(
m
->
n
->
page
[
npg
])
|
PTE_P
|
PTE_U
|
PTE_W
;
// drop my ref to vmnode
vmn_decref
(
o
);
return
0
;
...
...
@@ -660,14 +742,14 @@ pagefault(struct vmap *vmap, uint va, uint err)
return
-
1
;
}
}
else
if
(
m
->
va_type
==
COW
)
{
*
pte
=
PADDR
(
m
->
n
->
page
[
npg
])
|
PTE_P
|
PTE_U
|
PTE_COW
;
*
pte
=
v2p
(
m
->
n
->
page
[
npg
])
|
PTE_P
|
PTE_U
|
PTE_COW
;
}
else
{
if
(
m
->
n
->
ref
!=
1
)
{
panic
(
"pagefault"
);
}
*
pte
=
PADDR
(
m
->
n
->
page
[
npg
])
|
PTE_P
|
PTE_U
|
PTE_W
;
*
pte
=
v2p
(
m
->
n
->
page
[
npg
])
|
PTE_P
|
PTE_U
|
PTE_W
;
}
lcr3
(
PADDR
(
vmap
->
pgdir
));
// Reload hardware page tables
lcr3
(
v2p
(
vmap
->
pgdir
));
// Reload hardware page tables
release
(
&
m
->
lock
);
return
1
;
}
x86.h
浏览文件 @
649c423f
...
...
@@ -97,6 +97,30 @@ loadgs(ushort v)
__asm
volatile
(
"movw %0, %%gs"
:
:
"r"
(
v
));
}
static
inline
void
loadfs
(
ushort
v
)
{
__asm
volatile
(
"movw %0, %%fs"
:
:
"r"
(
v
));
}
static
inline
void
loades
(
ushort
v
)
{
__asm
volatile
(
"movw %0, %%es"
:
:
"r"
(
v
));
}
static
inline
void
loadds
(
ushort
v
)
{
__asm
volatile
(
"movw %0, %%ds"
:
:
"r"
(
v
));
}
static
inline
void
loadss
(
ushort
v
)
{
__asm
volatile
(
"movw %0, %%ss"
:
:
"r"
(
v
));
}
static
inline
uint
rebp
(
void
)
{
...
...
编写
预览
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论