The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/i386/vm_machdep.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1982, 1986 The Regents of the University of California.
    3  * Copyright (c) 1989, 1990 William Jolitz
    4  * Copyright (c) 1994 John Dyson
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by
    8  * the Systems Programming Group of the University of Utah Computer
    9  * Science Department, and William Jolitz.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *      This product includes software developed by the University of
   22  *      California, Berkeley and its contributors.
   23  * 4. Neither the name of the University nor the names of its contributors
   24  *    may be used to endorse or promote products derived from this software
   25  *    without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   37  * SUCH DAMAGE.
   38  *
   39  *      from: @(#)vm_machdep.c  7.3 (Berkeley) 5/13/91
   40  *      Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$
   41  * $FreeBSD: releng/5.0/sys/i386/i386/vm_machdep.c 107719 2002-12-10 02:33:45Z julian $
   42  */
   43 
   44 #include "opt_npx.h"
   45 #ifdef PC98
   46 #include "opt_pc98.h"
   47 #endif
   48 #include "opt_reset.h"
   49 #include "opt_isa.h"
   50 #include "opt_kstack_pages.h"
   51 
   52 #include <sys/param.h>
   53 #include <sys/systm.h>
   54 #include <sys/malloc.h>
   55 #include <sys/proc.h>
   56 #include <sys/kse.h>
   57 #include <sys/bio.h>
   58 #include <sys/buf.h>
   59 #include <sys/vnode.h>
   60 #include <sys/vmmeter.h>
   61 #include <sys/kernel.h>
   62 #include <sys/ktr.h>
   63 #include <sys/mutex.h>
   64 #include <sys/smp.h>
   65 #include <sys/sysctl.h>
   66 #include <sys/unistd.h>
   67 
   68 #include <machine/cpu.h>
   69 #include <machine/md_var.h>
   70 #include <machine/pcb.h>
   71 #include <machine/pcb_ext.h>
   72 #include <machine/vm86.h>
   73 
   74 #include <vm/vm.h>
   75 #include <vm/vm_param.h>
   76 #include <sys/lock.h>
   77 #include <vm/vm_kern.h>
   78 #include <vm/vm_page.h>
   79 #include <vm/vm_map.h>
   80 #include <vm/vm_extern.h>
   81 
   82 #include <sys/user.h>
   83 
   84 #ifdef PC98
   85 #include <pc98/pc98/pc98.h>
   86 #else
   87 #include <i386/isa/isa.h>
   88 #endif
   89 
   90 static void     cpu_reset_real(void);
   91 #ifdef SMP
   92 static void     cpu_reset_proxy(void);
   93 static u_int    cpu_reset_proxyid;
   94 static volatile u_int   cpu_reset_proxy_active;
   95 #endif
   96 extern int      _ucodesel, _udatasel;
   97 
   98 /*
   99  * quick version of vm_fault
  100  */
  101 int
  102 vm_fault_quick(v, prot)
  103         caddr_t v;
  104         int prot;
  105 {
  106         int r;
  107 
  108         if (prot & VM_PROT_WRITE)
  109                 r = subyte(v, fubyte(v));
  110         else
  111                 r = fubyte(v);
  112         return(r);
  113 }
  114 
  115 /*
  116  * Finish a fork operation, with process p2 nearly set up.
  117  * Copy and update the pcb, set up the stack so that the child
  118  * ready to run and return to user mode.
  119  */
  120 void
  121 cpu_fork(td1, p2, td2, flags)
  122         register struct thread *td1;
  123         register struct proc *p2;
  124         struct thread *td2;
  125         int flags;
  126 {
  127         register struct proc *p1;
  128         struct pcb *pcb2;
  129         struct mdproc *mdp2;
  130 #ifdef DEV_NPX
  131         register_t savecrit;
  132 #endif
  133 
  134         p1 = td1->td_proc;
  135         if ((flags & RFPROC) == 0) {
  136                 if ((flags & RFMEM) == 0) {
  137                         /* unshare user LDT */
  138                         struct mdproc *mdp1 = &p1->p_md;
  139                         struct proc_ldt *pldt = mdp1->md_ldt;
  140                         if (pldt && pldt->ldt_refcnt > 1) {
  141                                 pldt = user_ldt_alloc(mdp1, pldt->ldt_len);
  142                                 if (pldt == NULL)
  143                                         panic("could not copy LDT");
  144                                 mdp1->md_ldt = pldt;
  145                                 set_user_ldt(mdp1);
  146                                 user_ldt_free(td1);
  147                         }
  148                 }
  149                 return;
  150         }
  151 
  152         /* Ensure that p1's pcb is up to date. */
  153 #ifdef DEV_NPX
  154         if (td1 == curthread)
  155                 td1->td_pcb->pcb_gs = rgs();
  156         savecrit = intr_disable();
  157         if (PCPU_GET(fpcurthread) == td1)
  158                 npxsave(&td1->td_pcb->pcb_save);
  159         intr_restore(savecrit);
  160 #endif
  161 
  162         /* Point the pcb to the top of the stack */
  163         pcb2 = (struct pcb *)(td2->td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
  164         td2->td_pcb = pcb2;
  165 
  166         /* Copy p1's pcb */
  167         bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));
  168 
  169         /* Point mdproc and then copy over td1's contents */
  170         mdp2 = &p2->p_md;
  171         bcopy(&p1->p_md, mdp2, sizeof(*mdp2));
  172 
  173         /*
  174          * Create a new fresh stack for the new process.
  175          * Copy the trap frame for the return to user mode as if from a
  176          * syscall.  This copies most of the user mode register values.
  177          * The -16 is so we can expand the trapframe if we go to vm86.
  178          */
  179         td2->td_frame = (struct trapframe *)((caddr_t)td2->td_pcb - 16) - 1;
  180         bcopy(td1->td_frame, td2->td_frame, sizeof(struct trapframe));
  181 
  182         td2->td_frame->tf_eax = 0;              /* Child returns zero */
  183         td2->td_frame->tf_eflags &= ~PSL_C;     /* success */
  184         td2->td_frame->tf_edx = 1;
  185 
  186         /*
  187          * Set registers for trampoline to user mode.  Leave space for the
  188          * return address on stack.  These are the kernel mode register values.
  189          */
  190         pcb2->pcb_cr3 = vtophys(vmspace_pmap(p2->p_vmspace)->pm_pdir);
  191         pcb2->pcb_edi = 0;
  192         pcb2->pcb_esi = (int)fork_return;       /* fork_trampoline argument */
  193         pcb2->pcb_ebp = 0;
  194         pcb2->pcb_esp = (int)td2->td_frame - sizeof(void *);
  195         pcb2->pcb_ebx = (int)td2;               /* fork_trampoline argument */
  196         pcb2->pcb_eip = (int)fork_trampoline;
  197         pcb2->pcb_psl = td2->td_frame->tf_eflags & ~PSL_I; /* ints disabled */
  198         /*-
  199          * pcb2->pcb_dr*:       cloned above.
  200          * pcb2->pcb_savefpu:   cloned above.
  201          * pcb2->pcb_flags:     cloned above.
  202          * pcb2->pcb_onfault:   cloned above (always NULL here?).
  203          * pcb2->pcb_gs:        cloned above.
  204          * pcb2->pcb_ext:       cleared below.
  205          */
  206 
  207         /*
  208          * XXX don't copy the i/o pages.  this should probably be fixed.
  209          */
  210         pcb2->pcb_ext = 0;
  211 
  212         /* Copy the LDT, if necessary. */
  213         mtx_lock_spin(&sched_lock);
  214         if (mdp2->md_ldt != 0) {
  215                 if (flags & RFMEM) {
  216                         mdp2->md_ldt->ldt_refcnt++;
  217                 } else {
  218                         mdp2->md_ldt = user_ldt_alloc(mdp2,
  219                             mdp2->md_ldt->ldt_len);
  220                         if (mdp2->md_ldt == NULL)
  221                                 panic("could not copy LDT");
  222                 }
  223         }
  224         mtx_unlock_spin(&sched_lock);
  225 
  226         /*
  227          * Now, cpu_switch() can schedule the new process.
  228          * pcb_esp is loaded pointing to the cpu_switch() stack frame
  229          * containing the return address when exiting cpu_switch.
  230          * This will normally be to fork_trampoline(), which will have
  231          * %ebx loaded with the new proc's pointer.  fork_trampoline()
  232          * will set up a stack to call fork_return(p, frame); to complete
  233          * the return to user-mode.
  234          */
  235 }
  236 
  237 /*
  238  * Intercept the return address from a freshly forked process that has NOT
  239  * been scheduled yet.
  240  *
  241  * This is needed to make kernel threads stay in kernel mode.
  242  */
  243 void
  244 cpu_set_fork_handler(td, func, arg)
  245         struct thread *td;
  246         void (*func)(void *);
  247         void *arg;
  248 {
  249         /*
  250          * Note that the trap frame follows the args, so the function
  251          * is really called like this:  func(arg, frame);
  252          */
  253         td->td_pcb->pcb_esi = (int) func;       /* function */
  254         td->td_pcb->pcb_ebx = (int) arg;        /* first arg */
  255 }
  256 
  257 void
  258 cpu_exit(struct thread *td)
  259 {
  260         struct mdproc *mdp;
  261 
  262         mdp = &td->td_proc->p_md;
  263         if (mdp->md_ldt)
  264                 user_ldt_free(td);
  265         reset_dbregs();
  266 }
  267 
  268 void
  269 cpu_thread_exit(struct thread *td)
  270 {
  271         struct pcb *pcb = td->td_pcb; 
  272 #ifdef DEV_NPX
  273         npxexit(td);
  274 #endif
  275         if (pcb->pcb_flags & PCB_DBREGS) {
  276                 /*
  277                  * disable all hardware breakpoints
  278                  */
  279                 reset_dbregs();
  280                 pcb->pcb_flags &= ~PCB_DBREGS;
  281         }
  282 }
  283 
  284 void
  285 cpu_thread_clean(struct thread *td)
  286 {
  287         struct pcb *pcb;
  288 
  289         pcb = td->td_pcb; 
  290         if (pcb->pcb_ext != 0) {
  291                 /* XXXKSE  XXXSMP  not SMP SAFE.. what locks do we have? */
  292                 /* if (pcb->pcb_ext->ext_refcount-- == 1) ?? */
  293                 /*
  294                  * XXX do we need to move the TSS off the allocated pages
  295                  * before freeing them?  (not done here)
  296                  */
  297                 mtx_lock(&Giant);
  298                 kmem_free(kernel_map, (vm_offset_t)pcb->pcb_ext,
  299                     ctob(IOPAGES + 1));
  300                 mtx_unlock(&Giant);
  301                 pcb->pcb_ext = 0;
  302         }
  303 }
  304 
  305 void
  306 cpu_sched_exit(td)
  307         register struct thread *td;
  308 {
  309 }
  310 
  311 void
  312 cpu_thread_setup(struct thread *td)
  313 {
  314 
  315         td->td_pcb =
  316              (struct pcb *)(td->td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
  317         td->td_frame = (struct trapframe *)((caddr_t)td->td_pcb - 16) - 1;
  318 }
  319 
  320 /*
  321  * Initialize machine state (pcb and trap frame) for a new thread about to
  322  * upcall. Pu t enough state in the new thread's PCB to get it to go back 
  323  * userret(), where we can intercept it again to set the return (upcall)
  324  * Address and stack, along with those from upcals that are from other sources
  325  * such as those generated in thread_userret() itself.
  326  */
  327 void
  328 cpu_set_upcall(struct thread *td, void *pcb)
  329 {
  330         struct pcb *pcb2;
  331 
  332         td->td_flags |= TDF_UPCALLING;
  333 
  334         /* Point the pcb to the top of the stack. */
  335         pcb2 = td->td_pcb;
  336 
  337         /*
  338          * Copy the upcall pcb.  This loads kernel regs.
  339          * Those not loaded individually below get their default
  340          * values here.
  341          *
  342          * XXXKSE It might be a good idea to simply skip this as
  343          * the values of the other registers may be unimportant.
  344          * This would remove any requirement for knowing the KSE
  345          * at this time (see the matching comment below for
  346          * more analysis) (need a good safe default).
  347          */
  348         bcopy(pcb, pcb2, sizeof(*pcb2));
  349 
  350         /*
  351          * Create a new fresh stack for the new thread.
  352          * The -16 is so we can expand the trapframe if we go to vm86.
  353          * Don't forget to set this stack value into whatever supplies
  354          * the address for the fault handlers.
  355          * The contexts are filled in at the time we actually DO the
  356          * upcall as only then do we know which KSE we got.
  357          */
  358         td->td_frame = (struct trapframe *)((caddr_t)pcb2 - 16) - 1;
  359 
  360         /*
  361          * Set registers for trampoline to user mode.  Leave space for the
  362          * return address on stack.  These are the kernel mode register values.
  363          */
  364         pcb2->pcb_cr3 = vtophys(vmspace_pmap(td->td_proc->p_vmspace)->pm_pdir);
  365         pcb2->pcb_edi = 0;
  366         pcb2->pcb_esi = (int)fork_return;                   /* trampoline arg */
  367         pcb2->pcb_ebp = 0;
  368         pcb2->pcb_esp = (int)td->td_frame - sizeof(void *); /* trampoline arg */
  369         pcb2->pcb_ebx = (int)td;                            /* trampoline arg */
  370         pcb2->pcb_eip = (int)fork_trampoline;
  371         pcb2->pcb_psl &= ~(PSL_I);      /* interrupts must be disabled */
  372         /*
  373          * If we didn't copy the pcb, we'd need to do the following registers:
  374          * pcb2->pcb_dr*:       cloned above.
  375          * pcb2->pcb_savefpu:   cloned above.
  376          * pcb2->pcb_flags:     cloned above.
  377          * pcb2->pcb_onfault:   cloned above (always NULL here?).
  378          * pcb2->pcb_gs:        cloned above.  XXXKSE ???
  379          * pcb2->pcb_ext:       cleared below.
  380          */
  381          pcb2->pcb_ext = NULL;
  382 }
  383 
  384 /*
  385  * Set that machine state for performing an upcall that has to
  386  * be done in thread_userret() so that those upcalls generated
  387  * in thread_userret() itself can be done as well.
  388  */
  389 void
  390 cpu_set_upcall_kse(struct thread *td, struct kse *ke)
  391 {
  392 
  393         /* 
  394          * Do any extra cleaning that needs to be done.
  395          * The thread may have optional components
  396          * that are not present in a fresh thread.
  397          * This may be a recycled thread so make it look
  398          * as though it's newly allocated.
  399          */
  400         cpu_thread_clean(td);
  401 
  402         /*
  403          * Set the trap frame to point at the beginning of the uts
  404          * function.
  405          */
  406         td->td_frame->tf_esp =
  407             (int)ke->ke_stack.ss_sp + ke->ke_stack.ss_size - 16;
  408         td->td_frame->tf_eip = (int)ke->ke_upcall;
  409 
  410         /*
  411          * Pass the address of the mailbox for this kse to the uts
  412          * function as a parameter on the stack.
  413          */
  414         suword((void *)(td->td_frame->tf_esp + sizeof(void *)),
  415             (int)ke->ke_mailbox);
  416 }
  417 
  418 void
  419 cpu_wait(p)
  420         struct proc *p;
  421 {
  422 }
  423 
  424 /*
  425  * Convert kernel VA to physical address
  426  */
  427 u_long
  428 kvtop(void *addr)
  429 {
  430         vm_offset_t va;
  431 
  432         va = pmap_kextract((vm_offset_t)addr);
  433         if (va == 0)
  434                 panic("kvtop: zero page frame");
  435         return((int)va);
  436 }
  437 
  438 /*
  439  * Map an IO request into kernel virtual address space.
  440  *
  441  * All requests are (re)mapped into kernel VA space.
  442  * Notice that we use b_bufsize for the size of the buffer
  443  * to be mapped.  b_bcount might be modified by the driver.
  444  */
  445 void
  446 vmapbuf(bp)
  447         register struct buf *bp;
  448 {
  449         register caddr_t addr, kva;
  450         vm_offset_t pa;
  451         int pidx;
  452         struct vm_page *m;
  453 
  454         GIANT_REQUIRED;
  455 
  456         if ((bp->b_flags & B_PHYS) == 0)
  457                 panic("vmapbuf");
  458 
  459         for (addr = (caddr_t)trunc_page((vm_offset_t)bp->b_data), pidx = 0;
  460              addr < bp->b_data + bp->b_bufsize;
  461              addr += PAGE_SIZE, pidx++) {
  462                 /*
  463                  * Do the vm_fault if needed; do the copy-on-write thing
  464                  * when reading stuff off device into memory.
  465                  */
  466                 vm_fault_quick((addr >= bp->b_data) ? addr : bp->b_data,
  467                         (bp->b_iocmd == BIO_READ)?(VM_PROT_READ|VM_PROT_WRITE):VM_PROT_READ);
  468                 pa = trunc_page(pmap_kextract((vm_offset_t) addr));
  469                 if (pa == 0)
  470                         panic("vmapbuf: page not present");
  471                 m = PHYS_TO_VM_PAGE(pa);
  472                 vm_page_hold(m);
  473                 bp->b_pages[pidx] = m;
  474         }
  475         if (pidx > btoc(MAXPHYS))
  476                 panic("vmapbuf: mapped more than MAXPHYS");
  477         pmap_qenter((vm_offset_t)bp->b_saveaddr, bp->b_pages, pidx);
  478         
  479         kva = bp->b_saveaddr;
  480         bp->b_npages = pidx;
  481         bp->b_saveaddr = bp->b_data;
  482         bp->b_data = kva + (((vm_offset_t) bp->b_data) & PAGE_MASK);
  483 }
  484 
  485 /*
  486  * Free the io map PTEs associated with this IO operation.
  487  * We also invalidate the TLB entries and restore the original b_addr.
  488  */
  489 void
  490 vunmapbuf(bp)
  491         register struct buf *bp;
  492 {
  493         int pidx;
  494         int npages;
  495 
  496         GIANT_REQUIRED;
  497 
  498         if ((bp->b_flags & B_PHYS) == 0)
  499                 panic("vunmapbuf");
  500 
  501         npages = bp->b_npages;
  502         pmap_qremove(trunc_page((vm_offset_t)bp->b_data),
  503                      npages);
  504         vm_page_lock_queues();
  505         for (pidx = 0; pidx < npages; pidx++)
  506                 vm_page_unhold(bp->b_pages[pidx]);
  507         vm_page_unlock_queues();
  508 
  509         bp->b_data = bp->b_saveaddr;
  510 }
  511 
  512 /*
  513  * Force reset the processor by invalidating the entire address space!
  514  */
  515 
  516 #ifdef SMP
  517 static void
  518 cpu_reset_proxy()
  519 {
  520 
  521         cpu_reset_proxy_active = 1;
  522         while (cpu_reset_proxy_active == 1)
  523                 ;        /* Wait for other cpu to see that we've started */
  524         stop_cpus((1<<cpu_reset_proxyid));
  525         printf("cpu_reset_proxy: Stopped CPU %d\n", cpu_reset_proxyid);
  526         DELAY(1000000);
  527         cpu_reset_real();
  528 }
  529 #endif
  530 
  531 void
  532 cpu_reset()
  533 {
  534 #ifdef SMP
  535         if (smp_active == 0) {
  536                 cpu_reset_real();
  537                 /* NOTREACHED */
  538         } else {
  539 
  540                 u_int map;
  541                 int cnt;
  542                 printf("cpu_reset called on cpu#%d\n", PCPU_GET(cpuid));
  543 
  544                 map = PCPU_GET(other_cpus) & ~ stopped_cpus;
  545 
  546                 if (map != 0) {
  547                         printf("cpu_reset: Stopping other CPUs\n");
  548                         stop_cpus(map);         /* Stop all other CPUs */
  549                 }
  550 
  551                 if (PCPU_GET(cpuid) == 0) {
  552                         DELAY(1000000);
  553                         cpu_reset_real();
  554                         /* NOTREACHED */
  555                 } else {
  556                         /* We are not BSP (CPU #0) */
  557 
  558                         cpu_reset_proxyid = PCPU_GET(cpuid);
  559                         cpustop_restartfunc = cpu_reset_proxy;
  560                         cpu_reset_proxy_active = 0;
  561                         printf("cpu_reset: Restarting BSP\n");
  562                         started_cpus = (1<<0);          /* Restart CPU #0 */
  563 
  564                         cnt = 0;
  565                         while (cpu_reset_proxy_active == 0 && cnt < 10000000)
  566                                 cnt++;  /* Wait for BSP to announce restart */
  567                         if (cpu_reset_proxy_active == 0)
  568                                 printf("cpu_reset: Failed to restart BSP\n");
  569                         enable_intr();
  570                         cpu_reset_proxy_active = 2;
  571 
  572                         while (1);
  573                         /* NOTREACHED */
  574                 }
  575         }
  576 #else
  577         cpu_reset_real();
  578 #endif
  579 }
  580 
  581 static void
  582 cpu_reset_real()
  583 {
  584 
  585 #ifdef PC98
  586         /*
  587          * Attempt to do a CPU reset via CPU reset port.
  588          */
  589         disable_intr();
  590         if ((inb(0x35) & 0xa0) != 0xa0) {
  591                 outb(0x37, 0x0f);               /* SHUT0 = 0. */
  592                 outb(0x37, 0x0b);               /* SHUT1 = 0. */
  593         }
  594         outb(0xf0, 0x00);               /* Reset. */
  595 #else
  596         /*
  597          * Attempt to do a CPU reset via the keyboard controller,
  598          * do not turn of the GateA20, as any machine that fails
  599          * to do the reset here would then end up in no man's land.
  600          */
  601 
  602 #if !defined(BROKEN_KEYBOARD_RESET)
  603         outb(IO_KBD + 4, 0xFE);
  604         DELAY(500000);  /* wait 0.5 sec to see if that did it */
  605         printf("Keyboard reset did not work, attempting CPU shutdown\n");
  606         DELAY(1000000); /* wait 1 sec for printf to complete */
  607 #endif
  608 #endif /* PC98 */
  609         /* force a shutdown by unmapping entire address space ! */
  610         bzero((caddr_t) PTD, PAGE_SIZE);
  611 
  612         /* "good night, sweet prince .... <THUNK!>" */
  613         invltlb();
  614         /* NOTREACHED */
  615         while(1);
  616 }
  617 
  618 /*
  619  * Software interrupt handler for queued VM system processing.
  620  */   
  621 void  
  622 swi_vm(void *dummy) 
  623 {     
  624         if (busdma_swi_pending != 0)
  625                 busdma_swi();
  626 }
  627 
  628 /*
  629  * Tell whether this address is in some physical memory region.
  630  * Currently used by the kernel coredump code in order to avoid
  631  * dumping the ``ISA memory hole'' which could cause indefinite hangs,
  632  * or other unpredictable behaviour.
  633  */
  634 
  635 int
  636 is_physical_memory(addr)
  637         vm_offset_t addr;
  638 {
  639 
  640 #ifdef DEV_ISA
  641         /* The ISA ``memory hole''. */
  642         if (addr >= 0xa0000 && addr < 0x100000)
  643                 return 0;
  644 #endif
  645 
  646         /*
  647          * stuff other tests for known memory-mapped devices (PCI?)
  648          * here
  649          */
  650 
  651         return 1;
  652 }

Cache object: 0c2412a15870ae01a65d7f821718861b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.