openblt

a hobby OS from the late 90s
git clone http://frotz.net/git/openblt.git
Log | Files | Refs | LICENSE

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