Skip to content

Commit

Permalink
is_msi should be cached unless is_mrif is 1
Browse files Browse the repository at this point in the history
  • Loading branch information
ved-rivos committed Jun 22, 2024
1 parent dc44293 commit ec0bc03
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 8 deletions.
6 changes: 4 additions & 2 deletions iommu_ref_model/libiommu/include/iommu_atc.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ typedef struct {
uint8_t S;
uint32_t lru;
uint8_t valid;
// Whether is an MSI translation
uint8_t IS_MSI;
} tlb_t;
// Device directory cache
typedef struct {
Expand Down Expand Up @@ -62,15 +64,15 @@ extern tlb_t tlb[TLB_SIZE];
extern void
cache_ioatc_iotlb(
uint64_t vpn, uint8_t GV, uint8_t PSCV, uint32_t GSCID, uint32_t PSCID,
pte_t *vs_pte, gpte_t *g_pte, uint64_t PPN, uint8_t S);
pte_t *vs_pte, gpte_t *g_pte, uint64_t PPN, uint8_t S, uint8_t is_msi);

extern uint8_t
lookup_ioatc_iotlb(
uint64_t iova, uint8_t check_access_perms,
uint8_t priv, uint8_t is_read, uint8_t is_write, uint8_t is_exec,
uint8_t SUM, uint8_t PSCV, uint32_t PSCID, uint8_t GV, uint16_t GSCID,
uint32_t *cause, uint64_t *resp_pa, uint64_t *page_sz,
pte_t *vs_pte, gpte_t *g_pte);
pte_t *vs_pte, gpte_t *g_pteu, uint8_t *is_msi);

extern uint8_t
lookup_ioatc_dc(uint32_t device_id, device_context_t *DC);
Expand Down
9 changes: 7 additions & 2 deletions iommu_ref_model/libiommu/src/iommu_atc.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ lookup_ioatc_pc(
void
cache_ioatc_iotlb(
uint64_t vpn, uint8_t GV, uint8_t PSCV, uint32_t GSCID, uint32_t PSCID,
pte_t *vs_pte, gpte_t *g_pte, uint64_t PPN, uint8_t S) {
pte_t *vs_pte, gpte_t *g_pte, uint64_t PPN, uint8_t S, uint8_t IS_MSI) {

uint8_t i, replace = 0;
uint32_t lru = 0xFFFFFFFF;
Expand Down Expand Up @@ -137,6 +137,9 @@ cache_ioatc_iotlb(
// PPN and size
tlb[replace].PPN = PPN;
tlb[replace].S = S;
// Whether MSI
tlb[replace].IS_MSI = IS_MSI;

tlb[replace].valid = 1;
return;
}
Expand All @@ -148,7 +151,7 @@ lookup_ioatc_iotlb(
uint8_t priv, uint8_t is_read, uint8_t is_write, uint8_t is_exec,
uint8_t SUM, uint8_t PSCV, uint32_t PSCID, uint8_t GV, uint16_t GSCID,
uint32_t *cause, uint64_t *resp_pa, uint64_t *page_sz,
pte_t *vs_pte, gpte_t *g_pte) {
pte_t *vs_pte, gpte_t *g_pte, uint8_t *is_msi) {

uint8_t i, hit;
uint64_t vpn = iova / PAGESIZE;
Expand Down Expand Up @@ -211,6 +214,8 @@ lookup_ioatc_iotlb(
vs_pte->G = tlb[hit].G;
vs_pte->U = tlb[hit].U;
vs_pte->PBMT = tlb[hit].PBMT;

*is_msi = tlb[hit].IS_MSI;
return IOATC_HIT;

page_fault:
Expand Down
19 changes: 15 additions & 4 deletions iommu_ref_model/libiommu/src/iommu_translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ iommu_translate_iova(
check_access_perms = ( TTYP != PCIE_ATS_TRANSLATION_REQUEST ) ? 1 : 0;
if ( (ioatc_status = lookup_ioatc_iotlb(req->tr.iova, check_access_perms, priv, is_read, is_write,
is_exec, SUM, PSCV, PSCID, GV, GSCID, &cause, &pa, &page_sz,
&vs_pte, &g_pte)) == IOATC_FAULT )
&vs_pte, &g_pte, &is_msi)) == IOATC_FAULT )
goto stop_and_report_fault;

// Hit in IOATC - complete translation.
Expand Down Expand Up @@ -332,15 +332,26 @@ iommu_translate_iova(

// Cache the translation in the IOATC
// In the IOTLB the IOVA & PPN is stored in the NAPOT format
// While IOMMUs are expected typically to cache MSI PTEs that are configured
// in basic translate mode (M = 3), they might not cache PTEs configured in
// MRIF mode (M = 1). Two reasons together justify not caching MSI PTEs in
// MRIF mode: First, the information and actions required to store an MSI to
// an MRIF are far different than normal address translation; and second, by
// their nature, MSIs to MRIFs should occur less frequently. Hence, an IOMMU might
// perform MRIF-mode processing solely as an extension of cache-miss page table
// walks, leaving its address translation cache oblivious to MRIF-mode MSI PTEs.
napot_ppn = (((pa & ~(page_sz - 1)) | ((page_sz/2) - 1))/PAGESIZE);
napot_iova = (((req->tr.iova & ~(page_sz - 1)) | ((page_sz/2) - 1))/PAGESIZE);
napot_gpa = (((gpa & ~(page_sz - 1)) | ((page_sz/2) - 1))/PAGESIZE);
if ( req->tr.at == ADDR_TYPE_UNTRANSLATED ) {
if ( req->tr.at == ADDR_TYPE_UNTRANSLATED &&
(is_msi == 0 || (is_msi == 1 && is_mrif == 0)) ) {
// For Untranslated Requests cache the translations for future re-use
cache_ioatc_iotlb(napot_iova, GV, PSCV, iohgatp.GSCID, PSCID,
&vs_pte, &g_pte, napot_ppn, ((page_sz > PAGESIZE) ? 1 : 0));
&vs_pte, &g_pte, napot_ppn,
((page_sz > PAGESIZE) ? 1 : 0), is_msi);
}
if ( (TTYP == PCIE_ATS_TRANSLATION_REQUEST) &&
(is_msi == 0 || (is_msi == 1 && is_mrif == 0)) &&
((DC.tc.T2GPA == 1 && ((g_fill_ats_trans_in_ioatc & FILL_IOATC_ATS_T2GPA) != 0) ) ||
((g_fill_ats_trans_in_ioatc & FILL_IOATC_ATS_ALWAYS) != 0)) ) {
// If in T2GPA mode, cache the final GPA->SPA translation as
Expand All @@ -350,7 +361,7 @@ iommu_translate_iova(
cache_ioatc_iotlb((DC.tc.T2GPA == 1) ? napot_gpa : napot_iova,
GV, (DC.tc.T2GPA == 1) ? 0 : PSCV,
iohgatp.GSCID, (DC.tc.T2GPA == 1) ? 0 : PSCID,
&vs_pte, &g_pte, napot_ppn, ((page_sz > PAGESIZE) ? 1 : 0));
&vs_pte, &g_pte, napot_ppn, ((page_sz > PAGESIZE) ? 1 : 0), is_msi);
// Return the GPA as translation response if T2GPA is 1
pa = (DC.tc.T2GPA == 1) ? gpa : pa;
}
Expand Down

0 comments on commit ec0bc03

Please sign in to comment.