true, errp);
}
-void kvmppc_xive_source_reset(XiveSource *xsrc, Error **errp)
+static void kvmppc_xive_source_reset(XiveSource *xsrc, Error **errp)
{
int i;
Error *local_err = NULL;
size_t esb_len = (1ull << xsrc->esb_shift) * xsrc->nr_irqs;
size_t tima_len = 4ull << TM_SHIFT;
+ CPUState *cs;
+
+ /*
+ * The KVM XIVE device already in use. This is the case when
+ * rebooting under the XIVE-only interrupt mode.
+ */
+ if (xive->fd != -1) {
+ return;
+ }
if (!kvmppc_has_cap_xive()) {
error_setg(errp, "IRQ_XIVE capability must be present for KVM");
xive->change = qemu_add_vm_change_state_handler(
kvmppc_xive_change_state_handler, xive);
+ /* Connect the presenters to the initial VCPUs of the machine */
+ CPU_FOREACH(cs) {
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+
+ kvmppc_xive_cpu_connect(spapr_cpu_state(cpu)->tctx, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ }
+
+ /* Update the KVM sources */
+ kvmppc_xive_source_reset(xsrc, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
kvm_kernel_irqchip = true;
kvm_msi_via_irqfd_allowed = true;
kvm_gsi_direct_mapping = true;
#include "trace.h"
#include "sysemu/kvm.h"
#include "hw/ppc/spapr.h"
+#include "hw/ppc/spapr_cpu_core.h"
#include "hw/ppc/xics.h"
#include "hw/ppc/xics_spapr.h"
#include "kvm_ppc.h"
int xics_kvm_init(SpaprMachineState *spapr, Error **errp)
{
int rc;
+ CPUState *cs;
+ Error *local_err = NULL;
+
+ /*
+ * The KVM XICS device already in use. This is the case when
+ * rebooting under the XICS-only interrupt mode.
+ */
+ if (kernel_xics_fd != -1) {
+ return 0;
+ }
if (!kvm_enabled() || !kvm_check_extension(kvm_state, KVM_CAP_IRQ_XICS)) {
error_setg(errp,
kvm_msi_via_irqfd_allowed = true;
kvm_gsi_direct_mapping = true;
+ /* Create the presenters */
+ CPU_FOREACH(cs) {
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+
+ icp_kvm_realize(DEVICE(spapr_cpu_state(cpu)->icp), &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ goto fail;
+ }
+ }
+
+ /* Update the KVM sources */
+ ics_set_kvm_state(spapr->ics);
+
+ /* Connect the presenters to the initial VCPUs of the machine */
+ CPU_FOREACH(cs) {
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ icp_set_kvm_state(spapr_cpu_state(cpu)->icp);
+ }
+
return 0;
fail:
Object *obj;
Error *local_err = NULL;
- spapr_irq_init_device(spapr, &spapr_irq_xics, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
obj = object_new(TYPE_ICS_SIMPLE);
object_property_add_child(OBJECT(spapr), "ics", obj, &error_abort);
object_property_add_const_link(obj, ICS_PROP_XICS, OBJECT(spapr),
static void spapr_irq_reset_xics(SpaprMachineState *spapr, Error **errp)
{
- /* TODO: create the KVM XICS device */
+ Error *local_err = NULL;
+
+ spapr_irq_init_device(spapr, &spapr_irq_xics, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
}
static const char *spapr_irq_get_nodename_xics(SpaprMachineState *spapr)
uint32_t nr_servers = spapr_max_server_number(spapr);
DeviceState *dev;
int i;
- Error *local_err = NULL;
dev = qdev_create(NULL, TYPE_SPAPR_XIVE);
qdev_prop_set_uint32(dev, "nr-irqs", nr_irqs);
}
spapr_xive_hcall_init(spapr);
-
- spapr_irq_init_device(spapr, &spapr_irq_xive, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
}
static int spapr_irq_claim_xive(SpaprMachineState *spapr, int irq, bool lsi,
static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp)
{
CPUState *cs;
+ Error *local_err = NULL;
CPU_FOREACH(cs) {
PowerPCCPU *cpu = POWERPC_CPU(cs);
spapr_xive_set_tctx_os_cam(spapr_cpu_state(cpu)->tctx);
}
+ spapr_irq_init_device(spapr, &spapr_irq_xive, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
/* Activate the XIVE MMIOs */
spapr_xive_mmio_set_enabled(spapr->xive, true);
}
static void spapr_irq_init_dual(SpaprMachineState *spapr, int nr_irqs,
Error **errp)
{
- MachineState *machine = MACHINE(spapr);
Error *local_err = NULL;
- if (kvm_enabled() && machine_kernel_irqchip_allowed(machine)) {
- error_setg(errp, "No KVM support for the 'dual' machine");
- return;
- }
-
spapr_irq_xics.init(spapr, spapr_irq_xics.nr_irqs, &local_err);
if (local_err) {
error_propagate(errp, local_err);
* defaults to XICS at startup.
*/
if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
+ if (kvm_irqchip_in_kernel()) {
+ xics_kvm_disconnect(spapr, &error_fatal);
+ }
spapr_irq_xive.reset(spapr, &error_fatal);
}
static void spapr_irq_reset_dual(SpaprMachineState *spapr, Error **errp)
{
+ Error *local_err = NULL;
+
/*
* Deactivate the XIVE MMIOs. The XIVE backend will reenable them
* if selected.
*/
spapr_xive_mmio_set_enabled(spapr->xive, false);
+ /* Destroy all KVM devices */
+ if (kvm_irqchip_in_kernel()) {
+ xics_kvm_disconnect(spapr, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ error_prepend(errp, "KVM XICS disconnect failed: ");
+ return;
+ }
+ kvmppc_xive_disconnect(spapr->xive, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ error_prepend(errp, "KVM XIVE disconnect failed: ");
+ return;
+ }
+ }
+
spapr_irq_current(spapr)->reset(spapr, errp);
}
.dt_populate = spapr_dt_xics,
.cpu_intc_create = spapr_irq_cpu_intc_create_xics,
.post_load = spapr_irq_post_load_xics,
+ .reset = spapr_irq_reset_xics,
.set_irq = spapr_irq_set_irq_xics,
.get_nodename = spapr_irq_get_nodename_xics,
+ .init_emu = spapr_irq_init_emu_xics,
+ .init_kvm = spapr_irq_init_kvm_xics,
};