machdep.c revision 37099
1/*- 2 * Copyright (c) 1992 Terrence R. Lambert. 3 * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * William Jolitz. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 38 * $Id: machdep.c,v 1.300 1998/06/17 14:57:55 bde Exp $ 39 */ 40 41#include "apm.h" 42#include "ether.h" 43#include "npx.h" 44#include "opt_atalk.h" 45#include "opt_bounce.h" 46#include "opt_cpu.h" 47#include "opt_ddb.h" 48#include "opt_inet.h" 49#include "opt_ipx.h" 50#include "opt_maxmem.h" 51#include "opt_msgbuf.h" 52#include "opt_perfmon.h" 53#include "opt_smp.h" 54#include "opt_sysvipc.h" 55#include "opt_user_ldt.h" 56#include "opt_userconfig.h" 57#include "opt_vm86.h" 58 59#include <sys/param.h> 60#include <sys/systm.h> 61#include <sys/sysproto.h> 62#include <sys/signalvar.h> 63#include <sys/kernel.h> 64#include <sys/proc.h> 65#include <sys/buf.h> 66#include <sys/reboot.h> 67#include <sys/callout.h> 68#include <sys/malloc.h> 69#include <sys/mbuf.h> 70#include <sys/msgbuf.h> 71#include <sys/sysent.h> 72#include <sys/sysctl.h> 73#include <sys/vmmeter.h> 74 75#ifdef SYSVSHM 76#include <sys/shm.h> 77#endif 78 79#ifdef SYSVMSG 80#include <sys/msg.h> 81#endif 82 83#ifdef SYSVSEM 84#include <sys/sem.h> 85#endif 86 87#include <vm/vm.h> 88#include <vm/vm_param.h> 89#include <vm/vm_prot.h> 90#include <sys/lock.h> 91#include <vm/vm_kern.h> 92#include <vm/vm_object.h> 93#include <vm/vm_page.h> 94#include <vm/vm_map.h> 95#include <vm/vm_pager.h> 96#include <vm/vm_extern.h> 97 98#include <sys/user.h> 99#include <sys/exec.h> 100 101#include <ddb/ddb.h> 102 103#if defined(INET) || defined(IPX) || defined(NATM) || defined(NETATALK) \ 104 || NETHER > 0 || defined(NS) 105#define NETISR 106#endif 107 108#ifdef NETISR 109#include <net/netisr.h> 110#endif 111 112#if NAPM > 0 113#include <machine/apm_bios.h> 114#endif 115#include <machine/cpu.h> 116#include <machine/reg.h> 117#include <machine/clock.h> 118#include <machine/specialreg.h> 119#include <machine/cons.h> 120#include <machine/bootinfo.h> 121#include <machine/ipl.h> 122#include <machine/md_var.h> 123#include <machine/pcb_ext.h> /* pcb.h included via sys/user.h */ 124#ifdef SMP 125#include <machine/smp.h> 126#endif 127#ifdef PERFMON 128#include <machine/perfmon.h> 129#endif 130 131#include <i386/isa/isa_device.h> 132#include <i386/isa/intr_machdep.h> 133#ifndef VM86 134#include <i386/isa/rtc.h> 135#endif 136#include <machine/random.h> 137#include <sys/ptrace.h> 138 139extern void init386 __P((int first)); 140extern void dblfault_handler __P((void)); 141 142extern void printcpuinfo(void); /* XXX header file */ 143extern void earlysetcpuclass(void); /* same header file */ 144extern void finishidentcpu(void); 145extern void panicifcpuunsupported(void); 146extern void initializecpu(void); 147 148static void cpu_startup __P((void *)); 149SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL) 150 151static MALLOC_DEFINE(M_MBUF, "mbuf", "mbuf"); 152 153#ifdef BOUNCE_BUFFERS 154#ifdef BOUNCEPAGES 155int bouncepages = BOUNCEPAGES; 156#else 157int bouncepages = 0; 158#endif 159#endif /* BOUNCE_BUFFERS */ 160 161int _udatasel, _ucodesel; 162u_int atdevbase; 163 164#if defined(SWTCH_OPTIM_STATS) 165extern int swtch_optim_stats; 166SYSCTL_INT(_debug, OID_AUTO, swtch_optim_stats, 167 CTLFLAG_RD, &swtch_optim_stats, 0, ""); 168SYSCTL_INT(_debug, OID_AUTO, tlb_flush_count, 169 CTLFLAG_RD, &tlb_flush_count, 0, ""); 170#endif 171 172 173int physmem = 0; 174int cold = 1; 175 176static int 177sysctl_hw_physmem SYSCTL_HANDLER_ARGS 178{ 179 int error = sysctl_handle_int(oidp, 0, ctob(physmem), req); 180 return (error); 181} 182 183SYSCTL_PROC(_hw, HW_PHYSMEM, physmem, CTLTYPE_INT|CTLFLAG_RD, 184 0, 0, sysctl_hw_physmem, "I", ""); 185 186static int 187sysctl_hw_usermem SYSCTL_HANDLER_ARGS 188{ 189 int error = sysctl_handle_int(oidp, 0, 190 ctob(physmem - cnt.v_wire_count), req); 191 return (error); 192} 193 194SYSCTL_PROC(_hw, HW_USERMEM, usermem, CTLTYPE_INT|CTLFLAG_RD, 195 0, 0, sysctl_hw_usermem, "I", ""); 196 197int bootverbose = 0, Maxmem = 0; 198long dumplo; 199 200vm_offset_t phys_avail[10]; 201 202/* must be 2 less so 0 0 can signal end of chunks */ 203#define PHYS_AVAIL_ARRAY_END ((sizeof(phys_avail) / sizeof(vm_offset_t)) - 2) 204 205#ifdef NETISR 206static void setup_netisrs __P((struct linker_set *)); 207#endif 208 209static vm_offset_t buffer_sva, buffer_eva; 210vm_offset_t clean_sva, clean_eva; 211static vm_offset_t pager_sva, pager_eva; 212#ifdef NETISR 213extern struct linker_set netisr_set; 214#endif 215#if NNPX > 0 216extern struct isa_driver npxdriver; 217#endif 218 219#define offsetof(type, member) ((size_t)(&((type *)0)->member)) 220 221static void 222cpu_startup(dummy) 223 void *dummy; 224{ 225 register unsigned i; 226 register caddr_t v; 227 vm_offset_t maxaddr; 228 vm_size_t size = 0; 229 int firstaddr; 230 vm_offset_t minaddr; 231 232 if (boothowto & RB_VERBOSE) 233 bootverbose++; 234 235 /* 236 * Good {morning,afternoon,evening,night}. 237 */ 238 printf(version); 239 earlysetcpuclass(); 240 startrtclock(); 241 printcpuinfo(); 242 panicifcpuunsupported(); 243#ifdef PERFMON 244 perfmon_init(); 245#endif 246 printf("real memory = %d (%dK bytes)\n", ptoa(Maxmem), ptoa(Maxmem) / 1024); 247 /* 248 * Display any holes after the first chunk of extended memory. 249 */ 250 if (bootverbose) { 251 int indx; 252 253 printf("Physical memory chunk(s):\n"); 254 for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) { 255 int size1 = phys_avail[indx + 1] - phys_avail[indx]; 256 257 printf("0x%08lx - 0x%08lx, %d bytes (%d pages)\n", phys_avail[indx], 258 phys_avail[indx + 1] - 1, size1, size1 / PAGE_SIZE); 259 } 260 } 261 262#ifdef NETISR 263 /* 264 * Quickly wire in netisrs. 265 */ 266 setup_netisrs(&netisr_set); 267#endif 268 269 /* 270 * Calculate callout wheel size 271 */ 272 for (callwheelsize = 1, callwheelbits = 0; 273 callwheelsize < ncallout; 274 callwheelsize <<= 1, ++callwheelbits) 275 ; 276 callwheelmask = callwheelsize - 1; 277 278 /* 279 * Allocate space for system data structures. 280 * The first available kernel virtual address is in "v". 281 * As pages of kernel virtual memory are allocated, "v" is incremented. 282 * As pages of memory are allocated and cleared, 283 * "firstaddr" is incremented. 284 * An index into the kernel page table corresponding to the 285 * virtual memory address maintained in "v" is kept in "mapaddr". 286 */ 287 288 /* 289 * Make two passes. The first pass calculates how much memory is 290 * needed and allocates it. The second pass assigns virtual 291 * addresses to the various data structures. 292 */ 293 firstaddr = 0; 294again: 295 v = (caddr_t)firstaddr; 296 297#define valloc(name, type, num) \ 298 (name) = (type *)v; v = (caddr_t)((name)+(num)) 299#define valloclim(name, type, num, lim) \ 300 (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num))) 301 302#ifdef BOUNCE_BUFFERS 303 /* 304 * If there is more than 16MB of memory, allocate some bounce buffers 305 */ 306 if (Maxmem > 4096) { 307 if (bouncepages == 0) { 308 bouncepages = 64; 309 } 310 v = (caddr_t)((vm_offset_t)round_page(v)); 311 valloc(bouncememory, char, bouncepages * PAGE_SIZE); 312 } 313#endif 314 315 valloc(callout, struct callout, ncallout); 316 valloc(callwheel, struct callout_tailq, callwheelsize); 317#ifdef SYSVSHM 318 valloc(shmsegs, struct shmid_ds, shminfo.shmmni); 319#endif 320#ifdef SYSVSEM 321 valloc(sema, struct semid_ds, seminfo.semmni); 322 valloc(sem, struct sem, seminfo.semmns); 323 /* This is pretty disgusting! */ 324 valloc(semu, int, (seminfo.semmnu * seminfo.semusz) / sizeof(int)); 325#endif 326#ifdef SYSVMSG 327 valloc(msgpool, char, msginfo.msgmax); 328 valloc(msgmaps, struct msgmap, msginfo.msgseg); 329 valloc(msghdrs, struct msg, msginfo.msgtql); 330 valloc(msqids, struct msqid_ds, msginfo.msgmni); 331#endif 332 333 if (nbuf == 0) { 334 nbuf = 30; 335 if( physmem > 1024) 336 nbuf += min((physmem - 1024) / 8, 2048); 337 } 338 nswbuf = max(min(nbuf/4, 64), 16); 339 340 valloc(swbuf, struct buf, nswbuf); 341 valloc(buf, struct buf, nbuf); 342 343 344 /* 345 * End of first pass, size has been calculated so allocate memory 346 */ 347 if (firstaddr == 0) { 348 size = (vm_size_t)(v - firstaddr); 349 firstaddr = (int)kmem_alloc(kernel_map, round_page(size)); 350 if (firstaddr == 0) 351 panic("startup: no room for tables"); 352 goto again; 353 } 354 355 /* 356 * End of second pass, addresses have been assigned 357 */ 358 if ((vm_size_t)(v - firstaddr) != size) 359 panic("startup: table size inconsistency"); 360 361#ifdef BOUNCE_BUFFERS 362 clean_map = kmem_suballoc(kernel_map, &clean_sva, &clean_eva, 363 (nbuf*BKVASIZE) + (nswbuf*MAXPHYS) + 364 maxbkva + pager_map_size); 365 io_map = kmem_suballoc(clean_map, &minaddr, &maxaddr, maxbkva); 366#else 367 clean_map = kmem_suballoc(kernel_map, &clean_sva, &clean_eva, 368 (nbuf*BKVASIZE) + (nswbuf*MAXPHYS) + pager_map_size); 369#endif 370 buffer_map = kmem_suballoc(clean_map, &buffer_sva, &buffer_eva, 371 (nbuf*BKVASIZE)); 372 pager_map = kmem_suballoc(clean_map, &pager_sva, &pager_eva, 373 (nswbuf*MAXPHYS) + pager_map_size); 374 pager_map->system_map = 1; 375 exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr, 376 (16*(ARG_MAX+(PAGE_SIZE*3)))); 377 378 /* 379 * Finally, allocate mbuf pool. Since mclrefcnt is an off-size 380 * we use the more space efficient malloc in place of kmem_alloc. 381 */ 382 { 383 vm_offset_t mb_map_size; 384 385 mb_map_size = nmbufs * MSIZE + nmbclusters * MCLBYTES; 386 mb_map_size = roundup2(mb_map_size, max(MCLBYTES, PAGE_SIZE)); 387 mclrefcnt = malloc(mb_map_size / MCLBYTES, M_MBUF, M_NOWAIT); 388 bzero(mclrefcnt, mb_map_size / MCLBYTES); 389 mb_map = kmem_suballoc(kmem_map, (vm_offset_t *)&mbutl, &maxaddr, 390 mb_map_size); 391 mb_map->system_map = 1; 392 } 393 394 /* 395 * Initialize callouts 396 */ 397 SLIST_INIT(&callfree); 398 for (i = 0; i < ncallout; i++) { 399 SLIST_INSERT_HEAD(&callfree, &callout[i], c_links.sle); 400 } 401 402 for (i = 0; i < callwheelsize; i++) { 403 TAILQ_INIT(&callwheel[i]); 404 } 405 406#if defined(USERCONFIG) 407#if defined(USERCONFIG_BOOT) 408 if (1) { 409#else 410 if (boothowto & RB_CONFIG) { 411#endif 412 userconfig(); 413 cninit(); /* the preferred console may have changed */ 414 } 415#endif 416 417#ifdef BOUNCE_BUFFERS 418 /* 419 * init bounce buffers 420 */ 421 vm_bounce_init(); 422#endif 423 424 printf("avail memory = %d (%dK bytes)\n", ptoa(cnt.v_free_count), 425 ptoa(cnt.v_free_count) / 1024); 426 427 /* 428 * Set up buffers, so they can be used to read disk labels. 429 */ 430 bufinit(); 431 vm_pager_bufferinit(); 432 433#ifdef SMP 434 /* 435 * OK, enough kmem_alloc/malloc state should be up, lets get on with it! 436 */ 437 mp_start(); /* fire up the APs and APICs */ 438 mp_announce(); 439#endif /* SMP */ 440} 441 442#ifdef NETISR 443int 444register_netisr(num, handler) 445 int num; 446 netisr_t *handler; 447{ 448 449 if (num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs)) ) { 450 printf("register_netisr: bad isr number: %d\n", num); 451 return (EINVAL); 452 } 453 netisrs[num] = handler; 454 return (0); 455} 456 457static void 458setup_netisrs(ls) 459 struct linker_set *ls; 460{ 461 int i; 462 const struct netisrtab *nit; 463 464 for(i = 0; ls->ls_items[i]; i++) { 465 nit = (const struct netisrtab *)ls->ls_items[i]; 466 register_netisr(nit->nit_num, nit->nit_isr); 467 } 468} 469#endif /* NETISR */ 470 471/* 472 * Send an interrupt to process. 473 * 474 * Stack is set up to allow sigcode stored 475 * at top to call routine, followed by kcall 476 * to sigreturn routine below. After sigreturn 477 * resets the signal mask, the stack, and the 478 * frame pointer, it returns to the user 479 * specified pc, psl. 480 */ 481void 482sendsig(catcher, sig, mask, code) 483 sig_t catcher; 484 int sig, mask; 485 u_long code; 486{ 487 register struct proc *p = curproc; 488 register struct trapframe *regs; 489 register struct sigframe *fp; 490 struct sigframe sf; 491 struct sigacts *psp = p->p_sigacts; 492 int oonstack; 493 494 regs = p->p_md.md_regs; 495 oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; 496 /* 497 * Allocate and validate space for the signal handler context. 498 */ 499 if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack && 500 (psp->ps_sigonstack & sigmask(sig))) { 501 fp = (struct sigframe *)(psp->ps_sigstk.ss_sp + 502 psp->ps_sigstk.ss_size - sizeof(struct sigframe)); 503 psp->ps_sigstk.ss_flags |= SS_ONSTACK; 504 } else { 505 fp = (struct sigframe *)regs->tf_esp - 1; 506 } 507 508 /* 509 * grow() will return FALSE if the fp will not fit inside the stack 510 * and the stack can not be grown. useracc will return FALSE 511 * if access is denied. 512 */ 513 if ((grow(p, (int)fp) == FALSE) || 514 (useracc((caddr_t)fp, sizeof(struct sigframe), B_WRITE) == FALSE)) { 515 /* 516 * Process has trashed its stack; give it an illegal 517 * instruction to halt it in its tracks. 518 */ 519 SIGACTION(p, SIGILL) = SIG_DFL; 520 sig = sigmask(SIGILL); 521 p->p_sigignore &= ~sig; 522 p->p_sigcatch &= ~sig; 523 p->p_sigmask &= ~sig; 524 psignal(p, SIGILL); 525 return; 526 } 527 528 /* 529 * Build the argument list for the signal handler. 530 */ 531 if (p->p_sysent->sv_sigtbl) { 532 if (sig < p->p_sysent->sv_sigsize) 533 sig = p->p_sysent->sv_sigtbl[sig]; 534 else 535 sig = p->p_sysent->sv_sigsize + 1; 536 } 537 sf.sf_signum = sig; 538 sf.sf_code = code; 539 sf.sf_scp = &fp->sf_sc; 540 sf.sf_addr = (char *) regs->tf_err; 541 sf.sf_handler = catcher; 542 543 /* save scratch registers */ 544 sf.sf_sc.sc_eax = regs->tf_eax; 545 sf.sf_sc.sc_ebx = regs->tf_ebx; 546 sf.sf_sc.sc_ecx = regs->tf_ecx; 547 sf.sf_sc.sc_edx = regs->tf_edx; 548 sf.sf_sc.sc_esi = regs->tf_esi; 549 sf.sf_sc.sc_edi = regs->tf_edi; 550 sf.sf_sc.sc_cs = regs->tf_cs; 551 sf.sf_sc.sc_ds = regs->tf_ds; 552 sf.sf_sc.sc_ss = regs->tf_ss; 553 sf.sf_sc.sc_es = regs->tf_es; 554 sf.sf_sc.sc_isp = regs->tf_isp; 555 556 /* 557 * Build the signal context to be used by sigreturn. 558 */ 559 sf.sf_sc.sc_onstack = oonstack; 560 sf.sf_sc.sc_mask = mask; 561 sf.sf_sc.sc_sp = regs->tf_esp; 562 sf.sf_sc.sc_fp = regs->tf_ebp; 563 sf.sf_sc.sc_pc = regs->tf_eip; 564 sf.sf_sc.sc_ps = regs->tf_eflags; 565 sf.sf_sc.sc_trapno = regs->tf_trapno; 566 sf.sf_sc.sc_err = regs->tf_err; 567 568#ifdef VM86 569 /* 570 * If we're a vm86 process, we want to save the segment registers. 571 * We also change eflags to be our emulated eflags, not the actual 572 * eflags. 573 */ 574 if (regs->tf_eflags & PSL_VM) { 575 struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; 576 struct vm86_kernel *vm86 = &p->p_addr->u_pcb.pcb_ext->ext_vm86; 577 578 sf.sf_sc.sc_gs = tf->tf_vm86_gs; 579 sf.sf_sc.sc_fs = tf->tf_vm86_fs; 580 sf.sf_sc.sc_es = tf->tf_vm86_es; 581 sf.sf_sc.sc_ds = tf->tf_vm86_ds; 582 583 if (vm86->vm86_has_vme == 0) 584 sf.sf_sc.sc_ps = (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) 585 | (vm86->vm86_eflags & (PSL_VIF | PSL_VIP)); 586 587 /* 588 * We should never have PSL_T set when returning from vm86 589 * mode. It may be set here if we deliver a signal before 590 * getting to vm86 mode, so turn it off. 591 */ 592 tf->tf_eflags &= ~(PSL_VM | PSL_T | PSL_VIF | PSL_VIP); 593 } 594#endif /* VM86 */ 595 596 /* 597 * Copy the sigframe out to the user's stack. 598 */ 599 if (copyout(&sf, fp, sizeof(struct sigframe)) != 0) { 600 /* 601 * Something is wrong with the stack pointer. 602 * ...Kill the process. 603 */ 604 sigexit(p, SIGILL); 605 } 606 607 regs->tf_esp = (int)fp; 608 regs->tf_eip = (int)(((char *)PS_STRINGS) - *(p->p_sysent->sv_szsigcode)); 609 regs->tf_cs = _ucodesel; 610 regs->tf_ds = _udatasel; 611 regs->tf_es = _udatasel; 612 regs->tf_ss = _udatasel; 613} 614 615/* 616 * System call to cleanup state after a signal 617 * has been taken. Reset signal mask and 618 * stack state from context left by sendsig (above). 619 * Return to previous pc and psl as specified by 620 * context left by sendsig. Check carefully to 621 * make sure that the user has not modified the 622 * state to gain improper privileges. 623 */ 624int 625sigreturn(p, uap) 626 struct proc *p; 627 struct sigreturn_args /* { 628 struct sigcontext *sigcntxp; 629 } */ *uap; 630{ 631 register struct sigcontext *scp; 632 register struct sigframe *fp; 633 register struct trapframe *regs = p->p_md.md_regs; 634 int eflags; 635 636 /* 637 * (XXX old comment) regs->tf_esp points to the return address. 638 * The user scp pointer is above that. 639 * The return address is faked in the signal trampoline code 640 * for consistency. 641 */ 642 scp = uap->sigcntxp; 643 fp = (struct sigframe *) 644 ((caddr_t)scp - offsetof(struct sigframe, sf_sc)); 645 646 if (useracc((caddr_t)fp, sizeof (*fp), B_WRITE) == 0) 647 return(EFAULT); 648 649 eflags = scp->sc_ps; 650#ifdef VM86 651 if (eflags & PSL_VM) { 652 struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; 653 struct vm86_kernel *vm86; 654 655 /* 656 * if pcb_ext == 0 or vm86_inited == 0, the user hasn't 657 * set up the vm86 area, and we can't enter vm86 mode. 658 */ 659 if (p->p_addr->u_pcb.pcb_ext == 0) 660 return (EINVAL); 661 vm86 = &p->p_addr->u_pcb.pcb_ext->ext_vm86; 662 if (vm86->vm86_inited == 0) 663 return (EINVAL); 664 665 /* go back to user mode if both flags are set */ 666 if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) 667 trapsignal(p, SIGBUS, 0); 668 669 if (vm86->vm86_has_vme) { 670 eflags = (tf->tf_eflags & ~VME_USERCHANGE) | 671 (eflags & VME_USERCHANGE) | PSL_VM; 672 } else { 673 vm86->vm86_eflags = eflags; /* save VIF, VIP */ 674 eflags = (tf->tf_eflags & ~VM_USERCHANGE) | (eflags & VM_USERCHANGE) | PSL_VM; 675 } 676 tf->tf_vm86_ds = scp->sc_ds; 677 tf->tf_vm86_es = scp->sc_es; 678 tf->tf_vm86_fs = scp->sc_fs; 679 tf->tf_vm86_gs = scp->sc_gs; 680 tf->tf_ds = _udatasel; 681 tf->tf_es = _udatasel; 682 } else { 683#endif /* VM86 */ 684 /* 685 * Don't allow users to change privileged or reserved flags. 686 */ 687#define EFLAGS_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) 688 /* 689 * XXX do allow users to change the privileged flag PSL_RF. 690 * The cpu sets PSL_RF in tf_eflags for faults. Debuggers 691 * should sometimes set it there too. tf_eflags is kept in 692 * the signal context during signal handling and there is no 693 * other place to remember it, so the PSL_RF bit may be 694 * corrupted by the signal handler without us knowing. 695 * Corruption of the PSL_RF bit at worst causes one more or 696 * one less debugger trap, so allowing it is fairly harmless. 697 */ 698 if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) { 699#ifdef DEBUG 700 printf("sigreturn: eflags = 0x%x\n", eflags); 701#endif 702 return(EINVAL); 703 } 704 705 /* 706 * Don't allow users to load a valid privileged %cs. Let the 707 * hardware check for invalid selectors, excess privilege in 708 * other selectors, invalid %eip's and invalid %esp's. 709 */ 710#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) 711 if (!CS_SECURE(scp->sc_cs)) { 712#ifdef DEBUG 713 printf("sigreturn: cs = 0x%x\n", scp->sc_cs); 714#endif 715 trapsignal(p, SIGBUS, T_PROTFLT); 716 return(EINVAL); 717 } 718 regs->tf_ds = scp->sc_ds; 719 regs->tf_es = scp->sc_es; 720#ifdef VM86 721 } 722#endif 723 724 /* restore scratch registers */ 725 regs->tf_eax = scp->sc_eax; 726 regs->tf_ebx = scp->sc_ebx; 727 regs->tf_ecx = scp->sc_ecx; 728 regs->tf_edx = scp->sc_edx; 729 regs->tf_esi = scp->sc_esi; 730 regs->tf_edi = scp->sc_edi; 731 regs->tf_cs = scp->sc_cs; 732 regs->tf_ss = scp->sc_ss; 733 regs->tf_isp = scp->sc_isp; 734 735 if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0) 736 return(EINVAL); 737 738 if (scp->sc_onstack & 01) 739 p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK; 740 else 741 p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; 742 p->p_sigmask = scp->sc_mask & ~sigcantmask; 743 regs->tf_ebp = scp->sc_fp; 744 regs->tf_esp = scp->sc_sp; 745 regs->tf_eip = scp->sc_pc; 746 regs->tf_eflags = eflags; 747 return(EJUSTRETURN); 748} 749 750/* 751 * Machine dependent boot() routine 752 * 753 * I haven't seen anything to put here yet 754 * Possibly some stuff might be grafted back here from boot() 755 */ 756void 757cpu_boot(int howto) 758{ 759} 760 761/* 762 * Shutdown the CPU as much as possible 763 */ 764void 765cpu_halt(void) 766{ 767 for (;;) 768 __asm__ ("hlt"); 769} 770 771/* 772 * Turn the power off. 773 */ 774void 775cpu_power_down(void) 776{ 777#if NAPM > 0 778 apm_power_off(); 779#endif 780} 781 782/* 783 * Clear registers on exec 784 */ 785void 786setregs(p, entry, stack) 787 struct proc *p; 788 u_long entry; 789 u_long stack; 790{ 791 struct trapframe *regs = p->p_md.md_regs; 792 793#ifdef USER_LDT 794 struct pcb *pcb = &p->p_addr->u_pcb; 795 796 /* was i386_user_cleanup() in NetBSD */ 797 if (pcb->pcb_ldt) { 798 if (pcb == curpcb) 799 lldt(GSEL(GUSERLDT_SEL, SEL_KPL)); 800 kmem_free(kernel_map, (vm_offset_t)pcb->pcb_ldt, 801 pcb->pcb_ldt_len * sizeof(union descriptor)); 802 pcb->pcb_ldt_len = (int)pcb->pcb_ldt = 0; 803 } 804#endif 805 806 bzero((char *)regs, sizeof(struct trapframe)); 807 regs->tf_eip = entry; 808 regs->tf_esp = stack; 809 regs->tf_eflags = PSL_USER | (regs->tf_eflags & PSL_T); 810 regs->tf_ss = _udatasel; 811 regs->tf_ds = _udatasel; 812 regs->tf_es = _udatasel; 813 regs->tf_cs = _ucodesel; 814 815 /* 816 * Initialize the math emulator (if any) for the current process. 817 * Actually, just clear the bit that says that the emulator has 818 * been initialized. Initialization is delayed until the process 819 * traps to the emulator (if it is done at all) mainly because 820 * emulators don't provide an entry point for initialization. 821 */ 822 p->p_addr->u_pcb.pcb_flags &= ~FP_SOFTFP; 823 824 /* 825 * Arrange to trap the next npx or `fwait' instruction (see npx.c 826 * for why fwait must be trapped at least if there is an npx or an 827 * emulator). This is mainly to handle the case where npx0 is not 828 * configured, since the npx routines normally set up the trap 829 * otherwise. It should be done only at boot time, but doing it 830 * here allows modifying `npx_exists' for testing the emulator on 831 * systems with an npx. 832 */ 833 load_cr0(rcr0() | CR0_MP | CR0_TS); 834 835#if NNPX > 0 836 /* Initialize the npx (if any) for the current process. */ 837 npxinit(__INITIAL_NPXCW__); 838#endif 839} 840 841static int 842sysctl_machdep_adjkerntz SYSCTL_HANDLER_ARGS 843{ 844 int error; 845 error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, 846 req); 847 if (!error && req->newptr) 848 resettodr(); 849 return (error); 850} 851 852SYSCTL_PROC(_machdep, CPU_ADJKERNTZ, adjkerntz, CTLTYPE_INT|CTLFLAG_RW, 853 &adjkerntz, 0, sysctl_machdep_adjkerntz, "I", ""); 854 855SYSCTL_INT(_machdep, CPU_DISRTCSET, disable_rtc_set, 856 CTLFLAG_RW, &disable_rtc_set, 0, ""); 857 858SYSCTL_STRUCT(_machdep, CPU_BOOTINFO, bootinfo, 859 CTLFLAG_RD, &bootinfo, bootinfo, ""); 860 861SYSCTL_INT(_machdep, CPU_WALLCLOCK, wall_cmos_clock, 862 CTLFLAG_RW, &wall_cmos_clock, 0, ""); 863 864/* 865 * Initialize 386 and configure to run kernel 866 */ 867 868/* 869 * Initialize segments & interrupt table 870 */ 871 872int currentldt; 873int _default_ldt; 874#ifdef SMP 875union descriptor gdt[NGDT + NCPU]; /* global descriptor table */ 876#else 877union descriptor gdt[NGDT]; /* global descriptor table */ 878#endif 879struct gate_descriptor idt[NIDT]; /* interrupt descriptor table */ 880union descriptor ldt[NLDT]; /* local descriptor table */ 881#ifdef SMP 882/* table descriptors - used to load tables by microp */ 883struct region_descriptor r_gdt, r_idt; 884#endif 885 886extern struct i386tss common_tss; /* One tss per cpu */ 887#ifdef VM86 888extern struct segment_descriptor common_tssd; 889extern int private_tss; /* flag indicating private tss */ 890extern u_int my_tr; /* which task register setting */ 891#endif /* VM86 */ 892 893#if defined(I586_CPU) && !defined(NO_F00F_HACK) 894struct gate_descriptor *t_idt; 895extern int has_f00f_bug; 896#endif 897 898static struct i386tss dblfault_tss; 899static char dblfault_stack[PAGE_SIZE]; 900 901extern struct user *proc0paddr; 902 903 904/* software prototypes -- in more palatable form */ 905struct soft_segment_descriptor gdt_segs[ 906#ifdef SMP 907 NGDT + NCPU 908#endif 909 ] = { 910/* GNULL_SEL 0 Null Descriptor */ 911{ 0x0, /* segment base address */ 912 0x0, /* length */ 913 0, /* segment type */ 914 0, /* segment descriptor priority level */ 915 0, /* segment descriptor present */ 916 0, 0, 917 0, /* default 32 vs 16 bit size */ 918 0 /* limit granularity (byte/page units)*/ }, 919/* GCODE_SEL 1 Code Descriptor for kernel */ 920{ 0x0, /* segment base address */ 921 0xfffff, /* length - all address space */ 922 SDT_MEMERA, /* segment type */ 923 0, /* segment descriptor priority level */ 924 1, /* segment descriptor present */ 925 0, 0, 926 1, /* default 32 vs 16 bit size */ 927 1 /* limit granularity (byte/page units)*/ }, 928/* GDATA_SEL 2 Data Descriptor for kernel */ 929{ 0x0, /* segment base address */ 930 0xfffff, /* length - all address space */ 931 SDT_MEMRWA, /* segment type */ 932 0, /* segment descriptor priority level */ 933 1, /* segment descriptor present */ 934 0, 0, 935 1, /* default 32 vs 16 bit size */ 936 1 /* limit granularity (byte/page units)*/ }, 937/* GLDT_SEL 3 LDT Descriptor */ 938{ (int) ldt, /* segment base address */ 939 sizeof(ldt)-1, /* length - all address space */ 940 SDT_SYSLDT, /* segment type */ 941 SEL_UPL, /* segment descriptor priority level */ 942 1, /* segment descriptor present */ 943 0, 0, 944 0, /* unused - default 32 vs 16 bit size */ 945 0 /* limit granularity (byte/page units)*/ }, 946/* GTGATE_SEL 4 Null Descriptor - Placeholder */ 947{ 0x0, /* segment base address */ 948 0x0, /* length - all address space */ 949 0, /* segment type */ 950 0, /* segment descriptor priority level */ 951 0, /* segment descriptor present */ 952 0, 0, 953 0, /* default 32 vs 16 bit size */ 954 0 /* limit granularity (byte/page units)*/ }, 955/* GPANIC_SEL 5 Panic Tss Descriptor */ 956{ (int) &dblfault_tss, /* segment base address */ 957 sizeof(struct i386tss)-1,/* length - all address space */ 958 SDT_SYS386TSS, /* segment type */ 959 0, /* segment descriptor priority level */ 960 1, /* segment descriptor present */ 961 0, 0, 962 0, /* unused - default 32 vs 16 bit size */ 963 0 /* limit granularity (byte/page units)*/ }, 964/* GPROC0_SEL 6 Proc 0 Tss Descriptor */ 965{ 966 (int) &common_tss, /* segment base address */ 967 sizeof(struct i386tss)-1,/* length - all address space */ 968 SDT_SYS386TSS, /* segment type */ 969 0, /* segment descriptor priority level */ 970 1, /* segment descriptor present */ 971 0, 0, 972 0, /* unused - default 32 vs 16 bit size */ 973 0 /* limit granularity (byte/page units)*/ }, 974/* GUSERLDT_SEL 7 User LDT Descriptor per process */ 975{ (int) ldt, /* segment base address */ 976 (512 * sizeof(union descriptor)-1), /* length */ 977 SDT_SYSLDT, /* segment type */ 978 0, /* segment descriptor priority level */ 979 1, /* segment descriptor present */ 980 0, 0, 981 0, /* unused - default 32 vs 16 bit size */ 982 0 /* limit granularity (byte/page units)*/ }, 983/* GAPMCODE32_SEL 8 APM BIOS 32-bit interface (32bit Code) */ 984{ 0, /* segment base address (overwritten by APM) */ 985 0xfffff, /* length */ 986 SDT_MEMERA, /* segment type */ 987 0, /* segment descriptor priority level */ 988 1, /* segment descriptor present */ 989 0, 0, 990 1, /* default 32 vs 16 bit size */ 991 1 /* limit granularity (byte/page units)*/ }, 992/* GAPMCODE16_SEL 9 APM BIOS 32-bit interface (16bit Code) */ 993{ 0, /* segment base address (overwritten by APM) */ 994 0xfffff, /* length */ 995 SDT_MEMERA, /* segment type */ 996 0, /* segment descriptor priority level */ 997 1, /* segment descriptor present */ 998 0, 0, 999 0, /* default 32 vs 16 bit size */ 1000 1 /* limit granularity (byte/page units)*/ }, 1001/* GAPMDATA_SEL 10 APM BIOS 32-bit interface (Data) */ 1002{ 0, /* segment base address (overwritten by APM) */ 1003 0xfffff, /* length */ 1004 SDT_MEMRWA, /* segment type */ 1005 0, /* segment descriptor priority level */ 1006 1, /* segment descriptor present */ 1007 0, 0, 1008 1, /* default 32 vs 16 bit size */ 1009 1 /* limit granularity (byte/page units)*/ }, 1010}; 1011 1012static struct soft_segment_descriptor ldt_segs[] = { 1013 /* Null Descriptor - overwritten by call gate */ 1014{ 0x0, /* segment base address */ 1015 0x0, /* length - all address space */ 1016 0, /* segment type */ 1017 0, /* segment descriptor priority level */ 1018 0, /* segment descriptor present */ 1019 0, 0, 1020 0, /* default 32 vs 16 bit size */ 1021 0 /* limit granularity (byte/page units)*/ }, 1022 /* Null Descriptor - overwritten by call gate */ 1023{ 0x0, /* segment base address */ 1024 0x0, /* length - all address space */ 1025 0, /* segment type */ 1026 0, /* segment descriptor priority level */ 1027 0, /* segment descriptor present */ 1028 0, 0, 1029 0, /* default 32 vs 16 bit size */ 1030 0 /* limit granularity (byte/page units)*/ }, 1031 /* Null Descriptor - overwritten by call gate */ 1032{ 0x0, /* segment base address */ 1033 0x0, /* length - all address space */ 1034 0, /* segment type */ 1035 0, /* segment descriptor priority level */ 1036 0, /* segment descriptor present */ 1037 0, 0, 1038 0, /* default 32 vs 16 bit size */ 1039 0 /* limit granularity (byte/page units)*/ }, 1040 /* Code Descriptor for user */ 1041{ 0x0, /* segment base address */ 1042 0xfffff, /* length - all address space */ 1043 SDT_MEMERA, /* segment type */ 1044 SEL_UPL, /* segment descriptor priority level */ 1045 1, /* segment descriptor present */ 1046 0, 0, 1047 1, /* default 32 vs 16 bit size */ 1048 1 /* limit granularity (byte/page units)*/ }, 1049 /* Data Descriptor for user */ 1050{ 0x0, /* segment base address */ 1051 0xfffff, /* length - all address space */ 1052 SDT_MEMRWA, /* segment type */ 1053 SEL_UPL, /* segment descriptor priority level */ 1054 1, /* segment descriptor present */ 1055 0, 0, 1056 1, /* default 32 vs 16 bit size */ 1057 1 /* limit granularity (byte/page units)*/ }, 1058}; 1059 1060void 1061setidt(idx, func, typ, dpl, selec) 1062 int idx; 1063 inthand_t *func; 1064 int typ; 1065 int dpl; 1066 int selec; 1067{ 1068 struct gate_descriptor *ip; 1069 1070#if defined(I586_CPU) && !defined(NO_F00F_HACK) 1071 ip = (t_idt != NULL ? t_idt : idt) + idx; 1072#else 1073 ip = idt + idx; 1074#endif 1075 ip->gd_looffset = (int)func; 1076 ip->gd_selector = selec; 1077 ip->gd_stkcpy = 0; 1078 ip->gd_xx = 0; 1079 ip->gd_type = typ; 1080 ip->gd_dpl = dpl; 1081 ip->gd_p = 1; 1082 ip->gd_hioffset = ((int)func)>>16 ; 1083} 1084 1085#define IDTVEC(name) __CONCAT(X,name) 1086 1087extern inthand_t 1088 IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl), 1089 IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(fpusegm), 1090 IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot), 1091 IDTVEC(page), IDTVEC(mchk), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align), 1092 IDTVEC(syscall), IDTVEC(int0x80_syscall); 1093 1094void 1095sdtossd(sd, ssd) 1096 struct segment_descriptor *sd; 1097 struct soft_segment_descriptor *ssd; 1098{ 1099 ssd->ssd_base = (sd->sd_hibase << 24) | sd->sd_lobase; 1100 ssd->ssd_limit = (sd->sd_hilimit << 16) | sd->sd_lolimit; 1101 ssd->ssd_type = sd->sd_type; 1102 ssd->ssd_dpl = sd->sd_dpl; 1103 ssd->ssd_p = sd->sd_p; 1104 ssd->ssd_def32 = sd->sd_def32; 1105 ssd->ssd_gran = sd->sd_gran; 1106} 1107 1108void 1109init386(first) 1110 int first; 1111{ 1112 int x; 1113 unsigned biosbasemem, biosextmem; 1114 struct gate_descriptor *gdp; 1115 int gsel_tss; 1116 char *cp; 1117 1118 struct isa_device *idp; 1119#ifndef SMP 1120 /* table descriptors - used to load tables by microp */ 1121 struct region_descriptor r_gdt, r_idt; 1122#endif 1123 int pagesinbase, pagesinext; 1124 int target_page, pa_indx; 1125 int off; 1126 int speculative_mprobe; 1127 1128 /* 1129 * Prevent lowering of the ipl if we call tsleep() early. 1130 */ 1131 safepri = cpl; 1132 1133 proc0.p_addr = proc0paddr; 1134 1135 atdevbase = ISA_HOLE_START + KERNBASE; 1136 1137 /* 1138 * Initialize the console before we print anything out. 1139 */ 1140 cninit(); 1141 1142 /* 1143 * make gdt memory segments, the code segment goes up to end of the 1144 * page with etext in it, the data segment goes to the end of 1145 * the address space 1146 */ 1147 /* 1148 * XXX text protection is temporarily (?) disabled. The limit was 1149 * i386_btop(round_page(etext)) - 1. 1150 */ 1151 gdt_segs[GCODE_SEL].ssd_limit = i386_btop(0) - 1; 1152 gdt_segs[GDATA_SEL].ssd_limit = i386_btop(0) - 1; 1153#ifdef BDE_DEBUGGER 1154#define NGDT1 8 /* avoid overwriting db entries with APM ones */ 1155#else 1156#define NGDT1 (sizeof gdt_segs / sizeof gdt_segs[0]) 1157#endif 1158 for (x = 0; x < NGDT1; x++) 1159 ssdtosd(&gdt_segs[x], &gdt[x].sd); 1160#ifdef VM86 1161 common_tssd = gdt[GPROC0_SEL].sd; 1162#endif /* VM86 */ 1163 1164#ifdef SMP 1165 /* 1166 * Spin these up now. init_secondary() grabs them. We could use 1167 * #for(x,y,z) / #endfor cpp directives if they existed. 1168 */ 1169 for (x = 0; x < NCPU; x++) { 1170 gdt_segs[NGDT + x] = gdt_segs[GPROC0_SEL]; 1171 ssdtosd(&gdt_segs[NGDT + x], &gdt[NGDT + x].sd); 1172 } 1173#endif 1174 1175 /* make ldt memory segments */ 1176 /* 1177 * The data segment limit must not cover the user area because we 1178 * don't want the user area to be writable in copyout() etc. (page 1179 * level protection is lost in kernel mode on 386's). Also, we 1180 * don't want the user area to be writable directly (page level 1181 * protection of the user area is not available on 486's with 1182 * CR0_WP set, because there is no user-read/kernel-write mode). 1183 * 1184 * XXX - VM_MAXUSER_ADDRESS is an end address, not a max. And it 1185 * should be spelled ...MAX_USER... 1186 */ 1187#define VM_END_USER_RW_ADDRESS VM_MAXUSER_ADDRESS 1188 /* 1189 * The code segment limit has to cover the user area until we move 1190 * the signal trampoline out of the user area. This is safe because 1191 * the code segment cannot be written to directly. 1192 */ 1193#define VM_END_USER_R_ADDRESS (VM_END_USER_RW_ADDRESS + UPAGES * PAGE_SIZE) 1194 ldt_segs[LUCODE_SEL].ssd_limit = i386_btop(VM_END_USER_R_ADDRESS) - 1; 1195 ldt_segs[LUDATA_SEL].ssd_limit = i386_btop(VM_END_USER_RW_ADDRESS) - 1; 1196 for (x = 0; x < sizeof ldt_segs / sizeof ldt_segs[0]; x++) 1197 ssdtosd(&ldt_segs[x], &ldt[x].sd); 1198 1199 /* exceptions */ 1200 for (x = 0; x < NIDT; x++) 1201 setidt(x, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1202 setidt(0, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1203 setidt(1, &IDTVEC(dbg), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1204 setidt(2, &IDTVEC(nmi), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1205 setidt(3, &IDTVEC(bpt), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); 1206 setidt(4, &IDTVEC(ofl), SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); 1207 setidt(5, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1208 setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1209 setidt(7, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1210 setidt(8, 0, SDT_SYSTASKGT, SEL_KPL, GSEL(GPANIC_SEL, SEL_KPL)); 1211 setidt(9, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1212 setidt(10, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1213 setidt(11, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1214 setidt(12, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1215 setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1216 setidt(14, &IDTVEC(page), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1217 setidt(15, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1218 setidt(16, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1219 setidt(17, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1220 setidt(18, &IDTVEC(mchk), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1221 setidt(0x80, &IDTVEC(int0x80_syscall), 1222 SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL)); 1223 1224#include "isa.h" 1225#if NISA >0 1226 isa_defaultirq(); 1227#endif 1228 rand_initialize(); 1229 1230 r_gdt.rd_limit = sizeof(gdt) - 1; 1231 r_gdt.rd_base = (int) gdt; 1232 lgdt(&r_gdt); 1233 1234 r_idt.rd_limit = sizeof(idt) - 1; 1235 r_idt.rd_base = (int) idt; 1236 lidt(&r_idt); 1237 1238 _default_ldt = GSEL(GLDT_SEL, SEL_KPL); 1239 lldt(_default_ldt); 1240 currentldt = _default_ldt; 1241 1242#ifdef DDB 1243 kdb_init(); 1244 if (boothowto & RB_KDB) 1245 Debugger("Boot flags requested debugger"); 1246#endif 1247 1248 finishidentcpu(); /* Final stage of CPU initialization */ 1249 setidt(6, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1250 setidt(13, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); 1251 initializecpu(); /* Initialize CPU registers */ 1252 1253 /* make an initial tss so cpu can get interrupt stack on syscall! */ 1254#ifdef VM86 1255 common_tss.tss_esp0 = (int) proc0.p_addr + UPAGES*PAGE_SIZE - 16; 1256#else 1257 common_tss.tss_esp0 = (int) proc0.p_addr + UPAGES*PAGE_SIZE; 1258#endif /* VM86 */ 1259 common_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ; 1260 common_tss.tss_ioopt = (sizeof common_tss) << 16; 1261 gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); 1262 ltr(gsel_tss); 1263#ifdef VM86 1264 private_tss = 0; 1265 my_tr = GPROC0_SEL; 1266#endif 1267 1268 dblfault_tss.tss_esp = dblfault_tss.tss_esp0 = dblfault_tss.tss_esp1 = 1269 dblfault_tss.tss_esp2 = (int) &dblfault_stack[sizeof(dblfault_stack)]; 1270 dblfault_tss.tss_ss = dblfault_tss.tss_ss0 = dblfault_tss.tss_ss1 = 1271 dblfault_tss.tss_ss2 = GSEL(GDATA_SEL, SEL_KPL); 1272 dblfault_tss.tss_cr3 = (int)IdlePTD; 1273 dblfault_tss.tss_eip = (int) dblfault_handler; 1274 dblfault_tss.tss_eflags = PSL_KERNEL; 1275 dblfault_tss.tss_ds = dblfault_tss.tss_es = dblfault_tss.tss_fs = 1276 dblfault_tss.tss_gs = GSEL(GDATA_SEL, SEL_KPL); 1277 dblfault_tss.tss_cs = GSEL(GCODE_SEL, SEL_KPL); 1278 dblfault_tss.tss_ldt = GSEL(GLDT_SEL, SEL_KPL); 1279 1280#ifdef VM86 1281 initial_bioscalls(&biosbasemem, &biosextmem); 1282#else 1283 1284 /* Use BIOS values stored in RTC CMOS RAM, since probing 1285 * breaks certain 386 AT relics. 1286 */ 1287 biosbasemem = rtcin(RTC_BASELO)+ (rtcin(RTC_BASEHI)<<8); 1288 biosextmem = rtcin(RTC_EXTLO)+ (rtcin(RTC_EXTHI)<<8); 1289#endif 1290 1291 /* 1292 * If BIOS tells us that it has more than 640k in the basemem, 1293 * don't believe it - set it to 640k. 1294 */ 1295 if (biosbasemem > 640) { 1296 printf("Preposterous RTC basemem of %dK, truncating to 640K\n", 1297 biosbasemem); 1298 biosbasemem = 640; 1299 } 1300 if (bootinfo.bi_memsizes_valid && bootinfo.bi_basemem > 640) { 1301 printf("Preposterous BIOS basemem of %dK, truncating to 640K\n", 1302 bootinfo.bi_basemem); 1303 bootinfo.bi_basemem = 640; 1304 } 1305 1306 /* 1307 * Warn if the official BIOS interface disagrees with the RTC 1308 * interface used above about the amount of base memory or the 1309 * amount of extended memory. Prefer the BIOS value for the base 1310 * memory. This is necessary for machines that `steal' base 1311 * memory for use as BIOS memory, at least if we are going to use 1312 * the BIOS for apm. Prefer the RTC value for extended memory. 1313 * Eventually the hackish interface shouldn't even be looked at. 1314 */ 1315 if (bootinfo.bi_memsizes_valid) { 1316 if (bootinfo.bi_basemem != biosbasemem) { 1317 vm_offset_t pa; 1318 1319 printf( 1320 "BIOS basemem (%ldK) != RTC basemem (%dK), setting to BIOS value\n", 1321 bootinfo.bi_basemem, biosbasemem); 1322 biosbasemem = bootinfo.bi_basemem; 1323 1324 /* 1325 * XXX if biosbasemem is now < 640, there is `hole' 1326 * between the end of base memory and the start of 1327 * ISA memory. The hole may be empty or it may 1328 * contain BIOS code or data. Map it read/write so 1329 * that the BIOS can write to it. (Memory from 0 to 1330 * the physical end of the kernel is mapped read-only 1331 * to begin with and then parts of it are remapped. 1332 * The parts that aren't remapped form holes that 1333 * remain read-only and are unused by the kernel. 1334 * The base memory area is below the physical end of 1335 * the kernel and right now forms a read-only hole. 1336 * The part of it from PAGE_SIZE to 1337 * (trunc_page(biosbasemem * 1024) - 1) will be 1338 * remapped and used by the kernel later.) 1339 * 1340 * This code is similar to the code used in 1341 * pmap_mapdev, but since no memory needs to be 1342 * allocated we simply change the mapping. 1343 */ 1344 for (pa = trunc_page(biosbasemem * 1024); 1345 pa < ISA_HOLE_START; pa += PAGE_SIZE) { 1346 unsigned *pte; 1347 1348 pte = (unsigned *)vtopte(pa + KERNBASE); 1349 *pte = pa | PG_RW | PG_V; 1350 } 1351 } 1352 if (bootinfo.bi_extmem != biosextmem) 1353 printf("BIOS extmem (%ldK) != RTC extmem (%dK)\n", 1354 bootinfo.bi_extmem, biosextmem); 1355 } 1356 1357#ifdef SMP 1358 /* make hole for AP bootstrap code */ 1359 pagesinbase = mp_bootaddress(biosbasemem) / PAGE_SIZE; 1360#else 1361 pagesinbase = biosbasemem * 1024 / PAGE_SIZE; 1362#endif 1363 1364 pagesinext = biosextmem * 1024 / PAGE_SIZE; 1365 1366 /* 1367 * Special hack for chipsets that still remap the 384k hole when 1368 * there's 16MB of memory - this really confuses people that 1369 * are trying to use bus mastering ISA controllers with the 1370 * "16MB limit"; they only have 16MB, but the remapping puts 1371 * them beyond the limit. 1372 */ 1373 /* 1374 * If extended memory is between 15-16MB (16-17MB phys address range), 1375 * chop it to 15MB. 1376 */ 1377 if ((pagesinext > 3840) && (pagesinext < 4096)) 1378 pagesinext = 3840; 1379 1380 /* 1381 * Maxmem isn't the "maximum memory", it's one larger than the 1382 * highest page of the physical address space. It should be 1383 * called something like "Maxphyspage". 1384 */ 1385 Maxmem = pagesinext + 0x100000/PAGE_SIZE; 1386 /* 1387 * Indicate that we wish to do a speculative search for memory beyond 1388 * the end of the reported size if the indicated amount is 64MB (0x4000 1389 * pages) - which is the largest amount that the BIOS/bootblocks can 1390 * currently report. If a specific amount of memory is indicated via 1391 * the MAXMEM option or the npx0 "msize", then don't do the speculative 1392 * memory probe. 1393 */ 1394 if (Maxmem >= 0x4000) 1395 speculative_mprobe = TRUE; 1396 else 1397 speculative_mprobe = FALSE; 1398 1399#ifdef MAXMEM 1400 Maxmem = MAXMEM/4; 1401 speculative_mprobe = FALSE; 1402#endif 1403 1404#if NNPX > 0 1405 idp = find_isadev(isa_devtab_null, &npxdriver, 0); 1406 if (idp != NULL && idp->id_msize != 0) { 1407 Maxmem = idp->id_msize / 4; 1408 speculative_mprobe = FALSE; 1409 } 1410#endif 1411 1412#ifdef SMP 1413 /* look for the MP hardware - needed for apic addresses */ 1414 mp_probe(); 1415#endif 1416 1417 /* call pmap initialization to make new kernel address space */ 1418 pmap_bootstrap (first, 0); 1419 1420 /* 1421 * Size up each available chunk of physical memory. 1422 */ 1423 1424 /* 1425 * We currently don't bother testing base memory. 1426 * XXX ...but we probably should. 1427 */ 1428 pa_indx = 0; 1429 if (pagesinbase > 1) { 1430 phys_avail[pa_indx++] = PAGE_SIZE; /* skip first page of memory */ 1431 phys_avail[pa_indx] = ptoa(pagesinbase);/* memory up to the ISA hole */ 1432 physmem = pagesinbase - 1; 1433 } else { 1434 /* point at first chunk end */ 1435 pa_indx++; 1436 } 1437 1438 for (target_page = avail_start; target_page < ptoa(Maxmem); target_page += PAGE_SIZE) { 1439 int tmp, page_bad; 1440 1441 page_bad = FALSE; 1442 1443 /* 1444 * map page into kernel: valid, read/write, non-cacheable 1445 */ 1446 *(int *)CMAP1 = PG_V | PG_RW | PG_N | target_page; 1447 invltlb(); 1448 1449 tmp = *(int *)CADDR1; 1450 /* 1451 * Test for alternating 1's and 0's 1452 */ 1453 *(volatile int *)CADDR1 = 0xaaaaaaaa; 1454 if (*(volatile int *)CADDR1 != 0xaaaaaaaa) { 1455 page_bad = TRUE; 1456 } 1457 /* 1458 * Test for alternating 0's and 1's 1459 */ 1460 *(volatile int *)CADDR1 = 0x55555555; 1461 if (*(volatile int *)CADDR1 != 0x55555555) { 1462 page_bad = TRUE; 1463 } 1464 /* 1465 * Test for all 1's 1466 */ 1467 *(volatile int *)CADDR1 = 0xffffffff; 1468 if (*(volatile int *)CADDR1 != 0xffffffff) { 1469 page_bad = TRUE; 1470 } 1471 /* 1472 * Test for all 0's 1473 */ 1474 *(volatile int *)CADDR1 = 0x0; 1475 if (*(volatile int *)CADDR1 != 0x0) { 1476 /* 1477 * test of page failed 1478 */ 1479 page_bad = TRUE; 1480 } 1481 /* 1482 * Restore original value. 1483 */ 1484 *(int *)CADDR1 = tmp; 1485 1486 /* 1487 * Adjust array of valid/good pages. 1488 */ 1489 if (page_bad == FALSE) { 1490 /* 1491 * If this good page is a continuation of the 1492 * previous set of good pages, then just increase 1493 * the end pointer. Otherwise start a new chunk. 1494 * Note that "end" points one higher than end, 1495 * making the range >= start and < end. 1496 * If we're also doing a speculative memory 1497 * test and we at or past the end, bump up Maxmem 1498 * so that we keep going. The first bad page 1499 * will terminate the loop. 1500 */ 1501 if (phys_avail[pa_indx] == target_page) { 1502 phys_avail[pa_indx] += PAGE_SIZE; 1503 if (speculative_mprobe == TRUE && 1504 phys_avail[pa_indx] >= (64*1024*1024)) 1505 Maxmem++; 1506 } else { 1507 pa_indx++; 1508 if (pa_indx == PHYS_AVAIL_ARRAY_END) { 1509 printf("Too many holes in the physical address space, giving up\n"); 1510 pa_indx--; 1511 break; 1512 } 1513 phys_avail[pa_indx++] = target_page; /* start */ 1514 phys_avail[pa_indx] = target_page + PAGE_SIZE; /* end */ 1515 } 1516 physmem++; 1517 } 1518 } 1519 1520 *(int *)CMAP1 = 0; 1521 invltlb(); 1522 1523 /* 1524 * XXX 1525 * The last chunk must contain at least one page plus the message 1526 * buffer to avoid complicating other code (message buffer address 1527 * calculation, etc.). 1528 */ 1529 while (phys_avail[pa_indx - 1] + PAGE_SIZE + 1530 round_page(MSGBUF_SIZE) >= phys_avail[pa_indx]) { 1531 physmem -= atop(phys_avail[pa_indx] - phys_avail[pa_indx - 1]); 1532 phys_avail[pa_indx--] = 0; 1533 phys_avail[pa_indx--] = 0; 1534 } 1535 1536 Maxmem = atop(phys_avail[pa_indx]); 1537 1538 /* Trim off space for the message buffer. */ 1539 phys_avail[pa_indx] -= round_page(MSGBUF_SIZE); 1540 1541 avail_end = phys_avail[pa_indx]; 1542 1543 /* now running on new page tables, configured,and u/iom is accessible */ 1544 1545 /* Map the message buffer. */ 1546 for (off = 0; off < round_page(MSGBUF_SIZE); off += PAGE_SIZE) 1547 pmap_enter(kernel_pmap, (vm_offset_t)msgbufp + off, 1548 avail_end + off, VM_PROT_ALL, TRUE); 1549 1550 msgbufinit(msgbufp, MSGBUF_SIZE); 1551 1552 /* make a call gate to reenter kernel with */ 1553 gdp = &ldt[LSYS5CALLS_SEL].gd; 1554 1555 x = (int) &IDTVEC(syscall); 1556 gdp->gd_looffset = x++; 1557 gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL); 1558 gdp->gd_stkcpy = 1; 1559 gdp->gd_type = SDT_SYS386CGT; 1560 gdp->gd_dpl = SEL_UPL; 1561 gdp->gd_p = 1; 1562 gdp->gd_hioffset = ((int) &IDTVEC(syscall)) >>16; 1563 1564 /* XXX does this work? */ 1565 ldt[LBSDICALLS_SEL] = ldt[LSYS5CALLS_SEL]; 1566 1567 /* transfer to user mode */ 1568 1569 _ucodesel = LSEL(LUCODE_SEL, SEL_UPL); 1570 _udatasel = LSEL(LUDATA_SEL, SEL_UPL); 1571 1572 /* setup proc 0's pcb */ 1573 proc0.p_addr->u_pcb.pcb_flags = 0; 1574 proc0.p_addr->u_pcb.pcb_cr3 = (int)IdlePTD; 1575#ifdef SMP 1576 proc0.p_addr->u_pcb.pcb_mpnest = 1; 1577#endif 1578#ifdef VM86 1579 proc0.p_addr->u_pcb.pcb_ext = 0; 1580#endif 1581} 1582 1583#if defined(I586_CPU) && !defined(NO_F00F_HACK) 1584static void f00f_hack(void *unused); 1585SYSINIT(f00f_hack, SI_SUB_INTRINSIC, SI_ORDER_FIRST, f00f_hack, NULL); 1586 1587static void 1588f00f_hack(void *unused) { 1589#ifndef SMP 1590 struct region_descriptor r_idt; 1591#endif 1592 vm_offset_t tmp; 1593 1594 if (!has_f00f_bug) 1595 return; 1596 1597 printf("Intel Pentium F00F detected, installing workaround\n"); 1598 1599 r_idt.rd_limit = sizeof(idt) - 1; 1600 1601 tmp = kmem_alloc(kernel_map, PAGE_SIZE * 2); 1602 if (tmp == 0) 1603 panic("kmem_alloc returned 0"); 1604 if (((unsigned int)tmp & (PAGE_SIZE-1)) != 0) 1605 panic("kmem_alloc returned non-page-aligned memory"); 1606 /* Put the first seven entries in the lower page */ 1607 t_idt = (struct gate_descriptor*)(tmp + PAGE_SIZE - (7*8)); 1608 bcopy(idt, t_idt, sizeof(idt)); 1609 r_idt.rd_base = (int)t_idt; 1610 lidt(&r_idt); 1611 if (vm_map_protect(kernel_map, tmp, tmp + PAGE_SIZE, 1612 VM_PROT_READ, FALSE) != KERN_SUCCESS) 1613 panic("vm_map_protect failed"); 1614 return; 1615} 1616#endif /* defined(I586_CPU) && !NO_F00F_HACK */ 1617 1618int 1619ptrace_set_pc(p, addr) 1620 struct proc *p; 1621 unsigned long addr; 1622{ 1623 p->p_md.md_regs->tf_eip = addr; 1624 return (0); 1625} 1626 1627int 1628ptrace_single_step(p) 1629 struct proc *p; 1630{ 1631 p->p_md.md_regs->tf_eflags |= PSL_T; 1632 return (0); 1633} 1634 1635int ptrace_read_u_check(p, addr, len) 1636 struct proc *p; 1637 vm_offset_t addr; 1638 size_t len; 1639{ 1640 vm_offset_t gap; 1641 1642 if ((vm_offset_t) (addr + len) < addr) 1643 return EPERM; 1644 if ((vm_offset_t) (addr + len) <= sizeof(struct user)) 1645 return 0; 1646 1647 gap = (char *) p->p_md.md_regs - (char *) p->p_addr; 1648 1649 if ((vm_offset_t) addr < gap) 1650 return EPERM; 1651 if ((vm_offset_t) (addr + len) <= 1652 (vm_offset_t) (gap + sizeof(struct trapframe))) 1653 return 0; 1654 return EPERM; 1655} 1656 1657int ptrace_write_u(p, off, data) 1658 struct proc *p; 1659 vm_offset_t off; 1660 long data; 1661{ 1662 struct trapframe frame_copy; 1663 vm_offset_t min; 1664 struct trapframe *tp; 1665 1666 /* 1667 * Privileged kernel state is scattered all over the user area. 1668 * Only allow write access to parts of regs and to fpregs. 1669 */ 1670 min = (char *)p->p_md.md_regs - (char *)p->p_addr; 1671 if (off >= min && off <= min + sizeof(struct trapframe) - sizeof(int)) { 1672 tp = p->p_md.md_regs; 1673 frame_copy = *tp; 1674 *(int *)((char *)&frame_copy + (off - min)) = data; 1675 if (!EFLAGS_SECURE(frame_copy.tf_eflags, tp->tf_eflags) || 1676 !CS_SECURE(frame_copy.tf_cs)) 1677 return (EINVAL); 1678 *(int*)((char *)p->p_addr + off) = data; 1679 return (0); 1680 } 1681 min = offsetof(struct user, u_pcb) + offsetof(struct pcb, pcb_savefpu); 1682 if (off >= min && off <= min + sizeof(struct save87) - sizeof(int)) { 1683 *(int*)((char *)p->p_addr + off) = data; 1684 return (0); 1685 } 1686 return (EFAULT); 1687} 1688 1689int 1690fill_regs(p, regs) 1691 struct proc *p; 1692 struct reg *regs; 1693{ 1694 struct pcb *pcb; 1695 struct trapframe *tp; 1696 1697 tp = p->p_md.md_regs; 1698 regs->r_es = tp->tf_es; 1699 regs->r_ds = tp->tf_ds; 1700 regs->r_edi = tp->tf_edi; 1701 regs->r_esi = tp->tf_esi; 1702 regs->r_ebp = tp->tf_ebp; 1703 regs->r_ebx = tp->tf_ebx; 1704 regs->r_edx = tp->tf_edx; 1705 regs->r_ecx = tp->tf_ecx; 1706 regs->r_eax = tp->tf_eax; 1707 regs->r_eip = tp->tf_eip; 1708 regs->r_cs = tp->tf_cs; 1709 regs->r_eflags = tp->tf_eflags; 1710 regs->r_esp = tp->tf_esp; 1711 regs->r_ss = tp->tf_ss; 1712 pcb = &p->p_addr->u_pcb; 1713 regs->r_fs = pcb->pcb_fs; 1714 regs->r_gs = pcb->pcb_gs; 1715 return (0); 1716} 1717 1718int 1719set_regs(p, regs) 1720 struct proc *p; 1721 struct reg *regs; 1722{ 1723 struct pcb *pcb; 1724 struct trapframe *tp; 1725 1726 tp = p->p_md.md_regs; 1727 if (!EFLAGS_SECURE(regs->r_eflags, tp->tf_eflags) || 1728 !CS_SECURE(regs->r_cs)) 1729 return (EINVAL); 1730 tp->tf_es = regs->r_es; 1731 tp->tf_ds = regs->r_ds; 1732 tp->tf_edi = regs->r_edi; 1733 tp->tf_esi = regs->r_esi; 1734 tp->tf_ebp = regs->r_ebp; 1735 tp->tf_ebx = regs->r_ebx; 1736 tp->tf_edx = regs->r_edx; 1737 tp->tf_ecx = regs->r_ecx; 1738 tp->tf_eax = regs->r_eax; 1739 tp->tf_eip = regs->r_eip; 1740 tp->tf_cs = regs->r_cs; 1741 tp->tf_eflags = regs->r_eflags; 1742 tp->tf_esp = regs->r_esp; 1743 tp->tf_ss = regs->r_ss; 1744 pcb = &p->p_addr->u_pcb; 1745 pcb->pcb_fs = regs->r_fs; 1746 pcb->pcb_gs = regs->r_gs; 1747 return (0); 1748} 1749 1750#ifndef DDB 1751void 1752Debugger(const char *msg) 1753{ 1754 printf("Debugger(\"%s\") called.\n", msg); 1755} 1756#endif /* no DDB */ 1757 1758#include <sys/disklabel.h> 1759 1760/* 1761 * Determine the size of the transfer, and make sure it is 1762 * within the boundaries of the partition. Adjust transfer 1763 * if needed, and signal errors or early completion. 1764 */ 1765int 1766bounds_check_with_label(struct buf *bp, struct disklabel *lp, int wlabel) 1767{ 1768 struct partition *p = lp->d_partitions + dkpart(bp->b_dev); 1769 int labelsect = lp->d_partitions[0].p_offset; 1770 int maxsz = p->p_size, 1771 sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; 1772 1773 /* overwriting disk label ? */ 1774 /* XXX should also protect bootstrap in first 8K */ 1775 if (bp->b_blkno + p->p_offset <= LABELSECTOR + labelsect && 1776#if LABELSECTOR != 0 1777 bp->b_blkno + p->p_offset + sz > LABELSECTOR + labelsect && 1778#endif 1779 (bp->b_flags & B_READ) == 0 && wlabel == 0) { 1780 bp->b_error = EROFS; 1781 goto bad; 1782 } 1783 1784#if defined(DOSBBSECTOR) && defined(notyet) 1785 /* overwriting master boot record? */ 1786 if (bp->b_blkno + p->p_offset <= DOSBBSECTOR && 1787 (bp->b_flags & B_READ) == 0 && wlabel == 0) { 1788 bp->b_error = EROFS; 1789 goto bad; 1790 } 1791#endif 1792 1793 /* beyond partition? */ 1794 if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) { 1795 /* if exactly at end of disk, return an EOF */ 1796 if (bp->b_blkno == maxsz) { 1797 bp->b_resid = bp->b_bcount; 1798 return(0); 1799 } 1800 /* or truncate if part of it fits */ 1801 sz = maxsz - bp->b_blkno; 1802 if (sz <= 0) { 1803 bp->b_error = EINVAL; 1804 goto bad; 1805 } 1806 bp->b_bcount = sz << DEV_BSHIFT; 1807 } 1808 1809 bp->b_pblkno = bp->b_blkno + p->p_offset; 1810 return(1); 1811 1812bad: 1813 bp->b_flags |= B_ERROR; 1814 return(-1); 1815} 1816 1817#ifdef DDB 1818 1819/* 1820 * Provide inb() and outb() as functions. They are normally only 1821 * available as macros calling inlined functions, thus cannot be 1822 * called inside DDB. 1823 * 1824 * The actual code is stolen from <machine/cpufunc.h>, and de-inlined. 1825 */ 1826 1827#undef inb 1828#undef outb 1829 1830/* silence compiler warnings */ 1831u_char inb(u_int); 1832void outb(u_int, u_char); 1833 1834u_char 1835inb(u_int port) 1836{ 1837 u_char data; 1838 /* 1839 * We use %%dx and not %1 here because i/o is done at %dx and not at 1840 * %edx, while gcc generates inferior code (movw instead of movl) 1841 * if we tell it to load (u_short) port. 1842 */ 1843 __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port)); 1844 return (data); 1845} 1846 1847void 1848outb(u_int port, u_char data) 1849{ 1850 u_char al; 1851 /* 1852 * Use an unnecessary assignment to help gcc's register allocator. 1853 * This make a large difference for gcc-1.40 and a tiny difference 1854 * for gcc-2.6.0. For gcc-1.40, al had to be ``asm("ax")'' for 1855 * best results. gcc-2.6.0 can't handle this. 1856 */ 1857 al = data; 1858 __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port)); 1859} 1860 1861#endif /* DDB */ 1862