load program ok
This commit is contained in:
parent
dd540f15d0
commit
6c1c2e05ad
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"editor.detectIndentation": false,
|
"editor.detectIndentation": false,
|
||||||
"editor.tabSize": 8,
|
"editor.tabSize": 4,
|
||||||
"editor.insertSpaces": false,
|
"editor.insertSpaces": false,
|
||||||
"files.associations": {
|
"files.associations": {
|
||||||
"*.h": "c",
|
"*.h": "c",
|
||||||
|
|||||||
@ -46,7 +46,9 @@ struct Secthdr {
|
|||||||
u32 sh_addralign;
|
u32 sh_addralign;
|
||||||
u32 sh_entsize;
|
u32 sh_entsize;
|
||||||
};
|
};
|
||||||
|
typedef struct Elf Elf32_Ehdr;
|
||||||
|
typedef struct Proghdr Elf32_Phdr;
|
||||||
|
typedef struct Secthdr Elf32_Shdr;
|
||||||
// Values for Proghdr::p_type
|
// Values for Proghdr::p_type
|
||||||
#define PT_LOAD 1
|
#define PT_LOAD 1
|
||||||
|
|
||||||
|
|||||||
58
kern/main.c
58
kern/main.c
@ -3,6 +3,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <type.h>
|
#include <type.h>
|
||||||
#include <x86.h>
|
#include <x86.h>
|
||||||
|
#include <elf.h>
|
||||||
|
|
||||||
#include <kern/fs.h>
|
#include <kern/fs.h>
|
||||||
#include <kern/kmalloc.h>
|
#include <kern/kmalloc.h>
|
||||||
@ -37,6 +38,23 @@ init_segment_regs(PROCESS *p_proc)
|
|||||||
| RPL_USER;
|
| RPL_USER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
lml_map(phyaddr_t cr3, uintptr_t vaddr, phyaddr_t paddr, u32 flags) {
|
||||||
|
uintptr_t *pde_ptr = (uintptr_t *)K_PHY2LIN(cr3);
|
||||||
|
// pde_ptr += PDX(3 * GB); // get page table base addr
|
||||||
|
// get pdx item, pde_ptr + PDX(vaddr)
|
||||||
|
pde_ptr += PDX(vaddr);
|
||||||
|
if (!(*pde_ptr & PTE_P)) {
|
||||||
|
// pdx ot exists, allocate a page and assign to pde
|
||||||
|
*pde_ptr = phy_malloc_4k() | PTE_P | flags;
|
||||||
|
}
|
||||||
|
uintptr_t *ptx_ptr = (uintptr_t *)K_PHY2LIN(*pde_ptr & (~0xfff));
|
||||||
|
// get ptx item
|
||||||
|
ptx_ptr += PTX(vaddr);
|
||||||
|
// assume paddr is allocated, just set it to paddr[31:12] | FLAGS
|
||||||
|
*ptx_ptr = (paddr & (~0xfff)) | PTE_P | flags;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 内核的main函数
|
* 内核的main函数
|
||||||
* 用于初始化用户进程,然后将执行流交给用户进程
|
* 用于初始化用户进程,然后将执行流交给用户进程
|
||||||
@ -69,15 +87,49 @@ void kernel_main(void)
|
|||||||
// 推荐将文件加载到3GB + 48MB处,应用程序保证不会有16MB那么大
|
// 推荐将文件加载到3GB + 48MB处,应用程序保证不会有16MB那么大
|
||||||
read_file(filename[i], (void *)K_PHY2LIN(48 * MB));
|
read_file(filename[i], (void *)K_PHY2LIN(48 * MB));
|
||||||
// 现在你就需要将从磁盘中读出的ELF文件解析到用户进程的地址空间中
|
// 现在你就需要将从磁盘中读出的ELF文件解析到用户进程的地址空间中
|
||||||
panic("unimplement! load elf file");
|
// panic("unimplement! load elf file");
|
||||||
|
// ---------------------------- load elf --------------------------------------
|
||||||
|
void * elf_start = (void *)K_PHY2LIN(48 * MB);
|
||||||
|
assert(*(u32*)elf_start == ELF_MAGIC);
|
||||||
|
Elf32_Ehdr* ehdr = (Elf32_Ehdr*) elf_start;
|
||||||
|
for (int i = 0; i < ehdr->e_phnum; ++ i) {
|
||||||
|
Elf32_Phdr* phdr = elf_start + i * ehdr->e_phentsize + ehdr->e_phoff;
|
||||||
|
if (phdr->p_type == PT_LOAD) {
|
||||||
|
u32 vpage_fst = phdr->p_va & (~0xfff); // clear low 12 bit, start of the first pg
|
||||||
|
u32 vpage_lst = (phdr->p_va + phdr->p_memsz - 1) & (~0xfff); // start of the last pg
|
||||||
|
// in fact, we allocate 4k aligned vpage to every segment; its ok because elf32 segment align is 0x1000
|
||||||
|
u32 page_num = ((vpage_lst - vpage_fst) >> 12) + 1;
|
||||||
|
phyaddr_t newpage = 0; // useless initialization
|
||||||
|
for (int j = 0; j < page_num; ++ j) {
|
||||||
|
newpage = phy_malloc_4k();
|
||||||
|
lml_map(p_proc->pcb.cr3, vpage_fst + (j << 12), newpage, PTE_P | PTE_W | PTE_U);
|
||||||
|
}
|
||||||
|
phyaddr_t page_start = newpage - (page_num - 1) * 4 * KB;
|
||||||
|
memcpy((void*)K_PHY2LIN(page_start), (void*)(elf_start + phdr->p_offset), phdr->p_filesz);
|
||||||
|
memset((void*)K_PHY2LIN(page_start) + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 上一个实验中,我们开栈是用内核中的一个数组临时充当栈
|
// 上一个实验中,我们开栈是用内核中的一个数组临时充当栈
|
||||||
// 但是现在就不行了,用户是无法访问内核的地址空间(3GB ~ 3GB + 128MB)
|
// 但是现在就不行了,用户是无法访问内核的地址空间(3GB ~ 3GB + 128MB)
|
||||||
// 需要你自行处理给用户分配用户栈。
|
// 需要你自行处理给用户分配用户栈。
|
||||||
panic("unimplement! init user stack and esp");
|
// ---------------------------- alloc user stack ------------------------------
|
||||||
|
phyaddr_t ustack_low = phy_malloc_4k();
|
||||||
|
for (int i = 0; i < 6; ++ i) phy_malloc_4k();
|
||||||
|
phyaddr_t ustack_high = phy_malloc_4k(); // alloc 8 pages, 32KB stack for each program
|
||||||
|
for (int i = 0; i < 8; ++ i) {
|
||||||
|
lml_map(p_proc->pcb.cr3, (3*GB - (8-i)*PGSIZE), ustack_low + i*PGSIZE, PTE_P | PTE_W | PTE_U);
|
||||||
|
}
|
||||||
|
p_proc->pcb.user_regs.esp = 3*GB;
|
||||||
|
// p_proc->pcb.user_regs.esp -= 4;
|
||||||
|
// uintptr_t* ustack_top = (uintptr_t*)K_PHY2LIN(ustack_high + PGSIZE);
|
||||||
|
// ustack_top --;
|
||||||
|
// *ustack_top = ehdr->e_entry;
|
||||||
|
p_proc->pcb.user_regs.eip = ehdr->e_entry;
|
||||||
// 初始化用户寄存器
|
// 初始化用户寄存器
|
||||||
p_proc->pcb.user_regs.eflags = 0x1202; /* IF=1, IOPL=1 */
|
p_proc->pcb.user_regs.eflags = 0x1202; /* IF=1, IOPL=1 */
|
||||||
|
|
||||||
|
// panic("unimplement! init user stack and esp");
|
||||||
// 接下来初始化内核寄存器,
|
// 接下来初始化内核寄存器,
|
||||||
// 为什么需要初始化内核寄存器原因是加入了系统调用后
|
// 为什么需要初始化内核寄存器原因是加入了系统调用后
|
||||||
// 非常有可能出现系统调用执行过程中插入其余中断的情况,
|
// 非常有可能出现系统调用执行过程中插入其余中断的情况,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user