1 /* $NetBSD: netbsd32_machdep.c,v 1.25 2024/06/18 13:29:56 rin Exp $ */ 2 3 /* 4 * Copyright (c) 2018 Ryo Shimizu 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.25 2024/06/18 13:29:56 rin Exp $"); 31 32 #if defined(_KERNEL_OPT) 33 #include "opt_compat_netbsd.h" 34 #endif 35 36 #include <sys/param.h> 37 #include <sys/core.h> 38 #include <sys/exec.h> 39 #include <sys/lwp.h> 40 #include <sys/ptrace.h> 41 #include <sys/ras.h> 42 #include <sys/signalvar.h> 43 #include <sys/syscallargs.h> 44 #include <sys/compat_stub.h> 45 46 #include <uvm/uvm_extern.h> 47 48 #include <compat/netbsd32/netbsd32.h> 49 #include <compat/netbsd32/netbsd32_exec.h> 50 #include <compat/netbsd32/netbsd32_syscallargs.h> 51 52 #include <aarch64/armreg.h> 53 #include <aarch64/frame.h> 54 #include <aarch64/machdep.h> 55 #include <aarch64/userret.h> 56 57 #include <arm/cpufunc.h> 58 59 const char machine32[] = MACHINE; 60 const char machine_arch32[] = MACHINE32_ARCH; 61 62 void 63 netbsd32_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) 64 { 65 struct proc * const p = l->l_proc; 66 struct trapframe * const tf = lwp_trapframe(l); 67 68 netbsd32_adjust_limits(p); 69 70 aarch64_setregs_ptrauth(l, false); 71 72 p->p_flag |= PK_32; 73 74 /* 75 * void __start(struct ps_strings *ps_strings, const Obj_Entry *obj, 76 * void (*cleanup)(void)); 77 */ 78 memset(tf, 0, sizeof(*tf)); 79 tf->tf_reg[0] = (uint32_t)p->p_psstrp; 80 tf->tf_reg[12] = stack; /* r12 needed by pre 1.4 crt0.c */ 81 tf->tf_reg[13] = stack; /* sp */ 82 tf->tf_reg[14] = pack->ep_entry;/* lr */ 83 tf->tf_reg[18] = 0x77777777; /* svc_lr. adjust to arm_machdep.c */ 84 tf->tf_pc = pack->ep_entry; 85 86 87 /* set 32bit mode, and same endian as 64bit's */ 88 #ifdef __AARCH64EB__ 89 tf->tf_spsr = SPSR_M_USR32 | SPSR_A32_E; 90 #else 91 tf->tf_spsr = SPSR_M_USR32; 92 #endif 93 94 /* THUMB CODE? */ 95 if (pack->ep_entry & 1) 96 tf->tf_spsr |= SPSR_A32_T; 97 } 98 99 int 100 netbsd32_ptrace_translate_request(int req) 101 { 102 103 switch (req) { 104 case 0 ... PT_FIRSTMACH - 1: 105 return req; 106 case PT32_GETREGS: 107 return PT_GETREGS; 108 case PT32_SETREGS: 109 return PT_SETREGS; 110 case PT32_GETFPREGS: 111 return PT_GETFPREGS; 112 case PT32_SETFPREGS: 113 return PT_SETFPREGS; 114 /* not implemented for arm32 */ 115 case PT32_STEP: 116 case PT32_SETSTEP: 117 case PT32_CLEARSTEP: 118 default: 119 return -1; 120 } 121 } 122 123 /* aarch32 fpscr register is assigned to two registers fpsr/fpcr on aarch64 */ 124 #define FPSR_BITS \ 125 (FPSR_N32|FPSR_Z32|FPSR_C32|FPSR_V32|FPSR_QC| \ 126 FPSR_IDC|FPSR_IXC|FPSR_UFC|FPSR_OFC|FPSR_DZC|FPSR_IOC) 127 #define FPCR_BITS \ 128 (FPCR_AHP|FPCR_DN|FPCR_FZ|FPCR_RMODE|FPCR_STRIDE|FPCR_LEN| \ 129 FPCR_IDE|FPCR_IXE|FPCR_UFE|FPCR_OFE|FPCR_DZE|FPCR_IOE) 130 131 int 132 netbsd32_process_read_regs(struct lwp *l, struct reg32 *regs) 133 { 134 struct proc * const p = l->l_proc; 135 struct trapframe *tf = lwp_trapframe(l); 136 int i; 137 138 if ((p->p_flag & PK_32) == 0) 139 return EINVAL; 140 141 for (i = 0; i < 13; i++) 142 regs->r[i] = tf->tf_reg[i]; /* r0-r12 */ 143 regs->r_sp = tf->tf_reg[13]; /* r13 = sp */ 144 regs->r_lr = tf->tf_reg[14]; /* r14 = lr */ 145 regs->r_pc = tf->tf_pc; /* r15 = pc */ 146 regs->r_cpsr = tf->tf_spsr; 147 148 /* THUMB CODE? */ 149 if (tf->tf_spsr & SPSR_A32_T) 150 regs->r_pc |= 1; 151 152 return 0; 153 } 154 155 int 156 netbsd32_process_read_fpregs(struct lwp *l, struct fpreg32 *fpregs, 157 size_t *lenp) 158 { 159 struct proc * const p = l->l_proc; 160 struct pcb * const pcb = lwp_getpcb(l); 161 int i, j; 162 163 if ((p->p_flag & PK_32) == 0) 164 return EINVAL; 165 166 KASSERT(*lenp <= sizeof(*fpregs)); 167 fpu_save(l); 168 169 /* 170 * convert from aarch64's struct fpreg to arm's struct fpreg32 171 */ 172 #define VFP_FPEXC_EN 0x40000000 /* VFP Enable bit */ 173 #define VFP_FPEXC_VECITR 0x00000700 /* VECtor ITeRation count */ 174 fpregs->fpr_vfp.vfp_fpexc = VFP_FPEXC_EN | VFP_FPEXC_VECITR; 175 176 fpregs->fpr_vfp.vfp_fpscr = 177 (pcb->pcb_fpregs.fpsr & FPSR_BITS) | 178 (pcb->pcb_fpregs.fpcr & FPCR_BITS); 179 180 fpregs->fpr_vfp.vfp_fpinst = 0; 181 fpregs->fpr_vfp.vfp_fpinst2 = 0; 182 183 for (i = j = 0; i < 16; i++) { 184 #ifdef __AARCH64EB__ 185 fpregs->fpr_vfp.vfp_regs[j++] = 186 pcb->pcb_fpregs.fp_reg[i].u64[1]; 187 fpregs->fpr_vfp.vfp_regs[j++] = 188 pcb->pcb_fpregs.fp_reg[i].u64[0]; 189 #else 190 fpregs->fpr_vfp.vfp_regs[j++] = 191 pcb->pcb_fpregs.fp_reg[i].u64[0]; 192 fpregs->fpr_vfp.vfp_regs[j++] = 193 pcb->pcb_fpregs.fp_reg[i].u64[1]; 194 #endif 195 } 196 197 return 0; 198 } 199 200 int 201 netbsd32_process_write_regs(struct lwp *l, const struct reg32 *regs) 202 { 203 struct proc * const p = l->l_proc; 204 struct trapframe *tf = lwp_trapframe(l); 205 int i; 206 207 if ((p->p_flag & PK_32) == 0) 208 return EINVAL; 209 210 if (regs->r_pc >= VM_MAXUSER_ADDRESS32 || 211 regs->r_sp >= VM_MAXUSER_ADDRESS32) 212 return EINVAL; 213 214 for (i = 0; i < 13; i++) 215 tf->tf_reg[i] = regs->r[i]; /* r0-r12 */ 216 tf->tf_reg[13] = regs->r_sp; /* r13 = sp */ 217 tf->tf_reg[14] = regs->r_lr; /* r14 = lr */ 218 tf->tf_pc = regs->r_pc; /* r15 = pc */ 219 tf->tf_spsr &= ~(SPSR_NZCV | SPSR_A32_T); 220 tf->tf_spsr |= regs->r_cpsr & (SPSR_NZCV | SPSR_A32_T); 221 222 /* THUMB CODE? */ 223 if (regs->r_pc & 1) 224 tf->tf_spsr |= SPSR_A32_T; 225 226 return 0; 227 } 228 229 int 230 netbsd32_process_write_fpregs(struct lwp *l, const struct fpreg32 *fpregs, 231 size_t len) 232 { 233 struct proc * const p = l->l_proc; 234 struct pcb * const pcb = lwp_getpcb(l); 235 int i, j; 236 237 if ((p->p_flag & PK_32) == 0) 238 return EINVAL; 239 240 KASSERT(len <= sizeof(*fpregs)); 241 fpu_discard(l, true); // set used flag 242 243 pcb->pcb_fpregs.fpsr = fpregs->fpr_vfp.vfp_fpscr & FPSR_BITS; 244 pcb->pcb_fpregs.fpcr = fpregs->fpr_vfp.vfp_fpscr & FPCR_BITS; 245 246 for (i = j = 0; i < 16; i++) { 247 #ifdef __AARCH64EB__ 248 pcb->pcb_fpregs.fp_reg[i].u64[1] = 249 fpregs->fpr_vfp.vfp_regs[j++]; 250 pcb->pcb_fpregs.fp_reg[i].u64[0] = 251 fpregs->fpr_vfp.vfp_regs[j++]; 252 #else 253 pcb->pcb_fpregs.fp_reg[i].u64[0] = 254 fpregs->fpr_vfp.vfp_regs[j++]; 255 pcb->pcb_fpregs.fp_reg[i].u64[1] = 256 fpregs->fpr_vfp.vfp_regs[j++]; 257 #endif 258 } 259 260 return 0; 261 } 262 263 int 264 cpu_coredump32(struct lwp *l, struct coredump_iostate *iocookie, 265 struct core32 *chdr) 266 { 267 struct netbsd32_cpustate md_core32; 268 struct coreseg32 cseg; 269 int error; 270 271 if (iocookie == NULL) { 272 CORE_SETMAGIC(*chdr, COREMAGIC, MID_ARM6, 0); 273 chdr->c_hdrsize = ALIGN32(sizeof(*chdr)); 274 chdr->c_seghdrsize = ALIGN32(sizeof(cseg)); 275 chdr->c_cpusize = sizeof(md_core32); 276 chdr->c_nseg++; 277 return 0; 278 } 279 280 error = netbsd32_process_read_regs(l, &md_core32.regs); 281 if (error) 282 return error; 283 284 error = netbsd32_process_read_fpregs(l, &md_core32.fpregs, NULL); 285 if (error) 286 return error; 287 288 CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_ARM6, CORE_CPU); 289 cseg.c_addr = 0; 290 cseg.c_size = chdr->c_cpusize; 291 292 MODULE_HOOK_CALL(coredump_write_hook, (iocookie, UIO_SYSSPACE, 293 &cseg, chdr->c_seghdrsize), ENOSYS, error); 294 if (error) 295 return error; 296 297 MODULE_HOOK_CALL(coredump_write_hook, (iocookie, UIO_SYSSPACE, 298 &md_core32, sizeof(md_core32)), ENOSYS, error); 299 300 return error; 301 } 302 303 void 304 netbsd32_sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) 305 { 306 struct lwp * const l = curlwp; 307 struct proc * const p = l->l_proc; 308 struct trapframe * const tf = lwp_trapframe(l); 309 stack_t * const ss = &l->l_sigstk; 310 const int signo = ksi->ksi_signo; 311 const struct sigaction * const sa = &SIGACTION(p, signo); 312 const struct sigact_sigdesc * const sdesc = 313 &p->p_sigacts->sa_sigdesc[signo]; 314 const sig_t handler = sa->sa_handler; 315 struct netbsd32_sigframe_siginfo *fp, frame; 316 int error; 317 318 const bool onstack_p = 319 (ss->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 320 (sa->sa_flags & SA_ONSTACK); 321 322 vaddr_t sp = onstack_p ? 323 ((vaddr_t)ss->ss_sp + ss->ss_size) : 324 tf->tf_reg[13]; /* r13 = sp on aarch32 */ 325 326 fp = (struct netbsd32_sigframe_siginfo *)sp; 327 fp = (struct netbsd32_sigframe_siginfo *)STACK_ALIGN(fp - 1, (8 - 1)); 328 329 memset(&frame, 0, sizeof(frame)); 330 331 /* XXX: netbsd32_ksi_to_si32 */ 332 netbsd32_si_to_si32(&frame.sf_si, (const siginfo_t *)&ksi->ksi_info); 333 334 frame.sf_uc.uc_flags = _UC_SIGMASK; 335 frame.sf_uc.uc_sigmask = *mask; 336 frame.sf_uc.uc_link = (uint32_t)(uintptr_t)l->l_ctxlink; 337 frame.sf_uc.uc_flags |= (l->l_sigstk.ss_flags & SS_ONSTACK) ? 338 _UC_SETSTACK : _UC_CLRSTACK; 339 sendsig_reset(l, signo); 340 341 mutex_exit(p->p_lock); 342 cpu_getmcontext32(l, &frame.sf_uc.uc_mcontext, &frame.sf_uc.uc_flags); 343 error = copyout(&frame, fp, sizeof(frame)); 344 mutex_enter(p->p_lock); 345 346 if (error != 0) { 347 /* 348 * Process has trashed its stack; 349 * give it an illegal instruction to halt it in its tracks. 350 */ 351 sigexit(l, SIGILL); 352 /* NOTREACHED */ 353 } 354 355 tf->tf_reg[0] = signo; 356 tf->tf_reg[1] = (uint32_t)(uintptr_t)&fp->sf_si; 357 tf->tf_reg[2] = (uint32_t)(uintptr_t)&fp->sf_uc; 358 359 /* the trampoline uses r5 as the uc address */ 360 tf->tf_reg[5] = (uint32_t)(uintptr_t)&fp->sf_uc; 361 tf->tf_pc = (uint32_t)(uintptr_t)handler; 362 363 /* THUMB CODE? */ 364 if (((uintptr_t)handler) & 1) 365 tf->tf_spsr |= SPSR_A32_T; 366 else 367 tf->tf_spsr &= ~SPSR_A32_T; 368 369 tf->tf_reg[13] = (uint32_t)(uintptr_t)fp; /* sp */ 370 tf->tf_reg[14] = (uint32_t)(uintptr_t)sdesc->sd_tramp; /* lr */ 371 372 /* Remember if we're now on the signal stack */ 373 if (onstack_p) 374 ss->ss_flags |= SS_ONSTACK; 375 } 376 377 void 378 startlwp32(void *arg) 379 { 380 ucontext32_t *uc = arg; 381 lwp_t *l = curlwp; 382 int error __diagused; 383 384 /* 385 * entity of *uc is ucontext_t. therefore 386 * ucontext_t must be greater than ucontext32_t 387 */ 388 CTASSERT(sizeof(ucontext_t) >= sizeof(ucontext32_t)); 389 390 error = cpu_setmcontext32(l, &uc->uc_mcontext, uc->uc_flags); 391 KASSERT(error == 0); 392 393 /* Note: we are freeing ucontext_t, not ucontext32_t. */ 394 kmem_free(uc, sizeof(ucontext_t)); 395 userret(l); 396 } 397 398 int 399 cpu_mcontext32_validate(struct lwp *l, const mcontext32_t *mcp) 400 { 401 struct proc * const p __diagused = l->l_proc; 402 const uint32_t spsr = mcp->__gregs[_REG_CPSR]; 403 404 KASSERT(p->p_flag & PK_32); 405 406 if (__SHIFTOUT(spsr, SPSR_M) != SPSR_M_USR32) 407 return EINVAL; 408 409 #ifdef __AARCH64EB__ 410 if ((spsr & SPSR_A32_E) == 0) 411 return EINVAL; 412 #else 413 if ((spsr & SPSR_A32_E) != 0) 414 return EINVAL; 415 #endif 416 417 if ((spsr & (SPSR_A|SPSR_I|SPSR_F)) != 0) 418 return EINVAL; 419 420 return 0; 421 } 422 void 423 cpu_getmcontext32(struct lwp *l, mcontext32_t *mcp, unsigned int *flagsp) 424 { 425 struct trapframe * const tf = lwp_trapframe(l); 426 __greg32_t *gr = mcp->__gregs; 427 void *ras_pc; 428 429 gr[_REG_R0] = tf->tf_reg[0]; 430 gr[_REG_R1] = tf->tf_reg[1]; 431 gr[_REG_R2] = tf->tf_reg[2]; 432 gr[_REG_R3] = tf->tf_reg[3]; 433 gr[_REG_R4] = tf->tf_reg[4]; 434 gr[_REG_R5] = tf->tf_reg[5]; 435 gr[_REG_R6] = tf->tf_reg[6]; 436 gr[_REG_R7] = tf->tf_reg[7]; 437 gr[_REG_R8] = tf->tf_reg[8]; 438 gr[_REG_R9] = tf->tf_reg[9]; 439 gr[_REG_R10] = tf->tf_reg[10]; 440 gr[_REG_R11] = tf->tf_reg[11]; 441 gr[_REG_R12] = tf->tf_reg[12]; 442 gr[_REG_R13] = tf->tf_reg[13]; 443 gr[_REG_R14] = tf->tf_reg[14]; 444 gr[_REG_R15] = tf->tf_pc; 445 gr[_REG_CPSR] = tf->tf_spsr; 446 447 ras_pc = ras_lookup(l->l_proc, (void *)(uintptr_t)gr[_REG_R15]); 448 if (ras_pc != (void *)-1) { 449 gr[_REG_R15] = (__greg32_t)(uintptr_t)ras_pc; 450 } 451 *flagsp |= _UC_CPU; 452 453 /* fpu context */ 454 if (fpu_used_p(l)) { 455 const struct pcb * const pcb = lwp_getpcb(l); 456 int i, j; 457 458 fpu_save(l); 459 460 for (i = j = 0; i < 16; i++) { 461 #ifdef __AARCH64EB__ 462 mcp->__vfpregs.__vfp_fstmx[j++] = 463 pcb->pcb_fpregs.fp_reg[i].u64[1]; 464 mcp->__vfpregs.__vfp_fstmx[j++] = 465 pcb->pcb_fpregs.fp_reg[i].u64[0]; 466 #else 467 mcp->__vfpregs.__vfp_fstmx[j++] = 468 pcb->pcb_fpregs.fp_reg[i].u64[0]; 469 mcp->__vfpregs.__vfp_fstmx[j++] = 470 pcb->pcb_fpregs.fp_reg[i].u64[1]; 471 #endif 472 } 473 474 mcp->__vfpregs.__vfp_fpscr = 475 (pcb->pcb_fpregs.fpsr & FPSR_BITS) | 476 (pcb->pcb_fpregs.fpcr & FPCR_BITS); 477 mcp->__vfpregs.__vfp_fpsid = 0; /* XXX: build FPSID from MIDR */ 478 479 *flagsp |= _UC_FPU; 480 } 481 482 mcp->_mc_tlsbase = (uint32_t)(uintptr_t)l->l_private; 483 *flagsp |= _UC_TLSBASE; 484 } 485 486 int 487 cpu_setmcontext32(struct lwp *l, const mcontext32_t *mcp, unsigned int flags) 488 { 489 struct trapframe * const tf = lwp_trapframe(l); 490 const __greg32_t * const gr = mcp->__gregs; 491 struct proc * const p = l->l_proc; 492 int error, i, j; 493 494 if (flags & _UC_CPU) { 495 error = cpu_mcontext32_validate(l, mcp); 496 if (error != 0) 497 return error; 498 499 tf->tf_reg[0] = gr[_REG_R0]; 500 tf->tf_reg[1] = gr[_REG_R1]; 501 tf->tf_reg[2] = gr[_REG_R2]; 502 tf->tf_reg[3] = gr[_REG_R3]; 503 tf->tf_reg[4] = gr[_REG_R4]; 504 tf->tf_reg[5] = gr[_REG_R5]; 505 tf->tf_reg[6] = gr[_REG_R6]; 506 tf->tf_reg[7] = gr[_REG_R7]; 507 tf->tf_reg[8] = gr[_REG_R8]; 508 tf->tf_reg[9] = gr[_REG_R9]; 509 tf->tf_reg[10] = gr[_REG_R10]; 510 tf->tf_reg[11] = gr[_REG_R11]; 511 tf->tf_reg[12] = gr[_REG_R12]; 512 tf->tf_reg[13] = gr[_REG_R13]; 513 tf->tf_reg[14] = gr[_REG_R14]; 514 tf->tf_pc = gr[_REG_R15]; 515 tf->tf_spsr = gr[_REG_CPSR]; 516 } 517 518 if (flags & _UC_FPU) { 519 struct pcb * const pcb = lwp_getpcb(l); 520 fpu_discard(l, true); 521 522 for (i = j = 0; i < 16; i++) { 523 #ifdef __AARCH64EB__ 524 pcb->pcb_fpregs.fp_reg[i].u64[1] = 525 mcp->__vfpregs.__vfp_fstmx[j++]; 526 pcb->pcb_fpregs.fp_reg[i].u64[0] = 527 mcp->__vfpregs.__vfp_fstmx[j++]; 528 #else 529 pcb->pcb_fpregs.fp_reg[i].u64[0] = 530 mcp->__vfpregs.__vfp_fstmx[j++]; 531 pcb->pcb_fpregs.fp_reg[i].u64[1] = 532 mcp->__vfpregs.__vfp_fstmx[j++]; 533 #endif 534 } 535 pcb->pcb_fpregs.fpsr = 536 mcp->__vfpregs.__vfp_fpscr & FPSR_BITS; 537 pcb->pcb_fpregs.fpcr = 538 mcp->__vfpregs.__vfp_fpscr & FPCR_BITS; 539 } 540 541 if (flags &_UC_TLSBASE) 542 l->l_private = (void *)(uintptr_t)mcp->_mc_tlsbase; 543 544 mutex_enter(p->p_lock); 545 if (flags & _UC_SETSTACK) 546 l->l_sigstk.ss_flags |= SS_ONSTACK; 547 if (flags & _UC_CLRSTACK) 548 l->l_sigstk.ss_flags &= ~SS_ONSTACK; 549 mutex_exit(p->p_lock); 550 551 return 0; 552 } 553 554 static int 555 arm32_sync_icache(struct lwp *l, const void *args, register_t *retval) 556 { 557 struct netbsd32_arm_sync_icache_args ua; 558 struct faultbuf fb; 559 int error; 560 561 error = copyin(args, &ua, sizeof(ua)); 562 if (error != 0) 563 return error; 564 565 if ((vaddr_t)ua.addr + ua.len > VM_MAXUSER_ADDRESS32) 566 return EINVAL; 567 568 /* use cpu_set_onfault() by way of precaution */ 569 if ((error = cpu_set_onfault(&fb)) == 0) { 570 pmap_icache_sync_range( 571 vm_map_pmap(&l->l_proc->p_vmspace->vm_map), 572 (vaddr_t)ua.addr, (vaddr_t)ua.addr + ua.len); 573 cpu_unset_onfault(); 574 } 575 576 *retval = 0; 577 return error; 578 } 579 580 static int 581 arm32_drain_writebuf(struct lwp *l, const void *args, register_t *retval) 582 { 583 aarch64_drain_writebuf(); 584 585 *retval = 0; 586 return 0; 587 } 588 589 int 590 netbsd32_sysarch(struct lwp *l, const struct netbsd32_sysarch_args *uap, 591 register_t *retval) 592 { 593 /* { 594 syscallarg(int) op; 595 syscallarg(netbsd32_voidp) parms; 596 } */ 597 int error; 598 599 switch (SCARG(uap, op)) { 600 case ARM_SYNC_ICACHE: 601 error = arm32_sync_icache(l, 602 NETBSD32PTR64(SCARG(uap, parms)), retval); 603 break; 604 case ARM_DRAIN_WRITEBUF: 605 error = arm32_drain_writebuf(l, 606 NETBSD32PTR64(SCARG(uap, parms)), retval); 607 break; 608 case ARM_VFP_FPSCR: 609 printf("%s: ARM_VFP_FPSCR not implemented\n", __func__); 610 error = EINVAL; 611 break; 612 case ARM_FPU_USED: 613 printf("%s: ARM_FPU_USED not implemented\n", __func__); 614 error = EINVAL; 615 break; 616 default: 617 printf("%s: op=%d: not implemented\n", __func__, 618 SCARG(uap, op)); 619 error = EINVAL; 620 break; 621 } 622 return error; 623 } 624 625 vaddr_t 626 netbsd32_vm_default_addr(struct proc *p, vaddr_t base, vsize_t sz, 627 int topdown) 628 { 629 if (topdown) 630 return VM_DEFAULT_ADDRESS32_TOPDOWN(base, sz); 631 else 632 return VM_DEFAULT_ADDRESS32_BOTTOMUP(base, sz); 633 } 634 635 void 636 netbsd32_machdep_md_init(void) 637 { 638 639 /* nothing to do */ 640 } 641 642 void 643 netbsd32_machdep_md_fini(void) 644 { 645 646 /* nothing to do */ 647 } 648