1 /* 2 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 3 * Copyright (C) 1995, 1996 TooLs GmbH. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by TooLs GmbH. 17 * 4. The name of TooLs GmbH may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 /* 32 * Copyright (C) 2001 Benno Rice 33 * All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 44 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 45 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 46 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 47 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 49 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 50 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 51 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 52 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 53 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 54 * $NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $ 55 */ 56 57 #include <sys/cdefs.h> 58 __FBSDID("$FreeBSD$"); 59 60 #include "opt_ddb.h" 61 #include "opt_compat.h" 62 #include "opt_kstack_pages.h" 63 #include "opt_msgbuf.h" 64 65 #include <sys/param.h> 66 #include <sys/systm.h> 67 #include <sys/eventhandler.h> 68 #include <sys/imgact.h> 69 #include <sys/sysproto.h> 70 #include <sys/lock.h> 71 #include <sys/mutex.h> 72 #include <sys/ktr.h> 73 #include <sys/signalvar.h> 74 #include <sys/kernel.h> 75 #include <sys/proc.h> 76 #include <sys/malloc.h> 77 #include <sys/reboot.h> 78 #include <sys/bio.h> 79 #include <sys/buf.h> 80 #include <sys/bus.h> 81 #include <sys/mbuf.h> 82 #include <sys/vmmeter.h> 83 #include <sys/msgbuf.h> 84 #include <sys/exec.h> 85 #include <sys/sysctl.h> 86 #include <sys/uio.h> 87 #include <sys/linker.h> 88 #include <sys/cons.h> 89 #include <sys/ucontext.h> 90 #include <sys/sysent.h> 91 #include <net/netisr.h> 92 #include <vm/vm.h> 93 #include <vm/vm_kern.h> 94 #include <vm/vm_page.h> 95 #include <vm/vm_map.h> 96 #include <vm/vm_extern.h> 97 #include <vm/vm_object.h> 98 #include <vm/vm_pager.h> 99 #include <sys/user.h> 100 #include <sys/ptrace.h> 101 #include <machine/bat.h> 102 #include <machine/clock.h> 103 #include <machine/cpu.h> 104 #include <machine/md_var.h> 105 #include <machine/metadata.h> 106 #include <machine/reg.h> 107 #include <machine/fpu.h> 108 #include <machine/vmparam.h> 109 #include <machine/elf.h> 110 #include <machine/trap.h> 111 #include <machine/powerpc.h> 112 #include <dev/ofw/openfirm.h> 113 #include <ddb/ddb.h> 114 #include <sys/vnode.h> 115 #include <machine/sigframe.h> 116 117 int cold = 1; 118 119 char pcpu0[PAGE_SIZE]; 120 char uarea0[UAREA_PAGES * PAGE_SIZE]; 121 struct trapframe frame0; 122 123 vm_offset_t kstack0; 124 vm_offset_t kstack0_phys; 125 126 char machine[] = "powerpc"; 127 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, ""); 128 129 static char model[128]; 130 SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, model, 0, ""); 131 132 static int cacheline_size = CACHELINESIZE; 133 SYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size, 134 CTLFLAG_RD, &cacheline_size, 0, ""); 135 136 #ifdef DDB 137 /* start and end of kernel symbol table */ 138 void *ksym_start, *ksym_end; 139 #endif /* DDB */ 140 141 static void cpu_startup(void *); 142 SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) 143 144 void powerpc_init(u_int, u_int, u_int, void *); 145 146 int save_ofw_mapping(void); 147 int restore_ofw_mapping(void); 148 149 void install_extint(void (*)(void)); 150 151 int setfault(faultbuf); /* defined in locore.S */ 152 153 static int grab_mcontext(struct thread *, mcontext_t *, int); 154 155 void asm_panic(char *); 156 157 long Maxmem = 0; 158 159 struct pmap ofw_pmap; 160 extern int ofmsr; 161 162 struct bat battable[16]; 163 164 struct kva_md_info kmi; 165 166 static void 167 powerpc_ofw_shutdown(void *junk, int howto) 168 { 169 if (howto & RB_HALT) { 170 OF_halt(); 171 } 172 OF_reboot(); 173 } 174 175 static void 176 cpu_startup(void *dummy) 177 { 178 179 /* 180 * Initialise the decrementer-based clock. 181 */ 182 decr_init(); 183 184 /* 185 * Good {morning,afternoon,evening,night}. 186 */ 187 cpu_setup(PCPU_GET(cpuid)); 188 189 /* startrtclock(); */ 190 #ifdef PERFMON 191 perfmon_init(); 192 #endif 193 printf("real memory = %ld (%ld MB)\n", ptoa(Maxmem), 194 ptoa(Maxmem) / 1048576); 195 196 /* 197 * Display any holes after the first chunk of extended memory. 198 */ 199 if (bootverbose) { 200 int indx; 201 202 printf("Physical memory chunk(s):\n"); 203 for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { 204 int size1 = phys_avail[indx + 1] - phys_avail[indx]; 205 206 printf("0x%08x - 0x%08x, %d bytes (%d pages)\n", 207 phys_avail[indx], phys_avail[indx + 1] - 1, size1, 208 size1 / PAGE_SIZE); 209 } 210 } 211 212 vm_ksubmap_init(&kmi); 213 214 printf("avail memory = %ld (%ld MB)\n", ptoa(cnt.v_free_count), 215 ptoa(cnt.v_free_count) / 1048576); 216 217 /* 218 * Set up buffers, so they can be used to read disk labels. 219 */ 220 bufinit(); 221 vm_pager_bufferinit(); 222 223 EVENTHANDLER_REGISTER(shutdown_final, powerpc_ofw_shutdown, 0, 224 SHUTDOWN_PRI_LAST); 225 226 #ifdef SMP 227 /* 228 * OK, enough kmem_alloc/malloc state should be up, lets get on with it! 229 */ 230 mp_start(); /* fire up the secondaries */ 231 mp_announce(); 232 #endif /* SMP */ 233 } 234 235 extern char kernel_text[], _end[]; 236 237 extern void *trapcode, *trapsize; 238 extern void *alitrap, *alisize; 239 extern void *dsitrap, *dsisize; 240 extern void *decrint, *decrsize; 241 extern void *extint, *extsize; 242 extern void *ddblow, *ddbsize; 243 244 void 245 powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp) 246 { 247 struct pcpu *pc; 248 vm_offset_t end, off; 249 void *kmdp; 250 251 end = 0; 252 kmdp = NULL; 253 254 /* 255 * Parse metadata if present and fetch parameters. Must be done 256 * before console is inited so cninit gets the right value of 257 * boothowto. 258 */ 259 if (mdp != NULL) { 260 preload_metadata = mdp; 261 kmdp = preload_search_by_type("elf kernel"); 262 if (kmdp != NULL) { 263 boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); 264 kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); 265 end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); 266 } 267 } 268 269 /* 270 * Init params/tunables that can be overridden by the loader 271 */ 272 init_param1(); 273 274 /* 275 * Start initializing proc0 and thread0. 276 */ 277 proc_linkup(&proc0, &ksegrp0, &kse0, &thread0); 278 proc0.p_uarea = (struct user *)uarea0; 279 proc0.p_stats = &proc0.p_uarea->u_stats; 280 thread0.td_frame = &frame0; 281 282 /* 283 * Set up per-cpu data. 284 */ 285 pc = (struct pcpu *)(pcpu0 + PAGE_SIZE) - 1; 286 pcpu_init(pc, 0, sizeof(struct pcpu)); 287 pc->pc_curthread = &thread0; 288 pc->pc_curpcb = thread0.td_pcb; 289 pc->pc_cpuid = 0; 290 /* pc->pc_mid = mid; */ 291 292 __asm __volatile("mtsprg 0, %0" :: "r"(pc)); 293 294 mutex_init(); 295 296 /* 297 * Initialize the console before printing anything. 298 */ 299 cninit(); 300 301 /* 302 * Complain if there is no metadata. 303 */ 304 if (mdp == NULL || kmdp == NULL) { 305 printf("powerpc_init: no loader metadata.\n"); 306 } 307 308 #ifdef DDB 309 kdb_init(); 310 #endif 311 /* 312 * XXX: Initialize the interrupt tables. 313 */ 314 bcopy(&trapcode, (void *)EXC_RST, (size_t)&trapsize); 315 bcopy(&trapcode, (void *)EXC_MCHK, (size_t)&trapsize); 316 bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize); 317 bcopy(&trapcode, (void *)EXC_ISI, (size_t)&trapsize); 318 bcopy(&trapcode, (void *)EXC_EXI, (size_t)&trapsize); 319 bcopy(&trapcode, (void *)EXC_ALI, (size_t)&trapsize); 320 bcopy(&trapcode, (void *)EXC_PGM, (size_t)&trapsize); 321 bcopy(&trapcode, (void *)EXC_FPU, (size_t)&trapsize); 322 bcopy(&trapcode, (void *)EXC_DECR, (size_t)&trapsize); 323 bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize); 324 bcopy(&trapcode, (void *)EXC_TRC, (size_t)&trapsize); 325 bcopy(&trapcode, (void *)EXC_FPA, (size_t)&trapsize); 326 bcopy(&trapcode, (void *)EXC_THRM, (size_t)&trapsize); 327 bcopy(&trapcode, (void *)EXC_BPT, (size_t)&trapsize); 328 #ifdef DDB 329 bcopy(&ddblow, (void *)EXC_PGM, (size_t)&ddbsize); 330 bcopy(&ddblow, (void *)EXC_TRC, (size_t)&ddbsize); 331 bcopy(&ddblow, (void *)EXC_BPT, (size_t)&ddbsize); 332 #endif 333 __syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD); 334 335 /* 336 * Make sure translation has been enabled 337 */ 338 mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI); 339 340 /* 341 * Initialise virtual memory. 342 */ 343 pmap_bootstrap(startkernel, endkernel); 344 345 /* 346 * Initialize params/tunables that are derived from memsize 347 */ 348 init_param2(physmem); 349 350 /* 351 * Finish setting up thread0. 352 */ 353 thread0.td_kstack = kstack0; 354 thread0.td_pcb = (struct pcb *) 355 (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; 356 357 /* 358 * Map and initialise the message buffer. 359 */ 360 for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE) 361 pmap_kenter((vm_offset_t)msgbufp + off, msgbuf_phys + off); 362 msgbufinit(msgbufp, MSGBUF_SIZE); 363 } 364 365 void 366 bzero(void *buf, size_t len) 367 { 368 caddr_t p; 369 370 p = buf; 371 372 while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) { 373 *p++ = 0; 374 len--; 375 } 376 377 while (len >= sizeof(u_long) * 8) { 378 *(u_long*) p = 0; 379 *((u_long*) p + 1) = 0; 380 *((u_long*) p + 2) = 0; 381 *((u_long*) p + 3) = 0; 382 len -= sizeof(u_long) * 8; 383 *((u_long*) p + 4) = 0; 384 *((u_long*) p + 5) = 0; 385 *((u_long*) p + 6) = 0; 386 *((u_long*) p + 7) = 0; 387 p += sizeof(u_long) * 8; 388 } 389 390 while (len >= sizeof(u_long)) { 391 *(u_long*) p = 0; 392 len -= sizeof(u_long); 393 p += sizeof(u_long); 394 } 395 396 while (len) { 397 *p++ = 0; 398 len--; 399 } 400 } 401 402 void 403 sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 404 { 405 struct trapframe *tf; 406 struct sigframe *sfp; 407 struct sigacts *psp; 408 struct sigframe sf; 409 struct thread *td; 410 struct proc *p; 411 int oonstack, rndfsize; 412 413 td = curthread; 414 p = td->td_proc; 415 PROC_LOCK_ASSERT(p, MA_OWNED); 416 psp = p->p_sigacts; 417 mtx_assert(&psp->ps_mtx, MA_OWNED); 418 tf = td->td_frame; 419 oonstack = sigonstack(tf->fixreg[1]); 420 421 rndfsize = ((sizeof(sf) + 15) / 16) * 16; 422 423 CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, 424 catcher, sig); 425 426 /* 427 * Save user context 428 */ 429 memset(&sf, 0, sizeof(sf)); 430 grab_mcontext(td, &sf.sf_uc.uc_mcontext, 0); 431 sf.sf_uc.uc_sigmask = *mask; 432 sf.sf_uc.uc_stack = td->td_sigstk; 433 sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 434 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 435 436 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 437 438 /* 439 * Allocate and validate space for the signal handler context. 440 */ 441 if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 442 SIGISMEMBER(psp->ps_sigonstack, sig)) { 443 sfp = (struct sigframe *)((caddr_t)td->td_sigstk.ss_sp + 444 td->td_sigstk.ss_size - rndfsize); 445 } else { 446 sfp = (struct sigframe *)(tf->fixreg[1] - rndfsize); 447 } 448 449 /* 450 * Translate the signal if appropriate (Linux emu ?) 451 */ 452 if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 453 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 454 455 /* 456 * Save the floating-point state, if necessary, then copy it. 457 */ 458 /* XXX */ 459 460 /* 461 * Set up the registers to return to sigcode. 462 * 463 * r1/sp - sigframe ptr 464 * lr - sig function, dispatched to by blrl in trampoline 465 * r3 - sig number 466 * r4 - SIGINFO ? &siginfo : exception code 467 * r5 - user context 468 * srr0 - trampoline function addr 469 */ 470 tf->lr = (register_t)catcher; 471 tf->fixreg[1] = (register_t)sfp; 472 tf->fixreg[FIRSTARG] = sig; 473 tf->fixreg[FIRSTARG+2] = (register_t)&sfp->sf_uc; 474 if (SIGISMEMBER(psp->ps_siginfo, sig)) { 475 /* 476 * Signal handler installed with SA_SIGINFO. 477 */ 478 tf->fixreg[FIRSTARG+1] = (register_t)&sfp->sf_si; 479 480 /* 481 * Fill siginfo structure. 482 */ 483 sf.sf_si.si_signo = sig; 484 sf.sf_si.si_code = code; 485 sf.sf_si.si_addr = (void *)tf->srr0; 486 } else { 487 /* Old FreeBSD-style arguments. */ 488 tf->fixreg[FIRSTARG+1] = code; 489 } 490 mtx_unlock(&psp->ps_mtx); 491 PROC_UNLOCK(p); 492 493 tf->srr0 = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode)); 494 495 /* 496 * copy the frame out to userland. 497 */ 498 if (copyout((caddr_t)&sf, (caddr_t)sfp, sizeof(sf)) != 0) { 499 /* 500 * Process has trashed its stack. Kill it. 501 */ 502 CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 503 PROC_LOCK(p); 504 sigexit(td, SIGILL); 505 } 506 507 CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, 508 tf->srr0, tf->fixreg[1]); 509 510 PROC_LOCK(p); 511 mtx_lock(&psp->ps_mtx); 512 } 513 514 /* 515 * Build siginfo_t for SA thread 516 */ 517 void 518 cpu_thread_siginfo(int sig, u_long code, siginfo_t *si) 519 { 520 struct proc *p; 521 struct thread *td; 522 523 td = curthread; 524 p = td->td_proc; 525 PROC_LOCK_ASSERT(p, MA_OWNED); 526 527 bzero(si, sizeof(*si)); 528 si->si_signo = sig; 529 si->si_code = code; 530 /* XXXKSE fill other fields */ 531 } 532 533 int 534 sigreturn(struct thread *td, struct sigreturn_args *uap) 535 { 536 struct proc *p; 537 ucontext_t uc; 538 int error; 539 540 CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 541 542 if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 543 CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 544 return (EFAULT); 545 } 546 547 error = set_mcontext(td, &uc.uc_mcontext); 548 if (error != 0) 549 return (error); 550 551 p = td->td_proc; 552 PROC_LOCK(p); 553 td->td_sigmask = uc.uc_sigmask; 554 SIG_CANTMASK(td->td_sigmask); 555 signotify(td); 556 PROC_UNLOCK(p); 557 558 CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x", 559 td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]); 560 561 return (EJUSTRETURN); 562 } 563 564 #ifdef COMPAT_FREEBSD4 565 int 566 freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) 567 { 568 569 return sigreturn(td, (struct sigreturn_args *)uap); 570 } 571 #endif 572 573 /* 574 * get_mcontext/sendsig helper routine that doesn't touch the 575 * proc lock 576 */ 577 static int 578 grab_mcontext(struct thread *td, mcontext_t *mcp, int flags) 579 { 580 struct pcb *pcb; 581 582 pcb = td->td_pcb; 583 584 memset(mcp, 0, sizeof(mcontext_t)); 585 586 mcp->mc_vers = _MC_VERSION; 587 mcp->mc_flags = 0; 588 memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe)); 589 if (flags & GET_MC_CLEAR_RET) { 590 mcp->mc_gpr[3] = 0; 591 mcp->mc_gpr[4] = 0; 592 } 593 594 /* 595 * This assumes that floating-point context is *not* lazy, 596 * so if the thread has used FP there would have been a 597 * FP-unavailable exception that would have set things up 598 * correctly. 599 */ 600 if (pcb->pcb_flags & PCB_FPU) { 601 KASSERT(td == curthread, 602 ("get_mcontext: fp save not curthread")); 603 critical_enter(); 604 save_fpu(td); 605 critical_exit(); 606 mcp->mc_flags |= _MC_FP_VALID; 607 memcpy(&mcp->mc_fpscr, &pcb->pcb_fpu.fpscr, sizeof(double)); 608 memcpy(mcp->mc_fpreg, pcb->pcb_fpu.fpr, 32*sizeof(double)); 609 } 610 611 /* XXX Altivec context ? */ 612 613 mcp->mc_len = sizeof(*mcp); 614 615 return (0); 616 } 617 618 int 619 get_mcontext(struct thread *td, mcontext_t *mcp, int flags) 620 { 621 int error; 622 623 error = grab_mcontext(td, mcp, flags); 624 if (error == 0) { 625 PROC_LOCK(curthread->td_proc); 626 mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]); 627 PROC_UNLOCK(curthread->td_proc); 628 } 629 630 return (error); 631 } 632 633 int 634 set_mcontext(struct thread *td, const mcontext_t *mcp) 635 { 636 struct pcb *pcb; 637 struct trapframe *tf; 638 639 pcb = td->td_pcb; 640 tf = td->td_frame; 641 642 if (mcp->mc_vers != _MC_VERSION || 643 mcp->mc_len != sizeof(*mcp)) 644 return (EINVAL); 645 646 /* 647 * Don't let the user set privileged MSR bits 648 */ 649 if ((mcp->mc_srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) { 650 return (EINVAL); 651 } 652 653 memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame)); 654 655 if (mcp->mc_flags & _MC_FP_VALID) { 656 if ((pcb->pcb_flags & PCB_FPU) != PCB_FPU) { 657 critical_enter(); 658 enable_fpu(td); 659 critical_exit(); 660 } 661 memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double)); 662 memcpy(pcb->pcb_fpu.fpr, mcp->mc_fpreg, 32*sizeof(double)); 663 } 664 665 /* XXX Altivec context? */ 666 667 return (0); 668 } 669 670 void 671 cpu_boot(int howto) 672 { 673 } 674 675 /* 676 * Shutdown the CPU as much as possible. 677 */ 678 void 679 cpu_halt(void) 680 { 681 682 OF_exit(); 683 } 684 685 void 686 cpu_idle(void) 687 { 688 /* Insert code to halt (until next interrupt) for the idle loop */ 689 } 690 691 /* 692 * Set set up registers on exec. 693 */ 694 void 695 exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) 696 { 697 struct trapframe *tf; 698 struct ps_strings arginfo; 699 700 tf = trapframe(td); 701 bzero(tf, sizeof *tf); 702 tf->fixreg[1] = -roundup(-stack + 8, 16); 703 704 /* 705 * XXX Machine-independent code has already copied arguments and 706 * XXX environment to userland. Get them back here. 707 */ 708 (void)copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo)); 709 710 /* 711 * Set up arguments for _start(): 712 * _start(argc, argv, envp, obj, cleanup, ps_strings); 713 * 714 * Notes: 715 * - obj and cleanup are the auxilliary and termination 716 * vectors. They are fixed up by ld.elf_so. 717 * - ps_strings is a NetBSD extention, and will be 718 * ignored by executables which are strictly 719 * compliant with the SVR4 ABI. 720 * 721 * XXX We have to set both regs and retval here due to different 722 * XXX calling convention in trap.c and init_main.c. 723 */ 724 /* 725 * XXX PG: these get overwritten in the syscall return code. 726 * execve() should return EJUSTRETURN, like it does on NetBSD. 727 * Emulate by setting the syscall return value cells. The 728 * registers still have to be set for init's fork trampoline. 729 */ 730 td->td_retval[0] = arginfo.ps_nargvstr; 731 td->td_retval[1] = (register_t)arginfo.ps_argvstr; 732 tf->fixreg[3] = arginfo.ps_nargvstr; 733 tf->fixreg[4] = (register_t)arginfo.ps_argvstr; 734 tf->fixreg[5] = (register_t)arginfo.ps_envstr; 735 tf->fixreg[6] = 0; /* auxillary vector */ 736 tf->fixreg[7] = 0; /* termination vector */ 737 tf->fixreg[8] = (register_t)PS_STRINGS; /* NetBSD extension */ 738 739 tf->srr0 = entry; 740 tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT; 741 td->td_pcb->pcb_flags = 0; 742 } 743 744 #if !defined(DDB) 745 void 746 Debugger(const char *msg) 747 { 748 749 printf("Debugger(\"%s\") called.\n", msg); 750 } 751 #endif /* !defined(DDB) */ 752 753 /* XXX: dummy {fill,set}_[fp]regs */ 754 int 755 fill_regs(struct thread *td, struct reg *regs) 756 { 757 758 return (ENOSYS); 759 } 760 761 int 762 fill_dbregs(struct thread *td, struct dbreg *dbregs) 763 { 764 765 return (ENOSYS); 766 } 767 768 int 769 fill_fpregs(struct thread *td, struct fpreg *fpregs) 770 { 771 772 return (ENOSYS); 773 } 774 775 int 776 set_regs(struct thread *td, struct reg *regs) 777 { 778 779 return (ENOSYS); 780 } 781 782 int 783 set_dbregs(struct thread *td, struct dbreg *dbregs) 784 { 785 786 return (ENOSYS); 787 } 788 789 int 790 set_fpregs(struct thread *td, struct fpreg *fpregs) 791 { 792 793 return (ENOSYS); 794 } 795 796 int 797 ptrace_set_pc(struct thread *td, unsigned long addr) 798 { 799 800 /* XXX: coming soon... */ 801 return (ENOSYS); 802 } 803 804 int 805 ptrace_single_step(struct thread *td) 806 { 807 808 /* XXX: coming soon... */ 809 return (ENOSYS); 810 } 811 812 /* 813 * Initialise a struct pcpu. 814 */ 815 void 816 cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz) 817 { 818 819 } 820 821 /* 822 * kcopy(const void *src, void *dst, size_t len); 823 * 824 * Copy len bytes from src to dst, aborting if we encounter a fatal 825 * page fault. 826 * 827 * kcopy() _must_ save and restore the old fault handler since it is 828 * called by uiomove(), which may be in the path of servicing a non-fatal 829 * page fault. 830 */ 831 int 832 kcopy(const void *src, void *dst, size_t len) 833 { 834 struct thread *td; 835 faultbuf env, *oldfault; 836 int rv; 837 838 td = PCPU_GET(curthread); 839 oldfault = td->td_pcb->pcb_onfault; 840 if ((rv = setfault(env)) != 0) { 841 td->td_pcb->pcb_onfault = oldfault; 842 return rv; 843 } 844 845 memcpy(dst, src, len); 846 847 td->td_pcb->pcb_onfault = oldfault; 848 return (0); 849 } 850 851 void 852 asm_panic(char *pstr) 853 { 854 panic(pstr); 855 } 856