pager.c (2179B)
1 /* $Id: //depot/blt/kernel/pager.c#3 $ 2 ** 3 ** Copyright 2000, Sidney Cammeresi. All rights reserved. 4 ** Distributed under the terms of the OpenBLT License 5 */ 6 7 #include "kernel.h" 8 #include "memory.h" 9 #include "types.h" 10 #include "sem.h" 11 #include "list.h" 12 #include "pager.h" 13 14 int pager_port_no, pager_sem_no; 15 task_t *pager_task; 16 sem_t *pager_sem; 17 list_t pager_queue; 18 19 void terminate (void); 20 void k_debugger (regs *r, uint32 eip, uint32 cs, uint32 eflags); 21 22 void pager (void) 23 { 24 pager_fault_t *fault; 25 list_t *list; 26 node_t *node; 27 area_t *area; 28 29 pager_sem = rsrc_find_sem (pager_sem_no); 30 list_init (&pager_queue); 31 32 for (;;) 33 { 34 sem_acquire (pager_sem_no); 35 fault = list_remove_head (&pager_queue); 36 37 kprintf ("pager: got paging request %d for vaddr %x", fault->op, 38 fault->vaddr); 39 list = &fault->task->team->aspace->areas; 40 node = list->next; 41 while (node->next != (node_t *) list) 42 { 43 area = node->data; 44 kprintf ("pager: checking %x+%x", area->virt_addr, area->length); 45 if (((fault->vaddr >> 12) >= area->virt_addr) && 46 (fault->vaddr >> 12) < (area->virt_addr + area->length)) 47 { 48 /* shouldn't happen yet */ 49 kprintf ("pager: found it"); 50 continue; 51 } 52 node = node->next; 53 } 54 kprintf ("pager: task %d (%s) SEGV: eip = %x, addr = %x", 55 fault->task->rsrc.id, fault->task->rsrc.name, fault->eip, 56 fault->vaddr); 57 task_wake (fault->task, ERR_SEGV); 58 } 59 } 60 61 void page_fault (uint32 number, regs r, uint32 error, uint32 eip, uint32 cs, 62 uint32 eflags) 63 { 64 pager_fault_t *fault; 65 66 /* queue the paging request */ 67 fault = kmalloc (pager_fault_t); 68 fault->op = 666; 69 asm ("mov %%cr2, %0" : "=r" (fault->vaddr)); 70 fault->eip = eip; 71 fault->task = current; 72 list_add_tail (&pager_queue, fault); 73 74 /* wake up the kernel pager */ 75 current->flags = tSLEEP_PAGING; 76 pager_sem->count++; 77 task_wake (pager_task, ERR_NONE); /* XXX: sem_release requeues us */ 78 swtch (); 79 80 /* paging is done; check result */ 81 if (current->status == ERR_SEGV) { 82 if((cs & 0xFFF8) == SEL_UCODE) { 83 user_debug(&r, &eip, &eflags); 84 } else { 85 kprintf("pf: cs = %x\n",cs& 0xfff8); 86 } 87 88 current->flags = tDEAD; 89 k_debugger (&r, eip, cs, eflags); 90 terminate (); 91 } 92 } 93