498 |
503 |
499 iPhysMemSyncTemp.Alloc(1); |
504 iPhysMemSyncTemp.Alloc(1); |
500 r = K::MutexCreate(iPhysMemSyncMutex, KLitPhysMemSync, NULL, EFalse, KMutexOrdSyncPhysMem); |
505 r = K::MutexCreate(iPhysMemSyncMutex, KLitPhysMemSync, NULL, EFalse, KMutexOrdSyncPhysMem); |
501 if(r!=KErrNone) |
506 if(r!=KErrNone) |
502 Panic(EPhysMemSyncMutexCreateFailed); |
507 Panic(EPhysMemSyncMutexCreateFailed); |
503 // VerifyRam(); |
508 |
|
509 #ifdef FMM_VERIFY_RAM |
|
510 VerifyRam(); |
|
511 #endif |
504 } |
512 } |
505 |
513 |
506 |
514 |
507 void Mmu::Init2FinalCommon() |
515 void Mmu::Init2FinalCommon() |
508 { |
516 { |
509 __KTRACE_OPT2(KBOOT,KMMU,Kern::Printf("Mmu::Init2FinalCommon")); |
517 __KTRACE_OPT2(KBOOT,KMMU,Kern::Printf("Mmu::Init2FinalCommon")); |
510 // hack, reduce free memory to <2GB... |
518 // Reduce free memory to <2GB... |
511 while(FreeRamInPages()>=0x80000000/KPageSize) |
519 while(FreeRamInPages()>=0x80000000/KPageSize) |
512 { |
520 { |
513 TPhysAddr dummyPage; |
521 TPhysAddr dummyPage; |
514 TInt r = iRamPageAllocator->AllocRamPages(&dummyPage,1, EPageFixed); |
522 TInt r = iRamPageAllocator->AllocRamPages(&dummyPage,1, EPageFixed); |
515 __NK_ASSERT_ALWAYS(r==KErrNone); |
523 __NK_ASSERT_ALWAYS(r==KErrNone); |
516 } |
524 } |
517 // hack, reduce total RAM to <2GB... |
525 // Reduce total RAM to <2GB... |
518 if(TheSuperPage().iTotalRamSize<0) |
526 if(TheSuperPage().iTotalRamSize<0) |
519 TheSuperPage().iTotalRamSize = 0x80000000-KPageSize; |
527 TheSuperPage().iTotalRamSize = 0x80000000-KPageSize; |
520 |
528 |
521 // Save current free RAM size - there can never be more free RAM than this |
529 // Save current free RAM size - there can never be more free RAM than this |
522 TUint maxFreePages = FreeRamInPages(); |
530 TUint maxFreePages = FreeRamInPages(); |
1002 pi->SetUnused(); |
1008 pi->SetUnused(); |
1003 } |
1009 } |
1004 MmuLock::Unlock(); |
1010 MmuLock::Unlock(); |
1005 |
1011 |
1006 iRamPageAllocator->FreeRamPages(aPages,aCount, EPageFixed); |
1012 iRamPageAllocator->FreeRamPages(aPages,aCount, EPageFixed); |
|
1013 |
|
1014 #ifdef BTRACE_KERNEL_MEMORY |
|
1015 if (BTrace::CheckFilter(BTrace::EKernelMemory)) |
|
1016 {// Only loop round each page if EKernelMemory tracing is enabled |
|
1017 pages = aPages; |
|
1018 pagesEnd = aPages + aCount; |
|
1019 while (pages < pagesEnd) |
|
1020 { |
|
1021 BTrace8(BTrace::EKernelMemory, BTrace::EKernelMemoryDrvPhysFree, KPageSize, *pages++); |
|
1022 Epoc::DriverAllocdPhysRam -= KPageSize; |
|
1023 } |
|
1024 } |
|
1025 #endif |
1007 } |
1026 } |
1008 |
1027 |
1009 |
1028 |
1010 TInt Mmu::AllocPhysicalRam(TPhysAddr& aPhysAddr, TUint aCount, TUint aAlign, TRamAllocFlags aFlags) |
1029 TInt Mmu::AllocPhysicalRam(TPhysAddr& aPhysAddr, TUint aCount, TUint aAlign, TRamAllocFlags aFlags) |
1011 { |
1030 { |
1012 __KTRACE_OPT(KMMU,Kern::Printf("Mmu::AllocPhysicalRam(?,0x%x,d,%x)",aCount,aAlign,aFlags)); |
1031 __KTRACE_OPT(KMMU,Kern::Printf("Mmu::AllocPhysicalRam(?,0x%x,d,%x)",aCount,aAlign,aFlags)); |
1013 TInt r = AllocContiguousRam(aPhysAddr,aCount,aAlign,aFlags); |
1032 TInt r = AllocContiguousRam(aPhysAddr,aCount,aAlign,aFlags); |
1014 if (r!=KErrNone) |
1033 if (r!=KErrNone) |
1015 return r; |
1034 return r; |
|
1035 |
|
1036 // update page infos... |
|
1037 SetAllocPhysRam(aPhysAddr, aCount); |
|
1038 |
|
1039 return KErrNone; |
|
1040 } |
|
1041 |
|
1042 |
|
1043 void Mmu::FreePhysicalRam(TPhysAddr aPhysAddr, TUint aCount) |
|
1044 { |
|
1045 __KTRACE_OPT(KMMU,Kern::Printf("Mmu::FreePhysicalRam(0x%08x,0x%x)",aPhysAddr,aCount)); |
1016 |
1046 |
1017 // update page infos... |
1047 // update page infos... |
1018 SPageInfo* pi = SPageInfo::FromPhysAddr(aPhysAddr); |
1048 SPageInfo* pi = SPageInfo::FromPhysAddr(aPhysAddr); |
1019 SPageInfo* piEnd = pi+aCount; |
1049 SPageInfo* piEnd = pi+aCount; |
1020 TUint flash = 0; |
1050 TUint flash = 0; |
1021 MmuLock::Lock(); |
1051 MmuLock::Lock(); |
1022 while(pi<piEnd) |
1052 while(pi<piEnd) |
1023 { |
1053 { |
1024 MmuLock::Flash(flash,KMaxPageInfoUpdatesInOneGo); |
1054 MmuLock::Flash(flash,KMaxPageInfoUpdatesInOneGo); |
1025 pi->SetPhysAlloc(); |
1055 __ASSERT_ALWAYS(pi->Type()==SPageInfo::EPhysAlloc, Panic(EBadFreePhysicalRam)); |
|
1056 __ASSERT_ALWAYS(!pi->UseCount(), Panic(EBadFreePhysicalRam)); |
|
1057 pi->SetUnused(); |
1026 ++pi; |
1058 ++pi; |
1027 } |
1059 } |
1028 MmuLock::Unlock(); |
1060 MmuLock::Unlock(); |
1029 |
1061 |
|
1062 TUint bytes = aCount << KPageShift; |
|
1063 iRamPageAllocator->FreePhysicalRam(aPhysAddr, bytes); |
|
1064 |
|
1065 #ifdef BTRACE_KERNEL_MEMORY |
|
1066 BTrace8(BTrace::EKernelMemory, BTrace::EKernelMemoryDrvPhysFree, bytes, aPhysAddr); |
|
1067 Epoc::DriverAllocdPhysRam -= bytes; |
|
1068 #endif |
|
1069 } |
|
1070 |
|
1071 |
|
1072 TInt Mmu::FreeRamZone(TUint aZoneId) |
|
1073 { |
|
1074 TPhysAddr zoneBase; |
|
1075 TUint zonePages; |
|
1076 TInt r = iRamPageAllocator->GetZoneAddress(aZoneId, zoneBase, zonePages); |
|
1077 if (r != KErrNone) |
|
1078 return r; |
|
1079 FreePhysicalRam(zoneBase, zonePages); |
1030 return KErrNone; |
1080 return KErrNone; |
1031 } |
1081 } |
1032 |
1082 |
1033 |
1083 |
1034 void Mmu::FreePhysicalRam(TPhysAddr aPhysAddr, TUint aCount) |
1084 TInt Mmu::ClaimPhysicalRam(TPhysAddr aPhysAddr, TUint aCount, TRamAllocFlags aFlags) |
1035 { |
1085 { |
1036 __KTRACE_OPT(KMMU,Kern::Printf("Mmu::FreePhysicalRam(0x%08x,0x%x)",aPhysAddr,aCount)); |
1086 __KTRACE_OPT(KMMU,Kern::Printf("Mmu::ClaimPhysicalRam(0x%08x,0x%x,0x%08x)",aPhysAddr,aCount,aFlags)); |
|
1087 aPhysAddr &= ~KPageMask; |
|
1088 TInt r = iRamPageAllocator->ClaimPhysicalRam(aPhysAddr, aCount << KPageShift); |
|
1089 if(r != KErrNone) |
|
1090 return r; |
|
1091 |
|
1092 AllocatedPhysicalRam(aPhysAddr, aCount, aFlags); |
|
1093 return KErrNone; |
|
1094 } |
|
1095 |
|
1096 |
|
1097 void Mmu::AllocatedPhysicalRam(TPhysAddr aPhysAddr, TUint aCount, TRamAllocFlags aFlags) |
|
1098 { |
|
1099 __KTRACE_OPT(KMMU,Kern::Printf("Mmu::AllocatedPhysicalRam(0x%08x,0x%x,d,%x)",aPhysAddr,aCount,aFlags)); |
|
1100 |
|
1101 PagesAllocated((TPhysAddr*)(aPhysAddr|1), aCount, aFlags); |
1037 |
1102 |
1038 // update page infos... |
1103 // update page infos... |
|
1104 SetAllocPhysRam(aPhysAddr, aCount); |
|
1105 } |
|
1106 |
|
1107 |
|
1108 void Mmu::SetAllocPhysRam(TPhysAddr aPhysAddr, TUint aCount) |
|
1109 { |
1039 SPageInfo* pi = SPageInfo::FromPhysAddr(aPhysAddr); |
1110 SPageInfo* pi = SPageInfo::FromPhysAddr(aPhysAddr); |
1040 SPageInfo* piEnd = pi+aCount; |
1111 SPageInfo* piEnd = pi+aCount; |
1041 TUint flash = 0; |
1112 TUint flash = 0; |
1042 MmuLock::Lock(); |
1113 MmuLock::Lock(); |
1043 while(pi<piEnd) |
1114 while(pi<piEnd) |
1044 { |
1115 { |
1045 MmuLock::Flash(flash,KMaxPageInfoUpdatesInOneGo); |
1116 MmuLock::Flash(flash, KMaxPageInfoUpdatesInOneGo); |
1046 __ASSERT_ALWAYS(pi->Type()==SPageInfo::EPhysAlloc, Panic(EBadFreePhysicalRam)); |
1117 pi->SetPhysAlloc(); |
1047 __ASSERT_ALWAYS(!pi->UseCount(), Panic(EBadFreePhysicalRam)); |
|
1048 pi->SetUnused(); |
|
1049 ++pi; |
1118 ++pi; |
1050 } |
1119 } |
1051 MmuLock::Unlock(); |
1120 MmuLock::Unlock(); |
1052 |
1121 |
1053 iRamPageAllocator->FreePhysicalRam(aPhysAddr, aCount << KPageShift); |
1122 #ifdef BTRACE_KERNEL_MEMORY |
1054 } |
1123 TUint bytes = aCount << KPageShift; |
1055 |
1124 BTrace8(BTrace::EKernelMemory, BTrace::EKernelMemoryDrvPhysAlloc, bytes, aPhysAddr); |
1056 |
1125 Epoc::DriverAllocdPhysRam += bytes; |
1057 TInt Mmu::ClaimPhysicalRam(TPhysAddr aPhysAddr, TUint aCount, TRamAllocFlags aFlags) |
1126 #endif |
1058 { |
1127 } |
1059 __KTRACE_OPT(KMMU,Kern::Printf("Mmu::ClaimPhysicalRam(0x%08x,0x%x,0x%08x)",aPhysAddr,aCount,aFlags)); |
1128 |
1060 aPhysAddr &= ~KPageMask; |
1129 |
1061 TInt r = iRamPageAllocator->ClaimPhysicalRam(aPhysAddr,(aCount << KPageShift)); |
1130 void Mmu::SetAllocPhysRam(TPhysAddr* aPageList, TUint aNumPages) |
1062 if(r!=KErrNone) |
1131 { |
1063 return r; |
1132 TPhysAddr* page = aPageList; |
1064 |
1133 TPhysAddr* pageEnd = aPageList + aNumPages; |
1065 PagesAllocated((TPhysAddr*)(aPhysAddr|1), aCount, aFlags); |
|
1066 |
|
1067 // update page infos... |
|
1068 SPageInfo* pi = SPageInfo::FromPhysAddr(aPhysAddr); |
|
1069 SPageInfo* piEnd = pi+aCount; |
|
1070 TUint flash = 0; |
1134 TUint flash = 0; |
1071 MmuLock::Lock(); |
1135 MmuLock::Lock(); |
1072 while(pi<piEnd) |
1136 while (page < pageEnd) |
1073 { |
1137 { |
1074 MmuLock::Flash(flash,KMaxPageInfoUpdatesInOneGo); |
1138 MmuLock::Flash(flash, KMaxPageInfoUpdatesInOneGo / 2); |
1075 pi->SetPhysAlloc(); |
1139 TPhysAddr pagePhys = *page++; |
1076 ++pi; |
1140 __NK_ASSERT_DEBUG(pagePhys != KPhysAddrInvalid); |
|
1141 SPageInfo::FromPhysAddr(pagePhys)->SetPhysAlloc(); |
1077 } |
1142 } |
1078 MmuLock::Unlock(); |
1143 MmuLock::Unlock(); |
1079 |
1144 |
1080 return KErrNone; |
1145 #ifdef BTRACE_KERNEL_MEMORY |
1081 } |
1146 if (BTrace::CheckFilter(BTrace::EKernelMemory)) |
1082 |
1147 {// Only loop round each page if EKernelMemory tracing is enabled |
1083 |
1148 TPhysAddr* pAddr = aPageList; |
1084 void Mmu::AllocatedPhysicalRam(TPhysAddr aPhysAddr, TUint aCount, TRamAllocFlags aFlags) |
1149 TPhysAddr* pAddrEnd = aPageList + aNumPages; |
1085 { |
1150 while (pAddr < pAddrEnd) |
1086 __KTRACE_OPT(KMMU,Kern::Printf("Mmu::AllocatedPhysicalRam(0x%08x,0x%x,d,%x)",aPhysAddr,aCount,aFlags)); |
1151 { |
1087 |
1152 BTrace8(BTrace::EKernelMemory, BTrace::EKernelMemoryDrvPhysAlloc, KPageSize, *pAddr++); |
1088 PagesAllocated((TPhysAddr*)(aPhysAddr|1), aCount, aFlags); |
1153 Epoc::DriverAllocdPhysRam += KPageSize; |
1089 |
1154 } |
1090 // update page infos... |
1155 } |
1091 SPageInfo* pi = SPageInfo::FromPhysAddr(aPhysAddr); |
1156 #endif |
1092 SPageInfo* piEnd = pi+aCount; |
|
1093 TUint flash = 0; |
|
1094 MmuLock::Lock(); |
|
1095 while(pi<piEnd) |
|
1096 { |
|
1097 MmuLock::Flash(flash,KMaxPageInfoUpdatesInOneGo); |
|
1098 pi->SetPhysAlloc(); |
|
1099 ++pi; |
|
1100 } |
|
1101 MmuLock::Unlock(); |
|
1102 } |
1157 } |
1103 |
1158 |
1104 |
1159 |
1105 // |
1160 // |
1106 // Misc |
1161 // Misc |
1185 TLinAddr Mmu::TTempMapping::Map(TPhysAddr aPage, TUint aColour) |
1240 TLinAddr Mmu::TTempMapping::Map(TPhysAddr aPage, TUint aColour) |
1186 { |
1241 { |
1187 __NK_ASSERT_DEBUG(iSize>=1); |
1242 __NK_ASSERT_DEBUG(iSize>=1); |
1188 __NK_ASSERT_DEBUG(iCount==0); |
1243 __NK_ASSERT_DEBUG(iCount==0); |
1189 |
1244 |
|
1245 return Map(aPage, aColour, iBlankPte); |
|
1246 } |
|
1247 |
|
1248 |
|
1249 /** |
|
1250 Map a single physical page into this temporary mapping using the given page table entry (PTE) value. |
|
1251 |
|
1252 @param aPage The physical page to map. |
|
1253 @param aColour The required colour for the mapping. |
|
1254 @param aBlankPte The PTE value to use for mapping the page, |
|
1255 with the physical address component equal to zero. |
|
1256 |
|
1257 @return The linear address at which the page is mapped. |
|
1258 */ |
|
1259 TLinAddr Mmu::TTempMapping::Map(TPhysAddr aPage, TUint aColour, TPte aBlankPte) |
|
1260 { |
|
1261 __NK_ASSERT_DEBUG(iSize>=1); |
|
1262 __NK_ASSERT_DEBUG(iCount==0); |
|
1263 __NK_ASSERT_DEBUG(!(aBlankPte & ~KPageMask)); |
|
1264 |
|
1265 TUint colour = aColour & KPageColourMask; |
|
1266 TLinAddr addr = iLinAddr + (colour << KPageShift); |
|
1267 TPte* pPte = iPtePtr + colour; |
|
1268 iColour = colour; |
|
1269 |
|
1270 __ASSERT_DEBUG(*pPte == KPteUnallocatedEntry, MM::Panic(MM::ETempMappingAlreadyInUse)); |
|
1271 *pPte = (aPage & ~KPageMask) | aBlankPte; |
|
1272 CacheMaintenance::SinglePteUpdated((TLinAddr)pPte); |
|
1273 InvalidateTLBForPage(addr | KKernelOsAsid); |
|
1274 |
|
1275 iCount = 1; |
|
1276 return addr; |
|
1277 } |
|
1278 |
|
1279 |
|
1280 /** |
|
1281 Map a number of physical pages into this temporary mapping. |
|
1282 |
|
1283 Supervisor read/write access and EMemoryAttributeStandard memory attributes apply. |
|
1284 |
|
1285 @param aPages The array of physical pages to map. |
|
1286 @param aCount The number of pages to map. |
|
1287 @param aColour The required colour for the first page. |
|
1288 Consecutive pages will be coloured accordingly. |
|
1289 |
|
1290 @return The linear address at which the first page is mapped. |
|
1291 */ |
|
1292 TLinAddr Mmu::TTempMapping::Map(TPhysAddr* aPages, TUint aCount, TUint aColour) |
|
1293 { |
|
1294 __NK_ASSERT_DEBUG(iSize>=aCount); |
|
1295 __NK_ASSERT_DEBUG(iCount==0); |
|
1296 |
1190 TUint colour = aColour&KPageColourMask; |
1297 TUint colour = aColour&KPageColourMask; |
1191 TLinAddr addr = iLinAddr+(colour<<KPageShift); |
1298 TLinAddr addr = iLinAddr+(colour<<KPageShift); |
1192 TPte* pPte = iPtePtr+colour; |
1299 TPte* pPte = iPtePtr+colour; |
1193 iColour = colour; |
1300 iColour = colour; |
1194 |
1301 |
1195 __ASSERT_DEBUG(*pPte==KPteUnallocatedEntry,MM::Panic(MM::ETempMappingAlreadyInUse)); |
|
1196 *pPte = (aPage&~KPageMask) | iBlankPte; |
|
1197 CacheMaintenance::SinglePteUpdated((TLinAddr)pPte); |
|
1198 InvalidateTLBForPage(addr|KKernelOsAsid); |
|
1199 |
|
1200 iCount = 1; |
|
1201 return addr; |
|
1202 } |
|
1203 |
|
1204 /** |
|
1205 Map a single physical page into this temporary mapping using the given page table entry (PTE) value. |
|
1206 |
|
1207 @param aPage The physical page to map. |
|
1208 @param aColour The required colour for the mapping. |
|
1209 @param aBlankPte The PTE value to use for mapping the page, |
|
1210 with the physical address component equal to zero. |
|
1211 |
|
1212 @return The linear address at which the page is mapped. |
|
1213 */ |
|
1214 TLinAddr Mmu::TTempMapping::Map(TPhysAddr aPage, TUint aColour, TPte aBlankPte) |
|
1215 { |
|
1216 __NK_ASSERT_DEBUG(iSize>=1); |
|
1217 __NK_ASSERT_DEBUG(iCount==0); |
|
1218 |
|
1219 TUint colour = aColour&KPageColourMask; |
|
1220 TLinAddr addr = iLinAddr+(colour<<KPageShift); |
|
1221 TPte* pPte = iPtePtr+colour; |
|
1222 iColour = colour; |
|
1223 |
|
1224 __ASSERT_DEBUG(*pPte==KPteUnallocatedEntry,MM::Panic(MM::ETempMappingAlreadyInUse)); |
|
1225 *pPte = (aPage&~KPageMask) | aBlankPte; |
|
1226 CacheMaintenance::SinglePteUpdated((TLinAddr)pPte); |
|
1227 InvalidateTLBForPage(addr|KKernelOsAsid); |
|
1228 |
|
1229 iCount = 1; |
|
1230 return addr; |
|
1231 } |
|
1232 |
|
1233 |
|
1234 /** |
|
1235 Map a number of physical pages into this temporary mapping. |
|
1236 |
|
1237 Supervisor read/write access and EMemoryAttributeStandard memory attributes apply. |
|
1238 |
|
1239 @param aPages The array of physical pages to map. |
|
1240 @param aCount The number of pages to map. |
|
1241 @param aColour The required colour for the first page. |
|
1242 Consecutive pages will be coloured accordingly. |
|
1243 |
|
1244 @return The linear address at which the first page is mapped. |
|
1245 */ |
|
1246 TLinAddr Mmu::TTempMapping::Map(TPhysAddr* aPages, TUint aCount, TUint aColour) |
|
1247 { |
|
1248 __NK_ASSERT_DEBUG(iSize>=aCount); |
|
1249 __NK_ASSERT_DEBUG(iCount==0); |
|
1250 |
|
1251 TUint colour = aColour&KPageColourMask; |
|
1252 TLinAddr addr = iLinAddr+(colour<<KPageShift); |
|
1253 TPte* pPte = iPtePtr+colour; |
|
1254 iColour = colour; |
|
1255 |
|
1256 for(TUint i=0; i<aCount; ++i) |
1302 for(TUint i=0; i<aCount; ++i) |
1257 { |
1303 { |
1258 __ASSERT_DEBUG(pPte[i]==KPteUnallocatedEntry,MM::Panic(MM::ETempMappingAlreadyInUse)); |
1304 __ASSERT_DEBUG(pPte[i]==KPteUnallocatedEntry,MM::Panic(MM::ETempMappingAlreadyInUse)); |
1259 pPte[i] = (aPages[i]&~KPageMask) | iBlankPte; |
1305 pPte[i] = (aPages[i]&~KPageMask) | iBlankPte; |
1260 CacheMaintenance::SinglePteUpdated((TLinAddr)&pPte[i]); |
1306 CacheMaintenance::SinglePteUpdated((TLinAddr)&pPte[i]); |