1/* 2 * Copyright (c) 1991 Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * The Mach Operating System project at Carnegie-Mellon University. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 20 unchanged lines hidden (view full) --- 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: @(#)vm_page.c 7.4 (Berkeley) 5/7/91 |
37 * $Id: vm_page.c,v 1.128 1999/03/19 05:21:03 alc Exp $ |
38 */ 39 40/* 41 * Copyright (c) 1987, 1990 Carnegie-Mellon University. 42 * All rights reserved. 43 * 44 * Authors: Avadis Tevanian, Jr., Michael Wayne Young 45 * --- 95 unchanged lines hidden (view full) --- 141vm_page_t vm_page_array = 0; 142static int vm_page_array_size = 0; 143long first_page = 0; 144static long last_page; 145static vm_size_t page_mask; 146static int page_shift; 147int vm_page_zero_count = 0; 148 |
149static __inline int vm_page_hash __P((vm_object_t object, vm_pindex_t pindex)); 150static void vm_page_free_wakeup __P((void)); 151 152/* 153 * vm_set_page_size: 154 * 155 * Sets the page size, perhaps based upon the memory 156 * size. Must be called before any use of page-size --- 1271 unchanged lines hidden (view full) --- 1428 return NULL; 1429 goto retrylookup; 1430 } 1431 1432 return m; 1433} 1434 1435/* |
1436 * Mapping function for valid bits or for dirty bits in |
1437 * a page. May not block. |
1438 * 1439 * Inputs are required to range within a page. |
1440 */ |
1441 |
1442__inline int 1443vm_page_bits(int base, int size) 1444{ |
1445 int first_bit; 1446 int last_bit; |
1447 |
1448 KASSERT( 1449 base + size <= PAGE_SIZE, 1450 ("vm_page_bits: illegal base/size %d/%d", base, size) 1451 ); |
1452 |
1453 if (size == 0) /* handle degenerate case */ 1454 return(0); |
1455 |
1456 first_bit = base >> DEV_BSHIFT; 1457 last_bit = (base + size - 1) >> DEV_BSHIFT; 1458 1459 return ((2 << last_bit) - (1 << first_bit)); |
1460} 1461 1462/* 1463 * set a page valid and clean. May not block. |
1464 * 1465 * In order to maintain consistancy due to the DEV_BSIZE granularity 1466 * of the valid bits, we have to zero non-DEV_BSIZE aligned portions of 1467 * the page at the beginning and end of the valid range when the 1468 * associated valid bits are not already set. 1469 * 1470 * (base + size) must be less then or equal to PAGE_SIZE. |
1471 */ 1472void 1473vm_page_set_validclean(m, base, size) 1474 vm_page_t m; 1475 int base; 1476 int size; 1477{ |
1478 int pagebits; 1479 int frag; 1480 int endoff; 1481 1482 if (size == 0) /* handle degenerate case */ 1483 return; 1484 1485 /* 1486 * If the base is not DEV_BSIZE aligned and the valid 1487 * bit is clear, we have to zero out a portion of the 1488 * first block. 1489 */ 1490 1491 if ((frag = base & ~(DEV_BSIZE - 1)) != base && 1492 (m->valid & (1 << (base >> DEV_BSHIFT))) == 0 1493 ) { 1494 pmap_zero_page_area( 1495 VM_PAGE_TO_PHYS(m), 1496 frag, 1497 base - frag 1498 ); 1499 } 1500 1501 /* 1502 * If the ending offset is not DEV_BSIZE aligned and the 1503 * valid bit is clear, we have to zero out a portion of 1504 * the last block. 1505 */ 1506 1507 endoff = base + size; 1508 1509 if ((frag = endoff & ~(DEV_BSIZE - 1)) != endoff && 1510 (m->valid & (1 << (endoff >> DEV_BSHIFT))) == 0 1511 ) { 1512 pmap_zero_page_area( 1513 VM_PAGE_TO_PHYS(m), 1514 endoff, 1515 DEV_BSIZE - (endoff & (DEV_BSIZE - 1)) 1516 ); 1517 } 1518 1519 /* 1520 * Set valid, clear dirty bits. If validating the entire 1521 * page we can safely clear the pmap modify bit. 1522 */ 1523 1524 pagebits = vm_page_bits(base, size); |
1525 m->valid |= pagebits; 1526 m->dirty &= ~pagebits; |
1527 1528 if (base == 0 && size == PAGE_SIZE) |
1529 pmap_clear_modify(VM_PAGE_TO_PHYS(m)); 1530} 1531 1532/* 1533 * set a page (partially) invalid. May not block. 1534 */ 1535void 1536vm_page_set_invalid(m, base, size) --- 5 unchanged lines hidden (view full) --- 1542 1543 m->valid &= ~(bits = vm_page_bits(base, size)); 1544 if (m->valid == 0) 1545 m->dirty &= ~bits; 1546 m->object->generation++; 1547} 1548 1549/* |
1550 * vm_page_zero_invalid() 1551 * 1552 * The kernel assumes that the invalid portions of a page contain 1553 * garbage, but such pages can be mapped into memory by user code. 1554 * When this occurs, we must zero out the non-valid portions of the 1555 * page so user code sees what it expects. 1556 * 1557 * Pages are most often semi-valid when the end of a file is mapped 1558 * into memory and the file's size is not page aligned. |
1559 */ |
1560 1561void 1562vm_page_zero_invalid(vm_page_t m, boolean_t setvalid) 1563{ 1564 int b; 1565 int i; 1566 1567 /* 1568 * Scan the valid bits looking for invalid sections that 1569 * must be zerod. Invalid sub-DEV_BSIZE'd areas ( where the 1570 * valid bit may be set ) have already been zerod by 1571 * vm_page_set_validclean(). 1572 */ 1573 1574 for (b = i = 0; i <= PAGE_SIZE / DEV_BSIZE; ++i) { 1575 if (i == (PAGE_SIZE / DEV_BSIZE) || 1576 (m->valid & (1 << i)) 1577 ) { 1578 if (i > b) { 1579 pmap_zero_page_area( 1580 VM_PAGE_TO_PHYS(m), 1581 b << DEV_BSHIFT, 1582 (i - b) << DEV_BSHIFT 1583 ); 1584 } 1585 b = i + 1; 1586 } 1587 } 1588 1589 /* 1590 * setvalid is TRUE when we can safely set the zero'd areas 1591 * as being valid. We can do this if there are no cache consistancy 1592 * issues. e.g. it is ok to do with UFS, but not ok to do with NFS. 1593 */ 1594 1595 if (setvalid) 1596 m->valid = VM_PAGE_BITS_ALL; 1597} 1598 1599/* 1600 * vm_page_is_valid: 1601 * 1602 * Is (partial) page valid? Note that the case where size == 0 1603 * will return FALSE in the degenerate case where the page is 1604 * entirely invalid, and TRUE otherwise. 1605 * 1606 * May not block. 1607 */ 1608 |
1609int 1610vm_page_is_valid(m, base, size) 1611 vm_page_t m; 1612 int base; 1613 int size; 1614{ 1615 int bits = vm_page_bits(base, size); 1616 --- 272 unchanged lines hidden --- |