summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjdike <jdike>2003-08-29 16:44:43 +0000
committerjdike <jdike>2003-08-29 16:44:43 +0000
commitb33c69da3229290b727ebbb014f2082a8f8598f5 (patch)
tree528d189e48cbdf69bb01d838f0ceecab92908216
parentf866b36b98c39fb08a6726cdb9ac17d243739979 (diff)
downloaduml-history-b33c69da3229290b727ebbb014f2082a8f8598f5.tar.gz
Added support for fixing faults on physical memory.
-rw-r--r--arch/um/kernel/trap_kern.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index 187456b..642b144 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -21,6 +21,8 @@
#include "chan_kern.h"
#include "mconsole_kern.h"
#include "2_5compat.h"
+#include "mem.h"
+#include "mem_kern.h"
unsigned long handle_page_fault(unsigned long address, unsigned long ip,
int is_write, int is_user, int *code_out)
@@ -85,6 +87,33 @@ unsigned long handle_page_fault(unsigned long address, unsigned long ip,
return(handled);
}
+LIST_HEAD(physmem_remappers);
+
+void register_remapper(struct remapper *info)
+{
+ list_add(&info->list, &physmem_remappers);
+}
+
+static int check_remapped_addr(unsigned long address, int is_write)
+{
+ struct remapper *remapper;
+ struct list_head *ele;
+ __u64 offset;
+ int fd;
+
+ fd = phys_mapping(__pa(address), &offset);
+ if(fd == -1)
+ return(0);
+
+ list_for_each(ele, &physmem_remappers){
+ remapper = list_entry(ele, struct remapper, list);
+ if((*remapper->proc)(fd, address, is_write, offset))
+ return(1);
+ }
+
+ return(0);
+}
+
unsigned long segv(unsigned long address, unsigned long ip, int is_write,
int is_user, void *sc)
{
@@ -96,7 +125,9 @@ unsigned long segv(unsigned long address, unsigned long ip, int is_write,
flush_tlb_kernel_vm();
return(0);
}
- if(current->mm == NULL)
+ else if(check_remapped_addr(address & PAGE_MASK, is_write))
+ return(0);
+ else if(current->mm == NULL)
panic("Segfault with no mm");
handled = handle_page_fault(address, ip, is_write, is_user,
@@ -109,9 +140,8 @@ unsigned long segv(unsigned long address, unsigned long ip, int is_write,
current->thread.fault_addr = (void *) address;
do_longjmp(catcher, 1);
}
- else if(current->thread.fault_addr != NULL){
+ else if(current->thread.fault_addr != NULL)
panic("fault_addr set but no fault catcher");
- }
else if(arch_fixup(ip, sc))
return(0);