RE: [PATCH v1 06/15] intel_iommu: Handle PASID entry removing and updating

2025-06-17 Thread Duan, Zhenzhong


>-Original Message-
>From: Liu, Yi L 
>Subject: Re: [PATCH v1 06/15] intel_iommu: Handle PASID entry removing and
>updating
>
>On 2025/6/6 18:04, Zhenzhong Duan wrote:
>> This adds an new entry VTDPASIDCacheEntry in VTDAddressSpace to cache the
>> pasid entry and track PASID usage and future PASID tagged DMA address
>> translation support in vIOMMU.
>>
>> VTDAddressSpace of PCI_NO_PASID is allocated when device is plugged and
>> never freed. For other pasid, VTDAddressSpace instance is created/destroyed
>> per the guest pasid entry set up/destroy for passthrough devices. While for
>> emulated devices, VTDAddressSpace instance is created in the PASID tagged
>DMA
>> translation and be destroyed per guest PASID cache invalidation. This focuses
>> on the PASID cache management for passthrough devices as there is no PASID
>> capable emulated devices yet.
>>
>> When guest modifies a PASID entry, QEMU will capture the guest pasid
>selective
>> pasid cache invalidation, allocate or remove a VTDAddressSpace instance per
>the
>> invalidation reasons:
>>
>>  a) a present pasid entry moved to non-present
>>  b) a present pasid entry to be a present entry
>>  c) a non-present pasid entry moved to present
>>
>> This handles a) and b), following patch will handle c).
>>
>> vIOMMU emulator could figure out the reason by fetching latest guest pasid
>entry
>> and compare it with the PASID cache.
>
>To aovid confusion, maybe better to say cached pasid entry. :)

Sure.

>
>>
>> Signed-off-by: Yi Liu 
>> Signed-off-by: Yi Sun 
>> Signed-off-by: Zhenzhong Duan 
>> ---
>>   hw/i386/intel_iommu_internal.h |  26 
>>   include/hw/i386/intel_iommu.h  |   6 +
>>   hw/i386/intel_iommu.c  | 252 +++--
>>   hw/i386/trace-events   |   3 +
>>   4 files changed, 277 insertions(+), 10 deletions(-)
>>
>> diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
>> index 18bc22fc72..82b84db80f 100644
>> --- a/hw/i386/intel_iommu_internal.h
>> +++ b/hw/i386/intel_iommu_internal.h
>> @@ -315,6 +315,7 @@ typedef enum VTDFaultReason {
>> * request while disabled */
>>   VTD_FR_IR_SID_ERR = 0x26,   /* Invalid Source-ID */
>>
>> +VTD_FR_RTADDR_INV_TTM = 0x31,  /* Invalid TTM in RTADDR */
>>   /* PASID directory entry access failure */
>>   VTD_FR_PASID_DIR_ACCESS_ERR = 0x50,
>>   /* The Present(P) field of pasid directory entry is 0 */
>> @@ -492,6 +493,15 @@ typedef union VTDInvDesc VTDInvDesc;
>>   #define VTD_INV_DESC_PIOTLB_RSVD_VAL0 0xfff0f1c0ULL
>>   #define VTD_INV_DESC_PIOTLB_RSVD_VAL1 0xf80ULL
>>
>> +#define VTD_INV_DESC_PASIDC_G  (3ULL << 4)
>> +#define VTD_INV_DESC_PASIDC_PASID(val) (((val) >> 32) & 0xfULL)
>> +#define VTD_INV_DESC_PASIDC_DID(val)   (((val) >> 16) &
>VTD_DOMAIN_ID_MASK)
>> +#define VTD_INV_DESC_PASIDC_RSVD_VAL0  0xfff0f1c0ULL
>> +
>> +#define VTD_INV_DESC_PASIDC_DSI(0ULL << 4)
>> +#define VTD_INV_DESC_PASIDC_PASID_SI   (1ULL << 4)
>> +#define VTD_INV_DESC_PASIDC_GLOBAL (3ULL << 4)
>> +
>>   /* Information about page-selective IOTLB invalidate */
>>   struct VTDIOTLBPageInvInfo {
>>   uint16_t domain_id;
>> @@ -552,6 +562,21 @@ typedef struct VTDRootEntry VTDRootEntry;
>>   #define VTD_SM_CONTEXT_ENTRY_RSVD_VAL0(aw)  (0x1e0ULL |
>~VTD_HAW_MASK(aw))
>>   #define VTD_SM_CONTEXT_ENTRY_RSVD_VAL1  0xffe0ULL
>>
>> +typedef enum VTDPCInvType {
>> +/* pasid cache invalidation rely on guest PASID entry */
>> +VTD_PASID_CACHE_GLOBAL_INV, /* pasid cache global invalidation */
>> +VTD_PASID_CACHE_DOMSI,  /* pasid cache domain selective invalidation
>*/
>> +VTD_PASID_CACHE_PASIDSI,/* pasid cache pasid selective invalidation 
>> */
>> +} VTDPCInvType;
>> +
>> +typedef struct VTDPASIDCacheInfo {
>> +VTDPCInvType type;
>> +uint16_t domain_id;
>> +uint32_t pasid;
>> +PCIBus *bus;
>> +uint16_t devfn;
>> +} VTDPASIDCacheInfo;
>> +
>>   /* PASID Table Related Definitions */
>>   #define VTD_PASID_DIR_BASE_ADDR_MASK  (~0xfffULL)
>>   #define VTD_PASID_TABLE_BASE_ADDR_MASK (~0xfffULL)
>> @@ -563,6 +588,7 @@ typedef struct VTDRootEntry VTDRootEntry;
>>   #define VTD_PASID_TABLE_BITS_MASK (0x3fULL)
>>   #define VTD_PASID_TABLE_INDEX(pasid)  ((pasid) &
>VTD_PASID_

