/* See COPYRIGHT for copyright information. */
#include <inc/x86.h>
#include <inc/mmu.h>
#include <inc/error.h>
#include <inc/string.h>
#include <inc/assert.h>
#include <kern/pmap.h>
#include <kern/kclock.h>
#include <kern/env.h>
// These variables are set by i386_detect_memory()
static physaddr_t maxpa; // Maximum physical address
size_t npage; // Amount of physical memory (in pages)
static size_t basemem; // Amount of base memory (in bytes)
static size_t extmem; // Amount of extended memory (in bytes)
// These variables are set in i386_vm_init()
pde_t* boot_pgdir; // Virtual address of boot time page directory
physaddr_t boot_cr3; // Physical address of boot time page directory
static char* boot_freemem; // Pointer to next byte of free mem
struct Page* pages; // Virtual address of physical page array
static struct Page_list page_free_list; // Free list of physical pages
// Global descriptor table.
//
// The kernel and user segments are identical (except for the DPL).
// To load the SS register, the CPL must equal the DPL. Thus,
// we must duplicate the segments for the user and the kernel.
//
struct Segdesc gdt[] =
{
// 0x0 - unused (always faults -- for trapping NULL far pointers)
SEG_NULL,
// 0x8 - kernel code segment
[GD_KT >> 3] = SEG(STA_X | STA_R, 0x0, 0xffffffff, 0),
// 0x10 - kernel data segment
[GD_KD >> 3] = SEG(STA_W, 0x0, 0xffffffff, 0),
// 0x18 - user code segment
[GD_UT >> 3] = SEG(STA_X | STA_R, 0x0, 0xffffffff, 3),
// 0x20 - user data segment
[GD_UD >> 3] = SEG(STA_W, 0x0, 0xffffffff, 3),
// 0x28 - tss, initialized in idt_init()
[GD_TSS >> 3] = SEG_NULL
};
struct Pseudodesc gdt_pd = {
sizeof(gdt) - 1, (unsigned long) gdt
};
static int
nvram_read(int r)
{
return mc146818_read(r) | (mc146818_read(r + 1) << 8);
}
void
i386_detect_memory(void)
{
// CMOS tells us how many kilobytes there are
basemem = ROUNDDOWN(nvram_read(NVRAM_BASELO)*1024, PGSIZE);
extmem = ROUNDDOWN(nvram_read(NVRAM_EXTLO)*1024, PGSIZE);
// Calculate the maximum physical address based on whether
// or not there is any extended memory. See comment in <inc/mmu.h>.
if (extmem)
maxpa = EXTPHYSMEM + extmem;
else
maxpa = basemem;
npage = maxpa / PGSIZE;
cprintf("Physical memory: %dK available, ", (int)(maxpa/1024));
cprintf("base = %dK, extended = %dK\n", (int)(basemem/1024), (int)(extmem/1024));
}
// --------------------------------------------------------------
// Set up initial memory mappings and turn on MMU.
// --------------------------------------------------------------
static void check_boot_pgdir(void);
static void check_page_alloc();
static void page_check(void);
static void boot_map_segment(pde_t *pgdir, uintptr_t la, size_t size, physaddr_t pa, int perm);
//
// A simple physical memory allocator, used only a few times
// in the process of setting up the virtual memory system.
// page_alloc() is the real allocator.
//
// Allocate n bytes of physical memory aligned on an
// align-byte boundary. Align must be a power of two.
// Return kernel virtual address. Returned memory is uninitialized.
//
// If we're out of memory, boot_alloc should panic.
// This function may ONLY be used during initialization,
// before the page_free_list has been set up.
//
static void*
boot_alloc(uint32_t n, uint32_t align)
{
extern char end[];
void *v;
// Initialize boot_freemem if this is the first time.
// 'end' is a magic symbol automatically generated by the linker,
// which points to the end of the kernel's bss segment -
// i.e., the first virtual address that the linker
// did _not_ assign to any kernel code or global variables.
if (boot_freemem == 0)
boot_freemem = end;
// LAB 2: Your code here:
// Step 1: round boot_freemem up to be aligned properly
// Step 2: save current value of boot_freemem as allocated chunk
// Step 3: increase boot_freemem to record allocation
// Step 4: return allocated chunk
boot_freemem = ROUNDUP(boot_freemem,align);
v = (void *)boot_freemem;
boot_freemem += n;
return v;
}
// Set up a two-level page table:
// boot_pgdir is its linear (virtual) address of the root
// boot_cr3 is the physical adresss of the root
// Then turn on paging. Then effectively turn off segmentation.
// (i.e., the segment base addrs are set to zero).
//
// This function only sets up the kernel part of the address space
// (ie. addresses >= UTOP). The user part of the address space
// will be setup later.
//
// From UTOP to ULIM, the user is allowed to read but not write.
// Above ULIM the user cannot read (or write).
void
i386_vm_init(void)
{
pde_t* pgdir;
uint32_t cr0;
size_t n;
// Delete this line:
//panic("i386_vm_init: This function is not finished\n");
//////////////////////////////////////////////////////////////////////
// create initial page directory.
pgdir = boot_alloc(PGSIZE, PGSIZE);
memset(pgdir, 0, PGSIZE);
boot_pgdir = pgdir;
boot_cr3 = PADDR(pgdir);
//////////////////////////////////////////////////////////////////////
// Recursively insert PD in itself as a page table, to form
// a virtual page table at virtual address VPT.
// (For now, you don't have understand the greater purpose of the
// following two lines.)
// Permissions: kernel RW, user NONE
pgdir[PDX(VPT)] = PADDR(pgdir)|PTE_W|PTE_P;
// same for UVPT
// Permissions: kernel R, user R
pgdir[PDX(UVPT)] = PADDR(pgdir)|PTE_U|PTE_P;
//////////////////////////////////////////////////////////////////////
// Make 'pages' point to an array of size 'npage' of 'struct Page'.
// The kernel uses this structure to keep track of physical pages;
// 'npage' equals the number of physical pages in memory. User-level
// programs will get read-only access to the array as well.
// You must allocate the array yourself.
// Your code goes here:
pages = boot_alloc( sizeof(struct Page ) * npage, PGSIZE );
memset(pages, 0, sizeof(struct Page)*npage);
//////////////////////////////////////////////////////////////////////
// Make 'envs' point to an array of size 'NENV' of 'struct Env'.
// LAB 3: Your code here.
envs = boot_alloc( sizeof( struct Env ) * NENV, PGSIZE );
//////////////////////////////////////////////////////////////////////
// Now that we've allocated the initial kernel data structures, we set
// up the list of free physical pages. Once we've done so, all further
// memory management will go through the page_* functions. In
// particular, we can now map memory using boot_map_segment or page_insert
page_init();
check_page_alloc();
page_check();
//////////////////////////////////////////////////////////////////////
// Now we set up virtual memory
//////////////////////////////////////////////////////////////////////
// Map 'pages' read-only by the user at linear address UPAGES
// (ie. perm = PTE_U | PTE_P)
// Permissions:
// - pages -- kernel RW, user NONE
// - the read-only version mapped at UPAGES -- kernel R, user R
// Your code goes here:
boot_map_segment( pgdir, UPAGES, sizeof(struct Page ) * npage , PADDR ( pages ), PTE_U );
//////////////////////////////////////////////////////////////////////
// Map the 'envs' array read-only by the user at linear address UENVS
// (ie. perm = PTE_U | PTE_P).
// Permissions:
// - envs itself -- kernel RW, user NONE
// - the image of envs mapped at UENVS -- kernel R, user R
boot_map_segment( pgdir, UENVS, sizeof( struct Env ) * NENV, PADDR ( envs ), PTE_U );
//////////////////////////////////////////////////////////////////////
// Map the kernel stack (symbol name "bootstack"). The complete VA
// range of the stack, [KSTACKTOP-PTSIZE, KSTACKTOP), breaks into two
// pieces:
// * [KSTACKTOP-KSTKSIZE, KSTACKTOP) -- backed by physical memory
// * [KSTACKTOP-PTSIZE, KSTACKTOP-KSTKSIZE) -- not backed => faults
// Permissions: kernel RW, user NONE
// Your code goes here:
boot_map_segment( pgdir, KSTACKT
没有合适的资源?快使用搜索试试~ 我知道了~
mit 6.828(清华北大操作系统实习课使用)
5星 · 超过95%的资源 需积分: 45 181 下载量 137 浏览量
2009-06-18
17:26:31
上传
评论 6
收藏 3.02MB GZ 举报
温馨提示
共293个文件
c:68个
o:67个
h:34个
完成了6个lab必做的execise部分,希望能为大家提供点帮助~
资源推荐
资源详情
资源评论
收起资源包目录
mit 6.828(清华北大操作系统实习课使用) (293个子文件)
libjos.a 201KB
kernel.asm 415KB
fs.asm 355KB
sh.asm 311KB
testshell.asm 274KB
testpteshare.asm 266KB
init.asm 246KB
testpipe.asm 242KB
primespipe.asm 240KB
icode.asm 240KB
testfdsharing.asm 238KB
testpiperace2.asm 237KB
testpiperace.asm 236KB
testmalloc.asm 234KB
primes.asm 234KB
forktree.asm 233KB
pingpong.asm 233KB
ls.asm 229KB
testkbd.asm 221KB
lsfd.asm 220KB
num.asm 220KB
cat.asm 213KB
echo.asm 211KB
idle.asm 208KB
boot.asm 14KB
.bochsrc 33KB
boot 512B
pmap.c 29KB
fs.c 17KB
syscall.c 16KB
env.c 14KB
spawn.c 12KB
trap.c 10KB
console.c 10KB
sh.c 9KB
serv.c 9KB
fsformat.c 9KB
kdebug.c 7KB
fd.c 7KB
testpmap.c 7KB
fork.c 7KB
printfmt.c 6KB
file.c 6KB
pipe.c 6KB
monitor.c 5KB
string.c 4KB
fsipc.c 3KB
main.c 3KB
malloc.c 3KB
init.c 2KB
syscall.c 2KB
console.c 2KB
picirq.c 2KB
ide.c 2KB
ipc.c 2KB
test.c 2KB
testpiperace2.c 2KB
testpiperace.c 2KB
testshell.c 2KB
primespipe.c 2KB
ls.c 1KB
fprintf.c 1KB
pgfault.c 1KB
sched.c 1KB
testpipe.c 1KB
testfsipc.c 1KB
printf.c 1KB
init.c 1KB
primes.c 1KB
idle.c 939B
kclock.c 913B
testfdsharing.c 851B
writemotd.c 832B
testptelibrary.c 795B
testpteshare.c 791B
readline.c 702B
num.c 660B
libmain.c 638B
lsfd.c 587B
cat.c 554B
panic.c 552B
icode.c 546B
initsh.c 524B
printf.c 517B
forktree.c 512B
pingpong.c 512B
testmalloc.c 421B
testkbd.c 382B
echo.c 310B
wait.c 225B
spawninit.c 203B
spawnhello.c 191B
pageref.c 186B
hello.c 137B
exit.c 79B
cat 65KB
CODING 1KB
COPYRIGHT 11KB
COPYRIGHT 8KB
fs.c~ 17KB
共 293 条
- 1
- 2
- 3
资源评论
- zhuimengdj2014-02-28还不错的资源,学习操作系统可以好好看看
- yazhouren2012-04-05lab1-lab6怎么没分开呢? lab6是所有的lab1到lab5的集成吗? Mit 6.828,真的很好,学习操作系统知识很好的教程
- uestc03082016-04-27找了很久了,谢谢分享
- david7154322792013-11-26觉得北大的这个做的真的还是不错的
- chafee2012-09-18学习操作系统非常好的资料
juvensummer
- 粉丝: 1
- 资源: 2
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功