#include "asm/tlbflush.h"
#include "asm/a.out.h"
#include "asm/current.h"
+#include "asm/irq.h"
#include "user_util.h"
#include "kern_util.h"
#include "kern.h"
#include "chan_kern.h"
#include "mconsole_kern.h"
#include "2_5compat.h"
+#include "mem.h"
+#include "mem_kern.h"
int handle_page_fault(unsigned long address, unsigned long ip,
int is_write, int is_user, int *code_out)
if(is_write && !(vma->vm_flags & VM_WRITE))
goto out;
page = address & PAGE_MASK;
- if(page == (unsigned long) current->thread_info + PAGE_SIZE)
- panic("Kernel stack overflow");
pgd = pgd_offset(mm, page);
pmd = pmd_offset(pgd, page);
- survive:
do {
+ survive:
switch (handle_mm_fault(mm, vma, address, is_write)){
case VM_FAULT_MINOR:
current->min_flt++;
}
pte = pte_offset_kernel(pmd, page);
} while(!pte_present(*pte));
+ err = 0;
*pte = pte_mkyoung(*pte);
if(pte_write(*pte)) *pte = pte_mkdirty(*pte);
flush_tlb_page(vma, page);
- err = 0;
out:
up_read(&mm->mmap_sem);
return(err);
down_read(&mm->mmap_sem);
goto survive;
}
- err = -ENOMEM;
goto out;
}
+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)
{
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");
err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
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);
{
struct siginfo si;
- printk(KERN_ERR "Unfixable SEGV in '%s' (pid %d) at 0x%lx "
- "(ip 0x%lx)\n", current->comm, current->pid, address, ip);
si.si_signo = SIGSEGV;
si.si_code = SEGV_ACCERR;
si.si_addr = (void *) address;
else relay_signal(sig, regs);
}
+void winch(int sig, union uml_pt_regs *regs)
+{
+ do_IRQ(WINCH_IRQ, regs);
+}
+
void trap_init(void)
{
}