1 /*- 2 * Copyright (c) 1982, 1986 The Regents of the University of California. 3 * Copyright (c) 1989, 1990 William Jolitz 4 * Copyright (c) 1994 John Dyson 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * the Systems Programming Group of the University of Utah Computer 9 * Science Department, and William Jolitz. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * from: @(#)vm_machdep.c 7.3 (Berkeley) 5/13/91 40 * Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$ 41 * $Id: vm_machdep.c,v 1.37 1995/05/01 23:32:30 dyson Exp $ 42 */ 43 44 #include "npx.h" 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/proc.h> 48 #include <sys/malloc.h> 49 #include <sys/buf.h> 50 #include <sys/vnode.h> 51 #include <sys/user.h> 52 53 #include <machine/clock.h> 54 #include <machine/cpu.h> 55 #include <machine/md_var.h> 56 57 #include <vm/vm.h> 58 #include <vm/vm_kern.h> 59 60 #include <i386/isa/isa.h> 61 62 #ifdef BOUNCE_BUFFERS 63 vm_map_t io_map; 64 volatile int kvasfreecnt; 65 66 67 caddr_t bouncememory; 68 int bouncepages, bpwait; 69 vm_offset_t *bouncepa; 70 int bmwait, bmfreeing; 71 72 #define BITS_IN_UNSIGNED (8*sizeof(unsigned)) 73 int bounceallocarraysize; 74 unsigned *bounceallocarray; 75 int bouncefree; 76 77 #define SIXTEENMEG (4096*4096) 78 #define MAXBKVA 1024 79 int maxbkva = MAXBKVA*NBPG; 80 81 /* special list that can be used at interrupt time for eventual kva free */ 82 struct kvasfree { 83 vm_offset_t addr; 84 vm_offset_t size; 85 } kvaf[MAXBKVA]; 86 87 88 vm_offset_t vm_bounce_kva(); 89 /* 90 * get bounce buffer pages (count physically contiguous) 91 * (only 1 inplemented now) 92 */ 93 vm_offset_t 94 vm_bounce_page_find(count) 95 int count; 96 { 97 int bit; 98 int s,i; 99 100 if (count != 1) 101 panic("vm_bounce_page_find -- no support for > 1 page yet!!!"); 102 103 s = splbio(); 104 retry: 105 for (i = 0; i < bounceallocarraysize; i++) { 106 if (bounceallocarray[i] != 0xffffffff) { 107 bit = ffs(~bounceallocarray[i]); 108 if (bit) { 109 bounceallocarray[i] |= 1 << (bit - 1) ; 110 bouncefree -= count; 111 splx(s); 112 return bouncepa[(i * BITS_IN_UNSIGNED + (bit - 1))]; 113 } 114 } 115 } 116 bpwait = 1; 117 tsleep((caddr_t) &bounceallocarray, PRIBIO, "bncwai", 0); 118 goto retry; 119 } 120 121 void 122 vm_bounce_kva_free(addr, size, now) 123 vm_offset_t addr; 124 vm_offset_t size; 125 int now; 126 { 127 int s = splbio(); 128 kvaf[kvasfreecnt].addr = addr; 129 kvaf[kvasfreecnt].size = size; 130 ++kvasfreecnt; 131 if( now) { 132 /* 133 * this will do wakeups 134 */ 135 vm_bounce_kva(0,0); 136 } else { 137 if (bmwait) { 138 /* 139 * if anyone is waiting on the bounce-map, then wakeup 140 */ 141 wakeup((caddr_t) io_map); 142 bmwait = 0; 143 } 144 } 145 splx(s); 146 } 147 148 /* 149 * free count bounce buffer pages 150 */ 151 void 152 vm_bounce_page_free(pa, count) 153 vm_offset_t pa; 154 int count; 155 { 156 int allocindex; 157 int index; 158 int bit; 159 160 if (count != 1) 161 panic("vm_bounce_page_free -- no support for > 1 page yet!!!"); 162 163 for(index=0;index<bouncepages;index++) { 164 if( pa == bouncepa[index]) 165 break; 166 } 167 168 if( index == bouncepages) 169 panic("vm_bounce_page_free: invalid bounce buffer"); 170 171 allocindex = index / BITS_IN_UNSIGNED; 172 bit = index % BITS_IN_UNSIGNED; 173 174 bounceallocarray[allocindex] &= ~(1 << bit); 175 176 bouncefree += count; 177 if (bpwait) { 178 bpwait = 0; 179 wakeup((caddr_t) &bounceallocarray); 180 } 181 } 182 183 /* 184 * allocate count bounce buffer kva pages 185 */ 186 vm_offset_t 187 vm_bounce_kva(size, waitok) 188 int size; 189 int waitok; 190 { 191 int i; 192 vm_offset_t kva = 0; 193 vm_offset_t off; 194 int s = splbio(); 195 more: 196 if (!bmfreeing && kvasfreecnt) { 197 bmfreeing = 1; 198 for (i = 0; i < kvasfreecnt; i++) { 199 for(off=0;off<kvaf[i].size;off+=NBPG) { 200 pmap_kremove( kvaf[i].addr + off); 201 } 202 kmem_free_wakeup(io_map, kvaf[i].addr, 203 kvaf[i].size); 204 } 205 kvasfreecnt = 0; 206 bmfreeing = 0; 207 if( bmwait) { 208 bmwait = 0; 209 wakeup( (caddr_t) io_map); 210 } 211 } 212 213 if( size == 0) { 214 splx(s); 215 return NULL; 216 } 217 218 if ((kva = kmem_alloc_pageable(io_map, size)) == 0) { 219 if( !waitok) { 220 splx(s); 221 return NULL; 222 } 223 bmwait = 1; 224 tsleep((caddr_t) io_map, PRIBIO, "bmwait", 0); 225 goto more; 226 } 227 splx(s); 228 return kva; 229 } 230 231 /* 232 * same as vm_bounce_kva -- but really allocate (but takes pages as arg) 233 */ 234 vm_offset_t 235 vm_bounce_kva_alloc(count) 236 int count; 237 { 238 int i; 239 vm_offset_t kva; 240 vm_offset_t pa; 241 if( bouncepages == 0) { 242 kva = (vm_offset_t) malloc(count*NBPG, M_TEMP, M_WAITOK); 243 return kva; 244 } 245 kva = vm_bounce_kva(count*NBPG, 1); 246 for(i=0;i<count;i++) { 247 pa = vm_bounce_page_find(1); 248 pmap_kenter(kva + i * NBPG, pa); 249 } 250 return kva; 251 } 252 253 /* 254 * same as vm_bounce_kva_free -- but really free 255 */ 256 void 257 vm_bounce_kva_alloc_free(kva, count) 258 vm_offset_t kva; 259 int count; 260 { 261 int i; 262 vm_offset_t pa; 263 if( bouncepages == 0) { 264 free((caddr_t) kva, M_TEMP); 265 return; 266 } 267 for(i = 0; i < count; i++) { 268 pa = pmap_kextract(kva + i * NBPG); 269 vm_bounce_page_free(pa, 1); 270 } 271 vm_bounce_kva_free(kva, count*NBPG, 0); 272 } 273 274 /* 275 * do the things necessary to the struct buf to implement 276 * bounce buffers... inserted before the disk sort 277 */ 278 void 279 vm_bounce_alloc(bp) 280 struct buf *bp; 281 { 282 int countvmpg; 283 vm_offset_t vastart, vaend; 284 vm_offset_t vapstart, vapend; 285 vm_offset_t va, kva; 286 vm_offset_t pa; 287 int dobounceflag = 0; 288 int i; 289 290 if (bouncepages == 0) 291 return; 292 293 if (bp->b_flags & B_BOUNCE) { 294 printf("vm_bounce_alloc: called recursively???\n"); 295 return; 296 } 297 298 if (bp->b_bufsize < bp->b_bcount) { 299 printf( 300 "vm_bounce_alloc: b_bufsize(0x%lx) < b_bcount(0x%lx) !!\n", 301 bp->b_bufsize, bp->b_bcount); 302 panic("vm_bounce_alloc"); 303 } 304 305 /* 306 * This is not really necessary 307 * if( bp->b_bufsize != bp->b_bcount) { 308 * printf("size: %d, count: %d\n", bp->b_bufsize, bp->b_bcount); 309 * } 310 */ 311 312 313 vastart = (vm_offset_t) bp->b_data; 314 vaend = (vm_offset_t) bp->b_data + bp->b_bufsize; 315 316 vapstart = i386_trunc_page(vastart); 317 vapend = i386_round_page(vaend); 318 countvmpg = (vapend - vapstart) / NBPG; 319 320 /* 321 * if any page is above 16MB, then go into bounce-buffer mode 322 */ 323 va = vapstart; 324 for (i = 0; i < countvmpg; i++) { 325 pa = pmap_kextract(va); 326 if (pa >= SIXTEENMEG) 327 ++dobounceflag; 328 if( pa == 0) 329 panic("vm_bounce_alloc: Unmapped page"); 330 va += NBPG; 331 } 332 if (dobounceflag == 0) 333 return; 334 335 if (bouncepages < dobounceflag) 336 panic("Not enough bounce buffers!!!"); 337 338 /* 339 * allocate a replacement kva for b_addr 340 */ 341 kva = vm_bounce_kva(countvmpg*NBPG, 1); 342 #if 0 343 printf("%s: vapstart: %x, vapend: %x, countvmpg: %d, kva: %x ", 344 (bp->b_flags & B_READ) ? "read":"write", 345 vapstart, vapend, countvmpg, kva); 346 #endif 347 va = vapstart; 348 for (i = 0; i < countvmpg; i++) { 349 pa = pmap_kextract(va); 350 if (pa >= SIXTEENMEG) { 351 /* 352 * allocate a replacement page 353 */ 354 vm_offset_t bpa = vm_bounce_page_find(1); 355 pmap_kenter(kva + (NBPG * i), bpa); 356 #if 0 357 printf("r(%d): (%x,%x,%x) ", i, va, pa, bpa); 358 #endif 359 /* 360 * if we are writing, the copy the data into the page 361 */ 362 if ((bp->b_flags & B_READ) == 0) { 363 bcopy((caddr_t) va, (caddr_t) kva + (NBPG * i), NBPG); 364 } 365 } else { 366 /* 367 * use original page 368 */ 369 pmap_kenter(kva + (NBPG * i), pa); 370 } 371 va += NBPG; 372 } 373 374 /* 375 * flag the buffer as being bounced 376 */ 377 bp->b_flags |= B_BOUNCE; 378 /* 379 * save the original buffer kva 380 */ 381 bp->b_savekva = bp->b_data; 382 /* 383 * put our new kva into the buffer (offset by original offset) 384 */ 385 bp->b_data = (caddr_t) (((vm_offset_t) kva) | 386 ((vm_offset_t) bp->b_savekva & (NBPG - 1))); 387 #if 0 388 printf("b_savekva: %x, newva: %x\n", bp->b_savekva, bp->b_data); 389 #endif 390 return; 391 } 392 393 /* 394 * hook into biodone to free bounce buffer 395 */ 396 void 397 vm_bounce_free(bp) 398 struct buf *bp; 399 { 400 int i; 401 vm_offset_t origkva, bouncekva, bouncekvaend; 402 403 /* 404 * if this isn't a bounced buffer, then just return 405 */ 406 if ((bp->b_flags & B_BOUNCE) == 0) 407 return; 408 409 /* 410 * This check is not necessary 411 * if (bp->b_bufsize != bp->b_bcount) { 412 * printf("vm_bounce_free: b_bufsize=%d, b_bcount=%d\n", 413 * bp->b_bufsize, bp->b_bcount); 414 * } 415 */ 416 417 origkva = (vm_offset_t) bp->b_savekva; 418 bouncekva = (vm_offset_t) bp->b_data; 419 /* 420 printf("free: %d ", bp->b_bufsize); 421 */ 422 423 /* 424 * check every page in the kva space for b_addr 425 */ 426 for (i = 0; i < bp->b_bufsize; ) { 427 vm_offset_t mybouncepa; 428 vm_offset_t copycount; 429 430 copycount = i386_round_page(bouncekva + 1) - bouncekva; 431 mybouncepa = pmap_kextract(i386_trunc_page(bouncekva)); 432 433 /* 434 * if this is a bounced pa, then process as one 435 */ 436 if ( mybouncepa != pmap_kextract( i386_trunc_page( origkva))) { 437 vm_offset_t tocopy = copycount; 438 if (i + tocopy > bp->b_bufsize) 439 tocopy = bp->b_bufsize - i; 440 /* 441 * if this is a read, then copy from bounce buffer into original buffer 442 */ 443 if (bp->b_flags & B_READ) 444 bcopy((caddr_t) bouncekva, (caddr_t) origkva, tocopy); 445 /* 446 * free the bounce allocation 447 */ 448 449 /* 450 printf("(kva: %x, pa: %x)", bouncekva, mybouncepa); 451 */ 452 vm_bounce_page_free(mybouncepa, 1); 453 } 454 455 origkva += copycount; 456 bouncekva += copycount; 457 i += copycount; 458 } 459 460 /* 461 printf("\n"); 462 */ 463 /* 464 * add the old kva into the "to free" list 465 */ 466 467 bouncekva= i386_trunc_page((vm_offset_t) bp->b_data); 468 bouncekvaend= i386_round_page((vm_offset_t)bp->b_data + bp->b_bufsize); 469 470 /* 471 printf("freeva: %d\n", (bouncekvaend - bouncekva) / NBPG); 472 */ 473 vm_bounce_kva_free( bouncekva, (bouncekvaend - bouncekva), 0); 474 bp->b_data = bp->b_savekva; 475 bp->b_savekva = 0; 476 bp->b_flags &= ~B_BOUNCE; 477 478 return; 479 } 480 481 482 /* 483 * init the bounce buffer system 484 */ 485 void 486 vm_bounce_init() 487 { 488 int i; 489 490 kvasfreecnt = 0; 491 492 if (bouncepages == 0) 493 return; 494 495 bounceallocarraysize = (bouncepages + BITS_IN_UNSIGNED - 1) / BITS_IN_UNSIGNED; 496 bounceallocarray = malloc(bounceallocarraysize * sizeof(unsigned), M_TEMP, M_NOWAIT); 497 498 if (!bounceallocarray) 499 panic("Cannot allocate bounce resource array"); 500 501 bouncepa = malloc(bouncepages * sizeof(vm_offset_t), M_TEMP, M_NOWAIT); 502 if (!bouncepa) 503 panic("Cannot allocate physical memory array"); 504 505 for(i=0;i<bounceallocarraysize;i++) { 506 bounceallocarray[i] = 0xffffffff; 507 } 508 509 for(i=0;i<bouncepages;i++) { 510 vm_offset_t pa; 511 if( (pa = pmap_kextract((vm_offset_t) bouncememory + i * NBPG)) >= SIXTEENMEG) 512 panic("bounce memory out of range"); 513 if( pa == 0) 514 panic("bounce memory not resident"); 515 bouncepa[i] = pa; 516 bounceallocarray[i/(8*sizeof(int))] &= ~(1<<(i%(8*sizeof(int)))); 517 } 518 bouncefree = bouncepages; 519 520 } 521 #endif /* BOUNCE_BUFFERS */ 522 /* 523 * quick version of vm_fault 524 */ 525 526 void 527 vm_fault_quick( v, prot) 528 vm_offset_t v; 529 int prot; 530 { 531 if (prot & VM_PROT_WRITE) 532 subyte((char *)v, fubyte((char *)v)); 533 else 534 (void) fubyte((char *)v); 535 } 536 537 538 /* 539 * Finish a fork operation, with process p2 nearly set up. 540 * Copy and update the kernel stack and pcb, making the child 541 * ready to run, and marking it so that it can return differently 542 * than the parent. Returns 1 in the child process, 0 in the parent. 543 * We currently double-map the user area so that the stack is at the same 544 * address in each process; in the future we will probably relocate 545 * the frame pointers on the stack after copying. 546 */ 547 int 548 cpu_fork(p1, p2) 549 register struct proc *p1, *p2; 550 { 551 register struct user *up = p2->p_addr; 552 int offset; 553 554 /* 555 * Copy pcb and stack from proc p1 to p2. 556 * We do this as cheaply as possible, copying only the active 557 * part of the stack. The stack and pcb need to agree; 558 * this is tricky, as the final pcb is constructed by savectx, 559 * but its frame isn't yet on the stack when the stack is copied. 560 * swtch compensates for this when the child eventually runs. 561 * This should be done differently, with a single call 562 * that copies and updates the pcb+stack, 563 * replacing the bcopy and savectx. 564 */ 565 p2->p_addr->u_pcb = p1->p_addr->u_pcb; 566 offset = mvesp() - (int)kstack; 567 bcopy((caddr_t)kstack + offset, (caddr_t)p2->p_addr + offset, 568 (unsigned) ctob(UPAGES) - offset); 569 p2->p_md.md_regs = p1->p_md.md_regs; 570 571 pmap_activate(&p2->p_vmspace->vm_pmap, &up->u_pcb); 572 573 /* 574 * 575 * Arrange for a non-local goto when the new process 576 * is started, to resume here, returning nonzero from setjmp. 577 */ 578 if (savectx(&up->u_pcb, 1)) { 579 /* 580 * Return 1 in child. 581 */ 582 return (1); 583 } 584 return (0); 585 } 586 587 void 588 cpu_exit(p) 589 register struct proc *p; 590 { 591 592 #if NNPX > 0 593 npxexit(p); 594 #endif /* NNPX */ 595 cnt.v_swtch++; 596 cpu_switch(p); 597 panic("cpu_exit"); 598 } 599 600 void 601 cpu_wait(p) struct proc *p; { 602 /* extern vm_map_t upages_map; */ 603 604 /* drop per-process resources */ 605 pmap_remove(vm_map_pmap(u_map), (vm_offset_t) p->p_addr, 606 ((vm_offset_t) p->p_addr) + ctob(UPAGES)); 607 kmem_free(u_map, (vm_offset_t)p->p_addr, ctob(UPAGES)); 608 vmspace_free(p->p_vmspace); 609 } 610 611 /* 612 * Dump the machine specific header information at the start of a core dump. 613 */ 614 int 615 cpu_coredump(p, vp, cred) 616 struct proc *p; 617 struct vnode *vp; 618 struct ucred *cred; 619 { 620 621 return (vn_rdwr(UIO_WRITE, vp, (caddr_t) p->p_addr, ctob(UPAGES), 622 (off_t)0, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *)NULL, 623 p)); 624 } 625 626 /* 627 * Set a red zone in the kernel stack after the u. area. 628 */ 629 void 630 setredzone(pte, vaddr) 631 u_short *pte; 632 caddr_t vaddr; 633 { 634 /* eventually do this by setting up an expand-down stack segment 635 for ss0: selector, allowing stack access down to top of u. 636 this means though that protection violations need to be handled 637 thru a double fault exception that must do an integral task 638 switch to a known good context, within which a dump can be 639 taken. a sensible scheme might be to save the initial context 640 used by sched (that has physical memory mapped 1:1 at bottom) 641 and take the dump while still in mapped mode */ 642 } 643 644 /* 645 * Move pages from one kernel virtual address to another. 646 * Both addresses are assumed to reside in the Sysmap, 647 * and size must be a multiple of CLSIZE. 648 */ 649 650 void 651 pagemove(from, to, size) 652 register caddr_t from, to; 653 int size; 654 { 655 register vm_offset_t pa; 656 657 if (size & CLOFSET) 658 panic("pagemove"); 659 while (size > 0) { 660 pa = pmap_kextract((vm_offset_t)from); 661 if (pa == 0) 662 panic("pagemove 2"); 663 if (pmap_kextract((vm_offset_t)to) != 0) 664 panic("pagemove 3"); 665 pmap_kremove((vm_offset_t)from); 666 pmap_kenter((vm_offset_t)to, pa); 667 from += PAGE_SIZE; 668 to += PAGE_SIZE; 669 size -= PAGE_SIZE; 670 } 671 } 672 673 /* 674 * Convert kernel VA to physical address 675 */ 676 u_long 677 kvtop(void *addr) 678 { 679 vm_offset_t va; 680 681 va = pmap_kextract((vm_offset_t)addr); 682 if (va == 0) 683 panic("kvtop: zero page frame"); 684 return((int)va); 685 } 686 687 /* 688 * Map an IO request into kernel virtual address space. 689 * 690 * All requests are (re)mapped into kernel VA space. 691 * Notice that we use b_bufsize for the size of the buffer 692 * to be mapped. b_bcount might be modified by the driver. 693 */ 694 void 695 vmapbuf(bp) 696 register struct buf *bp; 697 { 698 register int npf; 699 register caddr_t addr; 700 int off; 701 vm_offset_t kva; 702 vm_offset_t pa, v; 703 704 if ((bp->b_flags & B_PHYS) == 0) 705 panic("vmapbuf"); 706 707 /* 708 * this is the kva that is to be used for 709 * the temporary kernel mapping 710 */ 711 kva = (vm_offset_t) bp->b_saveaddr; 712 713 for (addr = (caddr_t)trunc_page(bp->b_data); 714 addr < bp->b_data + bp->b_bufsize; 715 addr += PAGE_SIZE) { 716 717 /* 718 * do the vm_fault if needed, do the copy-on-write thing when 719 * reading stuff off device into memory. 720 */ 721 vm_fault_quick(addr, 722 (bp->b_flags&B_READ)?(VM_PROT_READ|VM_PROT_WRITE):VM_PROT_READ); 723 pa = pmap_kextract((vm_offset_t) addr); 724 if (pa == 0) 725 panic("vmapbuf: page not present"); 726 /* 727 * hold the data page 728 */ 729 #ifdef DIAGNOSTIC 730 if( VM_PAGE_TO_PHYS(PHYS_TO_VM_PAGE(pa)) != pa) 731 panic("vmapbuf: confused PHYS_TO_VM_PAGE mapping"); 732 #endif 733 vm_page_hold(PHYS_TO_VM_PAGE(pa)); 734 } 735 736 addr = bp->b_saveaddr = bp->b_data; 737 off = (int)addr & PGOFSET; 738 npf = btoc(round_page(bp->b_bufsize + off)); 739 bp->b_data = (caddr_t) (kva + off); 740 while (npf--) { 741 pa = pmap_kextract((vm_offset_t)addr); 742 if (pa == 0) 743 panic("vmapbuf: null page frame"); 744 pmap_kenter(kva, trunc_page(pa)); 745 addr += PAGE_SIZE; 746 kva += PAGE_SIZE; 747 } 748 } 749 750 /* 751 * Free the io map PTEs associated with this IO operation. 752 * We also invalidate the TLB entries and restore the original b_addr. 753 */ 754 void 755 vunmapbuf(bp) 756 register struct buf *bp; 757 { 758 register caddr_t addr; 759 vm_offset_t v,pa; 760 761 if ((bp->b_flags & B_PHYS) == 0) 762 panic("vunmapbuf"); 763 764 for (addr = (caddr_t)trunc_page((vm_offset_t) bp->b_data); 765 addr < bp->b_data + bp->b_bufsize; 766 addr += NBPG) 767 pmap_kremove((vm_offset_t) addr); 768 769 bp->b_data = bp->b_saveaddr; 770 bp->b_saveaddr = NULL; 771 772 /* 773 * unhold the pde, and data pages 774 */ 775 for (addr = (caddr_t)trunc_page((vm_offset_t) bp->b_data); 776 addr < bp->b_data + bp->b_bufsize; 777 addr += NBPG) { 778 /* 779 * release the data page 780 */ 781 pa = pmap_kextract((vm_offset_t) addr); 782 vm_page_unhold(PHYS_TO_VM_PAGE(pa)); 783 } 784 } 785 786 /* 787 * Force reset the processor by invalidating the entire address space! 788 */ 789 void 790 cpu_reset() { 791 792 /* 793 * Attempt to do a CPU reset via the keyboard controller, 794 * do not turn of the GateA20, as any machine that fails 795 * to do the reset here would then end up in no man's land. 796 */ 797 798 #ifndef BROKEN_KEYBOARD_RESET 799 outb(IO_KBD + 4, 0xFE); 800 DELAY(500000); /* wait 0.5 sec to see if that did it */ 801 printf("Keyboard reset did not work, attempting CPU shutdown\n"); 802 DELAY(1000000); /* wait 1 sec for printf to complete */ 803 #endif 804 805 /* force a shutdown by unmapping entire address space ! */ 806 bzero((caddr_t) PTD, NBPG); 807 808 /* "good night, sweet prince .... <THUNK!>" */ 809 pmap_update(); 810 /* NOTREACHED */ 811 while(1); 812 } 813 814 /* 815 * Grow the user stack to allow for 'sp'. This version grows the stack in 816 * chunks of SGROWSIZ. 817 */ 818 int 819 grow(p, sp) 820 struct proc *p; 821 u_int sp; 822 { 823 unsigned int nss; 824 caddr_t v; 825 struct vmspace *vm = p->p_vmspace; 826 827 if ((caddr_t)sp <= vm->vm_maxsaddr || (unsigned)sp >= (unsigned)USRSTACK) 828 return (1); 829 830 nss = roundup(USRSTACK - (unsigned)sp, PAGE_SIZE); 831 832 if (nss > p->p_rlimit[RLIMIT_STACK].rlim_cur) 833 return (0); 834 835 if (vm->vm_ssize && roundup(vm->vm_ssize << PAGE_SHIFT, 836 SGROWSIZ) < nss) { 837 int grow_amount; 838 /* 839 * If necessary, grow the VM that the stack occupies 840 * to allow for the rlimit. This allows us to not have 841 * to allocate all of the VM up-front in execve (which 842 * is expensive). 843 * Grow the VM by the amount requested rounded up to 844 * the nearest SGROWSIZ to provide for some hysteresis. 845 */ 846 grow_amount = roundup((nss - (vm->vm_ssize << PAGE_SHIFT)), SGROWSIZ); 847 v = (char *)USRSTACK - roundup(vm->vm_ssize << PAGE_SHIFT, 848 SGROWSIZ) - grow_amount; 849 /* 850 * If there isn't enough room to extend by SGROWSIZ, then 851 * just extend to the maximum size 852 */ 853 if (v < vm->vm_maxsaddr) { 854 v = vm->vm_maxsaddr; 855 grow_amount = MAXSSIZ - (vm->vm_ssize << PAGE_SHIFT); 856 } 857 if ((grow_amount == 0) || (vm_map_find(&vm->vm_map, NULL, 0, (vm_offset_t *)&v, 858 grow_amount, FALSE) != KERN_SUCCESS)) { 859 return (0); 860 } 861 vm->vm_ssize += grow_amount >> PAGE_SHIFT; 862 } 863 864 return (1); 865 } 866