363 aPhysicalAddress = physStart; |
363 aPhysicalAddress = physStart; |
364 return KErrNone; |
364 return KErrNone; |
365 } |
365 } |
366 } |
366 } |
367 |
367 |
|
368 |
368 TInt ArmMmu::PreparePagesForDMA(TLinAddr aLinAddr, TInt aSize, TInt aOsAsid, TPhysAddr* aPhysicalPageList) |
369 TInt ArmMmu::PreparePagesForDMA(TLinAddr aLinAddr, TInt aSize, TInt aOsAsid, TPhysAddr* aPhysicalPageList) |
369 //Returns the list of physical pages belonging to the specified memory space. |
370 //Returns the list of physical pages belonging to the specified memory space. |
370 //Checks these pages belong to a chunk marked as being trusted. |
371 //Checks these pages belong to a chunk marked as being trusted. |
371 //Locks these pages so they can not be moved by e.g. ram defragmenation. |
372 //Locks these pages so they can not be moved by e.g. ram defragmentation. |
372 { |
373 { |
373 SPageInfo* pi = NULL; |
374 SPageInfo* pi = NULL; |
374 DChunk* chunk = NULL; |
375 DChunk* chunk = NULL; |
375 TInt err = KErrNone; |
376 TInt err = KErrNone; |
|
377 |
|
378 __NK_ASSERT_DEBUG(MM::MaxPagesInOneGo == 32); // Needs to be a power of 2. |
|
379 TUint flashMask = MM::MaxPagesInOneGo - 1; |
376 |
380 |
377 __KTRACE_OPT(KMMU2,Kern::Printf("ArmMmu::PreparePagesForDMA %08x+%08x, asid=%d",aLinAddr,aSize,aOsAsid)); |
381 __KTRACE_OPT(KMMU2,Kern::Printf("ArmMmu::PreparePagesForDMA %08x+%08x, asid=%d",aLinAddr,aSize,aOsAsid)); |
378 |
382 |
379 TUint32* pageList = aPhysicalPageList; |
383 TUint32* pageList = aPhysicalPageList; |
380 TInt pagesInList = 0; //The number of pages we put in the list so far |
384 TInt pagesInList = 0; //The number of pages we put in the list so far |
386 |
390 |
387 |
391 |
388 MmuBase::Wait(); // RamAlloc Mutex for accessing page/directory tables. |
392 MmuBase::Wait(); // RamAlloc Mutex for accessing page/directory tables. |
389 NKern::LockSystem();// SystemlLock for accessing SPageInfo objects. |
393 NKern::LockSystem();// SystemlLock for accessing SPageInfo objects. |
390 |
394 |
|
395 // Get the page directory entry that maps aLinAddr. |
|
396 // If the address is in the global region check whether this asid maps |
|
397 // global pdes (i.e. the LSB of iAsidInfo is set), if not find the pde from |
|
398 // the kernel's initial page directory. |
391 TPde* pdePtr = (pdeIndex<(iLocalPdSize>>2) || (iAsidInfo[aOsAsid]&1)) ? PageDirectory(aOsAsid) : ::InitPageDirectory; |
399 TPde* pdePtr = (pdeIndex<(iLocalPdSize>>2) || (iAsidInfo[aOsAsid]&1)) ? PageDirectory(aOsAsid) : ::InitPageDirectory; |
392 pdePtr += pdeIndex;//This points to the first pde |
400 pdePtr += pdeIndex;//This points to the first pde |
393 |
401 |
394 while(pagesLeft) |
402 while(pagesLeft) |
395 { |
403 { |
397 if(pagesLeftInChunk>pagesLeft) |
405 if(pagesLeftInChunk>pagesLeft) |
398 pagesLeftInChunk = pagesLeft; |
406 pagesLeftInChunk = pagesLeft; |
399 |
407 |
400 pagesLeft -= pagesLeftInChunk; |
408 pagesLeft -= pagesLeftInChunk; |
401 |
409 |
402 TPte* pt = SafePageTableFromPde(*pdePtr++); |
410 TPte* pPte = SafePageTableFromPde(*pdePtr++); |
403 if(!pt) { err = KErrNotFound; goto fail; }// Cannot get page table. |
411 if(!pPte) |
|
412 {// Cannot get page table. |
|
413 err = KErrNotFound; |
|
414 goto fail; |
|
415 } |
404 |
416 |
405 pt += pageIndex; |
417 pPte += pageIndex; |
406 |
418 |
407 for(;pagesLeftInChunk--;) |
419 for(;pagesLeftInChunk--;) |
408 { |
420 {// This pte must be of type ArmV6 small page, the pde type will |
409 TPhysAddr phys = (*pt++ & KPteSmallPageAddrMask); |
421 // have already been checked by SafePageTableFromPde(). |
|
422 __NK_ASSERT_DEBUG((*pPte & KArmV6PteTypeMask) >= KArmV6PteSmallPage); |
|
423 TPhysAddr phys = (*pPte++ & KPteSmallPageAddrMask); |
410 pi = SPageInfo::SafeFromPhysAddr(phys); |
424 pi = SPageInfo::SafeFromPhysAddr(phys); |
411 if(!pi) { err = KErrNotFound; goto fail; }// Invalid address |
425 if(!pi) |
|
426 {// Invalid address |
|
427 err = KErrNotFound; |
|
428 goto fail; |
|
429 } |
412 |
430 |
413 __KTRACE_OPT(KMMU2,Kern::Printf("PageInfo: PA:%x T:%x S:%x O:%x C:%x",phys, pi->Type(), pi->State(), pi->Owner(), pi->LockCount())); |
431 __KTRACE_OPT(KMMU2,Kern::Printf("PageInfo: PA:%x T:%x S:%x O:%x C:%x",phys, pi->Type(), pi->State(), pi->Owner(), pi->LockCount())); |
414 if (chunk==NULL) |
432 if (chunk == NULL) |
415 {//This is the first page. Check 'trusted' bit. |
433 {//This is the first page. Check 'trusted' bit. |
416 if (pi->Type()!= SPageInfo::EChunk) |
434 if (pi->Type()!= SPageInfo::EChunk) |
417 { err = KErrAccessDenied; goto fail; }// The first page do not belong to chunk. |
435 {// The first page does not belong to a chunk. |
|
436 err = KErrAccessDenied; |
|
437 goto fail; |
|
438 } |
418 |
439 |
419 chunk = (DChunk*)pi->Owner(); |
440 chunk = (DChunk*)pi->Owner(); |
420 if ( (chunk == NULL) || ((chunk->iAttributes & DChunk::ETrustedChunk)== 0) ) |
441 if ((chunk == NULL) || ((chunk->iAttributes & DChunk::ETrustedChunk) == 0)) |
421 { err = KErrAccessDenied; goto fail; }// Not a trusted chunk |
442 {// Not a trusted chunk |
|
443 err = KErrAccessDenied; |
|
444 goto fail; |
|
445 } |
422 } |
446 } |
423 pi->Lock(); |
447 pi->Lock(); |
424 |
448 |
425 *pageList++ = phys; |
449 *pageList++ = phys; |
426 if ( (++pagesInList&127) == 0) //release system lock temporarily on every 512K |
450 |
|
451 if(!(++pagesInList & flashMask)) |
|
452 { |
427 NKern::FlashSystem(); |
453 NKern::FlashSystem(); |
|
454 } |
428 } |
455 } |
429 pageIndex = 0; |
456 pageIndex = 0; |
430 } |
457 } |
431 |
458 |
432 if (pi->Type()!= SPageInfo::EChunk) |
459 if (pi->Type() != SPageInfo::EChunk) |
433 { err = KErrAccessDenied; goto fail; }// The last page do not belong to chunk. |
460 {// The last page does not belong to a chunk. |
|
461 err = KErrAccessDenied; |
|
462 goto fail; |
|
463 } |
434 |
464 |
435 if (chunk && (chunk != (DChunk*)pi->Owner())) |
465 if (chunk && (chunk != (DChunk*)pi->Owner())) |
436 { err = KErrArgument; goto fail; }//The first & the last page do not belong to the same chunk. |
466 {//The first & the last page do not belong to the same chunk. |
|
467 err = KErrArgument; |
|
468 goto fail; |
|
469 } |
437 |
470 |
438 NKern::UnlockSystem(); |
471 NKern::UnlockSystem(); |
439 MmuBase::Signal(); |
472 MmuBase::Signal(); |
440 return KErrNone; |
473 return KErrNone; |
441 |
474 |
445 MmuBase::Signal(); |
478 MmuBase::Signal(); |
446 ReleasePagesFromDMA(aPhysicalPageList, pagesInList); |
479 ReleasePagesFromDMA(aPhysicalPageList, pagesInList); |
447 return err; |
480 return err; |
448 } |
481 } |
449 |
482 |
|
483 |
450 TInt ArmMmu::ReleasePagesFromDMA(TPhysAddr* aPhysicalPageList, TInt aPageCount) |
484 TInt ArmMmu::ReleasePagesFromDMA(TPhysAddr* aPhysicalPageList, TInt aPageCount) |
451 // Unlocks physical pages. |
485 // Unlocks physical pages. |
452 // @param aPhysicalPageList - points to the list of physical pages that should be released. |
486 // @param aPhysicalPageList - points to the list of physical pages that should be released. |
453 // @param aPageCount - the number of physical pages in the list. |
487 // @param aPageCount - the number of physical pages in the list. |
454 { |
488 { |
455 NKern::LockSystem(); |
489 NKern::LockSystem(); |
456 __KTRACE_OPT(KMMU2,Kern::Printf("ArmMmu::ReleasePagesFromDMA count:%d",aPageCount)); |
490 __KTRACE_OPT(KMMU2,Kern::Printf("ArmMmu::ReleasePagesFromDMA count:%d",aPageCount)); |
457 |
491 |
|
492 TUint flashMask = MM::MaxPagesInOneGo - 1; |
458 while (aPageCount--) |
493 while (aPageCount--) |
459 { |
494 { |
460 SPageInfo* pi = SPageInfo::SafeFromPhysAddr(*aPhysicalPageList++); |
495 SPageInfo* pi = SPageInfo::SafeFromPhysAddr(*aPhysicalPageList++); |
461 if(!pi) |
496 if(!pi) |
462 { |
497 { |
463 NKern::UnlockSystem(); |
498 NKern::UnlockSystem(); |
464 return KErrArgument; |
499 return KErrArgument; |
465 } |
500 } |
466 __KTRACE_OPT(KMMU2,Kern::Printf("PageInfo: T:%x S:%x O:%x C:%x",pi->Type(), pi->State(), pi->Owner(), pi->LockCount())); |
501 __KTRACE_OPT(KMMU2,Kern::Printf("PageInfo: T:%x S:%x O:%x C:%x",pi->Type(), pi->State(), pi->Owner(), pi->LockCount())); |
467 pi->Unlock(); |
502 pi->Unlock(); |
|
503 |
|
504 if(!(aPageCount & flashMask)) |
|
505 { |
|
506 NKern::FlashSystem(); |
|
507 } |
468 } |
508 } |
469 NKern::UnlockSystem(); |
509 NKern::UnlockSystem(); |
470 return KErrNone; |
510 return KErrNone; |
471 } |
511 } |
|
512 |
472 |
513 |
473 TPhysAddr ArmMmu::LinearToPhysical(TLinAddr aLinAddr, TInt aOsAsid) |
514 TPhysAddr ArmMmu::LinearToPhysical(TLinAddr aLinAddr, TInt aOsAsid) |
474 // |
515 // |
475 // Find the physical address corresponding to a given linear address in a specified OS |
516 // Find the physical address corresponding to a given linear address in a specified OS |
476 // address space. Call with system locked. |
517 // address space. Call with system locked. |