kernel/eka/memmodel/epoc/flexible/mmu/mmu.cpp
changeset 14 5d2844f35677
parent 8 538db54a451d
child 20 597aaf25e343
equal deleted inserted replaced
8:538db54a451d 14:5d2844f35677
   731 //	TRACE(("%O mapping=0x%08x",TheCurrentThread,mapping));
   731 //	TRACE(("%O mapping=0x%08x",TheCurrentThread,mapping));
   732 	TInt r = KErrNotFound;
   732 	TInt r = KErrNotFound;
   733 
   733 
   734 	if(mapping)
   734 	if(mapping)
   735 		{
   735 		{
   736 		// Pinning mappings should not be found from within an address space.
       
   737 		__NK_ASSERT_DEBUG(!mapping->IsPinned());
       
   738 		MmuLock::Lock();
   736 		MmuLock::Lock();
   739 
   737 
   740 		// check if we need to process page fault...
   738 		// check if we need to process page fault...
   741 		if(!Mmu::CheckPteTypePermissions(mapping->PteType(),aAccessPermissions) ||
   739 		if(!Mmu::CheckPteTypePermissions(mapping->PteType(),aAccessPermissions) ||
   742 			mapInstanceCount != mapping->MapInstanceCount())
   740 			mapInstanceCount != mapping->MapInstanceCount())
   745 			MmuLock::Unlock();
   743 			MmuLock::Unlock();
   746 			r = KErrAbort;
   744 			r = KErrAbort;
   747 			}
   745 			}
   748 		else
   746 		else
   749 			{
   747 			{
       
   748 			// Should not be able to take a fault on a pinned mapping if accessing it 
       
   749 			// with the correct permissions.
       
   750 			__NK_ASSERT_DEBUG(!mapping->IsPinned());
       
   751 
   750 			// we do need to handle fault so is this a demand paging or page moving fault
   752 			// we do need to handle fault so is this a demand paging or page moving fault
   751 			DMemoryObject* memory = mapping->Memory();
   753 			DMemoryObject* memory = mapping->Memory();
   752 			if(!memory)
   754 			if(!memory)
   753 				MmuLock::Unlock();
   755 				MmuLock::Unlock();
   754 			else
   756 			else
  2159 	return aPinObject != NULL ? KErrNone : KErrNoMemory;
  2161 	return aPinObject != NULL ? KErrNone : KErrNoMemory;
  2160 	}
  2162 	}
  2161 
  2163 
  2162 TInt M::PinVirtualMemory(TVirtualPinObject* aPinObject, TLinAddr aStart, TUint aSize, DThread* aThread)
  2164 TInt M::PinVirtualMemory(TVirtualPinObject* aPinObject, TLinAddr aStart, TUint aSize, DThread* aThread)
  2163 	{
  2165 	{
  2164 	NKern::ThreadEnterCS();
  2166 	__ASSERT_CRITICAL;
  2165 	TUint offsetInMapping;
  2167 	TUint offsetInMapping;
  2166 	TUint mapInstanceCount;
  2168 	TUint mapInstanceCount;
  2167 	DMemoryMapping* mapping = MM::FindMappingInThread(	(DMemModelThread*)aThread, 
  2169 	DMemoryMapping* mapping = MM::FindMappingInThread(	(DMemModelThread*)aThread, 
  2168 														aStart, 
  2170 														aStart, 
  2169 														aSize, 
  2171 														aSize, 
  2203 															mapping, mapInstanceCount);
  2205 															mapping, mapInstanceCount);
  2204 				memory->Close();
  2206 				memory->Close();
  2205 				}
  2207 				}
  2206 			}
  2208 			}
  2207 		mapping->Close();
  2209 		mapping->Close();
  2208 		}
  2210 		}	
  2209 	NKern::ThreadLeaveCS();
       
  2210 	
       
  2211 	return r;
  2211 	return r;
  2212 	}
  2212 	}
  2213 
  2213 
  2214 TInt M::CreateAndPinVirtualMemory(TVirtualPinObject*& aPinObject, TLinAddr aStart, TUint aSize)
  2214 TInt M::CreateAndPinVirtualMemory(TVirtualPinObject*& aPinObject, TLinAddr aStart, TUint aSize)
  2215 	{
  2215 	{
       
  2216 	__ASSERT_CRITICAL;
  2216 	aPinObject = 0;
  2217 	aPinObject = 0;
  2217 	NKern::ThreadEnterCS();
       
  2218 	TUint offsetInMapping;
  2218 	TUint offsetInMapping;
  2219 	TUint mapInstanceCount;
  2219 	TUint mapInstanceCount;
  2220 	DMemoryMapping* mapping = MM::FindMappingInThread(	(DMemModelThread*)&Kern::CurrentThread(), 
  2220 	DMemoryMapping* mapping = MM::FindMappingInThread(	(DMemModelThread*)&Kern::CurrentThread(), 
  2221 														aStart, 
  2221 														aStart, 
  2222 														aSize, 
  2222 														aSize, 
  2262 					}
  2262 					}
  2263 				memory->Close();
  2263 				memory->Close();
  2264 				}
  2264 				}
  2265 			}
  2265 			}
  2266 		mapping->Close();
  2266 		mapping->Close();
  2267 		}
  2267 		}	
  2268 	NKern::ThreadLeaveCS();
       
  2269 	
       
  2270 	return r;
  2268 	return r;
  2271 	}
  2269 	}
  2272 
  2270 
  2273 void M::UnpinVirtualMemory(TVirtualPinObject* aPinObject)
  2271 void M::UnpinVirtualMemory(TVirtualPinObject* aPinObject)
  2274 	{
  2272 	{
  2286 			mapping->Unpin();
  2284 			mapping->Unpin();
  2287 		mapping->AsyncClose();
  2285 		mapping->AsyncClose();
  2288 		}
  2286 		}
  2289 	}
  2287 	}
  2290 
  2288 
       
  2289 //
       
  2290 // Physical pinning
       
  2291 //
       
  2292 
  2291 TInt M::CreatePhysicalPinObject(TPhysicalPinObject*& aPinObject)
  2293 TInt M::CreatePhysicalPinObject(TPhysicalPinObject*& aPinObject)
  2292 	{
  2294 	{
  2293 	aPinObject = (TPhysicalPinObject*)new DPhysicalPinMapping;
  2295 	aPinObject = (TPhysicalPinObject*)new DPhysicalPinMapping;
  2294 	return aPinObject != NULL ? KErrNone : KErrNoMemory;
  2296 	return aPinObject != NULL ? KErrNone : KErrNoMemory;
  2295 	}
  2297 	}
  2296 
  2298 
  2297 //
       
  2298 // Physical pinning
       
  2299 //
       
  2300 
       
  2301 TInt M::PinPhysicalMemory(TPhysicalPinObject* aPinObject, TLinAddr aStart, TUint aSize, TBool aReadOnly,
  2299 TInt M::PinPhysicalMemory(TPhysicalPinObject* aPinObject, TLinAddr aStart, TUint aSize, TBool aReadOnly,
  2302 				TPhysAddr& aAddress, TPhysAddr* aPages, TUint32& aMapAttr, TUint& aColour, DThread* aThread)
  2300 				TPhysAddr& aAddress, TPhysAddr* aPages, TUint32& aMapAttr, TUint& aColour, DThread* aThread)
  2303 	{
  2301 	{
  2304 	NKern::ThreadEnterCS();
  2302 	__ASSERT_CRITICAL;
  2305 	TUint offsetInMapping;
  2303 	TUint offsetInMapping;
  2306 	TUint mapInstanceCount;
  2304 	TUint mapInstanceCount;
  2307 	DMemoryMapping* mapping = MM::FindMappingInThread(	(DMemModelThread*)aThread, 
  2305 	DMemoryMapping* mapping = MM::FindMappingInThread(	(DMemModelThread*)aThread, 
  2308 														aStart, 
  2306 														aStart, 
  2309 														aSize, 
  2307 														aSize, 
  2343 			{
  2341 			{
  2344 			MmuLock::Unlock();
  2342 			MmuLock::Unlock();
  2345 			}
  2343 			}
  2346 		mapping->Close();
  2344 		mapping->Close();
  2347 		}
  2345 		}
  2348 	NKern::ThreadLeaveCS();
       
  2349 	aColour = (aStart >>KPageShift) & KPageColourMask;
  2346 	aColour = (aStart >>KPageShift) & KPageColourMask;
  2350 	return r;
  2347 	return r;
  2351 	}
  2348 	}
  2352 
  2349 
  2353 void M::UnpinPhysicalMemory(TPhysicalPinObject* aPinObject)
  2350 void M::UnpinPhysicalMemory(TPhysicalPinObject* aPinObject)
  2366 			mapping->Unpin();
  2363 			mapping->Unpin();
  2367 		mapping->AsyncClose();
  2364 		mapping->AsyncClose();
  2368 		}
  2365 		}
  2369 	}
  2366 	}
  2370 
  2367 
       
  2368 
       
  2369 //
       
  2370 // Kernel map and pin.
       
  2371 //
       
  2372 
       
  2373 TInt M::CreateKernelMapObject(TKernelMapObject*& aMapObject, TUint aMaxReserveSize)
       
  2374 	{
       
  2375 	DKernelPinMapping*  pinObject = new DKernelPinMapping();
       
  2376 	aMapObject = (TKernelMapObject*) pinObject;
       
  2377 	if (pinObject == NULL)
       
  2378 		{
       
  2379 		return KErrNoMemory;
       
  2380 		}
       
  2381 	// Ensure we reserve enough bytes for all possible alignments of the start and 
       
  2382 	// end of the region to map.
       
  2383 	TUint reserveBytes = aMaxReserveSize? ((aMaxReserveSize + KPageMask) & ~KPageMask) + KPageSize : 0;
       
  2384 	TInt r = pinObject->Construct(reserveBytes);
       
  2385 	if (r != KErrNone)
       
  2386 		{// Failed so delete the kernel mapping object.
       
  2387 		pinObject->Close();
       
  2388 		aMapObject = NULL;
       
  2389 		}
       
  2390 	return r;
       
  2391 	}
       
  2392 
       
  2393 
       
  2394 TInt M::MapAndPinMemory(TKernelMapObject* aMapObject, DThread* aThread, TLinAddr aStart, 
       
  2395 						TUint aSize, TUint aMapAttributes, TLinAddr& aKernelAddr, TPhysAddr* aPages)
       
  2396 	{
       
  2397 	__ASSERT_CRITICAL;
       
  2398 	TUint offsetInMapping;
       
  2399 	TUint mapInstanceCount;
       
  2400 	DMemoryMapping* mapping = MM::FindMappingInThread(	(DMemModelThread*)aThread, 
       
  2401 														aStart, 
       
  2402 														aSize, 
       
  2403 														offsetInMapping, 
       
  2404 														mapInstanceCount);
       
  2405 	TInt r = KErrBadDescriptor;
       
  2406 	if (mapping)
       
  2407 		{
       
  2408 		DKernelPinMapping* kernelMap = (DKernelPinMapping*)aMapObject;
       
  2409 		TInt count = (((aStart + aSize + KPageMask) & ~KPageMask) - (aStart & ~KPageMask)) >> KPageShift;
       
  2410 		if (kernelMap->iReservePages && kernelMap->iReservePages < count)
       
  2411 			{
       
  2412 			mapping->Close();
       
  2413 			return KErrArgument;
       
  2414 			}
       
  2415 
       
  2416 		MmuLock::Lock();
       
  2417 		DMemoryObject* memory = mapping->Memory();
       
  2418 		if (mapInstanceCount == mapping->MapInstanceCount() && memory)
       
  2419 			{
       
  2420 			memory->Open();
       
  2421 			MmuLock::Unlock();
       
  2422 
       
  2423 			TUint startInMemory = (offsetInMapping >> KPageShift) + mapping->iStartIndex;
       
  2424 			TBool readOnly = aMapAttributes & Kern::EKernelMap_ReadOnly;
       
  2425 			TMappingPermissions permissions =  readOnly ? ESupervisorReadOnly : ESupervisorReadWrite;
       
  2426 			r = kernelMap->MapAndPin(memory, startInMemory, count, permissions);
       
  2427 			if (r == KErrNone)
       
  2428 				{
       
  2429 				__NK_ASSERT_DEBUG(!kernelMap->IsUserMapping());
       
  2430 				aKernelAddr = kernelMap->Base();
       
  2431 				TPhysAddr contigAddr;	// Ignore this value as aPages will be populated 
       
  2432 										// whether the memory is contiguous or not.
       
  2433 				r = kernelMap->PhysAddr(0, count, contigAddr, aPages);
       
  2434 				if (r>=KErrNone)
       
  2435 					{
       
  2436 					r = KErrNone; //Do not report discontiguous memory in return value.
       
  2437 					}
       
  2438 				else
       
  2439 					{
       
  2440 					UnmapAndUnpinMemory((TKernelMapObject*)kernelMap);
       
  2441 					}
       
  2442 				}
       
  2443 			memory->Close();
       
  2444 			}
       
  2445 		else // mapping has been reused or no memory...
       
  2446 			{
       
  2447 			MmuLock::Unlock();
       
  2448 			}
       
  2449 		mapping->Close();
       
  2450 		}
       
  2451 	return r;
       
  2452 	}
       
  2453 
       
  2454 
       
  2455 void M::UnmapAndUnpinMemory(TKernelMapObject* aMapObject)
       
  2456 	{
       
  2457 	DKernelPinMapping* mapping = (DKernelPinMapping*)aMapObject;
       
  2458 	if (mapping->IsAttached())
       
  2459 		mapping->UnmapAndUnpin();
       
  2460 	}
       
  2461 
       
  2462 
       
  2463 void M::DestroyKernelMapObject(TKernelMapObject*& aMapObject)
       
  2464 	{
       
  2465 	DKernelPinMapping* mapping = (DKernelPinMapping*)__e32_atomic_swp_ord_ptr(&aMapObject, 0);
       
  2466 	if (mapping)
       
  2467 		{
       
  2468 		if (mapping->IsAttached())
       
  2469 			mapping->UnmapAndUnpin();
       
  2470 		mapping->AsyncClose();
       
  2471 		}
       
  2472 	}
  2371 
  2473 
  2372 
  2474 
  2373 //
  2475 //
  2374 // Cache sync operations
  2476 // Cache sync operations
  2375 //
  2477 //