Re: [PATCH v1 06/15] intel_iommu: Handle PASID entry removing and updating

2025-06-17 Thread Yi Liu

On 2025/6/6 18:04, Zhenzhong Duan wrote:

This adds an new entry VTDPASIDCacheEntry in VTDAddressSpace to cache the
pasid entry and track PASID usage and future PASID tagged DMA address
translation support in vIOMMU.

VTDAddressSpace of PCI_NO_PASID is allocated when device is plugged and
never freed. For other pasid, VTDAddressSpace instance is created/destroyed
per the guest pasid entry set up/destroy for passthrough devices. While for
emulated devices, VTDAddressSpace instance is created in the PASID tagged DMA
translation and be destroyed per guest PASID cache invalidation. This focuses
on the PASID cache management for passthrough devices as there is no PASID
capable emulated devices yet.

When guest modifies a PASID entry, QEMU will capture the guest pasid selective
pasid cache invalidation, allocate or remove a VTDAddressSpace instance per the
invalidation reasons:

 a) a present pasid entry moved to non-present
 b) a present pasid entry to be a present entry
 c) a non-present pasid entry moved to present

This handles a) and b), following patch will handle c).

vIOMMU emulator could figure out the reason by fetching latest guest pasid entry
and compare it with the PASID cache.


To aovid confusion, maybe better to say cached pasid entry. :)



Signed-off-by: Yi Liu 
Signed-off-by: Yi Sun 
Signed-off-by: Zhenzhong Duan 
---
  hw/i386/intel_iommu_internal.h |  26 
  include/hw/i386/intel_iommu.h  |   6 +
  hw/i386/intel_iommu.c  | 252 +++--
  hw/i386/trace-events   |   3 +
  4 files changed, 277 insertions(+), 10 deletions(-)

diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index 18bc22fc72..82b84db80f 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -315,6 +315,7 @@ typedef enum VTDFaultReason {
* request while disabled */
  VTD_FR_IR_SID_ERR = 0x26,   /* Invalid Source-ID */
  
+VTD_FR_RTADDR_INV_TTM = 0x31,  /* Invalid TTM in RTADDR */

  /* PASID directory entry access failure */
  VTD_FR_PASID_DIR_ACCESS_ERR = 0x50,
  /* The Present(P) field of pasid directory entry is 0 */
@@ -492,6 +493,15 @@ typedef union VTDInvDesc VTDInvDesc;
  #define VTD_INV_DESC_PIOTLB_RSVD_VAL0 0xfff0f1c0ULL
  #define VTD_INV_DESC_PIOTLB_RSVD_VAL1 0xf80ULL
  
+#define VTD_INV_DESC_PASIDC_G  (3ULL << 4)

+#define VTD_INV_DESC_PASIDC_PASID(val) (((val) >> 32) & 0xfULL)
+#define VTD_INV_DESC_PASIDC_DID(val)   (((val) >> 16) & VTD_DOMAIN_ID_MASK)
+#define VTD_INV_DESC_PASIDC_RSVD_VAL0  0xfff0f1c0ULL
+
+#define VTD_INV_DESC_PASIDC_DSI(0ULL << 4)
+#define VTD_INV_DESC_PASIDC_PASID_SI   (1ULL << 4)
+#define VTD_INV_DESC_PASIDC_GLOBAL (3ULL << 4)
+
  /* Information about page-selective IOTLB invalidate */
  struct VTDIOTLBPageInvInfo {
  uint16_t domain_id;
@@ -552,6 +562,21 @@ typedef struct VTDRootEntry VTDRootEntry;
  #define VTD_SM_CONTEXT_ENTRY_RSVD_VAL0(aw)  (0x1e0ULL | ~VTD_HAW_MASK(aw))
  #define VTD_SM_CONTEXT_ENTRY_RSVD_VAL1  0xffe0ULL
  
+typedef enum VTDPCInvType {

+/* pasid cache invalidation rely on guest PASID entry */
+VTD_PASID_CACHE_GLOBAL_INV, /* pasid cache global invalidation */
+VTD_PASID_CACHE_DOMSI,  /* pasid cache domain selective invalidation */
+VTD_PASID_CACHE_PASIDSI,/* pasid cache pasid selective invalidation */
+} VTDPCInvType;
+
+typedef struct VTDPASIDCacheInfo {
+VTDPCInvType type;
+uint16_t domain_id;
+uint32_t pasid;
+PCIBus *bus;
+uint16_t devfn;
+} VTDPASIDCacheInfo;
+
  /* PASID Table Related Definitions */
  #define VTD_PASID_DIR_BASE_ADDR_MASK  (~0xfffULL)
  #define VTD_PASID_TABLE_BASE_ADDR_MASK (~0xfffULL)
@@ -563,6 +588,7 @@ typedef struct VTDRootEntry VTDRootEntry;
  #define VTD_PASID_TABLE_BITS_MASK (0x3fULL)
  #define VTD_PASID_TABLE_INDEX(pasid)  ((pasid) & VTD_PASID_TABLE_BITS_MASK)
  #define VTD_PASID_ENTRY_FPD   (1ULL << 1) /* Fault Processing Disable 
*/
+#define VTD_PASID_TBL_ENTRY_NUM   (1ULL << 6)
  
  /* PASID Granular Translation Type Mask */

  #define VTD_PASID_ENTRY_P  1ULL
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 50f9b27a45..fbc9da903a 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -95,6 +95,11 @@ struct VTDPASIDEntry {
  uint64_t val[8];
  };
  
+typedef struct VTDPASIDCacheEntry {

+struct VTDPASIDEntry pasid_entry;
+bool cache_filled;
+} VTDPASIDCacheEntry;
+
  struct VTDAddressSpace {
  PCIBus *bus;
  uint8_t devfn;
@@ -107,6 +112,7 @@ struct VTDAddressSpace {
  MemoryRegion iommu_ir_fault; /* Interrupt region for catching fault */
  IntelIOMMUState *iommu_state;
  VTDContextCacheEntry context_cache_entry;
+VTDPASIDCacheEntry pasid_cache_entry;
  QLIST_ENTRY(VTDAddressSpace) next;
  /* Superset of notifier flags that this address s

[PATCH v1 06/15] intel_iommu: Handle PASID entry removing and updating

2025-06-06 Thread Zhenzhong Duan
This adds an new entry VTDPASIDCacheEntry in VTDAddressSpace to cache the
pasid entry and track PASID usage and future PASID tagged DMA address
translation support in vIOMMU.

VTDAddressSpace of PCI_NO_PASID is allocated when device is plugged and
never freed. For other pasid, VTDAddressSpace instance is created/destroyed
per the guest pasid entry set up/destroy for passthrough devices. While for
emulated devices, VTDAddressSpace instance is created in the PASID tagged DMA
translation and be destroyed per guest PASID cache invalidation. This focuses
on the PASID cache management for passthrough devices as there is no PASID
capable emulated devices yet.

When guest modifies a PASID entry, QEMU will capture the guest pasid selective
pasid cache invalidation, allocate or remove a VTDAddressSpace instance per the
invalidation reasons:

a) a present pasid entry moved to non-present
b) a present pasid entry to be a present entry
c) a non-present pasid entry moved to present

This handles a) and b), following patch will handle c).

vIOMMU emulator could figure out the reason by fetching latest guest pasid entry
and compare it with the PASID cache.

Signed-off-by: Yi Liu 
Signed-off-by: Yi Sun 
Signed-off-by: Zhenzhong Duan 
---
 hw/i386/intel_iommu_internal.h |  26 
 include/hw/i386/intel_iommu.h  |   6 +
 hw/i386/intel_iommu.c  | 252 +++--
 hw/i386/trace-events   |   3 +
 4 files changed, 277 insertions(+), 10 deletions(-)

diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index 18bc22fc72..82b84db80f 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -315,6 +315,7 @@ typedef enum VTDFaultReason {
   * request while disabled */
 VTD_FR_IR_SID_ERR = 0x26,   /* Invalid Source-ID */
 
+VTD_FR_RTADDR_INV_TTM = 0x31,  /* Invalid TTM in RTADDR */
 /* PASID directory entry access failure */
 VTD_FR_PASID_DIR_ACCESS_ERR = 0x50,
 /* The Present(P) field of pasid directory entry is 0 */
@@ -492,6 +493,15 @@ typedef union VTDInvDesc VTDInvDesc;
 #define VTD_INV_DESC_PIOTLB_RSVD_VAL0 0xfff0f1c0ULL
 #define VTD_INV_DESC_PIOTLB_RSVD_VAL1 0xf80ULL
 
+#define VTD_INV_DESC_PASIDC_G  (3ULL << 4)
+#define VTD_INV_DESC_PASIDC_PASID(val) (((val) >> 32) & 0xfULL)
+#define VTD_INV_DESC_PASIDC_DID(val)   (((val) >> 16) & VTD_DOMAIN_ID_MASK)
+#define VTD_INV_DESC_PASIDC_RSVD_VAL0  0xfff0f1c0ULL
+
+#define VTD_INV_DESC_PASIDC_DSI(0ULL << 4)
+#define VTD_INV_DESC_PASIDC_PASID_SI   (1ULL << 4)
+#define VTD_INV_DESC_PASIDC_GLOBAL (3ULL << 4)
+
 /* Information about page-selective IOTLB invalidate */
 struct VTDIOTLBPageInvInfo {
 uint16_t domain_id;
@@ -552,6 +562,21 @@ typedef struct VTDRootEntry VTDRootEntry;
 #define VTD_SM_CONTEXT_ENTRY_RSVD_VAL0(aw)  (0x1e0ULL | ~VTD_HAW_MASK(aw))
 #define VTD_SM_CONTEXT_ENTRY_RSVD_VAL1  0xffe0ULL
 
+typedef enum VTDPCInvType {
+/* pasid cache invalidation rely on guest PASID entry */
+VTD_PASID_CACHE_GLOBAL_INV, /* pasid cache global invalidation */
+VTD_PASID_CACHE_DOMSI,  /* pasid cache domain selective invalidation */
+VTD_PASID_CACHE_PASIDSI,/* pasid cache pasid selective invalidation */
+} VTDPCInvType;
+
+typedef struct VTDPASIDCacheInfo {
+VTDPCInvType type;
+uint16_t domain_id;
+uint32_t pasid;
+PCIBus *bus;
+uint16_t devfn;
+} VTDPASIDCacheInfo;
+
 /* PASID Table Related Definitions */
 #define VTD_PASID_DIR_BASE_ADDR_MASK  (~0xfffULL)
 #define VTD_PASID_TABLE_BASE_ADDR_MASK (~0xfffULL)
@@ -563,6 +588,7 @@ typedef struct VTDRootEntry VTDRootEntry;
 #define VTD_PASID_TABLE_BITS_MASK (0x3fULL)
 #define VTD_PASID_TABLE_INDEX(pasid)  ((pasid) & VTD_PASID_TABLE_BITS_MASK)
 #define VTD_PASID_ENTRY_FPD   (1ULL << 1) /* Fault Processing Disable 
*/
+#define VTD_PASID_TBL_ENTRY_NUM   (1ULL << 6)
 
 /* PASID Granular Translation Type Mask */
 #define VTD_PASID_ENTRY_P  1ULL
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 50f9b27a45..fbc9da903a 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -95,6 +95,11 @@ struct VTDPASIDEntry {
 uint64_t val[8];
 };
 
+typedef struct VTDPASIDCacheEntry {
+struct VTDPASIDEntry pasid_entry;
+bool cache_filled;
+} VTDPASIDCacheEntry;
+
 struct VTDAddressSpace {
 PCIBus *bus;
 uint8_t devfn;
@@ -107,6 +112,7 @@ struct VTDAddressSpace {
 MemoryRegion iommu_ir_fault; /* Interrupt region for catching fault */
 IntelIOMMUState *iommu_state;
 VTDContextCacheEntry context_cache_entry;
+VTDPASIDCacheEntry pasid_cache_entry;
 QLIST_ENTRY(VTDAddressSpace) next;
 /* Superset of notifier flags that this address space has */
 IOMMUNotifierFlag notifier_flags;
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 112e09e305..c7162647e6 100644
--- a/hw/i38