RootEntry->Bits.ContextTablePointerHi = (UINT32) RShiftU64 ((UINT64)(UINTN)Buffer, 32);\r
RootEntry->Bits.Present = 1;\r
Buffer = (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);\r
+ FlushPageTableMemory (VtdIndex, (UINTN)RootEntry, sizeof(*RootEntry));\r
}\r
\r
ContextEntryTable = (VTD_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointerHi) ;\r
ContextEntry->Bits.AddressWidth = 0x2;\r
break;\r
}\r
+ FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry, sizeof(*ContextEntry));\r
}\r
\r
return EFI_SUCCESS;\r
goto Done;\r
}\r
}\r
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry, SIZE_4KB);\r
}\r
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start], (UINTN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);\r
}\r
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start], (UINTN)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);\r
\r
Done:\r
return SecondLevelPagingEntry;\r
IN UINTN VtdIndex\r
)\r
{\r
- if (mVtdUnitInformation[VtdIndex].HasDirtyPages) {\r
+ if (mVtdUnitInformation[VtdIndex].HasDirtyContext || mVtdUnitInformation[VtdIndex].HasDirtyPages) {\r
InvalidateVtdIOTLBGlobal (VtdIndex);\r
}\r
+ mVtdUnitInformation[VtdIndex].HasDirtyContext = FALSE;\r
mVtdUnitInformation[VtdIndex].HasDirtyPages = FALSE;\r
}\r
\r
/**\r
Return page table entry to match the address.\r
\r
+ @param[in] VtdIndex The index used to identify a VTd engine.\r
@param[in] SecondLevelPagingEntry The second level paging entry in VTd table for the device.\r
@param[in] Address The address to be checked.\r
@param[out] PageAttributes The page attribute of the page entry.\r
**/\r
VOID *\r
GetSecondLevelPageTableEntry (\r
+ IN UINTN VtdIndex,\r
IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,\r
IN PHYSICAL_ADDRESS Address,\r
OUT PAGE_ATTRIBUTE *PageAttribute\r
return NULL;\r
}\r
SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&L4PageTable[Index4], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);\r
+ FlushPageTableMemory (VtdIndex, (UINTN)&L4PageTable[Index4], sizeof(L4PageTable[Index4]));\r
}\r
\r
L3PageTable = (UINT64 *)(UINTN)(L4PageTable[Index4] & PAGING_4K_ADDRESS_MASK_64);\r
return NULL;\r
}\r
SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&L3PageTable[Index3], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);\r
+ FlushPageTableMemory (VtdIndex, (UINTN)&L3PageTable[Index3], sizeof(L3PageTable[Index3]));\r
}\r
if ((L3PageTable[Index3] & VTD_PG_PS) != 0) {\r
// 1G\r
L2PageTable[Index2] = Address & PAGING_2M_ADDRESS_MASK_64;\r
SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&L2PageTable[Index2], 0);\r
L2PageTable[Index2] |= VTD_PG_PS;\r
+ FlushPageTableMemory (VtdIndex, (UINTN)&L2PageTable[Index2], sizeof(L2PageTable[Index2]));\r
}\r
if ((L2PageTable[Index2] & VTD_PG_PS) != 0) {\r
// 2M\r
/**\r
Modify memory attributes of page entry.\r
\r
+ @param[in] VtdIndex The index used to identify a VTd engine.\r
@param[in] PageEntry The page entry.\r
@param[in] IoMmuAccess The IOMMU access.\r
@param[out] IsModified TRUE means page table modified. FALSE means page table not modified.\r
**/\r
VOID\r
ConvertSecondLevelPageEntryAttribute (\r
+ IN UINTN VtdIndex,\r
IN VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry,\r
IN UINT64 IoMmuAccess,\r
OUT BOOLEAN *IsModified\r
\r
CurrentPageEntry = PageEntry->Uint64;\r
SetSecondLevelPagingEntryAttribute (PageEntry, IoMmuAccess);\r
+ FlushPageTableMemory (VtdIndex, (UINTN)PageEntry, sizeof(*PageEntry));\r
NewPageEntry = PageEntry->Uint64;\r
if (CurrentPageEntry != NewPageEntry) {\r
*IsModified = TRUE;\r
/**\r
This function splits one page entry to small page entries.\r
\r
+ @param[in] VtdIndex The index used to identify a VTd engine.\r
@param[in] PageEntry The page entry to be splitted.\r
@param[in] PageAttribute The page attribute of the page entry.\r
@param[in] SplitAttribute How to split the page entry.\r
**/\r
RETURN_STATUS\r
SplitSecondLevelPage (\r
+ IN UINTN VtdIndex,\r
IN VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry,\r
IN PAGE_ATTRIBUTE PageAttribute,\r
IN PAGE_ATTRIBUTE SplitAttribute\r
for (Index = 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {\r
NewPageEntry[Index] = (BaseAddress + SIZE_4KB * Index) | (PageEntry->Uint64 & PAGE_PROGATE_BITS);\r
}\r
+ FlushPageTableMemory (VtdIndex, (UINTN)NewPageEntry, SIZE_4KB);\r
+\r
PageEntry->Uint64 = (UINT64)(UINTN)NewPageEntry;\r
SetSecondLevelPagingEntryAttribute (PageEntry, EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);\r
+ FlushPageTableMemory (VtdIndex, (UINTN)PageEntry, sizeof(*PageEntry));\r
return RETURN_SUCCESS;\r
} else {\r
return RETURN_UNSUPPORTED;\r
for (Index = 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {\r
NewPageEntry[Index] = (BaseAddress + SIZE_2MB * Index) | VTD_PG_PS | (PageEntry->Uint64 & PAGE_PROGATE_BITS);\r
}\r
+ FlushPageTableMemory (VtdIndex, (UINTN)NewPageEntry, SIZE_4KB);\r
+\r
PageEntry->Uint64 = (UINT64)(UINTN)NewPageEntry;\r
SetSecondLevelPagingEntryAttribute (PageEntry, EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);\r
+ FlushPageTableMemory (VtdIndex, (UINTN)PageEntry, sizeof(*PageEntry));\r
return RETURN_SUCCESS;\r
} else {\r
return RETURN_UNSUPPORTED;\r
EFI_STATUS\r
SetSecondLevelPagingAttribute (\r
IN UINTN VtdIndex,\r
+ IN UINT16 DomainIdentifier,\r
IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,\r
IN UINT64 BaseAddress,\r
IN UINT64 Length,\r
}\r
\r
while (Length != 0) {\r
- PageEntry = GetSecondLevelPageTableEntry (SecondLevelPagingEntry, BaseAddress, &PageAttribute);\r
+ PageEntry = GetSecondLevelPageTableEntry (VtdIndex, SecondLevelPagingEntry, BaseAddress, &PageAttribute);\r
if (PageEntry == NULL) {\r
DEBUG ((DEBUG_ERROR, "PageEntry - NULL\n"));\r
return RETURN_UNSUPPORTED;\r
PageEntryLength = PageAttributeToLength (PageAttribute);\r
SplitAttribute = NeedSplitPage (BaseAddress, Length, PageAttribute);\r
if (SplitAttribute == PageNone) {\r
- ConvertSecondLevelPageEntryAttribute (PageEntry, IoMmuAccess, &IsEntryModified);\r
+ ConvertSecondLevelPageEntryAttribute (VtdIndex, PageEntry, IoMmuAccess, &IsEntryModified);\r
if (IsEntryModified) {\r
mVtdUnitInformation[VtdIndex].HasDirtyPages = TRUE;\r
}\r
BaseAddress += PageEntryLength;\r
Length -= PageEntryLength;\r
} else {\r
- Status = SplitSecondLevelPage (PageEntry, PageAttribute, SplitAttribute);\r
+ Status = SplitSecondLevelPage (VtdIndex, PageEntry, PageAttribute, SplitAttribute);\r
if (RETURN_ERROR (Status)) {\r
DEBUG ((DEBUG_ERROR, "SplitSecondLevelPage - %r\n", Status));\r
return RETURN_UNSUPPORTED;\r
}\r
}\r
\r
- InvalidatePageEntry (VtdIndex);\r
-\r
return EFI_SUCCESS;\r
}\r
\r
EFI_STATUS\r
SetPageAttribute (\r
IN UINTN VtdIndex,\r
+ IN UINT16 DomainIdentifier,\r
IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,\r
IN UINT64 BaseAddress,\r
IN UINT64 Length,\r
EFI_STATUS Status;\r
Status = EFI_NOT_FOUND;\r
if (SecondLevelPagingEntry != NULL) {\r
- Status = SetSecondLevelPagingAttribute (VtdIndex, SecondLevelPagingEntry, BaseAddress, Length, IoMmuAccess);\r
+ Status = SetSecondLevelPagingAttribute (VtdIndex, DomainIdentifier, SecondLevelPagingEntry, BaseAddress, Length, IoMmuAccess);\r
}\r
return Status;\r
}\r
VTD_CONTEXT_ENTRY *ContextEntry;\r
VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;\r
UINT64 Pt;\r
+ UINTN PciDescriptorIndex;\r
+ UINT16 DomainIdentifier;\r
\r
SecondLevelPagingEntry = NULL;\r
\r
return EFI_DEVICE_ERROR;\r
}\r
\r
+ PciDescriptorIndex = GetPciDescriptor (VtdIndex, Segment, SourceId);\r
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo.AccessCount[PciDescriptorIndex]++;\r
+ //\r
+ // DomainId should not be 0.\r
+ //\r
+ DomainIdentifier = (UINT16)(PciDescriptorIndex + 1);\r
+\r
if (ExtContextEntry != NULL) {\r
if (ExtContextEntry->Bits.Present == 0) {\r
SecondLevelPagingEntry = CreateSecondLevelPagingEntry (VtdIndex, 0);\r
\r
ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt;\r
ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32) RShiftU64(Pt, 20);\r
- ExtContextEntry->Bits.DomainIdentifier = (UINT16) GetPciDescriptor (VtdIndex, Segment, SourceId);\r
+ ExtContextEntry->Bits.DomainIdentifier = DomainIdentifier;\r
ExtContextEntry->Bits.Present = 1;\r
+ FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry, sizeof(*ExtContextEntry));\r
DumpDmarExtContextEntryTable (mVtdUnitInformation[VtdIndex].ExtRootEntryTable);\r
+ mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;\r
} else {\r
SecondLevelPagingEntry = (VOID *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo, ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi);\r
DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%02x F%02x)\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));\r
\r
ContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt;\r
ContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32) RShiftU64(Pt, 20);\r
- ContextEntry->Bits.DomainIdentifier = (UINT16) GetPciDescriptor (VtdIndex, Segment, SourceId);\r
+ ContextEntry->Bits.DomainIdentifier = DomainIdentifier;\r
ContextEntry->Bits.Present = 1;\r
+ FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry, sizeof(*ContextEntry));\r
DumpDmarContextEntryTable (mVtdUnitInformation[VtdIndex].RootEntryTable);\r
+ mVtdUnitInformation[VtdIndex].HasDirtyContext = TRUE;\r
} else {\r
SecondLevelPagingEntry = (VOID *)(UINTN)VTD_64BITS_ADDRESS(ContextEntry->Bits.SecondLevelPageTranslationPointerLo, ContextEntry->Bits.SecondLevelPageTranslationPointerHi);\r
DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%02x F%02x)\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));\r
if (SecondLevelPagingEntry != mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry) {\r
Status = SetPageAttribute (\r
VtdIndex,\r
+ DomainIdentifier,\r
SecondLevelPagingEntry,\r
BaseAddress,\r
Length,\r
}\r
}\r
\r
+ InvalidatePageEntry (VtdIndex);\r
+\r
return EFI_SUCCESS;\r
}\r
\r
ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32) RShiftU64(Pt, 20);\r
ExtContextEntry->Bits.DomainIdentifier = ((1 << (UINT8)((UINTN)mVtdUnitInformation[VtdIndex].CapReg.Bits.ND * 2 + 4)) - 1);\r
ExtContextEntry->Bits.Present = 1;\r
+ FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry, sizeof(*ExtContextEntry));\r
} else if (ContextEntry != NULL) {\r
ContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt;\r
ContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32) RShiftU64(Pt, 20);\r
ContextEntry->Bits.DomainIdentifier = ((1 << (UINT8)((UINTN)mVtdUnitInformation[VtdIndex].CapReg.Bits.ND * 2 + 4)) - 1);\r
ContextEntry->Bits.Present = 1;\r
+ FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry, sizeof(*ContextEntry));\r
}\r
\r
return EFI_SUCCESS;\r