Lines Matching +full:cpu +full:- +full:interrupt +full:- +full:controller

2  * QEMU PowerPC sPAPR XIVE interrupt controller model
4 * Copyright (c) 2017-2019, IBM Corporation.
7 * COPYING file in the top-level directory.
12 #include "qemu/error-report.h"
14 #include "target/ppc/cpu.h"
28 * Helpers for CPU hotplug
46 if (enabled_cpu->vcpu_id == vcpu_id) { in kvm_cpu_is_enabled()
59 enabled_cpu->vcpu_id = vcpu_id; in kvm_cpu_enable()
74 * XIVE Thread Interrupt Management context (KVM)
79 SpaprXive *xive = SPAPR_XIVE(tctx->xptr); in kvmppc_xive_cpu_set_state()
83 assert(xive->fd != -1); in kvmppc_xive_cpu_set_state()
86 state[0] = *((uint64_t *) &tctx->regs[TM_QW1_OS]); in kvmppc_xive_cpu_set_state()
88 ret = kvm_set_one_reg(tctx->cs, KVM_REG_PPC_VP_STATE, state); in kvmppc_xive_cpu_set_state()
90 error_setg_errno(errp, -ret, in kvmppc_xive_cpu_set_state()
91 "XIVE: could not restore KVM state of CPU %ld", in kvmppc_xive_cpu_set_state()
92 kvm_arch_vcpu_id(tctx->cs)); in kvmppc_xive_cpu_set_state()
101 SpaprXive *xive = SPAPR_XIVE(tctx->xptr); in kvmppc_xive_cpu_get_state()
105 assert(xive->fd != -1); in kvmppc_xive_cpu_get_state()
107 ret = kvm_get_one_reg(tctx->cs, KVM_REG_PPC_VP_STATE, state); in kvmppc_xive_cpu_get_state()
109 error_setg_errno(errp, -ret, in kvmppc_xive_cpu_get_state()
110 "XIVE: could not capture KVM state of CPU %ld", in kvmppc_xive_cpu_get_state()
111 kvm_arch_vcpu_id(tctx->cs)); in kvmppc_xive_cpu_get_state()
116 *((uint64_t *) &tctx->regs[TM_QW1_OS]) = state[0]; in kvmppc_xive_cpu_get_state()
127 static void kvmppc_xive_cpu_do_synchronize_state(CPUState *cpu, in kvmppc_xive_cpu_do_synchronize_state() argument
132 s->ret = kvmppc_xive_cpu_get_state(s->tctx, s->errp); in kvmppc_xive_cpu_do_synchronize_state()
145 run_on_cpu(tctx->cs, kvmppc_xive_cpu_do_synchronize_state, in kvmppc_xive_cpu_synchronize_state()
154 SpaprXive *xive = SPAPR_XIVE(tctx->xptr); in kvmppc_xive_cpu_connect()
158 assert(xive->fd != -1); in kvmppc_xive_cpu_connect()
160 /* Check if CPU was hot unplugged and replugged. */ in kvmppc_xive_cpu_connect()
161 if (kvm_cpu_is_enabled(tctx->cs)) { in kvmppc_xive_cpu_connect()
165 vcpu_id = kvm_arch_vcpu_id(tctx->cs); in kvmppc_xive_cpu_connect()
169 ret = kvm_vcpu_enable_cap(tctx->cs, KVM_CAP_PPC_IRQ_XIVE, 0, xive->fd, in kvmppc_xive_cpu_connect()
172 error_setg_errno(errp, -ret, in kvmppc_xive_cpu_connect()
173 "XIVE: unable to connect CPU%ld to KVM device", in kvmppc_xive_cpu_connect()
175 if (ret == -ENOSPC) { in kvmppc_xive_cpu_connect()
176 error_append_hint(errp, "Try -smp maxcpus=N with N < %u\n", in kvmppc_xive_cpu_connect()
177 MACHINE(qdev_get_machine())->smp.max_cpus); in kvmppc_xive_cpu_connect()
182 kvm_cpu_enable(tctx->cs); in kvmppc_xive_cpu_connect()
187 * XIVE Interrupt Source (KVM)
203 end_idx = xive_get_field64(EAS_END_INDEX, eas->w); in kvmppc_xive_set_source_config()
204 end_blk = xive_get_field64(EAS_END_BLOCK, eas->w); in kvmppc_xive_set_source_config()
205 eisn = xive_get_field64(EAS_END_DATA, eas->w); in kvmppc_xive_set_source_config()
219 return kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_SOURCE_CONFIG, lisn, in kvmppc_xive_set_source_config()
225 kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_SOURCE_SYNC, lisn, in kvmppc_xive_sync_source()
230 * At reset, the interrupt sources are simply created and MASKED. We
236 SpaprXive *xive = SPAPR_XIVE(xsrc->xive); in kvmppc_xive_source_reset_one()
241 assert(xive->fd != -1); in kvmppc_xive_source_reset_one()
250 return kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_SOURCE, srcno, &state, in kvmppc_xive_source_reset_one()
256 SpaprXive *xive = SPAPR_XIVE(xsrc->xive); in kvmppc_xive_source_reset()
259 for (i = 0; i < xsrc->nr_irqs; i++) { in kvmppc_xive_source_reset()
262 if (!xive_eas_is_valid(&xive->eat[i])) { in kvmppc_xive_source_reset()
284 uint64_t *addr = xsrc->esb_mmap + xive_source_esb_mgmt(xsrc, srcno) + in xive_esb_rw()
289 return -1; in xive_esb_rw()
316 * and the interrupt should be re-triggered if the level is still in kvmppc_xive_esb_rw()
333 SpaprXive *xive = SPAPR_XIVE(xsrc->xive); in kvmppc_xive_source_get_state()
336 for (i = 0; i < xsrc->nr_irqs; i++) { in kvmppc_xive_source_get_state()
339 if (!xive_eas_is_valid(&xive->eat[i])) { in kvmppc_xive_source_get_state()
367 * sPAPR XIVE interrupt controller (KVM)
389 ret = kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_EQ_CONFIG, kvm_eq_idx, in kvmppc_xive_get_queue_config()
400 end->w1 = xive_set_field32(END_W1_GENERATION, 0ul, kvm_eq.qtoggle) | in kvmppc_xive_get_queue_config()
420 if (xive_get_field32(END_W0_UCOND_NOTIFY, end->w0)) { in kvmppc_xive_set_queue_config()
430 kvm_eq.qshift = xive_get_field32(END_W0_QSIZE, end->w0) + 12; in kvmppc_xive_set_queue_config()
436 kvm_eq.qtoggle = xive_get_field32(END_W1_GENERATION, end->w1); in kvmppc_xive_set_queue_config()
437 kvm_eq.qindex = xive_get_field32(END_W1_PAGE_OFF, end->w1); in kvmppc_xive_set_queue_config()
452 kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_EQ_CONFIG, kvm_eq_idx, in kvmppc_xive_set_queue_config()
458 kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_CTRL, KVM_DEV_XIVE_RESET, in kvmppc_xive_reset()
467 for (i = 0; i < xive->nr_ends; i++) { in kvmppc_xive_get_queues()
468 if (!xive_end_is_valid(&xive->endt[i])) { in kvmppc_xive_get_queues()
473 &xive->endt[i], errp); in kvmppc_xive_get_queues()
488 * triggered interrupt occurring while the VM is stopped. The previous
489 * state is saved in anticipation of a migration. The XIVE controller
490 * is then synced through KVM to flush any in-flight event
498 * runs again. If an interrupt was queued while the VM was stopped,
505 XiveSource *xsrc = &xive->source; in kvmppc_xive_change_state_handler()
514 for (i = 0; i < xsrc->nr_irqs; i++) { in kvmppc_xive_change_state_handler()
518 if (!xive_eas_is_valid(&xive->eat[i])) { in kvmppc_xive_change_state_handler()
526 * An interrupt was queued while the VM was stopped, in kvmppc_xive_change_state_handler()
543 for (i = 0; i < xsrc->nr_irqs; i++) { in kvmppc_xive_change_state_handler()
546 if (!xive_eas_is_valid(&xive->eat[i])) { in kvmppc_xive_change_state_handler()
554 * interrupt occurring while the VM is stopped (hotplug event in kvmppc_xive_change_state_handler()
564 * Sync the XIVE controller in KVM, to flush in-flight event in kvmppc_xive_change_state_handler()
568 kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_CTRL, in kvmppc_xive_change_state_handler()
578 assert(xive->fd != -1); in kvmppc_xive_synchronize_state()
587 kvmppc_xive_source_get_state(&xive->source); in kvmppc_xive_synchronize_state()
598 * the SpaprXive model, after the XIVE controller is synced in the VM
606 assert(xive->fd != -1); in kvmppc_xive_pre_save()
634 assert(xive->fd != -1); in kvmppc_xive_post_load()
637 for (i = 0; i < xive->nr_ends; i++) { in kvmppc_xive_post_load()
638 if (!xive_end_is_valid(&xive->endt[i])) { in kvmppc_xive_post_load()
643 &xive->endt[i], &local_err); in kvmppc_xive_post_load()
650 for (i = 0; i < xive->nr_irqs; i++) { in kvmppc_xive_post_load()
651 if (!xive_eas_is_valid(&xive->eat[i])) { in kvmppc_xive_post_load()
660 ret = kvmppc_xive_source_reset_one(&xive->source, i, &local_err); in kvmppc_xive_post_load()
665 ret = kvmppc_xive_set_source_config(xive, i, &xive->eat[i], &local_err); in kvmppc_xive_post_load()
672 * Restore the thread interrupt contexts of initial CPUs. in kvmppc_xive_post_load()
682 PowerPCCPU *cpu = POWERPC_CPU(cs); in kvmppc_xive_post_load() local
684 ret = kvmppc_xive_cpu_set_state(spapr_cpu_state(cpu)->tctx, &local_err); in kvmppc_xive_post_load()
705 addr = mmap(NULL, len, PROT_WRITE | PROT_READ, MAP_SHARED, xive->fd, in kvmppc_xive_mmap()
722 XiveSource *xsrc = &xive->source; in kvmppc_xive_connect()
732 * rebooting under the XIVE-only interrupt mode. in kvmppc_xive_connect()
734 if (xive->fd != -1) { in kvmppc_xive_connect()
740 return -1; in kvmppc_xive_connect()
746 error_setg_errno(errp, -fd, "XIVE: error creating KVM device"); in kvmppc_xive_connect()
747 return -1; in kvmppc_xive_connect()
749 xive->fd = fd; in kvmppc_xive_connect()
752 if (kvm_device_check_attr(xive->fd, KVM_DEV_XIVE_GRP_CTRL, in kvmppc_xive_connect()
754 ret = kvm_device_access(xive->fd, KVM_DEV_XIVE_GRP_CTRL, in kvmppc_xive_connect()
763 * 1. Source ESB pages - KVM mapping in kvmppc_xive_connect()
769 xsrc->esb_mmap = addr; in kvmppc_xive_connect()
771 memory_region_init_ram_device_ptr(&xsrc->esb_mmio_kvm, OBJECT(xsrc), in kvmppc_xive_connect()
772 "xive.esb-kvm", esb_len, xsrc->esb_mmap); in kvmppc_xive_connect()
773 memory_region_add_subregion_overlap(&xsrc->esb_mmio, 0, in kvmppc_xive_connect()
774 &xsrc->esb_mmio_kvm, 1); in kvmppc_xive_connect()
781 * 3. TIMA pages - KVM mapping in kvmppc_xive_connect()
787 xive->tm_mmap = addr; in kvmppc_xive_connect()
789 memory_region_init_ram_device_ptr(&xive->tm_mmio_kvm, OBJECT(xive), in kvmppc_xive_connect()
790 "xive.tima", tima_len, xive->tm_mmap); in kvmppc_xive_connect()
791 memory_region_add_subregion_overlap(&xive->tm_mmio, 0, in kvmppc_xive_connect()
792 &xive->tm_mmio_kvm, 1); in kvmppc_xive_connect()
794 xive->change = qemu_add_vm_change_state_handler( in kvmppc_xive_connect()
799 PowerPCCPU *cpu = POWERPC_CPU(cs); in kvmppc_xive_connect() local
801 ret = kvmppc_xive_cpu_connect(spapr_cpu_state(cpu)->tctx, errp); in kvmppc_xive_connect()
820 return -1; in kvmppc_xive_connect()
829 assert(xive->fd != -1); in kvmppc_xive_disconnect()
832 xsrc = &xive->source; in kvmppc_xive_disconnect()
835 if (xsrc->esb_mmap) { in kvmppc_xive_disconnect()
836 memory_region_del_subregion(&xsrc->esb_mmio, &xsrc->esb_mmio_kvm); in kvmppc_xive_disconnect()
837 object_unparent(OBJECT(&xsrc->esb_mmio_kvm)); in kvmppc_xive_disconnect()
838 munmap(xsrc->esb_mmap, esb_len); in kvmppc_xive_disconnect()
839 xsrc->esb_mmap = NULL; in kvmppc_xive_disconnect()
842 if (xive->tm_mmap) { in kvmppc_xive_disconnect()
843 memory_region_del_subregion(&xive->tm_mmio, &xive->tm_mmio_kvm); in kvmppc_xive_disconnect()
844 object_unparent(OBJECT(&xive->tm_mmio_kvm)); in kvmppc_xive_disconnect()
845 munmap(xive->tm_mmap, 4ull << TM_SHIFT); in kvmppc_xive_disconnect()
846 xive->tm_mmap = NULL; in kvmppc_xive_disconnect()
854 close(xive->fd); in kvmppc_xive_disconnect()
855 xive->fd = -1; in kvmppc_xive_disconnect()
865 if (xive->change) { in kvmppc_xive_disconnect()
866 qemu_del_vm_change_state_handler(xive->change); in kvmppc_xive_disconnect()
867 xive->change = NULL; in kvmppc_xive_disconnect()