Skip to content

Commit

Permalink
spapr-tce: make sPAPRTCETable a proper device
Browse files Browse the repository at this point in the history
Model TCE tables as a device that's hooked up as a child object to
the owner.  Besides the code cleanup, we get a few nice benefits:

1) free actually works now (it was dead code before)

2) the TCE information is visible in the device tree

3) we can expose table information as properties such that if we
   change the window_size, we can use globals to keep migration
   working.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
  • Loading branch information
Anthony Liguori committed Jul 9, 2013
1 parent 458aecf commit a47a391
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 55 deletions.
3 changes: 0 additions & 3 deletions hw/ppc/spapr.c
Expand Up @@ -1210,9 +1210,6 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
/* Set up EPOW events infrastructure */
spapr_events_init(spapr);

/* Set up IOMMU */
spapr_iommu_init();

/* Set up VIO bus */
spapr->vio_bus = spapr_vio_bus_init();

Expand Down
109 changes: 62 additions & 47 deletions hw/ppc/spapr_iommu.c
Expand Up @@ -36,17 +36,6 @@ enum sPAPRTCEAccess {
SPAPR_TCE_RW = 3,
};

struct sPAPRTCETable {
uint32_t liobn;
uint32_t window_size;
sPAPRTCE *table;
bool bypass;
int fd;
MemoryRegion iommu;
QLIST_ENTRY(sPAPRTCETable) list;
};


QLIST_HEAD(spapr_tce_tables, sPAPRTCETable) spapr_tce_tables;

static sPAPRTCETable *spapr_tce_find_by_liobn(uint32_t liobn)
Expand Down Expand Up @@ -135,32 +124,18 @@ static MemoryRegionIOMMUOps spapr_iommu_ops = {
.translate = spapr_tce_translate_iommu,
};

sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn, size_t window_size)
static int spapr_tce_table_realize(DeviceState *dev)
{
sPAPRTCETable *tcet;

if (spapr_tce_find_by_liobn(liobn)) {
fprintf(stderr, "Attempted to create TCE table with duplicate"
" LIOBN 0x%x\n", liobn);
return NULL;
}

if (!window_size) {
return NULL;
}

tcet = g_malloc0(sizeof(*tcet));
tcet->liobn = liobn;
tcet->window_size = window_size;
sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);

if (kvm_enabled()) {
tcet->table = kvmppc_create_spapr_tce(liobn,
window_size,
tcet->table = kvmppc_create_spapr_tce(tcet->liobn,
tcet->window_size,
&tcet->fd);
}

if (!tcet->table) {
size_t table_size = (window_size >> SPAPR_TCE_PAGE_SHIFT)
size_t table_size = (tcet->window_size >> SPAPR_TCE_PAGE_SHIFT)
* sizeof(sPAPRTCE);
tcet->table = g_malloc0(table_size);
}
Expand All @@ -170,21 +145,42 @@ sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn, size_t wi
"table @ %p, fd=%d\n", tcet, liobn, tcet->table, tcet->fd);
#endif

memory_region_init_iommu(&tcet->iommu, OBJECT(owner), &spapr_iommu_ops,
memory_region_init_iommu(&tcet->iommu, OBJECT(dev), &spapr_iommu_ops,
"iommu-spapr", UINT64_MAX);

QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);

vmstate_register(NULL, tcet->liobn, &vmstate_spapr_tce_table, tcet);
return 0;
}

sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn, size_t window_size)
{
sPAPRTCETable *tcet;

if (spapr_tce_find_by_liobn(liobn)) {
fprintf(stderr, "Attempted to create TCE table with duplicate"
" LIOBN 0x%x\n", liobn);
return NULL;
}

if (!window_size) {
return NULL;
}

tcet = SPAPR_TCE_TABLE(object_new(TYPE_SPAPR_TCE_TABLE));
tcet->liobn = liobn;
tcet->window_size = window_size;

object_property_add_child(OBJECT(owner), "tce-table", OBJECT(tcet), NULL);

qdev_init_nofail(DEVICE(tcet));

return tcet;
}

void spapr_tce_free(sPAPRTCETable *tcet)
static void spapr_tce_table_finalize(Object *obj)
{
QLIST_REMOVE(tcet, list);

vmstate_unregister(NULL, &vmstate_spapr_tce_table, tcet);
sPAPRTCETable *tcet = SPAPR_TCE_TABLE(obj);

QLIST_REMOVE(tcet, list);

Expand All @@ -193,8 +189,6 @@ void spapr_tce_free(sPAPRTCETable *tcet)
tcet->window_size) != 0)) {
g_free(tcet->table);
}

