mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-09 02:24:58 -06:00
intel_iommu: Process PASID-based iotlb invalidation
PASID-based iotlb (piotlb) is used during walking Intel VT-d stage-1 page table. This emulates the stage-1 page table iotlb invalidation requested by a PASID-based IOTLB Invalidate Descriptor (P_IOTLB). Signed-off-by: Yi Liu <yi.l.liu@intel.com> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> Reviewed-by: Clément Mathieu--Drif<clement.mathieu--drif@eviden.com> Acked-by: Jason Wang <jasowang@redhat.com> Reviewed-by: Yi Liu <yi.l.liu@intel.com> Message-Id: <20241212083757.605022-12-zhenzhong.duan@intel.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
16d4e418e9
commit
6ebe6cf2a0
2 changed files with 46 additions and 0 deletions
|
@ -322,6 +322,28 @@ static gboolean vtd_hash_remove_by_page(gpointer key, gpointer value,
|
||||||
return (entry->gfn & info->mask) == gfn || entry->gfn == gfn_tlb;
|
return (entry->gfn & info->mask) == gfn || entry->gfn == gfn_tlb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean vtd_hash_remove_by_page_piotlb(gpointer key, gpointer value,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
VTDIOTLBEntry *entry = (VTDIOTLBEntry *)value;
|
||||||
|
VTDIOTLBPageInvInfo *info = (VTDIOTLBPageInvInfo *)user_data;
|
||||||
|
uint64_t gfn = (info->addr >> VTD_PAGE_SHIFT_4K) & info->mask;
|
||||||
|
uint64_t gfn_tlb = (info->addr & entry->mask) >> VTD_PAGE_SHIFT_4K;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* According to spec, PASID-based-IOTLB Invalidation in page granularity
|
||||||
|
* doesn't invalidate IOTLB entries caching second-stage (PGTT=010b)
|
||||||
|
* or pass-through (PGTT=100b) mappings. Nested isn't supported yet,
|
||||||
|
* so only need to check first-stage (PGTT=001b) mappings.
|
||||||
|
*/
|
||||||
|
if (entry->pgtt != VTD_SM_PASID_ENTRY_FLT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry->domain_id == info->domain_id && entry->pasid == info->pasid &&
|
||||||
|
((entry->gfn & info->mask) == gfn || entry->gfn == gfn_tlb);
|
||||||
|
}
|
||||||
|
|
||||||
/* Reset all the gen of VTDAddressSpace to zero and set the gen of
|
/* Reset all the gen of VTDAddressSpace to zero and set the gen of
|
||||||
* IntelIOMMUState to 1. Must be called with IOMMU lock held.
|
* IntelIOMMUState to 1. Must be called with IOMMU lock held.
|
||||||
*/
|
*/
|
||||||
|
@ -2937,11 +2959,29 @@ static void vtd_piotlb_pasid_invalidate(IntelIOMMUState *s,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vtd_piotlb_page_invalidate(IntelIOMMUState *s, uint16_t domain_id,
|
||||||
|
uint32_t pasid, hwaddr addr, uint8_t am)
|
||||||
|
{
|
||||||
|
VTDIOTLBPageInvInfo info;
|
||||||
|
|
||||||
|
info.domain_id = domain_id;
|
||||||
|
info.pasid = pasid;
|
||||||
|
info.addr = addr;
|
||||||
|
info.mask = ~((1 << am) - 1);
|
||||||
|
|
||||||
|
vtd_iommu_lock(s);
|
||||||
|
g_hash_table_foreach_remove(s->iotlb,
|
||||||
|
vtd_hash_remove_by_page_piotlb, &info);
|
||||||
|
vtd_iommu_unlock(s);
|
||||||
|
}
|
||||||
|
|
||||||
static bool vtd_process_piotlb_desc(IntelIOMMUState *s,
|
static bool vtd_process_piotlb_desc(IntelIOMMUState *s,
|
||||||
VTDInvDesc *inv_desc)
|
VTDInvDesc *inv_desc)
|
||||||
{
|
{
|
||||||
uint16_t domain_id;
|
uint16_t domain_id;
|
||||||
uint32_t pasid;
|
uint32_t pasid;
|
||||||
|
hwaddr addr;
|
||||||
|
uint8_t am;
|
||||||
uint64_t mask[4] = {VTD_INV_DESC_PIOTLB_RSVD_VAL0,
|
uint64_t mask[4] = {VTD_INV_DESC_PIOTLB_RSVD_VAL0,
|
||||||
VTD_INV_DESC_PIOTLB_RSVD_VAL1,
|
VTD_INV_DESC_PIOTLB_RSVD_VAL1,
|
||||||
VTD_INV_DESC_ALL_ONE, VTD_INV_DESC_ALL_ONE};
|
VTD_INV_DESC_ALL_ONE, VTD_INV_DESC_ALL_ONE};
|
||||||
|
@ -2959,6 +2999,9 @@ static bool vtd_process_piotlb_desc(IntelIOMMUState *s,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VTD_INV_DESC_PIOTLB_PSI_IN_PASID:
|
case VTD_INV_DESC_PIOTLB_PSI_IN_PASID:
|
||||||
|
am = VTD_INV_DESC_PIOTLB_AM(inv_desc->val[1]);
|
||||||
|
addr = (hwaddr) VTD_INV_DESC_PIOTLB_ADDR(inv_desc->val[1]);
|
||||||
|
vtd_piotlb_page_invalidate(s, domain_id, pasid, addr, am);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -471,6 +471,9 @@ typedef union VTDInvDesc VTDInvDesc;
|
||||||
#define VTD_INV_DESC_PIOTLB_PSI_IN_PASID (3ULL << 4)
|
#define VTD_INV_DESC_PIOTLB_PSI_IN_PASID (3ULL << 4)
|
||||||
#define VTD_INV_DESC_PIOTLB_DID(val) (((val) >> 16) & VTD_DOMAIN_ID_MASK)
|
#define VTD_INV_DESC_PIOTLB_DID(val) (((val) >> 16) & VTD_DOMAIN_ID_MASK)
|
||||||
#define VTD_INV_DESC_PIOTLB_PASID(val) (((val) >> 32) & 0xfffffULL)
|
#define VTD_INV_DESC_PIOTLB_PASID(val) (((val) >> 32) & 0xfffffULL)
|
||||||
|
#define VTD_INV_DESC_PIOTLB_AM(val) ((val) & 0x3fULL)
|
||||||
|
#define VTD_INV_DESC_PIOTLB_IH(val) (((val) >> 6) & 0x1)
|
||||||
|
#define VTD_INV_DESC_PIOTLB_ADDR(val) ((val) & ~0xfffULL)
|
||||||
#define VTD_INV_DESC_PIOTLB_RSVD_VAL0 0xfff000000000f1c0ULL
|
#define VTD_INV_DESC_PIOTLB_RSVD_VAL0 0xfff000000000f1c0ULL
|
||||||
#define VTD_INV_DESC_PIOTLB_RSVD_VAL1 0xf80ULL
|
#define VTD_INV_DESC_PIOTLB_RSVD_VAL1 0xf80ULL
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue