Permalink
Browse files

PIC doesn't work after fork(), reinit PIC to fix

thx fleuria
  • Loading branch information...
SilverRainZ committed Sep 6, 2015
1 parent ed0656d commit fc0e84caa1c3ae95998342f2b03125e2226d0dd6
Showing with 53 additions and 11 deletions.
  1. +1 −1 mm/vmm.c
  2. +6 −0 notes/whyerror.md
  3. +10 −0 proc/init.asm
  4. +36 −10 proc/proc.c
View
@@ -240,7 +240,7 @@ pde_t *uvm_copy(pte_t *pgdir, uint32_t size){
printl("uvm_copy: phyaddr: 0x%x -> 0x%x\n", pa, mem);
memcpy((void *)mem, (void *)pa, PAGE_SIZE);
vmm_map(pgd, USER_BASE + i, mem, PTE_W | PTE_U | PTE_P);
vmm_map(pgd, USER_BASE + i, mem, PTE_R | PTE_U | PTE_P); // TODO (?)
}
return pgd;
}
View
@@ -62,3 +62,9 @@ stupid! 错误并不是发生在执行 userland 的时候, 而是因为刚进入
当要执行的 ISR 的段的 `DPL` < `CPL` 时, CPU 会从 tss 取出对应特权级的 ss 和 esp(这里是 ss0 和 esp0), 然而...
如果段描述符的 Access bit `DC` 置位时, 意味着该段可以被与之相等或更低特权级的段访问(所以就没有取出 tss 的内容了甚至 cs 寄存器的 CPL 也不改变)...但是 kerenl 的页表可是 `PTE_K`的, 所以发生 Page Fault.
#2015-9-6 进入 fork 生成的进程后, PIC 中断不发生, 而第一个进程却不会这样
不清楚为什么会这样, 只能强制在 `fork_ret` 中再初始化一次, 代码勉强工作.
// TODO
感谢F叔提供的思路!
View
@@ -11,6 +11,16 @@ __init_start:
; push (msg_arg1 - $$) + 0xc0000000
mov eax, 1
int 0x80
cmp eax, 0
jz child
jmp $
child:
mov eax, 1
int 0x80
cmp eax, 0
jz child2
jmp $
child2:
jmp $
msg_arg1:
View
@@ -19,29 +19,52 @@
// proc
#include <proc.h>
#include <pic.h>
extern void _isr_stub_ret();
extern void context_switch(struct context **old, struct context *new);
static uint32_t cur_pid = 0;
static struct proc *initproc = NULL;
static struct proc ptable[NPROC];
struct context *cpu_context;
struct proc *proc = NULL;
/* import irq_remap, only use in fork_ret */
extern void irq_remap();
/* do not ask me why use irq_remap here, irq didn't work after fork()
* and I don't know why, and have to reinit it
* thx to fleuria
*/
void fork_ret(){
static int fst = 1;
if (fst == 1){
fst = 0;
} else {
outb(PIC1_CMD, ICW1_INIT + ICW1_ICW4); // starts the initialization sequence (in cascade mode)
outb(PIC2_CMD, ICW1_INIT + ICW1_ICW4);
}
return;
}
static void print_proc(struct proc *pp){
void print_proc(struct proc *pp){
uint32_t pa;
vmm_get_mapping(pp->pgdir, USER_BASE, &pa);
printl("print_proc:\n name: %s\n",pp->name);
printl("print_proc:\n")
printl(" name: %s\n",pp->name);
printk(" pid: %d\n", pp->pid);
printl(" kern_stack: 0x%x\n",pp->kern_stack);
printl(" pgdir: 0x%x\n",pp->pgdir);
printl(" phy addr: 0x%x\n", pa);
}
static struct proc *proc_alloc(){
struct proc *pp;
char *tos;
@@ -78,15 +101,15 @@ static struct proc *proc_alloc(){
void proc_init(){
struct proc *pp;
extern char __init_start;
extern char __init_end;
printl("proc_userinit: clear ptable\n");
memset(ptable, 0, sizeof(struct proc) * NPROC);
printl("proc_userinit: prepare for init\n");
extern char __init_start;
extern char __init_end;
pp = proc_alloc();
pp->pgdir = (pde_t *)pmm_alloc();
@@ -116,6 +139,7 @@ void proc_init(){
printl("proc_init: init stack build\n");
strcpy(pp->name, "init");
pp->cwd = p2i("/");
pp->state = P_RUNABLE;
@@ -129,22 +153,23 @@ void scheduler(){
struct proc *pp;
printl("scheduler: start\n");
for (;;){
for (pp = &ptable[0]; pp < &ptable[NPROC]; pp++){
if (pp->state != P_RUNABLE){
continue;
}
printl("scheduler: proc `%s` will run\n", pp->name);
print_proc(pp);
printl("scheduler: proc `%s`(PID: %d) will run\n", pp->name, pp->pid);
printl("scheduler: switch pgdir & set tss\n");
uvm_switch(pp);
pp->state = P_RUNNING;
proc = pp;
printl(">>>> context switch\n");
context_switch(&cpu_context, pp->context);
printl("scheduler: return form proc `%s`\n", pp->name);
printl("<<<< return form proc `%s`\n", pp->name);
}
}
}
@@ -277,6 +302,7 @@ int fork(){
child->pgdir = uvm_copy(proc->pgdir, proc->size);
if (child->pgdir == 0){
panic("fork:");
pmm_free((uint32_t)child->kern_stack);
child->kern_stack = 0;
child->state = P_UNUSED;
@@ -291,7 +317,6 @@ int fork(){
*child->fm = *proc->fm; // return form same address
child->fm->eax = 0;
printl("fork: dup opened files\n");
for (i = 0; i < NOFILE; i++){
if (proc->ofile[i]){
@@ -300,9 +325,10 @@ int fork(){
}
child->cwd = idup(proc->cwd);
child->state = P_RUNABLE;
strncpy(child->name, "init2", 5);
strncpy(child->name, proc->name, sizeof(proc->name));
printl("fork: done\n");
return child->pid;

0 comments on commit fc0e84c

Please sign in to comment.