]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/amd64/amd64/vm_machdep.c
Merge ACPICA 20120420.
[FreeBSD/FreeBSD.git] / sys / amd64 / amd64 / vm_machdep.c
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  */
42
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD$");
45
46 #include "opt_isa.h"
47 #include "opt_cpu.h"
48 #include "opt_compat.h"
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/bio.h>
53 #include <sys/buf.h>
54 #include <sys/kernel.h>
55 #include <sys/ktr.h>
56 #include <sys/lock.h>
57 #include <sys/malloc.h>
58 #include <sys/mbuf.h>
59 #include <sys/mutex.h>
60 #include <sys/pioctl.h>
61 #include <sys/proc.h>
62 #include <sys/sf_buf.h>
63 #include <sys/smp.h>
64 #include <sys/sysctl.h>
65 #include <sys/sysent.h>
66 #include <sys/unistd.h>
67 #include <sys/vnode.h>
68 #include <sys/vmmeter.h>
69
70 #include <machine/cpu.h>
71 #include <machine/md_var.h>
72 #include <machine/pcb.h>
73 #include <machine/smp.h>
74 #include <machine/specialreg.h>
75 #include <machine/tss.h>
76
77 #include <vm/vm.h>
78 #include <vm/vm_extern.h>
79 #include <vm/vm_kern.h>
80 #include <vm/vm_page.h>
81 #include <vm/vm_map.h>
82 #include <vm/vm_param.h>
83
84 #include <x86/isa/isa.h>
85
86 static void     cpu_reset_real(void);
87 #ifdef SMP
88 static void     cpu_reset_proxy(void);
89 static u_int    cpu_reset_proxyid;
90 static volatile u_int   cpu_reset_proxy_active;
91 #endif
92
93 struct savefpu *
94 get_pcb_user_save_td(struct thread *td)
95 {
96         vm_offset_t p;
97
98         p = td->td_kstack + td->td_kstack_pages * PAGE_SIZE -
99             cpu_max_ext_state_size;
100         KASSERT((p % 64) == 0, ("Unaligned pcb_user_save area"));
101         return ((struct savefpu *)p);
102 }
103
104 struct savefpu *
105 get_pcb_user_save_pcb(struct pcb *pcb)
106 {
107         vm_offset_t p;
108
109         p = (vm_offset_t)(pcb + 1);
110         return ((struct savefpu *)p);
111 }
112
113 struct pcb *
114 get_pcb_td(struct thread *td)
115 {
116         vm_offset_t p;
117
118         p = td->td_kstack + td->td_kstack_pages * PAGE_SIZE -
119             cpu_max_ext_state_size - sizeof(struct pcb);
120         return ((struct pcb *)p);
121 }
122
123 void *
124 alloc_fpusave(int flags)
125 {
126         struct pcb *res;
127         struct savefpu_ymm *sf;
128
129         res = malloc(cpu_max_ext_state_size, M_DEVBUF, flags);
130         if (use_xsave) {
131                 sf = (struct savefpu_ymm *)res;
132                 bzero(&sf->sv_xstate.sx_hd, sizeof(sf->sv_xstate.sx_hd));
133                 sf->sv_xstate.sx_hd.xstate_bv = xsave_mask;
134         }
135         return (res);
136 }
137
138 /*
139  * Finish a fork operation, with process p2 nearly set up.
140  * Copy and update the pcb, set up the stack so that the child
141  * ready to run and return to user mode.
142  */
143 void
144 cpu_fork(td1, p2, td2, flags)
145         register struct thread *td1;
146         register struct proc *p2;
147         struct thread *td2;
148         int flags;
149 {
150         register struct proc *p1;
151         struct pcb *pcb2;
152         struct mdproc *mdp1, *mdp2;
153         struct proc_ldt *pldt;
154         pmap_t pmap2;
155
156         p1 = td1->td_proc;
157         if ((flags & RFPROC) == 0) {
158                 if ((flags & RFMEM) == 0) {
159                         /* unshare user LDT */
160                         mdp1 = &p1->p_md;
161                         mtx_lock(&dt_lock);
162                         if ((pldt = mdp1->md_ldt) != NULL &&
163                             pldt->ldt_refcnt > 1 &&
164                             user_ldt_alloc(p1, 1) == NULL)
165                                 panic("could not copy LDT");
166                         mtx_unlock(&dt_lock);
167                 }
168                 return;
169         }
170
171         /* Ensure that td1's pcb is up to date. */
172         fpuexit(td1);
173
174         /* Point the pcb to the top of the stack */
175         pcb2 = get_pcb_td(td2);
176         td2->td_pcb = pcb2;
177
178         /* Copy td1's pcb */
179         bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));
180
181         /* Properly initialize pcb_save */
182         pcb2->pcb_save = get_pcb_user_save_pcb(pcb2);
183         bcopy(get_pcb_user_save_td(td1), get_pcb_user_save_pcb(pcb2),
184             cpu_max_ext_state_size);
185
186         /* Point mdproc and then copy over td1's contents */
187         mdp2 = &p2->p_md;
188         bcopy(&p1->p_md, mdp2, sizeof(*mdp2));
189
190         /*
191          * Create a new fresh stack for the new process.
192          * Copy the trap frame for the return to user mode as if from a
193          * syscall.  This copies most of the user mode register values.
194          */
195         td2->td_frame = (struct trapframe *)td2->td_pcb - 1;
196         bcopy(td1->td_frame, td2->td_frame, sizeof(struct trapframe));
197
198         td2->td_frame->tf_rax = 0;              /* Child returns zero */
199         td2->td_frame->tf_rflags &= ~PSL_C;     /* success */
200         td2->td_frame->tf_rdx = 1;
201
202         /*
203          * If the parent process has the trap bit set (i.e. a debugger had
204          * single stepped the process to the system call), we need to clear
205          * the trap flag from the new frame unless the debugger had set PF_FORK
206          * on the parent.  Otherwise, the child will receive a (likely
207          * unexpected) SIGTRAP when it executes the first instruction after
208          * returning  to userland.
209          */
210         if ((p1->p_pfsflags & PF_FORK) == 0)
211                 td2->td_frame->tf_rflags &= ~PSL_T;
212
213         /*
214          * Set registers for trampoline to user mode.  Leave space for the
215          * return address on stack.  These are the kernel mode register values.
216          */
217         pmap2 = vmspace_pmap(p2->p_vmspace);
218         pcb2->pcb_cr3 = DMAP_TO_PHYS((vm_offset_t)pmap2->pm_pml4);
219         pcb2->pcb_r12 = (register_t)fork_return;        /* fork_trampoline argument */
220         pcb2->pcb_rbp = 0;
221         pcb2->pcb_rsp = (register_t)td2->td_frame - sizeof(void *);
222         pcb2->pcb_rbx = (register_t)td2;                /* fork_trampoline argument */
223         pcb2->pcb_rip = (register_t)fork_trampoline;
224         /*-
225          * pcb2->pcb_dr*:       cloned above.
226          * pcb2->pcb_savefpu:   cloned above.
227          * pcb2->pcb_flags:     cloned above.
228          * pcb2->pcb_onfault:   cloned above (always NULL here?).
229          * pcb2->pcb_[fg]sbase: cloned above
230          */
231
232         /* Setup to release spin count in fork_exit(). */
233         td2->td_md.md_spinlock_count = 1;
234         td2->td_md.md_saved_flags = PSL_KERNEL | PSL_I;
235
236         /* As an i386, do not copy io permission bitmap. */
237         pcb2->pcb_tssp = NULL;
238
239         /* New segment registers. */
240         set_pcb_flags(pcb2, PCB_FULL_IRET);
241
242         /* Copy the LDT, if necessary. */
243         mdp1 = &td1->td_proc->p_md;
244         mdp2 = &p2->p_md;
245         mtx_lock(&dt_lock);
246         if (mdp1->md_ldt != NULL) {
247                 if (flags & RFMEM) {
248                         mdp1->md_ldt->ldt_refcnt++;
249                         mdp2->md_ldt = mdp1->md_ldt;
250                         bcopy(&mdp1->md_ldt_sd, &mdp2->md_ldt_sd, sizeof(struct
251                             system_segment_descriptor));
252                 } else {
253                         mdp2->md_ldt = NULL;
254                         mdp2->md_ldt = user_ldt_alloc(p2, 0);
255                         if (mdp2->md_ldt == NULL)
256                                 panic("could not copy LDT");
257                         amd64_set_ldt_data(td2, 0, max_ldt_segment,
258                             (struct user_segment_descriptor *)
259                             mdp1->md_ldt->ldt_base);
260                 }
261         } else
262                 mdp2->md_ldt = NULL;
263         mtx_unlock(&dt_lock);
264
265         /*
266          * Now, cpu_switch() can schedule the new process.
267          * pcb_rsp is loaded pointing to the cpu_switch() stack frame
268          * containing the return address when exiting cpu_switch.
269          * This will normally be to fork_trampoline(), which will have
270          * %ebx loaded with the new proc's pointer.  fork_trampoline()
271          * will set up a stack to call fork_return(p, frame); to complete
272          * the return to user-mode.
273          */
274 }
275
276 /*
277  * Intercept the return address from a freshly forked process that has NOT
278  * been scheduled yet.
279  *
280  * This is needed to make kernel threads stay in kernel mode.
281  */
282 void
283 cpu_set_fork_handler(td, func, arg)
284         struct thread *td;
285         void (*func)(void *);
286         void *arg;
287 {
288         /*
289          * Note that the trap frame follows the args, so the function
290          * is really called like this:  func(arg, frame);
291          */
292         td->td_pcb->pcb_r12 = (long) func;      /* function */
293         td->td_pcb->pcb_rbx = (long) arg;       /* first arg */
294 }
295
296 void
297 cpu_exit(struct thread *td)
298 {
299
300         /*
301          * If this process has a custom LDT, release it.
302          */
303         mtx_lock(&dt_lock);
304         if (td->td_proc->p_md.md_ldt != 0)
305                 user_ldt_free(td);
306         else
307                 mtx_unlock(&dt_lock);
308 }
309
310 void
311 cpu_thread_exit(struct thread *td)
312 {
313         struct pcb *pcb;
314
315         critical_enter();
316         if (td == PCPU_GET(fpcurthread))
317                 fpudrop();
318         critical_exit();
319
320         pcb = td->td_pcb;
321
322         /* Disable any hardware breakpoints. */
323         if (pcb->pcb_flags & PCB_DBREGS) {
324                 reset_dbregs();
325                 clear_pcb_flags(pcb, PCB_DBREGS);
326         }
327 }
328
329 void
330 cpu_thread_clean(struct thread *td)
331 {
332         struct pcb *pcb;
333
334         pcb = td->td_pcb;
335
336         /*
337          * Clean TSS/iomap
338          */
339         if (pcb->pcb_tssp != NULL) {
340                 kmem_free(kernel_map, (vm_offset_t)pcb->pcb_tssp,
341                     ctob(IOPAGES + 1));
342                 pcb->pcb_tssp = NULL;
343         }
344 }
345
346 void
347 cpu_thread_swapin(struct thread *td)
348 {
349 }
350
351 void
352 cpu_thread_swapout(struct thread *td)
353 {
354 }
355
356 void
357 cpu_thread_alloc(struct thread *td)
358 {
359         struct pcb *pcb;
360         struct xstate_hdr *xhdr;
361
362         td->td_pcb = pcb = get_pcb_td(td);
363         td->td_frame = (struct trapframe *)pcb - 1;
364         pcb->pcb_save = get_pcb_user_save_pcb(pcb);
365         if (use_xsave) {
366                 xhdr = (struct xstate_hdr *)(pcb->pcb_save + 1);
367                 bzero(xhdr, sizeof(*xhdr));
368                 xhdr->xstate_bv = xsave_mask;
369         }
370 }
371
372 void
373 cpu_thread_free(struct thread *td)
374 {
375
376         cpu_thread_clean(td);
377 }
378
379 void
380 cpu_set_syscall_retval(struct thread *td, int error)
381 {
382
383         switch (error) {
384         case 0:
385                 td->td_frame->tf_rax = td->td_retval[0];
386                 td->td_frame->tf_rdx = td->td_retval[1];
387                 td->td_frame->tf_rflags &= ~PSL_C;
388                 break;
389
390         case ERESTART:
391                 /*
392                  * Reconstruct pc, we know that 'syscall' is 2 bytes,
393                  * lcall $X,y is 7 bytes, int 0x80 is 2 bytes.
394                  * We saved this in tf_err.
395                  * %r10 (which was holding the value of %rcx) is restored
396                  * for the next iteration.
397                  * %r10 restore is only required for freebsd/amd64 processes,
398                  * but shall be innocent for any ia32 ABI.
399                  */
400                 td->td_frame->tf_rip -= td->td_frame->tf_err;
401                 td->td_frame->tf_r10 = td->td_frame->tf_rcx;
402                 break;
403
404         case EJUSTRETURN:
405                 break;
406
407         default:
408                 if (td->td_proc->p_sysent->sv_errsize) {
409                         if (error >= td->td_proc->p_sysent->sv_errsize)
410                                 error = -1;     /* XXX */
411                         else
412                                 error = td->td_proc->p_sysent->sv_errtbl[error];
413                 }
414                 td->td_frame->tf_rax = error;
415                 td->td_frame->tf_rflags |= PSL_C;
416                 break;
417         }
418 }
419
420 /*
421  * Initialize machine state (pcb and trap frame) for a new thread about to
422  * upcall. Put enough state in the new thread's PCB to get it to go back 
423  * userret(), where we can intercept it again to set the return (upcall)
424  * Address and stack, along with those from upcals that are from other sources
425  * such as those generated in thread_userret() itself.
426  */
427 void
428 cpu_set_upcall(struct thread *td, struct thread *td0)
429 {
430         struct pcb *pcb2;
431
432         /* Point the pcb to the top of the stack. */
433         pcb2 = td->td_pcb;
434
435         /*
436          * Copy the upcall pcb.  This loads kernel regs.
437          * Those not loaded individually below get their default
438          * values here.
439          */
440         bcopy(td0->td_pcb, pcb2, sizeof(*pcb2));
441         clear_pcb_flags(pcb2, PCB_FPUINITDONE | PCB_USERFPUINITDONE);
442         pcb2->pcb_save = get_pcb_user_save_pcb(pcb2);
443         bcopy(get_pcb_user_save_td(td0), pcb2->pcb_save,
444             cpu_max_ext_state_size);
445         set_pcb_flags(pcb2, PCB_FULL_IRET);
446
447         /*
448          * Create a new fresh stack for the new thread.
449          */
450         bcopy(td0->td_frame, td->td_frame, sizeof(struct trapframe));
451
452         /* If the current thread has the trap bit set (i.e. a debugger had
453          * single stepped the process to the system call), we need to clear
454          * the trap flag from the new frame. Otherwise, the new thread will
455          * receive a (likely unexpected) SIGTRAP when it executes the first
456          * instruction after returning to userland.
457          */
458         td->td_frame->tf_rflags &= ~PSL_T;
459
460         /*
461          * Set registers for trampoline to user mode.  Leave space for the
462          * return address on stack.  These are the kernel mode register values.
463          */
464         pcb2->pcb_r12 = (register_t)fork_return;            /* trampoline arg */
465         pcb2->pcb_rbp = 0;
466         pcb2->pcb_rsp = (register_t)td->td_frame - sizeof(void *);      /* trampoline arg */
467         pcb2->pcb_rbx = (register_t)td;                     /* trampoline arg */
468         pcb2->pcb_rip = (register_t)fork_trampoline;
469         /*
470          * If we didn't copy the pcb, we'd need to do the following registers:
471          * pcb2->pcb_cr3:       cloned above.
472          * pcb2->pcb_dr*:       cloned above.
473          * pcb2->pcb_savefpu:   cloned above.
474          * pcb2->pcb_onfault:   cloned above (always NULL here?).
475          * pcb2->pcb_[fg]sbase: cloned above
476          */
477
478         /* Setup to release spin count in fork_exit(). */
479         td->td_md.md_spinlock_count = 1;
480         td->td_md.md_saved_flags = PSL_KERNEL | PSL_I;
481 }
482
483 /*
484  * Set that machine state for performing an upcall that has to
485  * be done in thread_userret() so that those upcalls generated
486  * in thread_userret() itself can be done as well.
487  */
488 void
489 cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
490         stack_t *stack)
491 {
492
493         /* 
494          * Do any extra cleaning that needs to be done.
495          * The thread may have optional components
496          * that are not present in a fresh thread.
497          * This may be a recycled thread so make it look
498          * as though it's newly allocated.
499          */
500         cpu_thread_clean(td);
501
502 #ifdef COMPAT_FREEBSD32
503         if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
504                 /*
505                  * Set the trap frame to point at the beginning of the uts
506                  * function.
507                  */
508                 td->td_frame->tf_rbp = 0;
509                 td->td_frame->tf_rsp =
510                    (((uintptr_t)stack->ss_sp + stack->ss_size - 4) & ~0x0f) - 4;
511                 td->td_frame->tf_rip = (uintptr_t)entry;
512
513                 /*
514                  * Pass the address of the mailbox for this kse to the uts
515                  * function as a parameter on the stack.
516                  */
517                 suword32((void *)(td->td_frame->tf_rsp + sizeof(int32_t)),
518                     (uint32_t)(uintptr_t)arg);
519
520                 return;
521         }
522 #endif
523
524         /*
525          * Set the trap frame to point at the beginning of the uts
526          * function.
527          */
528         td->td_frame->tf_rbp = 0;
529         td->td_frame->tf_rsp =
530             ((register_t)stack->ss_sp + stack->ss_size) & ~0x0f;
531         td->td_frame->tf_rsp -= 8;
532         td->td_frame->tf_rip = (register_t)entry;
533         td->td_frame->tf_ds = _udatasel;
534         td->td_frame->tf_es = _udatasel;
535         td->td_frame->tf_fs = _ufssel;
536         td->td_frame->tf_gs = _ugssel;
537         td->td_frame->tf_flags = TF_HASSEGS;
538
539         /*
540          * Pass the address of the mailbox for this kse to the uts
541          * function as a parameter on the stack.
542          */
543         td->td_frame->tf_rdi = (register_t)arg;
544 }
545
546 int
547 cpu_set_user_tls(struct thread *td, void *tls_base)
548 {
549         struct pcb *pcb;
550
551         if ((u_int64_t)tls_base >= VM_MAXUSER_ADDRESS)
552                 return (EINVAL);
553
554         pcb = td->td_pcb;
555         set_pcb_flags(pcb, PCB_FULL_IRET);
556 #ifdef COMPAT_FREEBSD32
557         if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
558                 pcb->pcb_gsbase = (register_t)tls_base;
559                 return (0);
560         }
561 #endif
562         pcb->pcb_fsbase = (register_t)tls_base;
563         return (0);
564 }
565
566 #ifdef SMP
567 static void
568 cpu_reset_proxy()
569 {
570         cpuset_t tcrp;
571
572         cpu_reset_proxy_active = 1;
573         while (cpu_reset_proxy_active == 1)
574                 ;       /* Wait for other cpu to see that we've started */
575         CPU_SETOF(cpu_reset_proxyid, &tcrp);
576         stop_cpus(tcrp);
577         printf("cpu_reset_proxy: Stopped CPU %d\n", cpu_reset_proxyid);
578         DELAY(1000000);
579         cpu_reset_real();
580 }
581 #endif
582
583 void
584 cpu_reset()
585 {
586 #ifdef SMP
587         cpuset_t map;
588         u_int cnt;
589
590         if (smp_active) {
591                 map = all_cpus;
592                 CPU_CLR(PCPU_GET(cpuid), &map);
593                 CPU_NAND(&map, &stopped_cpus);
594                 if (!CPU_EMPTY(&map)) {
595                         printf("cpu_reset: Stopping other CPUs\n");
596                         stop_cpus(map);
597                 }
598
599                 if (PCPU_GET(cpuid) != 0) {
600                         cpu_reset_proxyid = PCPU_GET(cpuid);
601                         cpustop_restartfunc = cpu_reset_proxy;
602                         cpu_reset_proxy_active = 0;
603                         printf("cpu_reset: Restarting BSP\n");
604
605                         /* Restart CPU #0. */
606                         CPU_SETOF(0, &started_cpus);
607                         wmb();
608
609                         cnt = 0;
610                         while (cpu_reset_proxy_active == 0 && cnt < 10000000)
611                                 cnt++;  /* Wait for BSP to announce restart */
612                         if (cpu_reset_proxy_active == 0)
613                                 printf("cpu_reset: Failed to restart BSP\n");
614                         enable_intr();
615                         cpu_reset_proxy_active = 2;
616
617                         while (1);
618                         /* NOTREACHED */
619                 }
620
621                 DELAY(1000000);
622         }
623 #endif
624         cpu_reset_real();
625         /* NOTREACHED */
626 }
627
628 static void
629 cpu_reset_real()
630 {
631         struct region_descriptor null_idt;
632         int b;
633
634         disable_intr();
635
636         /*
637          * Attempt to do a CPU reset via the keyboard controller,
638          * do not turn off GateA20, as any machine that fails
639          * to do the reset here would then end up in no man's land.
640          */
641         outb(IO_KBD + 4, 0xFE);
642         DELAY(500000);  /* wait 0.5 sec to see if that did it */
643
644         /*
645          * Attempt to force a reset via the Reset Control register at
646          * I/O port 0xcf9.  Bit 2 forces a system reset when it
647          * transitions from 0 to 1.  Bit 1 selects the type of reset
648          * to attempt: 0 selects a "soft" reset, and 1 selects a
649          * "hard" reset.  We try a "hard" reset.  The first write sets
650          * bit 1 to select a "hard" reset and clears bit 2.  The
651          * second write forces a 0 -> 1 transition in bit 2 to trigger
652          * a reset.
653          */
654         outb(0xcf9, 0x2);
655         outb(0xcf9, 0x6);
656         DELAY(500000);  /* wait 0.5 sec to see if that did it */
657
658         /*
659          * Attempt to force a reset via the Fast A20 and Init register
660          * at I/O port 0x92.  Bit 1 serves as an alternate A20 gate.
661          * Bit 0 asserts INIT# when set to 1.  We are careful to only
662          * preserve bit 1 while setting bit 0.  We also must clear bit
663          * 0 before setting it if it isn't already clear.
664          */
665         b = inb(0x92);
666         if (b != 0xff) {
667                 if ((b & 0x1) != 0)
668                         outb(0x92, b & 0xfe);
669                 outb(0x92, b | 0x1);
670                 DELAY(500000);  /* wait 0.5 sec to see if that did it */
671         }
672
673         printf("No known reset method worked, attempting CPU shutdown\n");
674         DELAY(1000000); /* wait 1 sec for printf to complete */
675
676         /* Wipe the IDT. */
677         null_idt.rd_limit = 0;
678         null_idt.rd_base = 0;
679         lidt(&null_idt);
680
681         /* "good night, sweet prince .... <THUNK!>" */
682         breakpoint();
683
684         /* NOTREACHED */
685         while(1);
686 }
687
688 /*
689  * Allocate an sf_buf for the given vm_page.  On this machine, however, there
690  * is no sf_buf object.  Instead, an opaque pointer to the given vm_page is
691  * returned.
692  */
693 struct sf_buf *
694 sf_buf_alloc(struct vm_page *m, int pri)
695 {
696
697         return ((struct sf_buf *)m);
698 }
699
700 /*
701  * Free the sf_buf.  In fact, do nothing because there are no resources
702  * associated with the sf_buf.
703  */
704 void
705 sf_buf_free(struct sf_buf *sf)
706 {
707 }
708
709 /*
710  * Software interrupt handler for queued VM system processing.
711  */   
712 void  
713 swi_vm(void *dummy) 
714 {     
715         if (busdma_swi_pending != 0)
716                 busdma_swi();
717 }
718
719 /*
720  * Tell whether this address is in some physical memory region.
721  * Currently used by the kernel coredump code in order to avoid
722  * dumping the ``ISA memory hole'' which could cause indefinite hangs,
723  * or other unpredictable behaviour.
724  */
725
726 int
727 is_physical_memory(vm_paddr_t addr)
728 {
729
730 #ifdef DEV_ISA
731         /* The ISA ``memory hole''. */
732         if (addr >= 0xa0000 && addr < 0x100000)
733                 return 0;
734 #endif
735
736         /*
737          * stuff other tests for known memory-mapped devices (PCI?)
738          * here
739          */
740
741         return 1;
742 }