Changeset 440 for trunk/kernel/mm/vmm.c
- Timestamp:
- May 3, 2018, 5:51:22 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/mm/vmm.c
r438 r440 198 198 bool_t mapping ) 199 199 { 200 assert( (process->ref_xp == XPTR( local_cxy , process )) , __FUNCTION__,201 "this function must be executed in reference cluster" );202 203 200 vmm_t * vmm = &process->vmm; 204 201 gpt_t * gpt = &vmm->gpt; 205 202 206 printk("\n***** VSL and GPT for process %x \n\n",207 process->pid );203 printk("\n***** VSL and GPT for process %x in cluster %x\n\n", 204 process->pid , local_cxy ); 208 205 209 206 // get lock protecting the vseg list … … 1036 1033 } // end vmm_remove_vseg() 1037 1034 1038 //////////////////////////////////////////////1039 error_t vmm_map_kernel_vseg( vseg_t * vseg,1040 uint32_t attr )1041 {1042 vpn_t vpn; // VPN of PTE to be set1043 vpn_t vpn_min; // VPN of first PTE to be set1044 vpn_t vpn_max; // VPN of last PTE to be set (excluded)1045 ppn_t ppn; // PPN of allocated physical page1046 uint32_t order; // ln( number of small pages for one single PTE )1047 page_t * page;1048 error_t error;1049 1050 // check vseg type : must be a kernel vseg1051 uint32_t type = vseg->type;1052 assert( ((type==VSEG_TYPE_KCODE) || (type==VSEG_TYPE_KDATA) || (type==VSEG_TYPE_KDEV)),1053 __FUNCTION__ , "not a kernel vseg\n" );1054 1055 // get pointer on page table1056 gpt_t * gpt = &process_zero.vmm.gpt;1057 1058 // define number of small pages per PTE1059 if( attr & GPT_SMALL ) order = 0; // 1 small page1060 else order = 9; // 512 small pages1061 1062 // loop on pages in vseg1063 vpn_min = vseg->vpn_base;1064 vpn_max = vpn_min + vseg->vpn_size;1065 for( vpn = vpn_min ; vpn < vpn_max ; vpn++ )1066 {1067 // allocate a physical page from local PPM1068 kmem_req_t req;1069 req.type = KMEM_PAGE;1070 req.size = order;1071 req.flags = AF_KERNEL | AF_ZERO;1072 page = (page_t *)kmem_alloc( &req );1073 if( page == NULL )1074 {1075 printk("\n[ERROR] in %s : cannot allocate physical memory\n", __FUNCTION__ );1076 return ENOMEM;1077 }1078 1079 // set page table entry1080 ppn = ppm_page2ppn( XPTR( local_cxy , page ) );1081 error = hal_gpt_set_pte( gpt,1082 vpn,1083 attr,1084 ppn );1085 if( error )1086 {1087 printk("\n[ERROR] in %s : cannot register PPE\n", __FUNCTION__ );1088 return ENOMEM;1089 }1090 }1091 1092 return 0;1093 1094 } // end vmm_map_kernel_vseg()1095 1096 1035 ///////////////////////////////////////// 1097 1036 void vmm_unmap_vseg( process_t * process, … … 1193 1132 1194 1133 ////////////////////////////////////////////////////////////////////////////////////////// 1195 // This low-level static function is called by the vmm_get_vseg() and vmm_resize_vseg()1196 // functions. It scan the list of registered vsegs to find the unique vseg containing1197 // a given virtual address.1134 // This low-level static function is called by the vmm_get_vseg(), vmm_get_pte(), 1135 // and vmm_resize_vseg() functions. It scan the local VSL to find the unique vseg 1136 // containing a given virtual address. 1198 1137 ////////////////////////////////////////////////////////////////////////////////////////// 1199 1138 // @ vmm : pointer on the process VMM. … … 1331 1270 vseg_t ** found_vseg ) 1332 1271 { 1333 vmm_t * vmm = &process->vmm; 1334 1335 // get vseg from vaddr 1336 vseg_t * vseg = vseg_from_vaddr( vmm , vaddr ); 1272 xptr_t vseg_xp; 1273 error_t error; 1274 vseg_t * vseg; 1275 vmm_t * vmm; 1276 1277 // get pointer on local VMM 1278 vmm = &process->vmm; 1279 1280 // try to get vseg from local VMM 1281 vseg = vseg_from_vaddr( vmm , vaddr ); 1337 1282 1338 1283 if( vseg == NULL ) // vseg not found in local cluster => try to get it from ref … … 1348 1293 1349 1294 // get extended pointer on reference vseg 1350 xptr_t vseg_xp;1351 error_t error;1352 1353 1295 rpc_vmm_get_vseg_client( ref_cxy , ref_ptr , vaddr , &vseg_xp , &error ); 1354 1296 1355 if( error ) return -1; // vseg not found => illegal user vaddr1297 if( error ) return -1; // vseg not found => illegal user vaddr 1356 1298 1357 1299 // allocate a vseg in local cluster 1358 1300 vseg = vseg_alloc(); 1359 1301 1360 if( vseg == NULL ) return -1; 1302 if( vseg == NULL ) return -1; // cannot allocate a local vseg 1361 1303 1362 1304 // initialise local vseg from reference … … 1496 1438 1497 1439 // initialise missing page from .elf file mapper for DATA and CODE types 1498 // (the vseg->mapper_xp field is an extended pointer on the .elf file mapper)1440 // the vseg->mapper_xp field is an extended pointer on the .elf file mapper 1499 1441 if( (type == VSEG_TYPE_CODE) || (type == VSEG_TYPE_DATA) ) 1500 1442 { … … 1521 1463 #endif 1522 1464 1465 1523 1466 // compute extended pointer on page base 1524 1467 xptr_t base_xp = ppm_page2base( page_xp ); … … 1535 1478 __FUNCTION__, CURRENT_THREAD, vpn ); 1536 1479 #endif 1480 1537 1481 1538 1482 if( GET_CXY( page_xp ) == local_cxy ) … … 1553 1497 __FUNCTION__, CURRENT_THREAD, vpn ); 1554 1498 #endif 1555 1556 1499 if( mapper_cxy == local_cxy ) 1557 1500 { … … 1644 1587 ppn_t * ppn ) 1645 1588 { 1646 vseg_t * vseg; // vseg containing VPN 1647 ppn_t old_ppn; // current PTE_PPN 1648 uint32_t old_attr; // current PTE_ATTR 1649 ppn_t new_ppn; // new PTE_PPN 1650 uint32_t new_attr; // new PTE_ATTR 1651 error_t error; 1652 1653 // this function must be called by a thread running in the reference cluster 1654 assert( (GET_CXY( process->ref_xp ) == local_cxy ) , __FUNCTION__ , 1655 "not called in the reference cluster\n" ); 1589 ppn_t old_ppn; // current PTE_PPN 1590 uint32_t old_attr; // current PTE_ATTR 1591 ppn_t new_ppn; // new PTE_PPN 1592 uint32_t new_attr; // new PTE_ATTR 1593 vmm_t * vmm; 1594 vseg_t * vseg; 1595 error_t error; 1656 1596 1657 1597 #if DEBUG_VMM_GET_PTE … … 1663 1603 1664 1604 // get VMM pointer 1665 vmm_t * vmm = &process->vmm; 1666 1667 // get vseg pointer from reference VSL 1668 error = vmm_get_vseg( process , vpn<<CONFIG_PPM_PAGE_SHIFT , &vseg ); 1669 1670 if( error ) 1671 { 1672 printk("\n[ERROR] in %s : out of segment / process = %x / vpn = %x\n", 1673 __FUNCTION__ , process->pid , vpn ); 1674 return error; 1675 } 1676 1677 #if( DEBUG_VMM_GET_PTE & 1 ) 1678 cycle = (uint32_t)hal_get_cycles(); 1679 if( DEBUG_VMM_GET_PTE < cycle ) 1680 printk("\n[DBG] %s : thread %x found vseg %s / vpn_base = %x / vpn_size = %x\n", 1681 __FUNCTION__, CURRENT_THREAD, vseg_type_str(vseg->type), vseg->vpn_base, vseg->vpn_size ); 1682 #endif 1605 vmm = &process->vmm; 1606 1607 // get local vseg descriptor 1608 error = vmm_get_vseg( process, 1609 ((intptr_t)vpn << CONFIG_PPM_PAGE_SHIFT), 1610 &vseg ); 1611 1612 // vseg has been checked by the vmm_handle_page_fault() function 1613 assert( (vseg != NULL) , __FUNCTION__, 1614 "vseg undefined / vpn %x / thread %x / process %x / core[%x,%d] / cycle %d\n", 1615 vpn, CURRENT_THREAD, process->pid, local_cxy, CURRENT_THREAD->core->lid, 1616 (uint32_t)hal_get_cycles() ); 1683 1617 1684 1618 if( cow ) //////////////// copy_on_write request ////////////////////// 1685 // get PTE from referenceGPT1619 // get PTE from local GPT 1686 1620 // allocate a new physical page if there is pending forks, 1687 1621 // initialize it from old physical page content, 1688 1622 // update PTE in all GPT copies, 1689 1623 { 1690 // access GPT to get current PTE attributes and PPN1624 // access local GPT to get current PTE attributes and PPN 1691 1625 hal_gpt_get_pte( &vmm->gpt , vpn , &old_attr , &old_ppn ); 1692 1626 1693 assert( (old_attr & GPT_MAPPED) , __FUNCTION__ , 1694 "PTE must be mapped for a copy-on-write exception\n" ); 1627 assert( (old_attr & GPT_MAPPED), __FUNCTION__, 1628 "PTE unmapped for a COW exception / vpn %x / thread %x / process %x / cycle %d\n", 1629 vpn, CURRENT_THREAD, process->pid, (uint32_t)hal_get_cycles() ); 1695 1630 1696 1631 #if( DEBUG_VMM_GET_PTE & 1 ) 1697 cycle = (uint32_t)hal_get_cycles();1698 1632 if( DEBUG_VMM_GET_PTE < cycle ) 1699 1633 printk("\n[DBG] %s : thread %x handling COW for vpn %x in process %x\n", … … 1745 1679 } 1746 1680 else //////////// page_fault request /////////////////////////// 1747 // get PTE from referenceGPT1681 // get PTE from local GPT 1748 1682 // allocate a physical page if it is a true page fault, 1683 // initialize it if type is FILE, CODE, or DATA, 1749 1684 // register in reference GPT, but don't update GPT copies 1750 1685 { 1751 // access GPT to get current PTE1686 // access local GPT to get current PTE 1752 1687 hal_gpt_get_pte( &vmm->gpt , vpn , &old_attr , &old_ppn ); 1753 1688 … … 1756 1691 1757 1692 #if( DEBUG_VMM_GET_PTE & 1 ) 1758 cycle = (uint32_t)hal_get_cycles();1759 1693 if( DEBUG_VMM_GET_PTE < cycle ) 1760 1694 printk("\n[DBG] %s : thread %x handling page fault for vpn %x in process %x\n", 1761 1695 __FUNCTION__, CURRENT_THREAD, vpn, process->pid ); 1762 1696 #endif 1763 1764 // allocate new_ppn, depending on vseg type 1697 // allocate new_ppn, and initialize the new page 1765 1698 error = vmm_get_one_ppn( vseg , vpn , &new_ppn ); 1766 1699 if( error ) … … 1801 1734 cycle = (uint32_t)hal_get_cycles(); 1802 1735 if( DEBUG_VMM_GET_PTE < cycle ) 1803 printk("\n[DBG] %s : thread ,%x exit / vpn %x in process %x / ppn %x / attr %x / cycle %d\n",1736 printk("\n[DBG] %s : thread %x exit / vpn %x in process %x / ppn %x / attr %x / cycle %d\n", 1804 1737 __FUNCTION__, CURRENT_THREAD, vpn, process->pid, new_ppn, new_attr, cycle ); 1805 1738 #endif … … 1814 1747 /////////////////////////////////////////////////// 1815 1748 error_t vmm_handle_page_fault( process_t * process, 1816 vpn_t vpn ) 1749 vpn_t vpn, 1750 bool_t is_cow ) 1817 1751 { 1818 1752 uint32_t attr; // missing page attributes 1819 1753 ppn_t ppn; // missing page PPN 1754 vseg_t * vseg; // vseg containing vpn 1755 uint32_t type; // vseg type 1756 cxy_t ref_cxy; // reference cluster for missing vpn 1757 process_t * ref_ptr; // reference process for missing vpn 1820 1758 error_t error; 1821 1759 1822 #if DEBUG_VMM_GET_PTE 1760 thread_t * this = CURRENT_THREAD; 1761 1762 #if DEBUG_VMM_HANDLE_PAGE_FAULT 1823 1763 uint32_t cycle = (uint32_t)hal_get_cycles(); 1824 if( DEBUG_VMM_GET_PTE < cycle ) 1825 printk("\n[DBG] %s : thread %x enter for vpn %x / process %x / cycle %d\n", 1826 __FUNCTION__ , CURRENT_THREAD , vpn , process->pid , cycle ); 1827 #endif 1764 if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle ) 1765 printk("\n[DBG] %s : thread %x enter for vpn %x / process %x / core[%x,%d] / cycle %d\n", 1766 __FUNCTION__, this, vpn, process->pid, local_cxy, this->core->lid, cycle ); 1767 #endif 1768 1769 // get local vseg (access reference VSL if required) 1770 error = vmm_get_vseg( process , vpn<<CONFIG_PPM_PAGE_SHIFT , &vseg ); 1771 1772 if( error ) 1773 { 1774 printk("\n[ERROR] in %s : vpn %x / process %x / thread %x / core[%x,%d] / cycle %d\n", 1775 __FUNCTION__, vpn, process->pid, this->trdid, local_cxy, this->core->lid, 1776 (uint32_t)hal_get_cycles() ); 1777 return error; 1778 } 1779 1780 // get segment type 1781 type = vseg->type; 1828 1782 1829 1783 // get reference process cluster and local pointer 1830 cxy_t ref_cxy = GET_CXY( process->ref_xp ); 1831 process_t * ref_ptr = GET_PTR( process->ref_xp ); 1832 1833 // get missing PTE attributes and PPN from reference cluster 1784 // for private vsegs (CODE and DATA type), 1785 // the reference is the local process descriptor. 1786 if( (type == VSEG_TYPE_STACK) || (type == VSEG_TYPE_CODE) ) 1787 { 1788 ref_cxy = local_cxy; 1789 ref_ptr = process; 1790 } 1791 else 1792 { 1793 ref_cxy = GET_CXY( process->ref_xp ); 1794 ref_ptr = GET_PTR( process->ref_xp ); 1795 } 1796 1797 // get missing PTE attributes and PPN 1834 1798 if( local_cxy != ref_cxy ) 1835 1799 { … … 1837 1801 ref_ptr, 1838 1802 vpn, 1839 false, // page_fault1803 is_cow, 1840 1804 &attr, 1841 1805 &ppn, … … 1855 1819 error = vmm_get_pte( process, 1856 1820 vpn, 1857 false, // page-fault1821 is_cow, 1858 1822 &attr, 1859 1823 &ppn ); 1860 1824 } 1861 1825 1862 #if DEBUG_VMM_ GET_PTE1826 #if DEBUG_VMM_HANDLE_PAGE_FAULT 1863 1827 cycle = (uint32_t)hal_get_cycles(); 1864 if( DEBUG_VMM_ GET_PTE< cycle )1828 if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle ) 1865 1829 printk("\n[DBG] %s : thread %x exit for vpn %x / process %x / cycle %d\n", 1866 __FUNCTION__ , CURRENT_THREAD , vpn , process->pid, cycle );1830 __FUNCTION__, this->trdid, vpn, process->pid, cycle ); 1867 1831 #endif 1868 1832 … … 1871 1835 } // end vmm_handle_page_fault() 1872 1836 1873 //////////////////////////////////////////// 1874 error_t vmm_handle_cow( process_t * process, 1875 vpn_t vpn ) 1876 { 1877 uint32_t attr; // page attributes 1878 ppn_t ppn; // page PPN 1879 error_t error; 1880 1881 #if DEBUG_VMM_GET_PTE 1882 uint32_t cycle = (uint32_t)hal_get_cycles(); 1883 if( DEBUG_VMM_GET_PTE < cycle ) 1884 printk("\n[DBG] %s : thread %x enter for vpn %x / process %x / cycle %d\n", 1885 __FUNCTION__ , CURRENT_THREAD , vpn , process->pid , cycle ); 1886 #endif 1887 1888 // get reference process cluster and local pointer 1889 cxy_t ref_cxy = GET_CXY( process->ref_xp ); 1890 process_t * ref_ptr = GET_PTR( process->ref_xp ); 1891 1892 // get new PTE attributes and PPN from reference cluster 1893 if( local_cxy != ref_cxy ) 1894 { 1895 rpc_vmm_get_pte_client( ref_cxy, 1896 ref_ptr, 1897 vpn, 1898 true, // copy-on-write 1899 &attr, 1900 &ppn, 1901 &error ); 1902 1903 // get local VMM pointer 1904 vmm_t * vmm = &process->vmm; 1905 1906 // update local GPT 1907 error |= hal_gpt_set_pte( &vmm->gpt, 1908 vpn, 1909 attr, 1910 ppn ); 1911 } 1912 else // local cluster is the reference cluster 1913 { 1914 error = vmm_get_pte( process, 1915 vpn, 1916 true, // copy-on-write 1917 &attr, 1918 &ppn ); 1919 } 1920 1921 #if DEBUG_VMM_GET_PTE 1922 cycle = (uint32_t)hal_get_cycles(); 1923 if( DEBUG_VMM_GET_PTE < cycle ) 1924 printk("\n[DBG] %s : thread %x exit for vpn %x / process %x / cycle %d\n", 1925 __FUNCTION__ , CURRENT_THREAD , vpn , process->pid , cycle ); 1926 #endif 1927 1928 return error; 1929 1930 } // end vmm_handle_cow() 1931 1932 /////////////////////////////////////////// 1933 error_t vmm_v2p_translate( bool_t ident, 1934 void * ptr, 1935 paddr_t * paddr ) 1936 { 1937 process_t * process = CURRENT_THREAD->process; 1938 1939 if( ident ) // identity mapping 1940 { 1941 *paddr = (paddr_t)PADDR( local_cxy , (lpa_t)ptr ); 1942 return 0; 1943 } 1944 1837 /* deprecated April 2018 [AG] 1838 1839 error_t vmm_v2p_translate( process_t * process, 1840 void * ptr, 1841 paddr_t * paddr ) 1842 { 1945 1843 // access page table 1946 1844 error_t error; … … 1953 1851 offset = (uint32_t)( ((intptr_t)ptr) & CONFIG_PPM_PAGE_MASK ); 1954 1852 1955 if( local_cxy == GET_CXY( process->ref_xp) ) // callingprocess is reference process1853 if( local_cxy == GET_CXY( process->ref_xp) ) // local process is reference process 1956 1854 { 1957 1855 error = vmm_get_pte( process, vpn , false , &attr , &ppn ); … … 1971 1869 } // end vmm_v2p_translate() 1972 1870 1973 1871 */
Note: See TracChangeset
for help on using the changeset viewer.