#define pmap_proc_iflush(p,va,len) /* nothing */
-void pmap_bootstrap(u_long, u_long, u_int, u_int);
+void pmap_bootstrap(u_long, u_long, u_int, u_int);
+int pmap_copyinsn(pmap_t, vaddr_t, uint32_t *);
/* make sure all page mappings are modulo 16K to prevent d$ aliasing */
#define PMAP_PREFER
-/* $OpenBSD: pmap.c,v 1.109 2023/01/23 19:31:41 miod Exp $ */
+/* $OpenBSD: pmap.c,v 1.110 2023/01/24 07:26:34 miod Exp $ */
/* $NetBSD: pmap.c,v 1.107 2001/08/31 16:47:41 eeh Exp $ */
/*
*
}
#endif
+
+/*
+ * Read an instruction from a given virtual memory address.
+ * EXEC_ONLY mappings are bypassed.
+ */
+int
+pmap_copyinsn(pmap_t pmap, vaddr_t va, uint32_t *insn)
+{
+ paddr_t pa;
+
+ if (pmap == pmap_kernel())
+ return EINVAL;
+
+ mtx_enter(&pmap->pm_mtx);
+ /* inline pmap_extract */
+ pa = pseg_get(pmap, va) & TLB_PA_MASK;
+ if (pa != 0)
+ *insn = lduwa(pa | (va & PAGE_MASK), ASI_PHYS_CACHED);
+ mtx_leave(&pmap->pm_mtx);
+
+ return pa == 0 ? EFAULT : 0;
+}
-/* $OpenBSD: trap.c,v 1.113 2023/01/16 05:32:05 deraadt Exp $ */
+/* $OpenBSD: trap.c,v 1.114 2023/01/24 07:26:34 miod Exp $ */
/* $NetBSD: trap.c,v 1.73 2001/08/09 01:03:01 eeh Exp $ */
/*
vaddr_t pc, u_long sfsr, vaddr_t afva, u_long afsr);
void syscall(struct trapframe *, register_t code, register_t pc);
+int copyinsn(struct proc *p, vaddr_t uva, int *insn);
+
/*
* If someone stole the FPU while we were away, do not enable it
* on return. This is not done in userret() above as it must follow
{
union instr ins;
- if (copyin((caddr_t)pc, &ins, sizeof(ins)) != 0) {
+ if (copyinsn(p, pc, &ins.i_int) != 0) {
/* XXX Can this happen? */
trapsignal(p, SIGILL, 0, ILL_ILLOPC, sv);
break;
{
union instr ins;
- if (copyin((caddr_t)pc, &ins, sizeof(ins)) != 0) {
+ if (copyinsn(p, pc, &ins.i_int) != 0) {
/* XXX Can this happen? */
trapsignal(p, SIGILL, 0, ILL_ILLOPC, sv);
break;
* Push the faulting instruction on the queue;
* we might need to emulate it.
*/
- copyin((caddr_t)pc, &p->p_md.md_fpstate->fs_queue[0].fq_instr, sizeof(int));
+ (void)copyinsn(p, pc,
+ &p->p_md.md_fpstate->fs_queue[0].fq_instr);
p->p_md.md_fpstate->fs_queue[0].fq_addr = (int *)pc;
p->p_md.md_fpstate->fs_qsize = 1;
}
mi_child_return(p);
}
+
+int
+copyinsn(struct proc *p, vaddr_t uva, int *insn)
+{
+ struct vm_map *map = &p->p_vmspace->vm_map;
+ int error = 0;
+
+ if (__predict_false((uva & 3) != 0))
+ return EFAULT;
+
+ do {
+ if (pmap_copyinsn(map->pmap, uva, (uint32_t *)insn) == 0)
+ break;
+ error = uvm_fault(map, trunc_page(uva), 0, PROT_EXEC);
+ } while (error == 0);
+
+ return error;
+}