Changeset 629 for trunk/kernel/mm
- Timestamp:
- May 17, 2019, 9:27:04 AM (6 years ago)
- Location:
- trunk/kernel/mm
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kernel/mm/vmm.c
r625 r629 741 741 child_vmm = &child_process->vmm; 742 742 743 // initialize the locks protecting the child VSL and GPT 744 remote_rwlock_init( XPTR( local_cxy , &child_vmm->gpt_lock ) , LOCK_VMM_GPT ); 743 // initialize the lock protecting the child VSL 745 744 remote_rwlock_init( XPTR( local_cxy , &child_vmm->vsl_lock ) , LOCK_VMM_VSL ); 746 745 … … 952 951 xptr_t vsl_root_xp = XPTR( local_cxy , &vmm->vsegs_root ); 953 952 xptr_t vsl_lock_xp = XPTR( local_cxy , &vmm->vsl_lock ); 954 xptr_t gpt_lock_xp = XPTR( local_cxy , &vmm->gpt_lock );955 953 956 954 // take the VSL lock … … 1022 1020 } 1023 1021 1024 // take the GPT lock1025 remote_rwlock_wr_acquire( gpt_lock_xp );1026 1027 1022 // release memory allocated to the GPT itself 1028 1023 hal_gpt_destroy( &vmm->gpt ); 1029 1030 // release the GPT lock1031 remote_rwlock_wr_release( gpt_lock_xp );1032 1024 1033 1025 #if DEBUG_VMM_DESTROY … … 1226 1218 { 1227 1219 vmm_t * vmm; // local pointer on process VMM 1220 xptr_t gpt_xp; // extended pointer on GPT 1228 1221 bool_t is_ref; // local process is reference process 1229 1222 uint32_t vseg_type; // vseg type … … 1250 1243 vmm = &process->vmm; 1251 1244 1245 // build extended pointer on GPT 1246 gpt_xp = XPTR( local_cxy , &vmm->gpt ); 1247 1252 1248 // get relevant vseg infos 1253 1249 vseg_type = vseg->type; … … 1268 1264 { 1269 1265 // get ppn and attr 1270 hal_gpt_get_pte( XPTR( local_cxy , &vmm->gpt ), vpn , &attr , &ppn );1266 hal_gpt_get_pte( gpt_xp , vpn , &attr , &ppn ); 1271 1267 1272 1268 if( attr & GPT_MAPPED ) // PTE is mapped … … 1278 1274 #endif 1279 1275 // unmap GPT entry in local GPT 1280 hal_gpt_reset_pte( &vmm->gpt, vpn );1276 hal_gpt_reset_pte( gpt_xp , vpn ); 1281 1277 1282 1278 // get pointers on physical page descriptor … … 1915 1911 { 1916 1912 vseg_t * vseg; // vseg containing vpn 1917 uint32_t new_attr; // newPTE_ATTR value1918 ppn_t new_ppn; // newPTE_PPN value1913 uint32_t attr; // PTE_ATTR value 1914 ppn_t ppn; // PTE_PPN value 1919 1915 uint32_t ref_attr; // PTE_ATTR value in reference GPT 1920 1916 ppn_t ref_ppn; // PTE_PPN value in reference GPT … … 1922 1918 process_t * ref_ptr; // reference process for missing vpn 1923 1919 xptr_t local_gpt_xp; // extended pointer on local GPT 1924 xptr_t local_lock_xp; // extended pointer on local GPT lock1925 1920 xptr_t ref_gpt_xp; // extended pointer on reference GPT 1926 xptr_t ref_lock_xp; // extended pointer on reference GPT lock1927 1921 error_t error; // value returned by called functions 1928 1922 1923 thread_t * this = CURRENT_THREAD; 1924 1925 #if (CONFIG_INSTRUMENTATION_PGFAULTS || DEBUG_VMM_HANDLE_PAGE_FAULT) 1926 uint32_t start_cycle = (uint32_t)hal_get_cycles(); 1927 #endif 1928 1929 1929 #if DEBUG_VMM_HANDLE_PAGE_FAULT 1930 uint32_t cycle = (uint32_t)hal_get_cycles(); 1931 thread_t * this = CURRENT_THREAD; 1932 if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle ) 1930 if( DEBUG_VMM_HANDLE_PAGE_FAULT < start_cycle ) 1933 1931 printk("\n[%s] thread[%x,%x] enter for vpn %x / cycle %d\n", 1934 __FUNCTION__, this->process->pid, this->trdid, vpn, cycle ); 1935 hal_vmm_display( process , true ); 1932 __FUNCTION__, this->process->pid, this->trdid, vpn, start_cycle ); 1933 #endif 1934 1935 #if (DEBUG_VMM_HANDLE_PAGE_FAULT & 1) 1936 hal_vmm_display( this->process , false ); 1936 1937 #endif 1937 1938 … … 1942 1943 if( error ) 1943 1944 { 1944 printk("\n[ERROR] in %s : vpn %x in process %x not in registered vseg / cycle %d\n",1945 __FUNCTION__ , vpn , process->pid, (uint32_t)hal_get_cycles());1945 printk("\n[ERROR] in %s : vpn %x in thread[%x,%x] not in registered vseg\n", 1946 __FUNCTION__ , vpn , process->pid, this->trdid ); 1946 1947 1947 1948 return EXCP_USER_ERROR; … … 1949 1950 1950 1951 #if DEBUG_VMM_HANDLE_PAGE_FAULT 1951 cycle = (uint32_t)hal_get_cycles(); 1952 if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle ) 1953 printk("\n[%s] threadr[%x,%x] found vseg %s / cycle %d\n", 1954 __FUNCTION__, this->process->pid, this->trdid, vseg_type_str(vseg->type), cycle ); 1955 #endif 1956 1957 //////////////// private vseg => access only the local GPT 1958 if( (vseg->type == VSEG_TYPE_STACK) || (vseg->type == VSEG_TYPE_CODE) ) 1959 { 1960 // build extended pointer on local GPT and local GPT lock 1961 local_gpt_xp = XPTR( local_cxy , &process->vmm.gpt ); 1962 local_lock_xp = XPTR( local_cxy , &process->vmm.gpt_lock ); 1963 1964 // take local GPT lock in write mode 1965 remote_rwlock_wr_acquire( local_lock_xp ); 1966 1967 // check VPN still unmapped in local GPT 1968 1969 // do nothing if VPN has been mapped by a a concurrent page_fault 1970 hal_gpt_get_pte( local_gpt_xp, 1971 vpn, 1972 &new_attr, 1973 &new_ppn ); 1974 1975 if( (new_attr & GPT_MAPPED) == 0 ) // VPN still unmapped 1976 { 1977 // allocate and initialise a physical page depending on the vseg type 1978 error = vmm_get_one_ppn( vseg , vpn , &new_ppn ); 1979 1980 if( error ) 1981 { 1982 printk("\n[ERROR] in %s : no memory / process = %x / vpn = %x\n", 1983 __FUNCTION__ , process->pid , vpn ); 1984 1985 // release local GPT lock in write mode 1986 remote_rwlock_wr_release( local_lock_xp ); 1987 1988 return EXCP_KERNEL_PANIC; 1989 } 1990 1991 // define new_attr from vseg flags 1992 new_attr = GPT_MAPPED | GPT_SMALL; 1993 if( vseg->flags & VSEG_USER ) new_attr |= GPT_USER; 1994 if( vseg->flags & VSEG_WRITE ) new_attr |= GPT_WRITABLE; 1995 if( vseg->flags & VSEG_EXEC ) new_attr |= GPT_EXECUTABLE; 1996 if( vseg->flags & VSEG_CACHE ) new_attr |= GPT_CACHABLE; 1997 1998 // set PTE (PPN & attribute) to local GPT 1999 error = hal_gpt_set_pte( local_gpt_xp, 2000 vpn, 2001 new_attr, 2002 new_ppn ); 2003 if ( error ) 2004 { 2005 printk("\n[ERROR] in %s : cannot update local GPT / process %x / vpn = %x\n", 2006 __FUNCTION__ , process->pid , vpn ); 2007 2008 // release local GPT lock in write mode 2009 remote_rwlock_wr_release( local_lock_xp ); 2010 2011 return EXCP_KERNEL_PANIC; 2012 } 2013 } 2014 2015 // release local GPT lock in write mode 2016 remote_rwlock_wr_release( local_lock_xp ); 2017 2018 #if DEBUG_VMM_HANDLE_PAGE_FAULT 2019 cycle = (uint32_t)hal_get_cycles(); 2020 if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle ) 2021 printk("\n[%s] private page fault handled / vpn %x / ppn %x / attr %x / cycle %d\n", 2022 __FUNCTION__, vpn, new_ppn, new_attr, cycle ); 2023 #endif 2024 return EXCP_NON_FATAL; 2025 2026 } // end local GPT access 2027 2028 //////////// public vseg => access reference GPT 2029 else 1952 if( DEBUG_VMM_HANDLE_PAGE_FAULT < start_cycle ) 1953 printk("\n[%s] thread[%x,%x] found vseg %s\n", 1954 __FUNCTION__, this->process->pid, this->trdid, vseg_type_str(vseg->type) ); 1955 #endif 1956 1957 // build extended pointer on local GPT 1958 local_gpt_xp = XPTR( local_cxy , &process->vmm.gpt ); 1959 1960 // lock target PTE in local GPT and get current PPN and attributes 1961 error = hal_gpt_lock_pte( local_gpt_xp, 1962 vpn, 1963 &attr, 1964 &ppn ); 1965 if( error ) 1966 { 1967 printk("\n[PANIC] in %s : cannot lock PTE in local GPT / vpn %x / process %x\n", 1968 __FUNCTION__ , vpn , process->pid ); 1969 1970 return EXCP_KERNEL_PANIC; 1971 } 1972 1973 // handle page fault only if PTE still unmapped after lock 1974 if( (attr & GPT_MAPPED) == 0 ) 2030 1975 { 2031 1976 // get reference process cluster and local pointer … … 2033 1978 ref_ptr = GET_PTR( process->ref_xp ); 2034 1979 2035 // build extended pointer on reference GPT and reference GPT lock 2036 ref_gpt_xp = XPTR( ref_cxy , &ref_ptr->vmm.gpt ); 2037 ref_lock_xp = XPTR( ref_cxy , &ref_ptr->vmm.gpt_lock ); 2038 2039 // build extended pointer on local GPT and local GPT lock 2040 local_gpt_xp = XPTR( local_cxy , &process->vmm.gpt ); 2041 local_lock_xp = XPTR( local_cxy , &process->vmm.gpt_lock ); 2042 2043 // take reference GPT lock in read mode 2044 remote_rwlock_rd_acquire( ref_lock_xp ); 2045 2046 // get directly PPN & attributes from reference GPT 2047 // this can avoids a costly RPC for a false page fault 2048 hal_gpt_get_pte( ref_gpt_xp, 2049 vpn, 2050 &ref_attr, 2051 &ref_ppn ); 2052 2053 // release reference GPT lock in read mode 2054 remote_rwlock_rd_release( ref_lock_xp ); 2055 2056 if( ref_attr & GPT_MAPPED ) // false page fault => update local GPT 1980 // private vseg or (local == reference) => access only the local GPT 1981 if( (vseg->type == VSEG_TYPE_STACK) || 1982 (vseg->type == VSEG_TYPE_CODE) || 1983 (ref_cxy == local_cxy ) ) 2057 1984 { 2058 // take local GPT lock in write mode 2059 remote_rwlock_wr_acquire( local_lock_xp ); 2060 2061 // check VPN still unmapped in local GPT 2062 hal_gpt_get_pte( local_gpt_xp, 1985 // allocate and initialise a physical page depending on the vseg type 1986 error = vmm_get_one_ppn( vseg , vpn , &ppn ); 1987 1988 if( error ) 1989 { 1990 printk("\n[ERROR] in %s : no physical page / process = %x / vpn = %x\n", 1991 __FUNCTION__ , process->pid , vpn ); 1992 1993 // unlock PTE in local GPT 1994 hal_gpt_unlock_pte( local_gpt_xp , vpn ); 1995 1996 return EXCP_KERNEL_PANIC; 1997 } 1998 1999 // define attr from vseg flags 2000 attr = GPT_MAPPED | GPT_SMALL; 2001 if( vseg->flags & VSEG_USER ) attr |= GPT_USER; 2002 if( vseg->flags & VSEG_WRITE ) attr |= GPT_WRITABLE; 2003 if( vseg->flags & VSEG_EXEC ) attr |= GPT_EXECUTABLE; 2004 if( vseg->flags & VSEG_CACHE ) attr |= GPT_CACHABLE; 2005 2006 // set PTE to local GPT 2007 hal_gpt_set_pte( local_gpt_xp, 2063 2008 vpn, 2064 &new_attr, 2065 &new_ppn ); 2066 2067 if( (new_attr & GPT_MAPPED) == 0 ) // VPN still unmapped 2068 { 2069 // update local GPT from reference GPT 2070 error = hal_gpt_set_pte( local_gpt_xp, 2071 vpn, 2072 ref_attr, 2073 ref_ppn ); 2074 if( error ) 2075 { 2076 printk("\n[ERROR] in %s : cannot update local GPT / process %x / vpn %x\n", 2077 __FUNCTION__ , process->pid , vpn ); 2078 2079 // release local GPT lock in write mode 2080 remote_rwlock_wr_release( local_lock_xp ); 2081 2082 return EXCP_KERNEL_PANIC; 2083 } 2084 } 2085 else // VPN has been mapped by a a concurrent page_fault 2086 { 2087 // keep PTE from local GPT 2088 ref_attr = new_attr; 2089 ref_ppn = new_ppn; 2090 } 2091 2092 // release local GPT lock in write mode 2093 remote_rwlock_wr_release( local_lock_xp ); 2094 2009 attr, 2010 ppn ); 2011 2012 #if (CONFIG_INSTRUMENTATION_PGFAULTS || DEBUG_VMM_HANDLE_PAGE_FAULT) 2013 uint32_t end_cycle = (uint32_t)hal_get_cycles(); 2014 #endif 2015 2095 2016 #if DEBUG_VMM_HANDLE_PAGE_FAULT 2096 cycle = (uint32_t)hal_get_cycles(); 2097 if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle ) 2098 printk("\n[%s] false page fault handled / vpn %x / ppn %x / attr %x / cycle %d\n", 2099 __FUNCTION__, vpn, ref_ppn, ref_attr, cycle ); 2017 if( DEBUG_VMM_HANDLE_PAGE_FAULT < end_cycle ) 2018 printk("\n[%s] local page fault handled / vpn %x / ppn %x / attr %x / cycle %d\n", 2019 __FUNCTION__, vpn, ppn, attr, end_cycle ); 2020 #endif 2021 2022 #if CONFIG_INSTRUMENTATION_PGFAULTS 2023 this->info.local_pgfault_nr++; 2024 this->info.local_pgfault_cost += (end_cycle - start_cycle); 2100 2025 #endif 2101 2026 return EXCP_NON_FATAL; 2102 } 2103 else // true page fault => update reference GPT 2027 2028 } // end local GPT access 2029 2030 // public vseg and (local != reference) => access ref GPT to update local GPT 2031 else 2104 2032 { 2105 // take reference GPT lock in write mode 2106 remote_rwlock_wr_acquire( ref_lock_xp ); 2107 2108 // check VPN still unmapped in reference GPT 2109 // do nothing if VPN has been mapped by a a concurrent page_fault 2033 // build extended pointer on reference GPT 2034 ref_gpt_xp = XPTR( ref_cxy , &ref_ptr->vmm.gpt ); 2035 2036 // get current PPN and attributes from reference GPT 2110 2037 hal_gpt_get_pte( ref_gpt_xp, 2111 2038 vpn, … … 2113 2040 &ref_ppn ); 2114 2041 2115 if( (ref_attr & GPT_MAPPED) == 0 ) // VPN actually unmapped 2116 { 2042 if( ref_attr & GPT_MAPPED ) // false page fault => update local GPT 2043 { 2044 // update local GPT from reference GPT values 2045 hal_gpt_set_pte( local_gpt_xp, 2046 vpn, 2047 ref_attr, 2048 ref_ppn ); 2049 2050 #if (CONFIG_INSTRUMENTATION_PGFAULTS || DEBUG_VMM_HANDLE_PAGE_FAULT) 2051 uint32_t end_cycle = (uint32_t)hal_get_cycles(); 2052 #endif 2053 2054 #if DEBUG_VMM_HANDLE_PAGE_FAULT 2055 if( DEBUG_VMM_HANDLE_PAGE_FAULT < end_cycle ) 2056 printk("\n[%s] false page fault handled / vpn %x / ppn %x / attr %x / cycle %d\n", 2057 __FUNCTION__, vpn, ref_ppn, ref_attr, end_cycle ); 2058 #endif 2059 2060 #if CONFIG_INSTRUMENTATION_PGFAULTS 2061 this->info.false_pgfault_nr++; 2062 this->info.false_pgfault_cost += (end_cycle - start_cycle); 2063 #endif 2064 return EXCP_NON_FATAL; 2065 } 2066 else // true page fault => update both GPTs 2067 { 2117 2068 // allocate and initialise a physical page depending on the vseg type 2118 error = vmm_get_one_ppn( vseg , vpn , & new_ppn );2069 error = vmm_get_one_ppn( vseg , vpn , &ppn ); 2119 2070 2120 2071 if( error ) … … 2123 2074 __FUNCTION__ , process->pid , vpn ); 2124 2075 2125 // release reference GPT lock in write mode2126 remote_rwlock_wr_release( ref_lock_xp);2076 // unlock PTE in local GPT 2077 hal_gpt_unlock_pte( local_gpt_xp , vpn ); 2127 2078 2128 return EXCP_KERNEL_PANIC;2079 return EXCP_KERNEL_PANIC; 2129 2080 } 2130 2081 2131 // define new_attr from vseg flags 2132 new_attr = GPT_MAPPED | GPT_SMALL; 2133 if( vseg->flags & VSEG_USER ) new_attr |= GPT_USER; 2134 if( vseg->flags & VSEG_WRITE ) new_attr |= GPT_WRITABLE; 2135 if( vseg->flags & VSEG_EXEC ) new_attr |= GPT_EXECUTABLE; 2136 if( vseg->flags & VSEG_CACHE ) new_attr |= GPT_CACHABLE; 2137 2138 // update reference GPT 2139 error = hal_gpt_set_pte( ref_gpt_xp, 2140 vpn, 2141 new_attr, 2142 new_ppn ); 2143 2144 // update local GPT (protected by reference GPT lock) 2145 error |= hal_gpt_set_pte( local_gpt_xp, 2082 // lock PTE in reference GPT 2083 error = hal_gpt_lock_pte( ref_gpt_xp, 2146 2084 vpn, 2147 new_attr, 2148 new_ppn ); 2149 2085 &ref_attr, 2086 &ref_ppn ); 2150 2087 if( error ) 2151 2088 { 2152 printk("\n[ ERROR] in %s : cannot update GPT / process %x / vpn =%x\n",2153 __FUNCTION__ , process->pid , vpn);2154 2155 // release reference GPT lock in write mode2156 remote_rwlock_wr_release( ref_lock_xp);2157 2089 printk("\n[PANIC] in %s : cannot lock PTE in ref GPT / vpn %x / process %x\n", 2090 __FUNCTION__ , vpn , process->pid ); 2091 2092 // unlock PTE in local GPT 2093 hal_gpt_unlock_pte( local_gpt_xp , vpn ); 2094 2158 2095 return EXCP_KERNEL_PANIC; 2159 2096 } 2097 2098 // define attr from vseg flags 2099 attr = GPT_MAPPED | GPT_SMALL; 2100 if( vseg->flags & VSEG_USER ) attr |= GPT_USER; 2101 if( vseg->flags & VSEG_WRITE ) attr |= GPT_WRITABLE; 2102 if( vseg->flags & VSEG_EXEC ) attr |= GPT_EXECUTABLE; 2103 if( vseg->flags & VSEG_CACHE ) attr |= GPT_CACHABLE; 2104 2105 // set PTE in reference GPT 2106 hal_gpt_set_pte( ref_gpt_xp, 2107 vpn, 2108 attr, 2109 ppn ); 2110 2111 // set PTE in local GPT 2112 hal_gpt_set_pte( local_gpt_xp, 2113 vpn, 2114 attr, 2115 ppn ); 2116 2117 #if (CONFIG_INSTRUMENTATION_PGFAULTS || DEBUG_VMM_HANDLE_PAGE_FAULT) 2118 uint32_t end_cycle = (uint32_t)hal_get_cycles(); 2119 #endif 2120 2121 #if DEBUG_VMM_HANDLE_PAGE_FAULT 2122 if( DEBUG_VMM_HANDLE_PAGE_FAULT < end_cycle ) 2123 printk("\n[%s] global page fault handled / vpn %x / ppn %x / attr %x / cycle %d\n", 2124 __FUNCTION__, vpn, ppn, attr, end_cycle ); 2125 #endif 2126 2127 #if CONFIG_INSTRUMENTATION_PGFAULTS 2128 this->info.global_pgfault_nr++; 2129 this->info.global_pgfault_cost += (end_cycle - start_cycle); 2130 #endif 2131 return EXCP_NON_FATAL; 2160 2132 } 2161 2162 // release reference GPT lock in write mode2163 remote_rwlock_wr_release( ref_lock_xp );2164 2165 #if DEBUG_VMM_HANDLE_PAGE_FAULT2166 cycle = (uint32_t)hal_get_cycles();2167 if( DEBUG_VMM_HANDLE_PAGE_FAULT < cycle )2168 printk("\n[%s] true page fault handled / vpn %x / ppn %x / attr %x / cycle %d\n",2169 __FUNCTION__, vpn, new_ppn, new_attr, cycle );2170 #endif2171 return EXCP_NON_FATAL;2172 2133 } 2173 2134 } 2135 else // page has been locally mapped by another concurrent thread 2136 { 2137 // unlock PTE in local GPT 2138 hal_gpt_unlock_pte( local_gpt_xp , vpn ); 2139 2140 return EXCP_NON_FATAL; 2141 } 2142 2174 2143 } // end vmm_handle_page_fault() 2175 2144 … … 2179 2148 { 2180 2149 vseg_t * vseg; // vseg containing vpn 2181 cxy_t ref_cxy; // reference cluster for missing vpn 2182 process_t * ref_ptr; // reference process for missing vpn 2183 xptr_t gpt_xp; // extended pointer on GPT 2184 xptr_t gpt_lock_xp; // extended pointer on GPT lock 2150 xptr_t gpt_xp; // extended pointer on GPT (local or reference) 2151 gpt_t * gpt_ptr; // local pointer on GPT (local or reference) 2152 cxy_t gpt_cxy; // GPT cluster identifier 2185 2153 uint32_t old_attr; // current PTE_ATTR value 2186 2154 ppn_t old_ppn; // current PTE_PPN value 2187 2155 uint32_t new_attr; // new PTE_ATTR value 2188 2156 ppn_t new_ppn; // new PTE_PPN value 2157 cxy_t ref_cxy; // reference process cluster 2158 process_t * ref_ptr; // local pointer on reference process 2189 2159 error_t error; 2190 2160 2191 thread_t * this = CURRENT_THREAD;2161 thread_t * this = CURRENT_THREAD; 2192 2162 2193 2163 #if DEBUG_VMM_HANDLE_COW 2194 uint32_t cycle 2164 uint32_t cycle = (uint32_t)hal_get_cycles(); 2195 2165 if( DEBUG_VMM_HANDLE_COW < cycle ) 2196 2166 printk("\n[%s] thread[%x,%x] enter for vpn %x / core[%x,%d] / cycle %d\n", 2197 2167 __FUNCTION__, this->process->pid, this->trdid, vpn, local_cxy, this->core->lid, cycle ); 2168 #endif 2169 2170 #if (DEBUG_VMM_HANDLE_PAGE_FAULT & 1) 2198 2171 hal_vmm_display( process , true ); 2199 2172 #endif 2200 2201 // access local GPT to get GPT_COW flag2202 bool_t cow = hal_gpt_pte_is_cow( &(process->vmm.gpt), vpn );2203 2204 if( cow == false ) return EXCP_USER_ERROR;2205 2173 2206 2174 // get local vseg … … 2210 2178 if( error ) 2211 2179 { 2212 printk("\n[ PANIC] in %svpn %x in thread[%x,%x] not in a registered vseg\n",2180 printk("\n[ERROR] in %s : vpn %x in thread[%x,%x] not in a registered vseg\n", 2213 2181 __FUNCTION__, vpn, process->pid, this->trdid ); 2214 2182 2215 return EXCP_ KERNEL_PANIC;2216 } 2217 2218 #if ( DEBUG_VMM_HANDLE_COW & 1)2183 return EXCP_USER_ERROR; 2184 } 2185 2186 #if DEBUG_VMM_HANDLE_COW 2219 2187 if( DEBUG_VMM_HANDLE_COW < cycle ) 2220 printk("\n[%s] thread[%x,%x] get vseg for vpn %x\n",2221 __FUNCTION__, this->process->pid, this->trdid, v pn);2222 #endif 2223 2224 // get reference GPTcluster and local pointer2188 printk("\n[%s] thread[%x,%x] get vseg %s\n", 2189 __FUNCTION__, this->process->pid, this->trdid, vseg_type_str(vseg->type) ); 2190 #endif 2191 2192 // get reference process cluster and local pointer 2225 2193 ref_cxy = GET_CXY( process->ref_xp ); 2226 2194 ref_ptr = GET_PTR( process->ref_xp ); 2227 2195 2228 // build relevant extended pointers on relevant GPT and GPT lock2229 // - access local GPT for a private vseg2230 // - access reference GPT for a public vseg2196 // build pointers on relevant GPT 2197 // - access only local GPT for a private vseg 2198 // - access reference GPT and all copies for a public vseg 2231 2199 if( (vseg->type == VSEG_TYPE_STACK) || (vseg->type == VSEG_TYPE_CODE) ) 2232 2200 { 2233 gpt_xp = XPTR( local_cxy , &process->vmm.gpt ); 2234 gpt_lock_xp = XPTR( local_cxy , &process->vmm.gpt_lock ); 2201 gpt_cxy = local_cxy; 2202 gpt_ptr = &process->vmm.gpt; 2203 gpt_xp = XPTR( gpt_cxy , gpt_ptr ); 2235 2204 } 2236 2205 else 2237 2206 { 2238 gpt_xp = XPTR( ref_cxy , &ref_ptr->vmm.gpt ); 2239 gpt_lock_xp = XPTR( ref_cxy , &ref_ptr->vmm.gpt_lock ); 2240 } 2241 2242 // take GPT lock in write mode 2243 remote_rwlock_wr_acquire( gpt_lock_xp ); 2244 2245 // get current PTE from reference GPT 2246 hal_gpt_get_pte( gpt_xp, 2247 vpn, 2248 &old_attr, 2249 &old_ppn ); 2250 2251 #if( DEBUG_VMM_HANDLE_COW & 1) 2207 gpt_cxy = ref_cxy; 2208 gpt_ptr = &ref_ptr->vmm.gpt; 2209 gpt_xp = XPTR( gpt_cxy , gpt_ptr ); 2210 } 2211 2212 // lock target PTE in relevant GPT (local or reference) 2213 error = hal_gpt_lock_pte( gpt_xp, 2214 vpn, 2215 &old_attr, 2216 &old_ppn ); 2217 if( error ) 2218 { 2219 printk("\n[PANIC] in %s : cannot lock PTE in GPT / cxy %x / vpn %x / process %x\n", 2220 __FUNCTION__ , gpt_cxy, vpn , process->pid ); 2221 2222 return EXCP_KERNEL_PANIC; 2223 } 2224 2225 #if DEBUG_VMM_HANDLE_COW 2252 2226 if( DEBUG_VMM_HANDLE_COW < cycle ) 2253 2227 printk("\n[%s] thread[%x,%x] get pte for vpn %x : ppn %x / attr %x\n", … … 2255 2229 #endif 2256 2230 2257 // the PTE must be mapped for a COW 2258 if( (old_attr & GPT_MAPPED) == 0 ) 2259 { 2260 printk("\n[PANIC] in %s : VPN %x in process %x unmapped\n", 2261 __FUNCTION__, vpn, process->pid ); 2262 2263 // release GPT lock in write mode 2264 remote_rwlock_wr_release( gpt_lock_xp ); 2265 2266 return EXCP_KERNEL_PANIC; 2231 // return user error if COW attribute not set or PTE2 unmapped 2232 if( ((old_attr & GPT_COW) == 0) || ((old_attr & GPT_MAPPED) == 0) ) 2233 { 2234 hal_gpt_unlock_pte( gpt_xp , vpn ); 2235 2236 return EXCP_USER_ERROR; 2267 2237 } 2268 2238 … … 2282 2252 uint32_t forks = hal_remote_l32( forks_xp ); 2283 2253 2284 #if ( DEBUG_VMM_HANDLE_COW & 1)2254 #if DEBUG_VMM_HANDLE_COW 2285 2255 if( DEBUG_VMM_HANDLE_COW < cycle ) 2286 2256 printk("\n[%s] thread[%x,%x] get forks = %d for vpn %x\n", … … 2296 2266 remote_busylock_release( forks_lock_xp ); 2297 2267 2298 // allocate a new p age2268 // allocate a new physical page depending on vseg type 2299 2269 page_xp = vmm_page_allocate( vseg , vpn ); 2300 2270 … … 2304 2274 __FUNCTION__ , vpn, process->pid ); 2305 2275 2306 // release GPT lock in write mode 2307 remote_rwlock_wr_acquire( gpt_lock_xp ); 2276 hal_gpt_unlock_pte( gpt_xp , vpn ); 2308 2277 2309 2278 return EXCP_KERNEL_PANIC; … … 2313 2282 new_ppn = ppm_page2ppn( page_xp ); 2314 2283 2315 #if ( DEBUG_VMM_HANDLE_COW & 1)2284 #if DEBUG_VMM_HANDLE_COW 2316 2285 if( DEBUG_VMM_HANDLE_COW < cycle ) 2317 2286 printk("\n[%s] thread[%x,%x] get new ppn %x for vpn %x\n", … … 2324 2293 CONFIG_PPM_PAGE_SIZE ); 2325 2294 2326 #if (DEBUG_VMM_HANDLE_COW & 1)2295 #if DEBUG_VMM_HANDLE_COW 2327 2296 if( DEBUG_VMM_HANDLE_COW < cycle ) 2328 2297 printk("\n[%s] thread[%x,%x] copied old page to new page\n", … … 2344 2313 } 2345 2314 2346 // build new_attr : reset COW and set WRITABLE,2347 new_attr = ( old_attr | GPT_WRITABLE) & (~GPT_COW);2348 2349 // update the relevant GPT 2350 // - private vseg => update local GPT2351 // - public vseg => update allGPT copies2315 // build new_attr : set WRITABLE, reset COW, reset LOCKED 2316 new_attr = (((old_attr | GPT_WRITABLE) & (~GPT_COW)) & (~GPT_LOCKED)); 2317 2318 // update the relevant GPT(s) 2319 // - private vseg => update only the local GPT 2320 // - public vseg => update the reference GPT AND all the GPT copies 2352 2321 if( (vseg->type == VSEG_TYPE_STACK) || (vseg->type == VSEG_TYPE_CODE) ) 2353 2322 { 2323 // set the new PTE2 2354 2324 hal_gpt_set_pte( gpt_xp, 2355 2325 vpn, … … 2376 2346 } 2377 2347 2378 // release GPT lock in write mode2379 remote_rwlock_wr_release( gpt_lock_xp );2380 2381 2348 #if DEBUG_VMM_HANDLE_COW 2382 2349 cycle = (uint32_t)hal_get_cycles(); -
trunk/kernel/mm/vmm.h
r625 r629 106 106 * 3. The GPT in the reference cluster can be directly accessed by remote threads to handle 107 107 * false page-fault (page is mapped in the reference GPT, but the PTE copy is missing 108 * in the local GPT). It is also protected by a remote_rwlock. 108 * in the local GPT). As each PTE can be protected by a specific GPT_LOCKED attribute 109 * for exclusive access, it is NOT protected by a global lock. 109 110 ********************************************************************************************/ 110 111 … … 115 116 uint32_t vsegs_nr; /*! total number of local vsegs */ 116 117 117 remote_rwlock_t gpt_lock; /*! lock protecting the local GPT */118 118 gpt_t gpt; /*! Generic Page Table (complete in reference) */ 119 119 … … 165 165 * This function is called by the process_make_fork() function. It partially copies 166 166 * the content of a remote parent process VMM to the local child process VMM: 167 * - AllDATA, ANON, REMOTE vsegs registered in the parent VSL are registered in the167 * - The DATA, ANON, REMOTE vsegs registered in the parent VSL are registered in the 168 168 * child VSL. All valid PTEs in parent GPT are copied to the child GPT, but the 169 169 * WRITABLE flag is reset and the COW flag is set. 170 * - AllCODE vsegs registered in the parent VSL are registered in the child VSL, but the170 * - The CODE vsegs registered in the parent VSL are registered in the child VSL, but the 171 171 * GPT entries are not copied in the child GPT, and will be dynamically updated from 172 172 * the .elf file when a page fault is reported. 173 * - AllFILE vsegs registered in the parent VSL are registered in the child VSL, and all173 * - The FILE vsegs registered in the parent VSL are registered in the child VSL, and all 174 174 * valid GPT entries in parent GPT are copied to the child GPT. The COW flag is not set. 175 175 * - No STACK vseg is copied from parent VMM to child VMM, because the child stack vseg … … 186 186 187 187 /********************************************************************************************* 188 * This function is called by the process_make_fork() function executing the fork syscall.189 * It set the COW flag, and reset the WRITABLE flag of all GPT entries of the DATA, MMAP,190 * a nd REMOTE vsegs of a process identified bythe <process> argument.188 * This function is called by the process_make_fork() function to update the COW attribute 189 * in the parent parent process vsegs. It set the COW flag, and reset the WRITABLE flag of 190 * all GPT entries of the DATA, MMAP, and REMOTE vsegs of the <process> argument. 191 191 * It must be called by a thread running in the reference cluster, that contains the complete 192 192 * VSL and GPT (use the rpc_vmm_set_cow_client() when the calling thread client is remote). … … 201 201 202 202 /********************************************************************************************* 203 * This function modifies aGPT entry identified by the <process> and <vpn> arguments203 * This function modifies one GPT entry identified by the <process> and <vpn> arguments 204 204 * in all clusters containing a process copy. 205 * It must be called by a thread running in the referencecluster.206 * It updates all copies of the process in all clusters, to maintain coherence in GPT copies,207 * using the list of copies stored in the owner process, and using remote_write accesses to208 * update the remote GPTs. It cannot fail, as only mapped entriesin GPT copies are updated.205 * It must be called by a thread running in the process owner cluster. 206 * It is used to update to maintain coherence in GPT copies, using the list of copies 207 * stored in the owner process, and uses remote_write accesses. 208 * It cannot fail, as only mapped PTE2 in GPT copies are updated. 209 209 ********************************************************************************************* 210 210 * @ process : local pointer on local process descriptor. … … 373 373 * is mapped in the reference GPT, but not in the local GPT. For this false page-fault, 374 374 * the local GPT is simply updated from the reference GPT. 375 * 3) if the missing VPN is public, and unmapped in the ref erence GPT, it's a true page fault.375 * 3) if the missing VPN is public, and unmapped in the ref GPT, it is a true page fault. 376 376 * The calling thread allocates a new physical page, computes the attributes, depending 377 377 * on vseg type, and updates directly (without RPC) the local GPT and the reference GPT. 378 378 * Other GPT copies will updated on demand. 379 * Concurrent accesses to the GPT are handled, thanks to the380 * remote_rwlock protecting each GPT copy.379 * Concurrent accesses to the GPT(s) are handled, by locking the target PTE before accessing 380 * the local and/or reference GPT(s). 381 381 ********************************************************************************************* 382 382 * @ process : local pointer on local process. … … 392 392 * It returns a kernel panic if VPN is not in a registered vseg or is not mapped. 393 393 * For a legal mapped vseg there is two cases: 394 * 1) If the missing VPN belongs to a private vseg (STACK or CODE segment types, non 395 * replicated in all clusters), it access the local GPT to get the current PPN and ATTR. 394 * 1) If the missing VPN belongs to a private vseg (STACK), it access only the local GPT. 396 395 * It access the forks counter in the current physical page descriptor. 397 396 * If there is a pending fork, it allocates a new physical page from the cluster defined … … 399 398 * and decrements the pending_fork counter in old physical page descriptor. 400 399 * Finally, it reset the COW flag and set the WRITE flag in local GPT. 401 * 2) If the missing VPN is public, it access the reference GPT to get the current PPN and402 * ATTR.It access the forks counter in the current physical page descriptor.400 * 2) If the missing VPN is public, it access only the reference GPT. 401 * It access the forks counter in the current physical page descriptor. 403 402 * If there is a pending fork, it allocates a new physical page from the cluster defined 404 403 * by the vseg type, copies the old physical page content to the new physical page, … … 406 405 * Finally it calls the vmm_global_update_pte() function to reset the COW flag and set 407 406 * the WRITE flag in all the GPT copies, using a RPC if the reference cluster is remote. 408 * In both cases, concurrent accesses to the GPT are protected by the remote_rwlock409 * atached to the GPT copy in VMM.407 * In both cases, concurrent accesses to the GPT are handled by locking the target PTE 408 * before accessing the GPT. 410 409 ********************************************************************************************* 411 410 * @ process : pointer on local process descriptor copy.
Note: See TracChangeset
for help on using the changeset viewer.