g_free(tcet);
}

MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet)
Expand All @@ -207,8 +201,9 @@ void spapr_tce_set_bypass(sPAPRTCETable *tcet, bool bypass)
tcet->bypass = bypass;
}

void spapr_tce_reset(sPAPRTCETable *tcet)
static void spapr_tce_reset(DeviceState *dev)
{
sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
size_t table_size = (tcet->window_size >> SPAPR_TCE_PAGE_SHIFT)
* sizeof(sPAPRTCE);

Expand Down Expand Up @@ -263,14 +258,6 @@ static target_ulong h_put_tce(PowerPCCPU *cpu, sPAPREnvironment *spapr,
return H_PARAMETER;
}

void spapr_iommu_init(void)
{
QLIST_INIT(&spapr_tce_tables);

/* hcall-tce */
spapr_register_hypercall(H_PUT_TCE, h_put_tce);
}

int spapr_dma_dt(void *fdt, int node_off, const char *propname,
uint32_t liobn, uint64_t window, uint32_t size)
{
Expand Down Expand Up @@ -311,3 +298,31 @@ int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname,
return spapr_dma_dt(fdt, node_off, propname,
tcet->liobn, 0, tcet->window_size);
}

static void spapr_tce_table_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->vmsd = &vmstate_spapr_tce_table;
dc->init = spapr_tce_table_realize;
dc->reset = spapr_tce_reset;

QLIST_INIT(&spapr_tce_tables);

/* hcall-tce */
spapr_register_hypercall(H_PUT_TCE, h_put_tce);
}

static TypeInfo spapr_tce_table_info = {
.name = TYPE_SPAPR_TCE_TABLE,
.parent = TYPE_DEVICE,
.instance_size = sizeof(sPAPRTCETable),
.class_init = spapr_tce_table_class_init,
.instance_finalize = spapr_tce_table_finalize,
};

static void register_types(void)
{
type_register_static(&spapr_tce_table_info);
}

type_init(register_types);
2 changes: 1 addition & 1 deletion hw/ppc/spapr_pci.c
Expand Up @@ -682,7 +682,7 @@ static void spapr_phb_reset(DeviceState *qdev)
sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);

/* Reset the IOMMU state */
spapr_tce_reset(sphb->tcet);
device_reset(DEVICE(sphb->tcet));
}

static Property spapr_phb_properties[] = {
Expand Down
2 changes: 1 addition & 1 deletion hw/ppc/spapr_vio.c
Expand Up @@ -316,7 +316,7 @@ int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq)
static void spapr_vio_quiesce_one(VIOsPAPRDevice *dev)
{
if (dev->tcet) {
spapr_tce_reset(dev->tcet);
device_reset(DEVICE(dev->tcet));
}
free_crq(dev);
}
Expand Down
18 changes: 15 additions & 3 deletions include/hw/ppc/spapr.h
Expand Up @@ -352,14 +352,26 @@ typedef struct sPAPRTCE {

typedef struct sPAPRTCETable sPAPRTCETable;

void spapr_iommu_init(void);
#define TYPE_SPAPR_TCE_TABLE "spapr-tce-table"
#define SPAPR_TCE_TABLE(obj) \
OBJECT_CHECK(sPAPRTCETable, (obj), TYPE_SPAPR_TCE_TABLE)

struct sPAPRTCETable {
DeviceState parent;
uint32_t liobn;
uint32_t window_size;
sPAPRTCE *table;
bool bypass;
int fd;
MemoryRegion iommu;
QLIST_ENTRY(sPAPRTCETable) list;
};

void spapr_events_init(sPAPREnvironment *spapr);
void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq);
sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
size_t window_size);
MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet);
void spapr_tce_free(sPAPRTCETable *tcet);
void spapr_tce_reset(sPAPRTCETable *tcet);
void spapr_tce_set_bypass(sPAPRTCETable *tcet, bool bypass);
int spapr_dma_dt(void *fdt, int node_off, const char *propname,
uint32_t liobn, uint64_t window, uint32_t size);
Expand Down

0 comments on commit a47a391

Please sign in to comment.