#include "linux/ptrace.h"
#include "asm/semaphore.h"
#include "asm/pgtable.h"
+#include "asm/pgalloc.h"
#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)
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
pte_t *pte;
unsigned long page;
goto good_area;
else if(!(vma->vm_flags & VM_GROWSDOWN))
goto out;
+ else if(!ARCH_IS_STACKGROW(address))
+ goto out;
else if(expand_stack(vma, address))
goto 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:
+ pud = pud_offset(pgd, page);
+ pmd = pmd_offset(pud, page);
do {
+ survive:
switch (handle_mm_fault(mm, vma, address, is_write)){
case VM_FAULT_MINOR:
current->min_flt++;
default:
BUG();
}
+ pgd = pgd_offset(mm, page);
+ pud = pud_offset(pgd, page);
+ pmd = pmd_offset(pud, page);
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)
{
}
-spinlock_t trap_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(trap_lock);
static int trap_index = 0;