-/* $OpenBSD: pmap.h,v 1.15 2020/08/25 17:49:58 kettenis Exp $ */
+/* $OpenBSD: pmap.h,v 1.16 2021/05/11 18:21:12 kettenis Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
void pmap_bootstrap_cpu(void);
int pmap_slbd_fault(pmap_t, vaddr_t);
+int pmap_slbd_enter(pmap_t, vaddr_t);
int pmap_set_user_slb(pmap_t, vaddr_t, vaddr_t *, vsize_t *);
void pmap_clear_user_slb(void);
void pmap_unset_user_slb(void);
-/* $OpenBSD: pmap.c,v 1.55 2020/12/23 17:54:04 kettenis Exp $ */
+/* $OpenBSD: pmap.c,v 1.56 2021/05/11 18:21:12 kettenis Exp $ */
/*
* Copyright (c) 2015 Martin Pieuchot
return slbd;
}
+int
+pmap_slbd_enter(pmap_t pm, vaddr_t va)
+{
+ struct slb_desc *slbd;
+
+ PMAP_VP_LOCK(pm);
+ slbd = pmap_slbd_lookup(pm, va);
+ if (slbd == NULL)
+ slbd = pmap_slbd_alloc(pm, va);
+ PMAP_VP_UNLOCK(pm);
+
+ return slbd ? 0 : EFAULT;
+}
+
int
pmap_set_user_slb(pmap_t pm, vaddr_t va, vaddr_t *kva, vsize_t *len)
{
-/* $OpenBSD: trap.c,v 1.50 2021/05/05 07:29:01 mpi Exp $ */
+/* $OpenBSD: trap.c,v 1.51 2021/05/11 18:21:12 kettenis Exp $ */
/*
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
int type = frame->exc;
union sigval sv;
struct vm_map *map;
+ struct vm_map_entry *entry;
pmap_t pm;
vaddr_t va;
int access_type;
va = curpcb->pcb_userva | (va & SEGMENT_MASK);
}
if (frame->dsisr & DSISR_STORE)
- access_type = PROT_READ | PROT_WRITE;
+ access_type = PROT_WRITE;
else
access_type = PROT_READ;
error = uvm_fault(map, trunc_page(va), 0, access_type);
error = pmap_slbd_fault(pm, frame->dar);
if (error == 0)
break;
- frame->dsisr = 0;
- /* FALLTHROUGH */
+
+ if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p),
+ "[%s]%d/%d sp=%lx inside %lx-%lx: not MAP_STACK\n",
+ uvm_map_inentry_sp, p->p_vmspace->vm_map.sserial))
+ goto out;
+
+ /*
+ * Unfortunately, the hardware doesn't tell us whether
+ * this was a read or a write fault. So we check
+ * whether there is a mapping at the fault address and
+ * insert a new SLB entry. Executing the faulting
+ * instruction again should result in a Data Storage
+ * Interrupt that does indicate whether we're dealing
+ * with with a read or a write fault.
+ */
+ map = &p->p_vmspace->vm_map;
+ vm_map_lock_read(map);
+ if (uvm_map_lookup_entry(map, frame->dar, &entry))
+ error = pmap_slbd_enter(pm, frame->dar);
+ else
+ error = EFAULT;
+ vm_map_unlock_read(map);
+ if (error) {
+ sv.sival_ptr = (void *)frame->dar;
+ trapsignal(p, SIGSEGV, 0, SEGV_MAPERR, sv);
+ }
+ break;
case EXC_DSI|EXC_USER:
if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p),
map = &p->p_vmspace->vm_map;
va = frame->dar;
if (frame->dsisr & DSISR_STORE)
- access_type = PROT_READ | PROT_WRITE;
+ access_type = PROT_WRITE;
else
access_type = PROT_READ;
error = uvm_fault(map, trunc_page(va), 0, access_type);