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#ifndef lint 58static const char rcsid[] =
| 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#ifndef lint 58static const char rcsid[] =
|
168long Maxmem = 0; 169 170static int chosen; 171 172struct pmap ofw_pmap; 173extern int ofmsr; 174 175struct bat battable[16]; 176 177static void identifycpu(void); 178 179struct kva_md_info kmi; 180 181static void 182powerpc_ofw_shutdown(void *junk, int howto) 183{ 184 if (howto & RB_HALT) { 185 OF_exit(); 186 } 187} 188 189static void 190cpu_startup(void *dummy) 191{ 192 193 /* 194 * Good {morning,afternoon,evening,night}. 195 */ 196 identifycpu(); 197 198 /* startrtclock(); */ 199#ifdef PERFMON 200 perfmon_init(); 201#endif 202 printf("real memory = %ld (%ldK bytes)\n", ptoa(Maxmem), 203 ptoa(Maxmem) / 1024); 204 205 /* 206 * Display any holes after the first chunk of extended memory. 207 */ 208 if (bootverbose) { 209 int indx; 210 211 printf("Physical memory chunk(s):\n"); 212 for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { 213 int size1 = phys_avail[indx + 1] - phys_avail[indx]; 214 215 printf("0x%08x - 0x%08x, %d bytes (%d pages)\n", 216 phys_avail[indx], phys_avail[indx + 1] - 1, size1, 217 size1 / PAGE_SIZE); 218 } 219 } 220 221 vm_ksubmap_init(&kmi); 222 223 printf("avail memory = %ld (%ldK bytes)\n", ptoa(cnt.v_free_count), 224 ptoa(cnt.v_free_count) / 1024); 225 226 /* 227 * Set up buffers, so they can be used to read disk labels. 228 */ 229 bufinit(); 230 vm_pager_bufferinit(); 231 232 EVENTHANDLER_REGISTER(shutdown_final, powerpc_ofw_shutdown, 0, 233 SHUTDOWN_PRI_LAST); 234 235#ifdef SMP 236 /* 237 * OK, enough kmem_alloc/malloc state should be up, lets get on with it! 238 */ 239 mp_start(); /* fire up the secondaries */ 240 mp_announce(); 241#endif /* SMP */ 242} 243 244void 245identifycpu() 246{ 247 unsigned int pvr, version, revision; 248 249 /* 250 * Find cpu type (Do it by OpenFirmware?) 251 */ 252 __asm ("mfpvr %0" : "=r"(pvr)); 253 version = pvr >> 16; 254 revision = pvr & 0xffff; 255 switch (version) { 256 case 0x0000: 257 sprintf(model, "Simulator (psim)"); 258 break; 259 case 0x0001: 260 sprintf(model, "601"); 261 break; 262 case 0x0003: 263 sprintf(model, "603 (Wart)"); 264 break; 265 case 0x0004: 266 sprintf(model, "604 (Zephyr)"); 267 break; 268 case 0x0005: 269 sprintf(model, "602 (Galahad)"); 270 break; 271 case 0x0006: 272 sprintf(model, "603e (Stretch)"); 273 break; 274 case 0x0007: 275 if ((revision && 0xf000) == 0x0000) 276 sprintf(model, "603ev (Valiant)"); 277 else 278 sprintf(model, "603r (Goldeneye)"); 279 break; 280 case 0x0008: 281 if ((revision && 0xf000) == 0x0000) 282 sprintf(model, "G3 / 750 (Arthur)"); 283 else 284 sprintf(model, "G3 / 755 (Goldfinger)"); 285 break; 286 case 0x0009: 287 if ((revision && 0xf000) == 0x0000) 288 sprintf(model, "604e (Sirocco)"); 289 else 290 sprintf(model, "604r (Mach V)"); 291 break; 292 case 0x000a: 293 sprintf(model, "604r (Mach V)"); 294 break; 295 case 0x000c: 296 sprintf(model, "G4 / 7400 (Max)"); 297 break; 298 case 0x0014: 299 sprintf(model, "620 (Red October)"); 300 break; 301 case 0x0081: 302 sprintf(model, "8240 (Kahlua)"); 303 break; 304 case 0x8000: 305 sprintf(model, "G4 / 7450 (V'ger)"); 306 break; 307 case 0x800c: 308 sprintf(model, "G4 / 7410 (Nitro)"); 309 break; 310 case 0x8081: 311 sprintf(model, "8245 (Kahlua II)"); 312 break; 313 default: 314 sprintf(model, "Version %x", version); 315 break; 316 } 317 sprintf(model + strlen(model), " (Revision %x)", revision); 318 printf("CPU: PowerPC %s\n", model); 319} 320 321extern char kernel_text[], _end[]; 322 323extern void *trapcode, *trapsize; 324extern void *alitrap, *alisize; 325extern void *dsitrap, *dsisize; 326extern void *isitrap, *isisize; 327extern void *decrint, *decrsize; 328extern void *tlbimiss, *tlbimsize; 329extern void *tlbdlmiss, *tlbdlmsize; 330extern void *tlbdsmiss, *tlbdsmsize; 331extern void *extint, *extsize; 332 333#if 0 /* XXX: interrupt handler. We'll get to this later */ 334extern void ext_intr(void); 335#endif 336 337#ifdef DDB 338extern ddblow, ddbsize; 339#endif 340#ifdef IPKDB 341extern ipkdblow, ipkdbsize; 342#endif 343 344void 345powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp) 346{ 347 struct pcpu *pc; 348 vm_offset_t end, off; 349 void *kmdp; 350 351 end = 0; 352 kmdp = NULL; 353 354 /* 355 * Parse metadata if present and fetch parameters. Must be done 356 * before console is inited so cninit gets the right value of 357 * boothowto. 358 */ 359 if (mdp != NULL) { 360 preload_metadata = mdp; 361 kmdp = preload_search_by_type("elf kernel"); 362 if (kmdp != NULL) { 363 boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); 364 kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); 365 end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); 366 } 367 } 368 369 /* 370 * Initialize the console before printing anything. 371 */ 372 cninit(); 373 374 /* 375 * Complain if there is no metadata. 376 */ 377 if (mdp == NULL || kmdp == NULL) { 378 printf("powerpc_init: no loader metadata.\n"); 379 } 380 381#ifdef DDB 382 kdb_init(); 383#endif 384 385 /* 386 * XXX: Initialize the interrupt tables. 387 */ 388 bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize); 389 bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize); 390 bcopy(&trapcode, (void *)EXC_EXI, (size_t)&trapsize); 391 bcopy(&trapcode, (void *)EXC_ALI, (size_t)&trapsize); 392 bcopy(&trapcode, (void *)EXC_PGM, (size_t)&trapsize); 393 bcopy(&trapcode, (void *)EXC_FPU, (size_t)&trapsize); 394 bcopy(&trapcode, (void *)EXC_DECR, (size_t)&trapsize); 395 bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize); 396 bcopy(&trapcode, (void *)EXC_TRC, (size_t)&trapsize); 397 398 /* 399 * Start initializing proc0 and thread0. 400 */ 401 proc_linkup(&proc0, &ksegrp0, &kse0, &thread0); 402 proc0.p_uarea = (struct user *)uarea0; 403 proc0.p_stats = &proc0.p_uarea->u_stats; 404 thread0.td_frame = &frame0; 405 406 /* 407 * Set up per-cpu data. 408 */ 409 pc = (struct pcpu *)(pcpu0 + PAGE_SIZE) - 1; 410 pcpu_init(pc, 0, sizeof(struct pcpu)); 411 pc->pc_curthread = &thread0; 412 pc->pc_curpcb = thread0.td_pcb; 413 pc->pc_cpuid = 0; 414 /* pc->pc_mid = mid; */ 415 416 __asm __volatile("mtsprg 0, %0" :: "r"(pc)); 417 418 mutex_init(); 419 420 /* 421 * Make sure translation has been enabled 422 */ 423 mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI); 424 425 /* 426 * Initialise virtual memory. 427 */ 428 pmap_bootstrap(startkernel, endkernel); 429 430 /* 431 * Initialize tunables. 432 */ 433 init_param1(); 434 init_param2(physmem); 435 436 /* 437 * Finish setting up thread0. 438 */ 439 thread0.td_kstack = kstack0; 440 thread0.td_pcb = (struct pcb *) 441 (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; 442 443 /* 444 * Map and initialise the message buffer. 445 */ 446 for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE) 447 pmap_kenter((vm_offset_t)msgbufp + off, msgbuf_phys + off); 448 msgbufinit(msgbufp, MSGBUF_SIZE); 449} 450 451void 452bzero(void *buf, size_t len) 453{ 454 caddr_t p; 455 456 p = buf; 457 458 while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) { 459 *p++ = 0; 460 len--; 461 } 462 463 while (len >= sizeof(u_long) * 8) { 464 *(u_long*) p = 0; 465 *((u_long*) p + 1) = 0; 466 *((u_long*) p + 2) = 0; 467 *((u_long*) p + 3) = 0; 468 len -= sizeof(u_long) * 8; 469 *((u_long*) p + 4) = 0; 470 *((u_long*) p + 5) = 0; 471 *((u_long*) p + 6) = 0; 472 *((u_long*) p + 7) = 0; 473 p += sizeof(u_long) * 8; 474 } 475 476 while (len >= sizeof(u_long)) { 477 *(u_long*) p = 0; 478 len -= sizeof(u_long); 479 p += sizeof(u_long); 480 } 481 482 while (len) { 483 *p++ = 0; 484 len--; 485 } 486} 487 488void 489sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 490{ 491 struct trapframe *tf; 492 struct sigframe *sfp; 493 struct sigacts *psp; 494 struct sigframe sf; 495 struct thread *td; 496 struct proc *p; 497 int oonstack, rndfsize; 498 499 td = curthread; 500 p = td->td_proc; 501 psp = p->p_sigacts; 502 tf = td->td_frame; 503 oonstack = sigonstack(tf->fixreg[1]); 504 505 rndfsize = ((sizeof(sf) + 15) / 16) * 16; 506 507 CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, 508 catcher, sig); 509 510 /* 511 * Save user context 512 */ 513 memset(&sf, 0, sizeof(sf)); 514 sf.sf_uc.uc_sigmask = *mask; 515 sf.sf_uc.uc_stack = p->p_sigstk; 516 sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK) 517 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 518 519 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 520 memcpy(&sf.sf_uc.uc_mcontext.mc_frame, tf, sizeof(struct trapframe)); 521 522 /* 523 * Allocate and validate space for the signal handler context. 524 */ 525 if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack && 526 SIGISMEMBER(psp->ps_sigonstack, sig)) { 527 sfp = (struct sigframe *)((caddr_t)p->p_sigstk.ss_sp + 528 p->p_sigstk.ss_size - rndfsize); 529 } else { 530 sfp = (struct sigframe *)(tf->fixreg[1] - rndfsize); 531 } 532 PROC_UNLOCK(p); 533 534 /* 535 * Translate the signal if appropriate (Linux emu ?) 536 */ 537 if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 538 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 539 540 /* 541 * Save the floating-point state, if necessary, then copy it. 542 */ 543 /* XXX */ 544 545 /* 546 * Set up the registers to return to sigcode. 547 * 548 * r1/sp - sigframe ptr 549 * lr - sig function, dispatched to by blrl in trampoline 550 * r3 - sig number 551 * r4 - SIGINFO ? &siginfo : exception code 552 * r5 - user context 553 * srr0 - trampoline function addr 554 */ 555 tf->lr = (register_t)catcher; 556 tf->fixreg[1] = (register_t)sfp; 557 tf->fixreg[FIRSTARG] = sig; 558 tf->fixreg[FIRSTARG+2] = (register_t)&sfp->sf_uc; 559 560 PROC_LOCK(p); 561 if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { 562 /* 563 * Signal handler installed with SA_SIGINFO. 564 */ 565 tf->fixreg[FIRSTARG+1] = (register_t)&sfp->sf_si; 566 567 /* 568 * Fill siginfo structure. 569 */ 570 sf.sf_si.si_signo = sig; 571 sf.sf_si.si_code = code; 572 sf.sf_si.si_addr = (void *)tf->srr0; 573 } else { 574 /* Old FreeBSD-style arguments. */ 575 tf->fixreg[FIRSTARG+1] = code; 576 } 577 PROC_UNLOCK(p); 578 579 tf->srr0 = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode)); 580 581 /* 582 * copy the frame out to userland. 583 */ 584 if (copyout((caddr_t)&sf, (caddr_t)sfp, sizeof(sf)) != 0) { 585 /* 586 * Process has trashed its stack. Kill it. 587 */ 588 CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 589 PROC_LOCK(p); 590 sigexit(td, SIGILL); 591 } 592 593 CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, 594 tf->srr0, tf->fixreg[1]); 595 596 PROC_LOCK(p); 597} 598 599int 600sigreturn(struct thread *td, struct sigreturn_args *uap) 601{ 602 struct trapframe *tf; 603 struct proc *p; 604 ucontext_t uc; 605 606 CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 607 608 if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 609 CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 610 return (EFAULT); 611 } 612 613 /* 614 * Don't let the user set privileged MSR bits 615 */ 616 tf = td->td_frame; 617 if ((uc.uc_mcontext.mc_frame.srr1 & PSL_USERSTATIC) != 618 (tf->srr1 & PSL_USERSTATIC)) { 619 return (EINVAL); 620 } 621 622 /* 623 * Restore the user-supplied context 624 */ 625 memcpy(tf, &uc.uc_mcontext.mc_frame, sizeof(struct trapframe)); 626 627 p = td->td_proc; 628 PROC_LOCK(p); 629 p->p_sigmask = uc.uc_sigmask; 630 SIG_CANTMASK(p->p_sigmask); 631 signotify(p); 632 PROC_UNLOCK(p); 633 634 /* 635 * Restore FP state 636 */ 637 /* XXX */ 638 639 CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x", 640 td, tf->srr0, tf->fixreg[1]); 641 642 return (EJUSTRETURN); 643} 644 645#ifdef COMPAT_FREEBSD4 646int 647freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) 648{ 649 650 return sigreturn(td, (struct sigreturn_args *)uap); 651} 652#endif 653 654void 655cpu_boot(int howto) 656{ 657} 658 659/* 660 * Shutdown the CPU as much as possible. 661 */ 662void 663cpu_halt(void) 664{ 665 666 OF_exit(); 667} 668 669/* 670 * Set set up registers on exec. 671 */ 672void 673exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) 674{ 675 struct trapframe *tf; 676 struct ps_strings arginfo; 677 678 tf = trapframe(td); 679 bzero(tf, sizeof *tf); 680 tf->fixreg[1] = -roundup(-stack + 8, 16); 681 682 /* 683 * XXX Machine-independent code has already copied arguments and 684 * XXX environment to userland. Get them back here. 685 */ 686 (void)copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo)); 687 688 /* 689 * Set up arguments for _start(): 690 * _start(argc, argv, envp, obj, cleanup, ps_strings); 691 * 692 * Notes: 693 * - obj and cleanup are the auxilliary and termination 694 * vectors. They are fixed up by ld.elf_so. 695 * - ps_strings is a NetBSD extention, and will be 696 * ignored by executables which are strictly 697 * compliant with the SVR4 ABI. 698 * 699 * XXX We have to set both regs and retval here due to different 700 * XXX calling convention in trap.c and init_main.c. 701 */ 702 /* 703 * XXX PG: these get overwritten in the syscall return code. 704 * execve() should return EJUSTRETURN, like it does on NetBSD. 705 * Emulate by setting the syscall return value cells. The 706 * registers still have to be set for init's fork trampoline. 707 */ 708 td->td_retval[0] = arginfo.ps_nargvstr; 709 td->td_retval[1] = (register_t)arginfo.ps_argvstr; 710 tf->fixreg[3] = arginfo.ps_nargvstr; 711 tf->fixreg[4] = (register_t)arginfo.ps_argvstr; 712 tf->fixreg[5] = (register_t)arginfo.ps_envstr; 713 tf->fixreg[6] = 0; /* auxillary vector */ 714 tf->fixreg[7] = 0; /* termination vector */ 715 tf->fixreg[8] = (register_t)PS_STRINGS; /* NetBSD extension */ 716 717 tf->srr0 = entry; 718 tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT; 719 td->td_pcb->pcb_flags = 0; 720} 721 722#if !defined(DDB) 723void 724Debugger(const char *msg) 725{ 726 727 printf("Debugger(\"%s\") called.\n", msg); 728} 729#endif /* !defined(DDB) */ 730 731/* XXX: dummy {fill,set}_[fp]regs */ 732int 733fill_regs(struct thread *td, struct reg *regs) 734{ 735 736 return (ENOSYS); 737} 738 739int 740fill_dbregs(struct thread *td, struct dbreg *dbregs) 741{ 742 743 return (ENOSYS); 744} 745 746int 747fill_fpregs(struct thread *td, struct fpreg *fpregs) 748{ 749 750 return (ENOSYS); 751} 752 753int 754set_regs(struct thread *td, struct reg *regs) 755{ 756 757 return (ENOSYS); 758} 759 760int 761set_dbregs(struct thread *td, struct dbreg *dbregs) 762{ 763 764 return (ENOSYS); 765} 766 767int 768set_fpregs(struct thread *td, struct fpreg *fpregs) 769{ 770 771 return (ENOSYS); 772} 773 774int 775ptrace_set_pc(struct thread *td, unsigned long addr) 776{ 777 778 /* XXX: coming soon... */ 779 return (ENOSYS); 780} 781 782int 783ptrace_single_step(struct thread *td) 784{ 785 786 /* XXX: coming soon... */ 787 return (ENOSYS); 788} 789 790/* 791 * Initialise a struct pcpu. 792 */ 793void 794cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz) 795{ 796 797 pcpu->pc_current_asngen = 1; 798} 799 800/* 801 * kcopy(const void *src, void *dst, size_t len); 802 * 803 * Copy len bytes from src to dst, aborting if we encounter a fatal 804 * page fault. 805 * 806 * kcopy() _must_ save and restore the old fault handler since it is 807 * called by uiomove(), which may be in the path of servicing a non-fatal 808 * page fault. 809 */ 810int 811kcopy(const void *src, void *dst, size_t len) 812{ 813 struct thread *td; 814 faultbuf env, *oldfault; 815 int rv; 816 817 td = PCPU_GET(curthread); 818 oldfault = td->td_pcb->pcb_onfault; 819 if ((rv = setfault(env)) != 0) { 820 td->td_pcb->pcb_onfault = oldfault; 821 return rv; 822 } 823 824 memcpy(dst, src, len); 825 826 td->td_pcb->pcb_onfault = oldfault; 827 return (0); 828}
| 155long Maxmem = 0; 156 157static int chosen; 158 159struct pmap ofw_pmap; 160extern int ofmsr; 161 162struct bat battable[16]; 163 164static void identifycpu(void); 165 166struct kva_md_info kmi; 167 168static void 169powerpc_ofw_shutdown(void *junk, int howto) 170{ 171 if (howto & RB_HALT) { 172 OF_exit(); 173 } 174} 175 176static void 177cpu_startup(void *dummy) 178{ 179 180 /* 181 * Good {morning,afternoon,evening,night}. 182 */ 183 identifycpu(); 184 185 /* startrtclock(); */ 186#ifdef PERFMON 187 perfmon_init(); 188#endif 189 printf("real memory = %ld (%ldK bytes)\n", ptoa(Maxmem), 190 ptoa(Maxmem) / 1024); 191 192 /* 193 * Display any holes after the first chunk of extended memory. 194 */ 195 if (bootverbose) { 196 int indx; 197 198 printf("Physical memory chunk(s):\n"); 199 for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { 200 int size1 = phys_avail[indx + 1] - phys_avail[indx]; 201 202 printf("0x%08x - 0x%08x, %d bytes (%d pages)\n", 203 phys_avail[indx], phys_avail[indx + 1] - 1, size1, 204 size1 / PAGE_SIZE); 205 } 206 } 207 208 vm_ksubmap_init(&kmi); 209 210 printf("avail memory = %ld (%ldK bytes)\n", ptoa(cnt.v_free_count), 211 ptoa(cnt.v_free_count) / 1024); 212 213 /* 214 * Set up buffers, so they can be used to read disk labels. 215 */ 216 bufinit(); 217 vm_pager_bufferinit(); 218 219 EVENTHANDLER_REGISTER(shutdown_final, powerpc_ofw_shutdown, 0, 220 SHUTDOWN_PRI_LAST); 221 222#ifdef SMP 223 /* 224 * OK, enough kmem_alloc/malloc state should be up, lets get on with it! 225 */ 226 mp_start(); /* fire up the secondaries */ 227 mp_announce(); 228#endif /* SMP */ 229} 230 231void 232identifycpu() 233{ 234 unsigned int pvr, version, revision; 235 236 /* 237 * Find cpu type (Do it by OpenFirmware?) 238 */ 239 __asm ("mfpvr %0" : "=r"(pvr)); 240 version = pvr >> 16; 241 revision = pvr & 0xffff; 242 switch (version) { 243 case 0x0000: 244 sprintf(model, "Simulator (psim)"); 245 break; 246 case 0x0001: 247 sprintf(model, "601"); 248 break; 249 case 0x0003: 250 sprintf(model, "603 (Wart)"); 251 break; 252 case 0x0004: 253 sprintf(model, "604 (Zephyr)"); 254 break; 255 case 0x0005: 256 sprintf(model, "602 (Galahad)"); 257 break; 258 case 0x0006: 259 sprintf(model, "603e (Stretch)"); 260 break; 261 case 0x0007: 262 if ((revision && 0xf000) == 0x0000) 263 sprintf(model, "603ev (Valiant)"); 264 else 265 sprintf(model, "603r (Goldeneye)"); 266 break; 267 case 0x0008: 268 if ((revision && 0xf000) == 0x0000) 269 sprintf(model, "G3 / 750 (Arthur)"); 270 else 271 sprintf(model, "G3 / 755 (Goldfinger)"); 272 break; 273 case 0x0009: 274 if ((revision && 0xf000) == 0x0000) 275 sprintf(model, "604e (Sirocco)"); 276 else 277 sprintf(model, "604r (Mach V)"); 278 break; 279 case 0x000a: 280 sprintf(model, "604r (Mach V)"); 281 break; 282 case 0x000c: 283 sprintf(model, "G4 / 7400 (Max)"); 284 break; 285 case 0x0014: 286 sprintf(model, "620 (Red October)"); 287 break; 288 case 0x0081: 289 sprintf(model, "8240 (Kahlua)"); 290 break; 291 case 0x8000: 292 sprintf(model, "G4 / 7450 (V'ger)"); 293 break; 294 case 0x800c: 295 sprintf(model, "G4 / 7410 (Nitro)"); 296 break; 297 case 0x8081: 298 sprintf(model, "8245 (Kahlua II)"); 299 break; 300 default: 301 sprintf(model, "Version %x", version); 302 break; 303 } 304 sprintf(model + strlen(model), " (Revision %x)", revision); 305 printf("CPU: PowerPC %s\n", model); 306} 307 308extern char kernel_text[], _end[]; 309 310extern void *trapcode, *trapsize; 311extern void *alitrap, *alisize; 312extern void *dsitrap, *dsisize; 313extern void *isitrap, *isisize; 314extern void *decrint, *decrsize; 315extern void *tlbimiss, *tlbimsize; 316extern void *tlbdlmiss, *tlbdlmsize; 317extern void *tlbdsmiss, *tlbdsmsize; 318extern void *extint, *extsize; 319 320#if 0 /* XXX: interrupt handler. We'll get to this later */ 321extern void ext_intr(void); 322#endif 323 324#ifdef DDB 325extern ddblow, ddbsize; 326#endif 327#ifdef IPKDB 328extern ipkdblow, ipkdbsize; 329#endif 330 331void 332powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp) 333{ 334 struct pcpu *pc; 335 vm_offset_t end, off; 336 void *kmdp; 337 338 end = 0; 339 kmdp = NULL; 340 341 /* 342 * Parse metadata if present and fetch parameters. Must be done 343 * before console is inited so cninit gets the right value of 344 * boothowto. 345 */ 346 if (mdp != NULL) { 347 preload_metadata = mdp; 348 kmdp = preload_search_by_type("elf kernel"); 349 if (kmdp != NULL) { 350 boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); 351 kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); 352 end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t); 353 } 354 } 355 356 /* 357 * Initialize the console before printing anything. 358 */ 359 cninit(); 360 361 /* 362 * Complain if there is no metadata. 363 */ 364 if (mdp == NULL || kmdp == NULL) { 365 printf("powerpc_init: no loader metadata.\n"); 366 } 367 368#ifdef DDB 369 kdb_init(); 370#endif 371 372 /* 373 * XXX: Initialize the interrupt tables. 374 */ 375 bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize); 376 bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize); 377 bcopy(&trapcode, (void *)EXC_EXI, (size_t)&trapsize); 378 bcopy(&trapcode, (void *)EXC_ALI, (size_t)&trapsize); 379 bcopy(&trapcode, (void *)EXC_PGM, (size_t)&trapsize); 380 bcopy(&trapcode, (void *)EXC_FPU, (size_t)&trapsize); 381 bcopy(&trapcode, (void *)EXC_DECR, (size_t)&trapsize); 382 bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize); 383 bcopy(&trapcode, (void *)EXC_TRC, (size_t)&trapsize); 384 385 /* 386 * Start initializing proc0 and thread0. 387 */ 388 proc_linkup(&proc0, &ksegrp0, &kse0, &thread0); 389 proc0.p_uarea = (struct user *)uarea0; 390 proc0.p_stats = &proc0.p_uarea->u_stats; 391 thread0.td_frame = &frame0; 392 393 /* 394 * Set up per-cpu data. 395 */ 396 pc = (struct pcpu *)(pcpu0 + PAGE_SIZE) - 1; 397 pcpu_init(pc, 0, sizeof(struct pcpu)); 398 pc->pc_curthread = &thread0; 399 pc->pc_curpcb = thread0.td_pcb; 400 pc->pc_cpuid = 0; 401 /* pc->pc_mid = mid; */ 402 403 __asm __volatile("mtsprg 0, %0" :: "r"(pc)); 404 405 mutex_init(); 406 407 /* 408 * Make sure translation has been enabled 409 */ 410 mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI); 411 412 /* 413 * Initialise virtual memory. 414 */ 415 pmap_bootstrap(startkernel, endkernel); 416 417 /* 418 * Initialize tunables. 419 */ 420 init_param1(); 421 init_param2(physmem); 422 423 /* 424 * Finish setting up thread0. 425 */ 426 thread0.td_kstack = kstack0; 427 thread0.td_pcb = (struct pcb *) 428 (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; 429 430 /* 431 * Map and initialise the message buffer. 432 */ 433 for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE) 434 pmap_kenter((vm_offset_t)msgbufp + off, msgbuf_phys + off); 435 msgbufinit(msgbufp, MSGBUF_SIZE); 436} 437 438void 439bzero(void *buf, size_t len) 440{ 441 caddr_t p; 442 443 p = buf; 444 445 while (((vm_offset_t) p & (sizeof(u_long) - 1)) && len) { 446 *p++ = 0; 447 len--; 448 } 449 450 while (len >= sizeof(u_long) * 8) { 451 *(u_long*) p = 0; 452 *((u_long*) p + 1) = 0; 453 *((u_long*) p + 2) = 0; 454 *((u_long*) p + 3) = 0; 455 len -= sizeof(u_long) * 8; 456 *((u_long*) p + 4) = 0; 457 *((u_long*) p + 5) = 0; 458 *((u_long*) p + 6) = 0; 459 *((u_long*) p + 7) = 0; 460 p += sizeof(u_long) * 8; 461 } 462 463 while (len >= sizeof(u_long)) { 464 *(u_long*) p = 0; 465 len -= sizeof(u_long); 466 p += sizeof(u_long); 467 } 468 469 while (len) { 470 *p++ = 0; 471 len--; 472 } 473} 474 475void 476sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) 477{ 478 struct trapframe *tf; 479 struct sigframe *sfp; 480 struct sigacts *psp; 481 struct sigframe sf; 482 struct thread *td; 483 struct proc *p; 484 int oonstack, rndfsize; 485 486 td = curthread; 487 p = td->td_proc; 488 psp = p->p_sigacts; 489 tf = td->td_frame; 490 oonstack = sigonstack(tf->fixreg[1]); 491 492 rndfsize = ((sizeof(sf) + 15) / 16) * 16; 493 494 CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, 495 catcher, sig); 496 497 /* 498 * Save user context 499 */ 500 memset(&sf, 0, sizeof(sf)); 501 sf.sf_uc.uc_sigmask = *mask; 502 sf.sf_uc.uc_stack = p->p_sigstk; 503 sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK) 504 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 505 506 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 507 memcpy(&sf.sf_uc.uc_mcontext.mc_frame, tf, sizeof(struct trapframe)); 508 509 /* 510 * Allocate and validate space for the signal handler context. 511 */ 512 if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack && 513 SIGISMEMBER(psp->ps_sigonstack, sig)) { 514 sfp = (struct sigframe *)((caddr_t)p->p_sigstk.ss_sp + 515 p->p_sigstk.ss_size - rndfsize); 516 } else { 517 sfp = (struct sigframe *)(tf->fixreg[1] - rndfsize); 518 } 519 PROC_UNLOCK(p); 520 521 /* 522 * Translate the signal if appropriate (Linux emu ?) 523 */ 524 if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 525 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 526 527 /* 528 * Save the floating-point state, if necessary, then copy it. 529 */ 530 /* XXX */ 531 532 /* 533 * Set up the registers to return to sigcode. 534 * 535 * r1/sp - sigframe ptr 536 * lr - sig function, dispatched to by blrl in trampoline 537 * r3 - sig number 538 * r4 - SIGINFO ? &siginfo : exception code 539 * r5 - user context 540 * srr0 - trampoline function addr 541 */ 542 tf->lr = (register_t)catcher; 543 tf->fixreg[1] = (register_t)sfp; 544 tf->fixreg[FIRSTARG] = sig; 545 tf->fixreg[FIRSTARG+2] = (register_t)&sfp->sf_uc; 546 547 PROC_LOCK(p); 548 if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { 549 /* 550 * Signal handler installed with SA_SIGINFO. 551 */ 552 tf->fixreg[FIRSTARG+1] = (register_t)&sfp->sf_si; 553 554 /* 555 * Fill siginfo structure. 556 */ 557 sf.sf_si.si_signo = sig; 558 sf.sf_si.si_code = code; 559 sf.sf_si.si_addr = (void *)tf->srr0; 560 } else { 561 /* Old FreeBSD-style arguments. */ 562 tf->fixreg[FIRSTARG+1] = code; 563 } 564 PROC_UNLOCK(p); 565 566 tf->srr0 = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode)); 567 568 /* 569 * copy the frame out to userland. 570 */ 571 if (copyout((caddr_t)&sf, (caddr_t)sfp, sizeof(sf)) != 0) { 572 /* 573 * Process has trashed its stack. Kill it. 574 */ 575 CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 576 PROC_LOCK(p); 577 sigexit(td, SIGILL); 578 } 579 580 CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, 581 tf->srr0, tf->fixreg[1]); 582 583 PROC_LOCK(p); 584} 585 586int 587sigreturn(struct thread *td, struct sigreturn_args *uap) 588{ 589 struct trapframe *tf; 590 struct proc *p; 591 ucontext_t uc; 592 593 CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 594 595 if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 596 CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 597 return (EFAULT); 598 } 599 600 /* 601 * Don't let the user set privileged MSR bits 602 */ 603 tf = td->td_frame; 604 if ((uc.uc_mcontext.mc_frame.srr1 & PSL_USERSTATIC) != 605 (tf->srr1 & PSL_USERSTATIC)) { 606 return (EINVAL); 607 } 608 609 /* 610 * Restore the user-supplied context 611 */ 612 memcpy(tf, &uc.uc_mcontext.mc_frame, sizeof(struct trapframe)); 613 614 p = td->td_proc; 615 PROC_LOCK(p); 616 p->p_sigmask = uc.uc_sigmask; 617 SIG_CANTMASK(p->p_sigmask); 618 signotify(p); 619 PROC_UNLOCK(p); 620 621 /* 622 * Restore FP state 623 */ 624 /* XXX */ 625 626 CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x", 627 td, tf->srr0, tf->fixreg[1]); 628 629 return (EJUSTRETURN); 630} 631 632#ifdef COMPAT_FREEBSD4 633int 634freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) 635{ 636 637 return sigreturn(td, (struct sigreturn_args *)uap); 638} 639#endif 640 641void 642cpu_boot(int howto) 643{ 644} 645 646/* 647 * Shutdown the CPU as much as possible. 648 */ 649void 650cpu_halt(void) 651{ 652 653 OF_exit(); 654} 655 656/* 657 * Set set up registers on exec. 658 */ 659void 660exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) 661{ 662 struct trapframe *tf; 663 struct ps_strings arginfo; 664 665 tf = trapframe(td); 666 bzero(tf, sizeof *tf); 667 tf->fixreg[1] = -roundup(-stack + 8, 16); 668 669 /* 670 * XXX Machine-independent code has already copied arguments and 671 * XXX environment to userland. Get them back here. 672 */ 673 (void)copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo)); 674 675 /* 676 * Set up arguments for _start(): 677 * _start(argc, argv, envp, obj, cleanup, ps_strings); 678 * 679 * Notes: 680 * - obj and cleanup are the auxilliary and termination 681 * vectors. They are fixed up by ld.elf_so. 682 * - ps_strings is a NetBSD extention, and will be 683 * ignored by executables which are strictly 684 * compliant with the SVR4 ABI. 685 * 686 * XXX We have to set both regs and retval here due to different 687 * XXX calling convention in trap.c and init_main.c. 688 */ 689 /* 690 * XXX PG: these get overwritten in the syscall return code. 691 * execve() should return EJUSTRETURN, like it does on NetBSD. 692 * Emulate by setting the syscall return value cells. The 693 * registers still have to be set for init's fork trampoline. 694 */ 695 td->td_retval[0] = arginfo.ps_nargvstr; 696 td->td_retval[1] = (register_t)arginfo.ps_argvstr; 697 tf->fixreg[3] = arginfo.ps_nargvstr; 698 tf->fixreg[4] = (register_t)arginfo.ps_argvstr; 699 tf->fixreg[5] = (register_t)arginfo.ps_envstr; 700 tf->fixreg[6] = 0; /* auxillary vector */ 701 tf->fixreg[7] = 0; /* termination vector */ 702 tf->fixreg[8] = (register_t)PS_STRINGS; /* NetBSD extension */ 703 704 tf->srr0 = entry; 705 tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT; 706 td->td_pcb->pcb_flags = 0; 707} 708 709#if !defined(DDB) 710void 711Debugger(const char *msg) 712{ 713 714 printf("Debugger(\"%s\") called.\n", msg); 715} 716#endif /* !defined(DDB) */ 717 718/* XXX: dummy {fill,set}_[fp]regs */ 719int 720fill_regs(struct thread *td, struct reg *regs) 721{ 722 723 return (ENOSYS); 724} 725 726int 727fill_dbregs(struct thread *td, struct dbreg *dbregs) 728{ 729 730 return (ENOSYS); 731} 732 733int 734fill_fpregs(struct thread *td, struct fpreg *fpregs) 735{ 736 737 return (ENOSYS); 738} 739 740int 741set_regs(struct thread *td, struct reg *regs) 742{ 743 744 return (ENOSYS); 745} 746 747int 748set_dbregs(struct thread *td, struct dbreg *dbregs) 749{ 750 751 return (ENOSYS); 752} 753 754int 755set_fpregs(struct thread *td, struct fpreg *fpregs) 756{ 757 758 return (ENOSYS); 759} 760 761int 762ptrace_set_pc(struct thread *td, unsigned long addr) 763{ 764 765 /* XXX: coming soon... */ 766 return (ENOSYS); 767} 768 769int 770ptrace_single_step(struct thread *td) 771{ 772 773 /* XXX: coming soon... */ 774 return (ENOSYS); 775} 776 777/* 778 * Initialise a struct pcpu. 779 */ 780void 781cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz) 782{ 783 784 pcpu->pc_current_asngen = 1; 785} 786 787/* 788 * kcopy(const void *src, void *dst, size_t len); 789 * 790 * Copy len bytes from src to dst, aborting if we encounter a fatal 791 * page fault. 792 * 793 * kcopy() _must_ save and restore the old fault handler since it is 794 * called by uiomove(), which may be in the path of servicing a non-fatal 795 * page fault. 796 */ 797int 798kcopy(const void *src, void *dst, size_t len) 799{ 800 struct thread *td; 801 faultbuf env, *oldfault; 802 int rv; 803 804 td = PCPU_GET(curthread); 805 oldfault = td->td_pcb->pcb_onfault; 806 if ((rv = setfault(env)) != 0) { 807 td->td_pcb->pcb_onfault = oldfault; 808 return rv; 809 } 810 811 memcpy(dst, src, len); 812 813 td->td_pcb->pcb_onfault = oldfault; 814 return (0); 815}
|