Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
X
xv6-public
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
问题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
银宸时代
OS Lab Group
奖励实验
xv6-public
提交
9aa0337d
提交
9aa0337d
7月 29, 2011
创建
作者:
Frans Kaashoek
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Map kernel high
Very important to give qemu memory through PHYSTOP :(
上级
dccb9152
隐藏空白字符变更
内嵌
并排
正在显示
20 个修改的文件
包含
207 行增加
和
70 行删除
+207
-70
Makefile
Makefile
+2
-2
bootmain.c
bootmain.c
+6
-5
bootother.S
bootother.S
+9
-5
console.c
console.c
+5
-1
defs.h
defs.h
+2
-0
exec.c
exec.c
+1
-0
ide.c
ide.c
+1
-0
kalloc.c
kalloc.c
+19
-3
main.c
main.c
+23
-10
mmu.h
mmu.h
+0
-8
mp.c
mp.c
+3
-1
multiboot.S
multiboot.S
+7
-4
param.h
param.h
+0
-2
proc.c
proc.c
+1
-0
spinlock.c
spinlock.c
+2
-1
syscall.c
syscall.c
+1
-0
sysproc.c
sysproc.c
+1
-0
trap.c
trap.c
+1
-0
vm.c
vm.c
+99
-28
x86.h
x86.h
+24
-0
没有找到文件。
Makefile
浏览文件 @
9aa0337d
...
...
@@ -109,7 +109,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
...
...
@@ -200,7 +200,7 @@ QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \
ifndef
CPUS
CPUS
:=
2
endif
QEMUOPTS
=
-hdb
fs.img xv6.img
-smp
$(CPUS)
QEMUOPTS
=
-hdb
fs.img xv6.img
-smp
$(CPUS)
-m
512
qemu
:
fs.img xv6.img
$(QEMU)
-serial
mon:stdio
$(QEMUOPTS)
...
...
bootmain.c
浏览文件 @
9aa0337d
...
...
@@ -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
);
entry
();
}
...
...
bootother.S
浏览文件 @
9aa0337d
#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,6 +25,8 @@
#define CR0_PE 1
#define RELOC1(x) ((x) + KERNBASE) // same as V2P, but without casts
.code16
.globl start
start:
...
...
@@ -40,7 +43,7 @@ start:
movl %eax, %cr0
//PAGEBREAK!
ljmp
$(SEG_KCODE<<3), $start32
ljmp
l $(SEG_KCODE<<3), $(start32+KERNBASE)
.code32
start32:
...
...
@@ -53,10 +56,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 +72,9 @@ 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
浏览文件 @
9aa0337d
...
...
@@ -9,6 +9,7 @@
#include "spinlock.h"
#include "fs.h"
#include "file.h"
#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
#include "x86.h"
...
...
@@ -60,6 +61,9 @@ cprintf(char *fmt, ...)
if
(
locking
)
acquire
(
&
cons
.
lock
);
if
(
fmt
==
0
)
panic
(
"null fmt"
);
argp
=
(
uint
*
)(
void
*
)(
&
fmt
+
1
);
state
=
0
;
for
(
i
=
0
;
(
c
=
fmt
[
i
]
&
0xff
)
!=
0
;
i
++
){
...
...
@@ -121,7 +125,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
浏览文件 @
9aa0337d
...
...
@@ -62,6 +62,7 @@ extern uchar ioapicid;
void
ioapicinit
(
void
);
// kalloc.c
char
*
pgalloc
(
void
);
char
*
kalloc
(
void
);
void
kfree
(
char
*
);
void
kinit
(
void
);
...
...
@@ -160,6 +161,7 @@ void uartintr(void);
void
uartputc
(
int
);
// vm.c
void
pginit
(
char
*
(
*
alloc
)());
void
seginit
(
void
);
void
kvmalloc
(
void
);
void
vmenable
(
void
);
...
...
exec.c
浏览文件 @
9aa0337d
#include "types.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
#include "defs.h"
...
...
ide.c
浏览文件 @
9aa0337d
...
...
@@ -3,6 +3,7 @@
#include "types.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
#include "x86.h"
...
...
kalloc.c
浏览文件 @
9aa0337d
...
...
@@ -5,6 +5,7 @@
#include "types.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "spinlock.h"
...
...
@@ -18,6 +19,20 @@ struct {
}
kmem
;
extern
char
end
[];
// first address after kernel loaded from ELF file
char
*
newend
;
// 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
;
}
// Initialize free list of physical pages.
void
...
...
@@ -26,8 +41,8 @@ kinit(void)
char
*
p
;
initlock
(
&
kmem
.
lock
,
"kmem"
);
p
=
(
char
*
)
PGROUNDUP
((
uint
)
end
);
for
(;
p
+
PGSIZE
<=
(
char
*
)
PHYSTOP
;
p
+=
PGSIZE
)
p
=
(
char
*
)
PGROUNDUP
((
uint
)
new
end
);
for
(;
p
+
PGSIZE
<=
(
char
*
)
p2v
(
PHYSTOP
)
;
p
+=
PGSIZE
)
kfree
(
p
);
}
...
...
@@ -41,7 +56,7 @@ kfree(char *v)
{
struct
run
*
r
;
if
((
uint
)
v
%
PGSIZE
||
v
<
end
||
(
uint
)
v
>=
PHYSTOP
)
if
((
uint
)
v
%
PGSIZE
||
v
<
end
||
v2p
(
v
)
>=
PHYSTOP
)
panic
(
"kfree"
);
// Fill with junk to catch dangling refs.
...
...
@@ -67,6 +82,7 @@ kalloc(void)
if
(
r
)
kmem
.
freelist
=
r
->
next
;
release
(
&
kmem
.
lock
);
cprintf
(
"kalloc: 0x%x
\n
"
,
r
);
return
(
char
*
)
r
;
}
main.c
浏览文件 @
9aa0337d
#include "types.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
#include "x86.h"
...
...
@@ -9,6 +10,8 @@ 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
...
...
@@ -16,6 +19,7 @@ void mainc(void);
int
main
(
void
)
{
pginit
(
pgalloc
);
mpinit
();
// collect info about this machine
lapicinit
(
mpbcpu
());
seginit
();
// set up segments
...
...
@@ -46,7 +50,6 @@ mainc(void)
ioapicinit
();
// another interrupt controller
consoleinit
();
// I/O devices & their interrupts
uartinit
();
// serial port
kvmalloc
();
// initialize the kernel page table
pinit
();
// process table
tvinit
();
// trap vectors
binit
();
// buffer cache
...
...
@@ -57,7 +60,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
();
}
...
...
@@ -66,16 +70,25 @@ 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
();
}
// Common CPU setup code.
// Bootstrap CPU comes here from mainc().
// Other CPUs jump here from bootother.S.
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
}
...
...
@@ -91,7 +104,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
++
){
...
...
@@ -103,9 +116,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
浏览文件 @
9aa0337d
...
...
@@ -106,18 +106,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
浏览文件 @
9aa0337d
...
...
@@ -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"
...
...
@@ -39,6 +40,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
)
...
...
@@ -83,7 +85,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
浏览文件 @
9aa0337d
...
...
@@ -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
浏览文件 @
9aa0337d
...
...
@@ -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 0x1000000 // use phys mem up to here as free pool
#define MAXARG 32 // max exec arguments
#define LOGSIZE 10 // size of log
proc.c
浏览文件 @
9aa0337d
#include "types.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "x86.h"
#include "proc.h"
...
...
spinlock.c
浏览文件 @
9aa0337d
...
...
@@ -4,6 +4,7 @@
#include "defs.h"
#include "param.h"
#include "x86.h"
#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
#include "spinlock.h"
...
...
@@ -71,7 +72,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
浏览文件 @
9aa0337d
#include "types.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
#include "x86.h"
...
...
sysproc.c
浏览文件 @
9aa0337d
...
...
@@ -2,6 +2,7 @@
#include "x86.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
...
...
trap.c
浏览文件 @
9aa0337d
#include "types.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
#include "x86.h"
...
...
vm.c
浏览文件 @
9aa0337d
...
...
@@ -2,20 +2,71 @@
#include "types.h"
#include "defs.h"
#include "x86.h"
#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
#include "elf.h"
extern
char
data
[];
// defined in data.S
static
pde_t
*
kpgdir
;
// for use in scheduler()
struct
segdesc
gdt
[
NSEGS
];
// Allocate one page table for the machine for the kernel address
// space for scheduler processes.
// page map for during boot
// XXX build a static page table in assembly
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
kvmalloc
(
void
)
pginit
(
char
*
(
*
alloc
)(
void
)
)
{
kpgdir
=
setupkvm
();
uint
cr0
;
kpgdir
=
(
pde_t
*
)
alloc
();
pgmap
((
void
*
)
0
,
(
void
*
)
PHYSTOP
,
0
);
// map pa 0 at va 0
pgmap
((
void
*
)
KERNBASE
,
(
void
*
)
(
KERNBASE
+
PHYSTOP
),
0
);
// map pa 0 at va KERNBASE
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.
...
...
@@ -57,7 +108,7 @@ walkpgdir(pde_t *pgdir, const void *va, int create)
pde
=
&
pgdir
[
PDX
(
va
)];
if
(
*
pde
&
PTE_P
){
pgtab
=
(
pte_t
*
)
PTE_ADDR
(
*
pde
);
pgtab
=
(
pte_t
*
)
p2v
(
PTE_ADDR
(
*
pde
)
);
}
else
{
if
(
!
create
||
(
pgtab
=
(
pte_t
*
)
kalloc
())
==
0
)
return
0
;
...
...
@@ -66,7 +117,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.
*
pde
=
PADDR
(
pgtab
)
|
PTE_P
|
PTE_W
|
PTE_U
;
*
pde
=
v2p
(
pgtab
)
|
PTE_P
|
PTE_W
|
PTE_U
;
}
return
&
pgtab
[
PTX
(
va
)];
}
...
...
@@ -105,29 +156,30 @@ mappages(pde_t *pgdir, void *la, uint size, uint pa, int perm)
// page protection bits prevent it from using anything other
// than its memory.
//
//
// setupkvm() and exec() set up every page table like this:
// 0..
640K : user memory (text, data, stack, heap)
//
640K..1M : mapped direct (for IO space)
//
1M..end : mapped direct (for the kernel's text and data)
//
end..PHYSTOP : mapped direct (kernel heap and user pages
)
// 0..
KERNBASE : user memory (text, data, stack, heap), mapped to some phys mem
//
KERNBASE+640K..KERNBASE+1M: mapped to 640K..1M
//
KERNBASE+1M..KERNBASE+end : mapped to 1M..end
//
KERNBASE+end..KERBASE+PHYSTOP : mapped to end..PHYSTOP (free memory
)
// 0xfe000000..0 : mapped direct (devices such as ioapic)
//
// The kernel allocates memory for its heap and for user memory
// between kernend and the end of physical memory (PHYSTOP).
// The virtual address space of each user program includes the kernel
// (which is inaccessible in user mode). The user program addresses
// range from 0 till 640KB (USERTOP), which where the I/O hole starts
// (both in physical memory and in the kernel's virtual address
// space).
// (which is inaccessible in user mode). The user program sits in
// the bottom of the address space, and the kernel at the top at KERNBASE.
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.
...
...
@@ -142,12 +194,21 @@ 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
;
}
// Allocate one page table for the machine for the kernel address
// space for scheduler processes.
void
kvmalloc
(
void
)
{
kpgdir
=
setupkvm
();
switchkvm
();
}
// Turn on paging.
void
vmenable
(
void
)
...
...
@@ -158,6 +219,16 @@ vmenable(void)
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,
...
...
@@ -165,7 +236,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.
...
...
@@ -180,7 +251,7 @@ switchuvm(struct proc *p)
ltr
(
SEG_TSS
<<
3
);
if
(
p
->
pgdir
==
0
)
panic
(
"switchuvm: no pgdir"
);
lcr3
(
PADDR
(
p
->
pgdir
));
// switch to new address space
lcr3
(
v2p
(
p
->
pgdir
));
// switch to new address space
popcli
();
}
...
...
@@ -195,7 +266,7 @@ inituvm(pde_t *pgdir, char *init, uint sz)
panic
(
"inituvm: more than a page"
);
mem
=
kalloc
();
memset
(
mem
,
0
,
PGSIZE
);
mappages
(
pgdir
,
0
,
PGSIZE
,
PADDR
(
mem
),
PTE_W
|
PTE_U
);
mappages
(
pgdir
,
0
,
PGSIZE
,
v2p
(
mem
),
PTE_W
|
PTE_U
);
memmove
(
mem
,
init
,
sz
);
}
...
...
@@ -245,7 +316,7 @@ allocuvm(pde_t *pgdir, uint oldsz, uint newsz)
return
0
;
}
memset
(
mem
,
0
,
PGSIZE
);
mappages
(
pgdir
,
(
char
*
)
a
,
PGSIZE
,
PADDR
(
mem
),
PTE_W
|
PTE_U
);
mappages
(
pgdir
,
(
char
*
)
a
,
PGSIZE
,
v2p
(
mem
),
PTE_W
|
PTE_U
);
}
return
newsz
;
}
...
...
@@ -289,7 +360,7 @@ freevm(pde_t *pgdir)
deallocuvm
(
pgdir
,
USERTOP
,
0
);
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
);
}
...
...
@@ -315,7 +386,7 @@ copyuvm(pde_t *pgdir, uint sz)
if
((
mem
=
kalloc
())
==
0
)
goto
bad
;
memmove
(
mem
,
(
char
*
)
pa
,
PGSIZE
);
if
(
mappages
(
d
,
(
void
*
)
i
,
PGSIZE
,
PADDR
(
mem
),
PTE_W
|
PTE_U
)
<
0
)
if
(
mappages
(
d
,
(
void
*
)
i
,
PGSIZE
,
v2p
(
mem
),
PTE_W
|
PTE_U
)
<
0
)
goto
bad
;
}
return
d
;
...
...
x86.h
浏览文件 @
9aa0337d
...
...
@@ -96,6 +96,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
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论