442 __KTRACE_OPT(KMMU,Kern::Printf("Address invalid")); |
442 __KTRACE_OPT(KMMU,Kern::Printf("Address invalid")); |
443 } |
443 } |
444 return phys; |
444 return phys; |
445 } |
445 } |
446 |
446 |
|
447 |
447 TInt ArmMmu::PreparePagesForDMA(TLinAddr aLinAddr, TInt aSize, TPhysAddr* aPhysicalPageList) |
448 TInt ArmMmu::PreparePagesForDMA(TLinAddr aLinAddr, TInt aSize, TPhysAddr* aPhysicalPageList) |
448 //Returns the list of physical pages belonging to the specified memory space. |
449 //Returns the list of physical pages belonging to the specified memory space. |
449 //Checks these pages belong to a chunk marked as being trusted. |
450 //Checks these pages belong to a chunk marked as being trusted. |
450 //Locks these pages so they can not be moved by e.g. ram defragmenation. |
451 //Locks these pages so they can not be moved by e.g. ram defragmentation. |
451 { |
452 { |
452 SPageInfo* pi = NULL; |
453 SPageInfo* pi = NULL; |
453 DChunk* chunk = NULL; |
454 DChunk* chunk = NULL; |
454 TInt err = KErrNone; |
455 TInt err = KErrNone; |
|
456 |
|
457 __NK_ASSERT_DEBUG(MM::MaxPagesInOneGo == 32); // Needs to be a power of 2. |
|
458 TUint flashMask = MM::MaxPagesInOneGo - 1; |
455 |
459 |
456 __KTRACE_OPT(KMMU2,Kern::Printf("ArmMmu::PreparePagesForDMA %08x+%08x, asid=%d",aLinAddr,aSize)); |
460 __KTRACE_OPT(KMMU2,Kern::Printf("ArmMmu::PreparePagesForDMA %08x+%08x, asid=%d",aLinAddr,aSize)); |
457 |
461 |
458 TUint32* pageList = aPhysicalPageList; |
462 TUint32* pageList = aPhysicalPageList; |
459 TInt pagesInList = 0; //The number of pages we put in the list so far |
463 TInt pagesInList = 0; //The number of pages we put in the list so far |
472 if(pagesLeftInChunk>pagesLeft) |
476 if(pagesLeftInChunk>pagesLeft) |
473 pagesLeftInChunk = pagesLeft; |
477 pagesLeftInChunk = pagesLeft; |
474 |
478 |
475 pagesLeft -= pagesLeftInChunk; |
479 pagesLeft -= pagesLeftInChunk; |
476 |
480 |
477 TPte* pt = SafePageTableFromPde(*pdePtr++); |
481 TPte* pPte = SafePageTableFromPde(*pdePtr++); |
478 if(!pt) { err = KErrNotFound; goto fail; }// Cannot get page table. |
482 if(!pPte) |
479 |
483 {// Cannot get page table. |
480 pt += pageIndex; |
484 err = KErrNotFound; |
|
485 goto fail; |
|
486 } |
|
487 |
|
488 pPte += pageIndex; |
481 |
489 |
482 for(;pagesLeftInChunk--;) |
490 for(;pagesLeftInChunk--;) |
483 { |
491 { |
484 TPhysAddr phys = (*pt++ & KPteSmallPageAddrMask); |
492 TPhysAddr phys = (*pPte++ & KPteSmallPageAddrMask); |
485 pi = SPageInfo::SafeFromPhysAddr(phys); |
493 pi = SPageInfo::SafeFromPhysAddr(phys); |
486 if(!pi) { err = KErrNotFound; goto fail; }// Invalid address |
494 if(!pi) |
487 |
495 {// Invalid address |
|
496 err = KErrNotFound; |
|
497 goto fail; |
|
498 } |
|
499 |
488 __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())); |
500 __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())); |
489 if (chunk==NULL) |
501 if (chunk == NULL) |
490 {//This is the first page. Check 'trusted' bit. |
502 {//This is the first page. Check 'trusted' bit. |
491 if (pi->Type()!= SPageInfo::EChunk) |
503 if (pi->Type()!= SPageInfo::EChunk) |
492 { err = KErrAccessDenied; goto fail; }// The first page do not belong to chunk. |
504 {// The first page does not belong to a chunk. |
|
505 err = KErrAccessDenied; |
|
506 goto fail; |
|
507 } |
493 |
508 |
494 chunk = (DChunk*)pi->Owner(); |
509 chunk = (DChunk*)pi->Owner(); |
495 if ( (chunk == NULL) || ((chunk->iAttributes & DChunk::ETrustedChunk)== 0) ) |
510 if ((chunk == NULL) || ((chunk->iAttributes & DChunk::ETrustedChunk) == 0)) |
496 { err = KErrAccessDenied; goto fail; } // Not a trusted chunk |
511 {// Not a trusted chunk |
|
512 err = KErrAccessDenied; |
|
513 goto fail; |
|
514 } |
497 } |
515 } |
498 pi->Lock(); |
516 pi->Lock(); |
499 |
517 |
500 *pageList++ = phys; |
518 *pageList++ = phys; |
501 if ( (++pagesInList&127) == 0) //release system lock temporarily on every 512K |
519 |
|
520 if(!(++pagesInList & flashMask)) |
|
521 { |
502 NKern::FlashSystem(); |
522 NKern::FlashSystem(); |
|
523 } |
503 } |
524 } |
504 pageIndex = 0; |
525 pageIndex = 0; |
505 } |
526 } |
506 |
527 |
507 if (pi->Type()!= SPageInfo::EChunk) |
528 if (pi->Type() != SPageInfo::EChunk) |
508 { err = KErrAccessDenied; goto fail; }// The last page do not belong to chunk. |
529 {// The last page does not belong to a chunk. |
|
530 err = KErrAccessDenied; |
|
531 goto fail; |
|
532 } |
509 |
533 |
510 if (chunk && (chunk != (DChunk*)pi->Owner())) |
534 if (chunk && (chunk != (DChunk*)pi->Owner())) |
511 { err = KErrArgument; goto fail; }//The first & the last page do not belong to the same chunk. |
535 {//The first & the last page do not belong to the same chunk. |
|
536 err = KErrArgument; |
|
537 goto fail; |
|
538 } |
512 |
539 |
513 NKern::UnlockSystem(); |
540 NKern::UnlockSystem(); |
514 MmuBase::Signal(); |
541 MmuBase::Signal(); |
515 return KErrNone; |
542 return KErrNone; |
516 |
543 |
520 MmuBase::Signal(); |
547 MmuBase::Signal(); |
521 ReleasePagesFromDMA(aPhysicalPageList, pagesInList); |
548 ReleasePagesFromDMA(aPhysicalPageList, pagesInList); |
522 return err; |
549 return err; |
523 } |
550 } |
524 |
551 |
|
552 |
525 TInt ArmMmu::ReleasePagesFromDMA(TPhysAddr* aPhysicalPageList, TInt aPageCount) |
553 TInt ArmMmu::ReleasePagesFromDMA(TPhysAddr* aPhysicalPageList, TInt aPageCount) |
526 // Unlocks physical pages. |
554 // Unlocks physical pages. |
527 // @param aPhysicalPageList - points to the list of physical pages that should be released. |
555 // @param aPhysicalPageList - points to the list of physical pages that should be released. |
528 // @param aPageCount - the number of physical pages in the list. |
556 // @param aPageCount - the number of physical pages in the list. |
529 { |
557 { |
530 NKern::LockSystem(); |
558 NKern::LockSystem(); |
531 __KTRACE_OPT(KMMU2,Kern::Printf("ArmMmu::ReleasePagesFromDMA count:%d",aPageCount)); |
559 __KTRACE_OPT(KMMU2,Kern::Printf("ArmMmu::ReleasePagesFromDMA count:%d",aPageCount)); |
532 |
560 |
|
561 TUint flashMask = MM::MaxPagesInOneGo - 1; |
533 while (aPageCount--) |
562 while (aPageCount--) |
534 { |
563 { |
535 SPageInfo* pi = SPageInfo::SafeFromPhysAddr(*aPhysicalPageList++); |
564 SPageInfo* pi = SPageInfo::SafeFromPhysAddr(*aPhysicalPageList++); |
536 if(!pi) |
565 if(!pi) |
537 { |
566 { |
538 NKern::UnlockSystem(); |
567 NKern::UnlockSystem(); |
539 return KErrArgument; |
568 return KErrArgument; |
540 } |
569 } |
541 __KTRACE_OPT(KMMU2,Kern::Printf("PageInfo: T:%x S:%x O:%x C:%x",pi->Type(), pi->State(), pi->Owner(), pi->LockCount())); |
570 __KTRACE_OPT(KMMU2,Kern::Printf("PageInfo: T:%x S:%x O:%x C:%x",pi->Type(), pi->State(), pi->Owner(), pi->LockCount())); |
542 pi->Unlock(); |
571 pi->Unlock(); |
|
572 |
|
573 if(!(aPageCount & flashMask)) |
|
574 { |
|
575 NKern::FlashSystem(); |
|
576 } |
543 } |
577 } |
544 NKern::UnlockSystem(); |
578 NKern::UnlockSystem(); |
545 return KErrNone; |
579 return KErrNone; |
546 } |
580 } |
|
581 |
547 |
582 |
548 |
583 |
549 void ArmMmu::Init1() |
584 void ArmMmu::Init1() |
550 { |
585 { |
551 __KTRACE_OPT2(KBOOT,KMMU,Kern::Printf("ArmMmu::Init1")); |
586 __KTRACE_OPT2(KBOOT,KMMU,Kern::Printf("ArmMmu::Init1")); |