Skip to content

Commit

Permalink
hw/i386/amd_viommu: Initial support for HW-assisted AMD vIOMMU
Browse files Browse the repository at this point in the history
Introduce a new device model for hardware-assisted AMD vIOMMU.
Initially, it only supports DMA remapping feature for the guest VM.

Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
  • Loading branch information
ssuthiku-amd committed Jun 21, 2023
1 parent 9feaf2e commit ee05645
Show file tree
Hide file tree
Showing 8 changed files with 1,004 additions and 1 deletion.
6 changes: 6 additions & 0 deletions hw/i386/Kconfig
Expand Up @@ -92,6 +92,7 @@ config Q35
bool
imply VTD
imply AMD_IOMMU
imply AMD_VIOMMU
imply E1000E_PCI_EXPRESS
imply VMPORT
imply VMMOUSE
Expand Down Expand Up @@ -130,6 +131,11 @@ config AMD_IOMMU
bool
select X86_IOMMU

config AMD_VIOMMU
bool
select X86_IOMMU
depends on AMD_IOMMU

config VMPORT
bool

Expand Down
8 changes: 7 additions & 1 deletion hw/i386/acpi-build.c
Expand Up @@ -2509,6 +2509,11 @@ void build_ivrs(GArray *table_data, BIOSLinker *linker, const char *oem_id,
(2UL << 10) | /* HATSup */
(2UL << 12) ; /* GATSup*/
efr2 = 0;
} else if (object_dynamic_cast(OBJECT(iommu), TYPE_AMD_VIOMMU_DEVICE)) {
s = AMD_VIOMMU_DEVICE(iommu);

efr = s->hwinfo.efr;
efr2 = s->hwinfo.efr2;
}
build_amd_iommu(table_data, s, efr, efr2);
}
Expand Down Expand Up @@ -2651,7 +2656,8 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
build_mcfg(tables_blob, tables->linker, &mcfg, x86ms->oem_id,
x86ms->oem_table_id);
}
if (object_dynamic_cast(OBJECT(iommu), TYPE_AMD_IOMMU_DEVICE)) {
if (object_dynamic_cast(OBJECT(iommu), TYPE_AMD_IOMMU_DEVICE) ||
object_dynamic_cast(OBJECT(iommu), TYPE_AMD_VIOMMU_DEVICE)) {
acpi_add_table(table_offsets, tables_blob);
build_ivrs(tables_blob, tables->linker, x86ms->oem_id,
x86ms->oem_table_id);
Expand Down
48 changes: 48 additions & 0 deletions hw/i386/amd_iommu.h
Expand Up @@ -22,6 +22,7 @@
#define AMD_IOMMU_H

#include "hw/pci/pci.h"
#include "hw/vfio/pci.h"
#include "hw/i386/x86-iommu.h"
#include "qom/object.h"

Expand Down Expand Up @@ -65,6 +66,7 @@
#define AMDVI_MMIO_PPR_TAIL 0x2038

#define AMDVI_MMIO_SIZE 0x4000
#define AMD_VIOMMU_MMIO_SIZE 0x4000

#define AMDVI_MMIO_DEVTAB_SIZE_MASK ((1ULL << 12) - 1)
#define AMDVI_MMIO_DEVTAB_BASE_MASK (((1ULL << 52) - 1) & ~ \
Expand Down Expand Up @@ -248,6 +250,9 @@
#define AMDVI_DEV_LINT0_PASS_MASK (1ULL << 62)
#define AMDVI_DEV_LINT1_PASS_MASK (1ULL << 63)

#define AMDVI_DEVTAB_SIZE 8192
#define AMDVI_DEVID_MAX 0xFFFF

/* Interrupt remapping table fields (Guest VAPIC not enabled) */
union irte {
uint32_t val;
Expand Down Expand Up @@ -312,6 +317,24 @@ struct AMDVIPCIState {
uint32_t capab_offset; /* capability offset pointer */
};

struct AMDVIHwpt {
uint32_t hwpt_id;
int iommufd;
uint32_t parent_id; /* ioas_id or hwpt_id */
uint32_t users;
};

struct AMDIOMMUFDDevice {
PCIBus *bus;
uint8_t devfn;
struct AMDVIHwpt v1_hwpt;
IOMMUFDDevice *idev;
AMDVIState *iommu_state;
QLIST_ENTRY(AMDIOMMUFDDevice) next;
};

typedef struct AMDIOMMUFDDevice AMDIOMMUFDDevice;

struct AMDVIState {
X86IOMMUState iommu; /* IOMMU bus device */
AMDVIPCIState pci; /* IOMMU PCI device */
Expand All @@ -328,6 +351,10 @@ struct AMDVIState {

hwaddr devtab_base; /* device table base address */
size_t devtab_len; /* device table length */
MemoryRegion devtab_mr; /* device table region */

uint8_t devtab[AMDVI_DEVTAB_SIZE];
int dev_domid[AMDVI_DEVID_MAX];

hwaddr cmdbuf; /* command buffer base address */
uint64_t cmdbuf_len; /* command buffer length */
Expand Down Expand Up @@ -366,8 +393,29 @@ struct AMDVIState {

/* Interrupt remapping */
bool ga_enabled;

uint32_t gid;

/* AMD IOMMU HW info */
struct iommu_hw_info_amd hwinfo;

/* /dev/iommu interface */
IOMMUFDBackend *iommufd;
struct IOMMUFDDevice *idev;
QLIST_HEAD(, AMDIOMMUFDDevice) amd_idev_list;
GHashTable *amd_iommufd_dev; /* AMDIOMMUFDDevice */
};

#define TYPE_AMD_VIOMMU_DEVICE "amd-viommu"
#define AMD_VIOMMU_DEVICE(obj)\
OBJECT_CHECK(AMDVIState, (obj), TYPE_AMD_VIOMMU_DEVICE)

#define TYPE_AMD_VIOMMU_PCI "AMD-VIOMMU-PCI"

#define TYPE_AMD_VIOMMU_MEMORY_REGION "amd-viommu-memory-region"

typedef struct AMDVIAddressSpace AMDVIAddressSpace;

struct AMDVIAddressSpace {
uint8_t bus_num; /* bus number */
uint8_t devfn; /* device function */
Expand Down

0 comments on commit ee05645

Please sign in to comment.