summaryrefslogtreecommitdiff
path: root/hw/spapr_vio.c
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2011-04-01 15:15:26 +1100
committerAlexander Graf <agraf@suse.de>2011-04-01 18:34:56 +0200
commit00dc738d8a08fce0f0d327e081bb2bd7b6fba888 (patch)
tree01f3616328994f4680cb6dd0bc1cc9aa3e6f9858 /hw/spapr_vio.c
parentb5cec4c5f294ca3af24e7edf4f37cc2de0ae0e03 (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.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 10acb4c30..605079cda 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;