UbixOS  2.0
pagefault.c
Go to the documentation of this file.
1 /*-
2  * Copyright (c) 2002-2018 The UbixOS Project.
3  * All rights reserved.
4  *
5  * This was developed by Christopher W. Olsen for the UbixOS Project.
6  *
7  * Redistribution and use in source and binary forms, with or without modification, are permitted
8  * provided that the following conditions are met:
9  *
10  * 1) Redistributions of source code must retain the above copyright notice, this list of
11  * conditions, the following disclaimer and the list of authors.
12  * 2) Redistributions in binary form must reproduce the above copyright notice, this list of
13  * conditions, the following disclaimer and the list of authors in the documentation and/or
14  * other materials provided with the distribution.
15  * 3) Neither the name of the UbixOS Project nor the names of its contributors may be used to
16  * endorse or promote products derived from this software without specific prior written
17  * permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <vmm/vmm.h>
30 #include <ubixos/sched.h>
31 #include <ubixos/kpanic.h>
32 #include <ubixos/spinlock.h>
33 #include <lib/kprintf.h>
34 #include <sys/trap.h>
35 
36 static struct spinLock pageFaultSpinLock = SPIN_LOCK_INITIALIZER;
37 
38 /*****************************************************************************************
39 
40  Function: void vmm_pageFault(uInt32 memAddr,uInt32 eip,uInt32 esp);
41  Description: This is the page fault handler, it will handle COW and trap all other
42  exceptions and segfault the thread.
43 
44  Notes:
45 
46  07/30/02 - Fixed COW However I Need To Think Of A Way To Impliment
47  A Paging System Also Start To Add Security Levels
48 
49  07/27/04 - Added spin locking to ensure that we are thread safe. I know that spining a
50  cpu is a waste of resources but for now it prevents errors.
51 
52  *****************************************************************************************/
53 /* void vmm_pageFault(uInt32 memAddr,uInt32 eip,uInt32 esp) { */
54 void vmm_pageFault(struct trapframe *frame, uint32_t cr2) {
55  uInt32 i = 0x0, pageTableIndex = 0x0, pageDirectoryIndex = 0x0;
56  uInt32 *pageDir = 0x0, *pageTable = 0x0;
57  uInt32 *src = 0x0, *dst = 0x0;
58 
59  uint32_t esp = frame->tf_esp;
60  uint32_t eip = frame->tf_eip;
61  uint32_t memAddr = cr2;
62 
63 //MrOlsen 2017-12-15 -
64  kprintf("CR2: [0x%X], EIP: 0x%X, ERR: 0x%X, PID: %i\n", cr2, frame->tf_eip, frame->tf_err, _current->id);
65 
66  /* Try to aquire lock otherwise spin till we do */
67  spinLock(&pageFaultSpinLock);
68 
69  /* Set page dir pointer to the address of the visable page directory */
70  pageDir = (uint32_t *) PD_BASE_ADDR;
71 
72  /* UBU - This is a temp panic for 0x0 read write later on I will handle this differently */
73  if (memAddr == 0x0) {
74  kprintf("Segfault At Address: [0x%X], ESP: [0x%X], PID: [%i], EIP: [0x%X]\n", memAddr, esp, _current->id, eip);
75  kpanic("Error We Wrote To 0x0\n");
76  }
77 
78  /* Calculate The Page Directory Index */
79  pageDirectoryIndex = PD_INDEX(memAddr);
80 
81  /* Calculate The Page Table Index */
82  pageTableIndex = PT_INDEX(memAddr);
83 
84  /* UBU - This is a temporary routine for handling access to a page of a non existant page table */
85  if (pageDir[pageDirectoryIndex] == 0x0) {
86  kprintf("Segfault At Address: [0x%X][0x%X][%i][0x%X], Not A Valid Page Table\n", memAddr, esp, _current->id, eip);
87  spinUnlock(&pageFaultSpinLock);
89  }
90  else {
91  /* Set pageTable To Point To Virtual Address Of Page Table */
92  pageTable = (uint32_t *) (PT_BASE_ADDR + (PAGE_SIZE * pageDirectoryIndex));
93 
94  /* Test if this is a COW on page */
95  if (((uint32_t) pageTable[pageTableIndex] & PAGE_COW) == PAGE_COW) {
96  /* Set Src To Base Address Of Page To Copy */
97  src = (uInt32 *) (memAddr & 0xFFFFF000);
98  /* Allocate A Free Page For Destination */
99  /* USE vmInfo */
100  dst = (uInt32 *) vmm_getFreeVirtualPage(_current->id, 1, 0x1);
101  /* Copy Memory */
102  for (i = 0; i < PD_ENTRIES; i++) {
103  dst[i] = src[i];
104  }
105  /* Adjust The COW Counter For Physical Page */
106  adjustCowCounter(((uInt32) pageTable[pageTableIndex] & 0xFFFFF000), -1);
107  /* Remap In New Page */
108  pageTable[pageTableIndex] = (uInt32) (vmm_getPhysicalAddr((uInt32) dst) | (memAddr & 0xFFF));
109  /* Unlink From Memory Map Allocated Page */
110  vmm_unmapPage((uInt32) dst, 1);
111  }
112  else if (pageTable[pageTableIndex] != 0x0) {
113  kprintf("Security failed pagetable not user permission\n");
114  kprintf("pageDir: [0x%X]\n", pageDir[pageDirectoryIndex]);
115  kprintf("pageTable: [0x%X:0x%X:0x%X:0x%X]\n", pageTable[pageTableIndex], pageTableIndex, pageDirectoryIndex, eip);
116  kprintf("Segfault At Address: [0x%X][0x%X][%i][0x%X] Non Mapped.\n", memAddr, esp, _current->id, eip);
117  kpanic("SIT HERE FOR NOW");
118  die_if_kernel("SEGFAULT", frame, 0xC);
119  spinUnlock(&pageFaultSpinLock);
120  endTask(_current->id);
121  }
122  else if (memAddr < (_current->td.vm_dsize + _current->td.vm_daddr)) {
123  kprintf("THIS IS BAD");
124  die_if_kernel("SEGFAULT", frame, 0xC);
125  pageTable[pageTableIndex] = (uInt32) vmm_findFreePage(_current->id) | PAGE_DEFAULT;
126  }
127  else {
128  spinUnlock(&pageFaultSpinLock);
129  /* Need To Create A Routine For Attempting To Access Non Mapped Memory */
130  kprintf("pageDir: [0x%X]\n", pageDir[pageDirectoryIndex]);
131  kprintf("pageTable: [0x%X:0x%X:0x%X:0x%X]\n", pageTable[pageTableIndex], pageTableIndex, pageDirectoryIndex, eip);
132  kprintf("Segfault At Address: [0x%X][0x%X][%i][0x%X] Non Mapped!\n", memAddr, esp, _current->id, eip);
133  die_if_kernel("SEGFAULT", frame, 0xC);
134  kpanic("SIT HERE FOR NOW");
135  kprintf("Out Of Stack Space: [0x%X]\n", memAddr & 0xFF0000);
136  endTask(_current->id);
137  }
138  }
139  asm volatile(
140  "movl %cr3,%eax\n"
141  "movl %eax,%cr3\n"
142  );
143 
144  /* Release the spin lock */
145  spinUnlock(&pageFaultSpinLock);
146  kprintf("CR2-RET");
147  return;
148 }
trapframe::tf_eip
int tf_eip
Definition: trap.h:50
spinlock.h
uInt32
unsigned long int uInt32
Definition: objgfx30.h:49
trap.h
PAGE_COW
#define PAGE_COW
Definition: paging.h:64
spinUnlock
void spinUnlock(spinLock_t *lock)
Definition: spinlock.c:36
vmm.h
vmm_getPhysicalAddr
uint32_t vmm_getPhysicalAddr(uint32_t)
Definition: getphysicaladdr.c:38
adjustCowCounter
int adjustCowCounter(uint32_t baseAddr, int adjustment)
SPIN_LOCK_INITIALIZER
#define SPIN_LOCK_INITIALIZER
Definition: spinlock.h:36
sched.h
kpanic
void kpanic(const char *fmt,...)
print panic message and halt system
Definition: kpanic.c:41
vmm_unmapPage
void vmm_unmapPage(uint32_t, unmapFlags_t)
Definition: unmappage.c:47
taskStruct::td
struct thread td
Definition: sched.h:78
spinLock
void spinLock(spinLock_t *lock)
Definition: spinlock.c:55
kpanic.h
taskStruct::id
pidType id
Definition: sched.h:63
vmm_findFreePage
uint32_t vmm_findFreePage(pidType pid)
Definition: vmm_memory.c:221
vmm_getFreeVirtualPage
void * vmm_getFreeVirtualPage(pidType, int, int)
Definition: getfreevirtualpage.c:47
trapframe::tf_err
int tf_err
Definition: trap.h:49
kprintf.h
PD_INDEX
#define PD_INDEX(v_addr)
Definition: paging.h:40
PAGE_DEFAULT
#define PAGE_DEFAULT
Definition: paging.h:68
PD_BASE_ADDR
#define PD_BASE_ADDR
Definition: paging.h:45
uint32_t
__uint32_t uint32_t
Definition: types.h:46
trapframe
Definition: trap.h:34
endTask
void endTask(pidType)
Definition: endtask.c:44
thread::vm_dsize
u_long vm_dsize
Definition: thread.h:44
_current
kTask_t * _current
Definition: sched.c:50
PT_INDEX
#define PT_INDEX(v_addr)
Definition: paging.h:42
thread::vm_daddr
u_long vm_daddr
Definition: thread.h:43
spinLock
Definition: spinlock.h:41
die_if_kernel
void die_if_kernel(char *str, struct trapframe *regs, long err)
Definition: trap.c:59
PD_ENTRIES
#define PD_ENTRIES
Definition: paging.h:48
PAGE_SIZE
#define PAGE_SIZE
Definition: paging.h:37
trapframe::tf_esp
int tf_esp
Definition: trap.h:54
kprintf
int kprintf(const char *,...)
Definition: kprintf.c:259
PT_BASE_ADDR
#define PT_BASE_ADDR
Definition: paging.h:46
vmm_pageFault
void vmm_pageFault(struct trapframe *frame, uint32_t cr2)
Definition: pagefault.c:53