hw/riscv/riscv-iommu: implement reset protocol
Add a riscv_iommu_reset() helper in the base emulation code that implements the expected reset behavior as defined by the riscv-iommu spec. Devices can then use this helper in their own reset callbacks. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20241106133407.604587-7-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
parent
01c1caa9d1
commit
9afd26715e
@ -31,6 +31,7 @@
|
|||||||
#include "cpu_bits.h"
|
#include "cpu_bits.h"
|
||||||
#include "riscv-iommu.h"
|
#include "riscv-iommu.h"
|
||||||
#include "riscv-iommu-bits.h"
|
#include "riscv-iommu-bits.h"
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
/* RISC-V IOMMU PCI Device Emulation */
|
/* RISC-V IOMMU PCI Device Emulation */
|
||||||
#define RISCV_PCI_CLASS_SYSTEM_IOMMU 0x0806
|
#define RISCV_PCI_CLASS_SYSTEM_IOMMU 0x0806
|
||||||
@ -66,6 +67,12 @@ typedef struct RISCVIOMMUStatePci {
|
|||||||
RISCVIOMMUState iommu; /* common IOMMU state */
|
RISCVIOMMUState iommu; /* common IOMMU state */
|
||||||
} RISCVIOMMUStatePci;
|
} RISCVIOMMUStatePci;
|
||||||
|
|
||||||
|
struct RISCVIOMMUPciClass {
|
||||||
|
/*< public >*/
|
||||||
|
DeviceRealize parent_realize;
|
||||||
|
ResettablePhases parent_phases;
|
||||||
|
};
|
||||||
|
|
||||||
/* interrupt delivery callback */
|
/* interrupt delivery callback */
|
||||||
static void riscv_iommu_pci_notify(RISCVIOMMUState *iommu, unsigned vector)
|
static void riscv_iommu_pci_notify(RISCVIOMMUState *iommu, unsigned vector)
|
||||||
{
|
{
|
||||||
@ -167,10 +174,23 @@ static const Property riscv_iommu_pci_properties[] = {
|
|||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void riscv_iommu_pci_reset_hold(Object *obj, ResetType type)
|
||||||
|
{
|
||||||
|
RISCVIOMMUStatePci *pci = RISCV_IOMMU_PCI(obj);
|
||||||
|
RISCVIOMMUState *iommu = &pci->iommu;
|
||||||
|
|
||||||
|
riscv_iommu_reset(iommu);
|
||||||
|
|
||||||
|
trace_riscv_iommu_pci_reset_hold(type);
|
||||||
|
}
|
||||||
|
|
||||||
static void riscv_iommu_pci_class_init(ObjectClass *klass, void *data)
|
static void riscv_iommu_pci_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||||
|
ResettableClass *rc = RESETTABLE_CLASS(klass);
|
||||||
|
|
||||||
|
rc->phases.hold = riscv_iommu_pci_reset_hold;
|
||||||
|
|
||||||
k->realize = riscv_iommu_pci_realize;
|
k->realize = riscv_iommu_pci_realize;
|
||||||
k->exit = riscv_iommu_pci_exit;
|
k->exit = riscv_iommu_pci_exit;
|
||||||
|
@ -54,6 +54,12 @@ struct RISCVIOMMUStateSys {
|
|||||||
uint8_t *msix_pba;
|
uint8_t *msix_pba;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct RISCVIOMMUSysClass {
|
||||||
|
/*< public >*/
|
||||||
|
DeviceRealize parent_realize;
|
||||||
|
ResettablePhases parent_phases;
|
||||||
|
};
|
||||||
|
|
||||||
static uint64_t msix_table_mmio_read(void *opaque, hwaddr addr,
|
static uint64_t msix_table_mmio_read(void *opaque, hwaddr addr,
|
||||||
unsigned size)
|
unsigned size)
|
||||||
{
|
{
|
||||||
@ -212,9 +218,23 @@ static Property riscv_iommu_sys_properties[] = {
|
|||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void riscv_iommu_sys_reset_hold(Object *obj, ResetType type)
|
||||||
|
{
|
||||||
|
RISCVIOMMUStateSys *sys = RISCV_IOMMU_SYS(obj);
|
||||||
|
RISCVIOMMUState *iommu = &sys->iommu;
|
||||||
|
|
||||||
|
riscv_iommu_reset(iommu);
|
||||||
|
|
||||||
|
trace_riscv_iommu_sys_reset_hold(type);
|
||||||
|
}
|
||||||
|
|
||||||
static void riscv_iommu_sys_class_init(ObjectClass *klass, void *data)
|
static void riscv_iommu_sys_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
ResettableClass *rc = RESETTABLE_CLASS(klass);
|
||||||
|
|
||||||
|
rc->phases.hold = riscv_iommu_sys_reset_hold;
|
||||||
|
|
||||||
dc->realize = riscv_iommu_sys_realize;
|
dc->realize = riscv_iommu_sys_realize;
|
||||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||||
device_class_set_props(dc, riscv_iommu_sys_properties);
|
device_class_set_props(dc, riscv_iommu_sys_properties);
|
||||||
|
@ -2262,6 +2262,41 @@ static void riscv_iommu_unrealize(DeviceState *dev)
|
|||||||
g_hash_table_unref(s->ctx_cache);
|
g_hash_table_unref(s->ctx_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void riscv_iommu_reset(RISCVIOMMUState *s)
|
||||||
|
{
|
||||||
|
uint32_t reg_clr;
|
||||||
|
int ddtp_mode;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear DDTP while setting DDTP_mode back to user
|
||||||
|
* initial setting.
|
||||||
|
*/
|
||||||
|
ddtp_mode = s->enable_off ?
|
||||||
|
RISCV_IOMMU_DDTP_MODE_OFF : RISCV_IOMMU_DDTP_MODE_BARE;
|
||||||
|
s->ddtp = set_field(0, RISCV_IOMMU_DDTP_MODE, ddtp_mode);
|
||||||
|
riscv_iommu_reg_set64(s, RISCV_IOMMU_REG_DDTP, s->ddtp);
|
||||||
|
|
||||||
|
reg_clr = RISCV_IOMMU_CQCSR_CQEN | RISCV_IOMMU_CQCSR_CIE |
|
||||||
|
RISCV_IOMMU_CQCSR_CQON | RISCV_IOMMU_CQCSR_BUSY;
|
||||||
|
riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_CQCSR, 0, reg_clr);
|
||||||
|
|
||||||
|
reg_clr = RISCV_IOMMU_FQCSR_FQEN | RISCV_IOMMU_FQCSR_FIE |
|
||||||
|
RISCV_IOMMU_FQCSR_FQON | RISCV_IOMMU_FQCSR_BUSY;
|
||||||
|
riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_FQCSR, 0, reg_clr);
|
||||||
|
|
||||||
|
reg_clr = RISCV_IOMMU_PQCSR_PQEN | RISCV_IOMMU_PQCSR_PIE |
|
||||||
|
RISCV_IOMMU_PQCSR_PQON | RISCV_IOMMU_PQCSR_BUSY;
|
||||||
|
riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_PQCSR, 0, reg_clr);
|
||||||
|
|
||||||
|
riscv_iommu_reg_mod64(s, RISCV_IOMMU_REG_TR_REQ_CTL, 0,
|
||||||
|
RISCV_IOMMU_TR_REQ_CTL_GO_BUSY);
|
||||||
|
|
||||||
|
riscv_iommu_reg_set32(s, RISCV_IOMMU_REG_IPSR, 0);
|
||||||
|
|
||||||
|
g_hash_table_remove_all(s->ctx_cache);
|
||||||
|
g_hash_table_remove_all(s->iot_cache);
|
||||||
|
}
|
||||||
|
|
||||||
static const Property riscv_iommu_properties[] = {
|
static const Property riscv_iommu_properties[] = {
|
||||||
DEFINE_PROP_UINT32("version", RISCVIOMMUState, version,
|
DEFINE_PROP_UINT32("version", RISCVIOMMUState, version,
|
||||||
RISCV_IOMMU_SPEC_DOT_VER),
|
RISCV_IOMMU_SPEC_DOT_VER),
|
||||||
|
@ -89,6 +89,7 @@ struct RISCVIOMMUState {
|
|||||||
void riscv_iommu_pci_setup_iommu(RISCVIOMMUState *iommu, PCIBus *bus,
|
void riscv_iommu_pci_setup_iommu(RISCVIOMMUState *iommu, PCIBus *bus,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
void riscv_iommu_set_cap_igs(RISCVIOMMUState *s, riscv_iommu_igs_mode mode);
|
void riscv_iommu_set_cap_igs(RISCVIOMMUState *s, riscv_iommu_igs_mode mode);
|
||||||
|
void riscv_iommu_reset(RISCVIOMMUState *s);
|
||||||
|
|
||||||
/* private helpers */
|
/* private helpers */
|
||||||
|
|
||||||
|
@ -17,3 +17,5 @@ riscv_iommu_ats_inval(const char *id) "%s: dev-iotlb invalidate"
|
|||||||
riscv_iommu_ats_prgr(const char *id) "%s: dev-iotlb page request group response"
|
riscv_iommu_ats_prgr(const char *id) "%s: dev-iotlb page request group response"
|
||||||
riscv_iommu_sys_irq_sent(uint32_t vector) "IRQ sent to vector %u"
|
riscv_iommu_sys_irq_sent(uint32_t vector) "IRQ sent to vector %u"
|
||||||
riscv_iommu_sys_msi_sent(uint32_t vector, uint64_t msi_addr, uint32_t msi_data, uint32_t result) "MSI sent to vector %u msi_addr 0x%"PRIx64" msi_data 0x%x result %u"
|
riscv_iommu_sys_msi_sent(uint32_t vector, uint64_t msi_addr, uint32_t msi_data, uint32_t result) "MSI sent to vector %u msi_addr 0x%"PRIx64" msi_data 0x%x result %u"
|
||||||
|
riscv_iommu_sys_reset_hold(int reset_type) "reset type %d"
|
||||||
|
riscv_iommu_pci_reset_hold(int reset_type) "reset type %d"
|
||||||
|
@ -30,12 +30,14 @@ typedef struct RISCVIOMMUState RISCVIOMMUState;
|
|||||||
typedef struct RISCVIOMMUSpace RISCVIOMMUSpace;
|
typedef struct RISCVIOMMUSpace RISCVIOMMUSpace;
|
||||||
|
|
||||||
#define TYPE_RISCV_IOMMU_PCI "riscv-iommu-pci"
|
#define TYPE_RISCV_IOMMU_PCI "riscv-iommu-pci"
|
||||||
OBJECT_DECLARE_SIMPLE_TYPE(RISCVIOMMUStatePci, RISCV_IOMMU_PCI)
|
OBJECT_DECLARE_TYPE(RISCVIOMMUStatePci, RISCVIOMMUPciClass, RISCV_IOMMU_PCI)
|
||||||
typedef struct RISCVIOMMUStatePci RISCVIOMMUStatePci;
|
typedef struct RISCVIOMMUStatePci RISCVIOMMUStatePci;
|
||||||
|
typedef struct RISCVIOMMUPciClass RISCVIOMMUPciClass;
|
||||||
|
|
||||||
#define TYPE_RISCV_IOMMU_SYS "riscv-iommu-device"
|
#define TYPE_RISCV_IOMMU_SYS "riscv-iommu-device"
|
||||||
OBJECT_DECLARE_SIMPLE_TYPE(RISCVIOMMUStateSys, RISCV_IOMMU_SYS)
|
OBJECT_DECLARE_TYPE(RISCVIOMMUStateSys, RISCVIOMMUSysClass, RISCV_IOMMU_SYS)
|
||||||
typedef struct RISCVIOMMUStateSys RISCVIOMMUStateSys;
|
typedef struct RISCVIOMMUStateSys RISCVIOMMUStateSys;
|
||||||
|
typedef struct RISCVIOMMUSysClass RISCVIOMMUSysClass;
|
||||||
|
|
||||||
#define FDT_IRQ_TYPE_EDGE_LOW 1
|
#define FDT_IRQ_TYPE_EDGE_LOW 1
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user