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