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