diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2011-04-01 15:15:26 +1100 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2011-04-01 18:34:56 +0200 |
commit | 00dc738d8a08fce0f0d327e081bb2bd7b6fba888 (patch) | |
tree | 01f3616328994f4680cb6dd0bc1cc9aa3e6f9858 /hw/spapr_vio.c | |
parent | b5cec4c5f294ca3af24e7edf4f37cc2de0ae0e03 (diff) |
Add PAPR H_VIO_SIGNAL hypercall and infrastructure for VIO interrupts
This patch adds infrastructure to support interrupts from PAPR virtual IO
devices. This includes correctly advertising those interrupts in the
device tree, and implementing the H_VIO_SIGNAL hypercall, used to
enable and disable individual device interrupts.
Signed-off-by: David Gibson <dwg@au1.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'hw/spapr_vio.c')
-rw-r--r-- | hw/spapr_vio.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index 10acb4c308..605079cda5 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -105,6 +105,16 @@ static int vio_make_devnode(VIOsPAPRDevice *dev, } } + if (dev->qirq) { + uint32_t ints_prop[] = {cpu_to_be32(dev->vio_irq_num), 0}; + + ret = fdt_setprop(fdt, node_off, "interrupts", ints_prop, + sizeof(ints_prop)); + if (ret < 0) { + return ret; + } + } + if (info->devnode) { ret = (info->devnode)(dev, fdt, node_off); if (ret < 0) { @@ -140,6 +150,30 @@ void spapr_vio_bus_register_withprop(VIOsPAPRDeviceInfo *info) qdev_register(&info->qdev); } +static target_ulong h_vio_signal(CPUState *env, sPAPREnvironment *spapr, + target_ulong opcode, + target_ulong *args) +{ + target_ulong reg = args[0]; + target_ulong mode = args[1]; + VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg); + VIOsPAPRDeviceInfo *info; + + if (!dev) { + return H_PARAMETER; + } + + info = (VIOsPAPRDeviceInfo *)dev->qdev.info; + + if (mode & ~info->signal_mask) { + return H_PARAMETER; + } + + dev->signal_state = mode; + + return H_SUCCESS; +} + VIOsPAPRBus *spapr_vio_bus_init(void) { VIOsPAPRBus *bus; @@ -156,6 +190,9 @@ VIOsPAPRBus *spapr_vio_bus_init(void) qbus = qbus_create(&spapr_vio_bus_info, dev, "spapr-vio"); bus = DO_UPCAST(VIOsPAPRBus, bus, qbus); + /* hcall-vio */ + spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal); + for (qinfo = device_info_list; qinfo; qinfo = qinfo->next) { VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo; |