From 07e4ac81aa3a476ddbd3c161d4a975a463a11f5f Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 29 Jan 2016 10:16:35 +0000 Subject: [PATCH] libxendevicemodel: functions for handling emulated IRQs Includes injection (set level) and routing of PCI INTx to ISA IRQs. Signed-off-by: Ian Campbell --- tools/libs/devicemodel/Makefile | 1 + tools/libs/devicemodel/emuirq.c | 125 ++++++++++++++++++ .../libs/devicemodel/include/xendevicemodel.h | 20 +++ tools/libs/devicemodel/libxendevicemodel.map | 4 + 4 files changed, 150 insertions(+) create mode 100644 tools/libs/devicemodel/emuirq.c diff --git a/tools/libs/devicemodel/Makefile b/tools/libs/devicemodel/Makefile index 07358fc906..86d2b1b821 100644 --- a/tools/libs/devicemodel/Makefile +++ b/tools/libs/devicemodel/Makefile @@ -14,6 +14,7 @@ LDLIBS += $(LDLIBS_libxentoollog) LDLIBS += $(LDLIBS_libxencall) SRCS-y += core.c +SRCS-y += emuirq.c LIB_OBJS := $(patsubst %.c,%.o,$(SRCS-y)) PIC_OBJS := $(patsubst %.c,%.opic,$(SRCS-y)) diff --git a/tools/libs/devicemodel/emuirq.c b/tools/libs/devicemodel/emuirq.c new file mode 100644 index 0000000000..7b5a55dc38 --- /dev/null +++ b/tools/libs/devicemodel/emuirq.c @@ -0,0 +1,125 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; If not, see . + */ + +#include +#include +#include + +#include "private.h" + +int xendevicemodel_set_pci_intx_level(xendevicemodel_handle *dm, + uint8_t domain, uint8_t bus, uint8_t dev, + uint8_t intx, bool assert) +{ + xen_hvm_set_pci_intx_level_t *arg; + int ret = -1; + + arg = xencall_alloc_buffer(dm->call, sizeof(*arg)); + if ( arg == NULL ) + { + LOGE(ERROR, "unable to allocate memory for set PCI INTx hypercall"); + goto err; + } + + arg->domid = dm->domid; + arg->domain = domain; + arg->bus = bus; + arg->device = dev; + arg->intx = intx; + arg->level = assert ? 1 : 0; + + ret = xencall2(dm->call, __HYPERVISOR_hvm_op, + HVMOP_set_pci_intx_level, + (uintptr_t)(arg)); + + if ( ret ) + LOGE(ERROR, "set PCI INTx hypercall failed"); + + xencall_free_buffer(dm->call, arg); + + err: + return ret; +} + +int xendevicemodel_route_pci_intx_to_isa_irq(xendevicemodel_handle *dm, + uint8_t intx, uint8_t isa_irq) +{ + xen_hvm_set_pci_link_route_t *arg; + int ret = -1; + + arg = xencall_alloc_buffer(dm->call, sizeof(*arg)); + if ( arg == NULL ) + { + LOGE(ERROR, + "unable to allocate memory for route PCI INTx to ISA IRQ hypercall"); + goto err; + } + + arg->domid = dm->domid; + arg->link = intx; + arg->isa_irq = isa_irq; + + ret = xencall2(dm->call, __HYPERVISOR_hvm_op, + HVMOP_set_pci_link_route, + (uintptr_t)arg); + + if ( ret ) + LOGE(ERROR, "route PCI INTx to ISA IRQ hypercall failed"); + + xencall_free_buffer(dm->call, arg); + + err: + return ret; +} + +int xendevicemodel_set_isa_irq_level(xendevicemodel_handle *dm, + uint8_t isa_irq, bool assert) +{ + xen_hvm_set_isa_irq_level_t *arg; + int ret = -1; + + arg = xencall_alloc_buffer(dm->call, sizeof(*arg)); + if ( arg == NULL ) + { + LOGE(ERROR, "unable to allocate memory for set ISA IRQ level hypercall"); + goto err; + } + + arg->domid = dm->domid; + arg->isa_irq = isa_irq; + arg->level = assert ? 1 : 0; + + ret = xencall2(dm->call, __HYPERVISOR_hvm_op, + HVMOP_set_isa_irq_level, + (uintptr_t)arg); + + if ( ret ) + LOGE(ERROR, "set ISA IRQ level hypercall failed"); + + xencall_free_buffer(dm->call, arg); + + err: + return ret; +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/tools/libs/devicemodel/include/xendevicemodel.h b/tools/libs/devicemodel/include/xendevicemodel.h index f859e023cb..991ea63279 100644 --- a/tools/libs/devicemodel/include/xendevicemodel.h +++ b/tools/libs/devicemodel/include/xendevicemodel.h @@ -104,6 +104,7 @@ int xendevicemodel_close(xendevicemodel_handle *dm); /* * Indicate domain lifecycle changes to the hypervisor. + * ==================================================== * * shutdown, reboot and s3_suspend indicate to the hypervisor that * emulation has resulted in the given guest behaviour. @@ -117,6 +118,25 @@ int xendevicemodel_reboot(xendevicemodel_handle *dm); int xendevicemodel_s3_suspend(xendevicemodel_handle *dm); int xendevicemodel_s3_awaken(xendevicemodel_handle *dm); +/* + * Emulated interrupt control and injection. + * ========================================= + * + * For PCI INTX and ISA IRQ related functions: + * + * @intx PCI INTA (=0) thru INTD (=3). + * @isa_irq ISA IRQ 0..15 (inclusive). + * @assert Whether the given interrupt of the given type should be + * asserted or deasserted. + */ +int xendevicemodel_set_pci_intx_level(xendevicemodel_handle *dm, + uint8_t domain, uint8_t bus, uint8_t dev, + uint8_t intx, bool assert); +int xendevicemodel_route_pci_intx_to_isa_irq(xendevicemodel_handle *dm, + uint8_t intx, uint8_t isa_irq); +int xendevicemodel_set_isa_irq_level(xendevicemodel_handle *dm, + uint8_t isa_irq, bool assert); + #endif /* * Local variables: diff --git a/tools/libs/devicemodel/libxendevicemodel.map b/tools/libs/devicemodel/libxendevicemodel.map index 1c3d93a372..085a189bca 100644 --- a/tools/libs/devicemodel/libxendevicemodel.map +++ b/tools/libs/devicemodel/libxendevicemodel.map @@ -8,5 +8,9 @@ VERS_1.0 { xendevicemodel_s3_suspend; xendevicemodel_s3_awaken; + xendevicemodel_set_pci_intx_level; + xendevicemodel_route_pci_intx_to_isa_irq; + xendevicemodel_set_isa_irq_level; + local: *; /* Do not expose anything by default */ }; -- 2.39.5