From patchwork Tue Feb 18 02:04:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gavin Shan X-Patchwork-Id: 11387765 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 41883109A for ; Tue, 18 Feb 2020 02:05:40 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 184E020836 for ; Tue, 18 Feb 2020 02:05:40 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="KzrE5fIu" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 184E020836 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Received: from localhost ([::1]:55748 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j3sGZ-00065v-7w for patchwork-qemu-devel@patchwork.kernel.org; Mon, 17 Feb 2020 21:05:39 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:52935) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j3sFs-0004cC-LC for qemu-devel@nongnu.org; Mon, 17 Feb 2020 21:04:57 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j3sFr-0007ir-B4 for qemu-devel@nongnu.org; Mon, 17 Feb 2020 21:04:56 -0500 Received: from us-smtp-delivery-1.mimecast.com ([207.211.31.120]:28310 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1j3sFr-0007ia-7O for qemu-devel@nongnu.org; Mon, 17 Feb 2020 21:04:55 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1581991494; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tySIqj25vFkbJUOWFkZJcKmdOpzjeZeQsC3TdET8Seg=; b=KzrE5fIuhghJPyeVDpqU5WmOdQmXgaXmmrooPf5eA7bnwT0FJIIVscBfYP359ga3DB/Iqv fcroTxEfU4YN8mrv6HsBsvN4y4wriTd7aI4zT+r79kQni2/zb7UyuHmACTss2m/cdBpBhy g0Ku54ln0rb3gQ/7l03AACJDJoOklXY= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-133-EEsYTni9NtSTE5nXilQMHg-1; Mon, 17 Feb 2020 21:04:53 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 3A7FB100550E; Tue, 18 Feb 2020 02:04:51 +0000 (UTC) Received: from localhost.localdomain.com (vpn2-54-110.bne.redhat.com [10.64.54.110]) by smtp.corp.redhat.com (Postfix) with ESMTP id D0F141BC6D; Tue, 18 Feb 2020 02:04:44 +0000 (UTC) From: Gavin Shan To: qemu-devel@nongnu.org, qemu-arm@nongnu.org Subject: [PATCH v4 3/3] hw/arm/virt: Simulate NMI injection Date: Tue, 18 Feb 2020 13:04:16 +1100 Message-Id: <20200218020416.50244-4-gshan@redhat.com> In-Reply-To: <20200218020416.50244-1-gshan@redhat.com> References: <20200218020416.50244-1-gshan@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-MC-Unique: EEsYTni9NtSTE5nXilQMHg-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 207.211.31.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, drjones@redhat.com, jthierry@redhat.com, aik@ozlabs.ru, maz@kernel.org, richard.henderson@linaro.org, eric.auger@redhat.com, shan.gavin@gmail.com, pbonzini@redhat.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" This implements the backend to support HMP/QMP "nmi" command, which is used to inject NMI interrupt to crash guest for debugging purpose. As ARM architecture doesn't have NMI supported, so we're simulating the behaviour by injecting SError or data abort to guest for "virt" board. An additonal IRQ line is introduced for SError on each CPU. The IRQ line is connected to SError exception handler. The IRQ line on CPU#0 is raised when HMP/QMP "nmi" is issued to inject SError or data abort to crash guest. Note the IRQ line can be shared with other devices who want to have the capability of reporting errors in future. Signed-off-by: Gavin Shan --- hw/arm/virt.c | 34 +++++++++++++++++++++++++++++- hw/intc/arm_gic_common.c | 3 +++ hw/intc/arm_gicv3_common.c | 3 +++ include/hw/intc/arm_gic_common.h | 1 + include/hw/intc/arm_gicv3_common.h | 1 + 5 files changed, 41 insertions(+), 1 deletion(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index f788fe27d6..78549faa75 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -71,6 +71,8 @@ #include "hw/mem/pc-dimm.h" #include "hw/mem/nvdimm.h" #include "hw/acpi/generic_event_device.h" +#include "sysemu/hw_accel.h" +#include "hw/nmi.h" #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ @@ -690,7 +692,7 @@ static void create_gic(VirtMachineState *vms) } else if (vms->virt) { qemu_irq irq = qdev_get_gpio_in(vms->gic, ppibase + ARCH_GIC_MAINT_IRQ); - sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, irq); + sysbus_connect_irq(gicbusdev, i + 5 * smp_cpus, irq); } qdev_connect_gpio_out_named(cpudev, "pmu-interrupt", 0, @@ -704,6 +706,8 @@ static void create_gic(VirtMachineState *vms) qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ)); sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus, qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ)); + sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus, + qdev_get_gpio_in(cpudev, ARM_CPU_SERROR)); } fdt_add_gic_node(vms); @@ -2026,10 +2030,36 @@ static int virt_kvm_type(MachineState *ms, const char *type_str) return requested_pa_size > 40 ? requested_pa_size : 0; } + +static void do_inject_serror(CPUState *cpu, run_on_cpu_data data) +{ + VirtMachineState *vms = data.host_ptr; + GICv3State *gicv3; + GICState *gicv2; + + cpu_synchronize_state(cpu); + + if (vms->gic_version == 3) { + gicv3 = ARM_GICV3_COMMON(OBJECT(vms->gic)); + qemu_irq_raise(gicv3->cpu[0].parent_serror); + } else { + gicv2 = ARM_GIC_COMMON(OBJECT(vms->gic)); + qemu_irq_raise(gicv2->parent_serror[0]); + } +} + +static void virt_inject_serror(NMIState *n, int cpu_index, Error **errp) +{ + VirtMachineState *vms = VIRT_MACHINE(n); + + async_run_on_cpu(first_cpu, do_inject_serror, RUN_ON_CPU_HOST_PTR(vms)); +} + static void virt_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); + NMIClass *nc = NMI_CLASS(oc); mc->init = machvirt_init; /* Start with max_cpus set to 512, which is the maximum supported by KVM. @@ -2058,6 +2088,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) hc->unplug_request = virt_machine_device_unplug_request_cb; mc->numa_mem_supported = true; mc->auto_enable_numa_with_memhp = true; + nc->nmi_monitor_handler = virt_inject_serror; } static void virt_instance_init(Object *obj) @@ -2141,6 +2172,7 @@ static const TypeInfo virt_machine_info = { .instance_init = virt_instance_init, .interfaces = (InterfaceInfo[]) { { TYPE_HOTPLUG_HANDLER }, + { TYPE_NMI }, { } }, }; diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c index e6c4fe7a5a..f39cefdeea 100644 --- a/hw/intc/arm_gic_common.c +++ b/hw/intc/arm_gic_common.c @@ -155,6 +155,9 @@ void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler, for (i = 0; i < s->num_cpu; i++) { sysbus_init_irq(sbd, &s->parent_vfiq[i]); } + for (i = 0; i < s->num_cpu; i++) { + sysbus_init_irq(sbd, &s->parent_serror[i]); + } if (s->virt_extn) { for (i = 0; i < s->num_cpu; i++) { sysbus_init_irq(sbd, &s->maintenance_irq[i]); diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c index 58ef65f589..19a04449a0 100644 --- a/hw/intc/arm_gicv3_common.c +++ b/hw/intc/arm_gicv3_common.c @@ -288,6 +288,9 @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler, for (i = 0; i < s->num_cpu; i++) { sysbus_init_irq(sbd, &s->cpu[i].parent_vfiq); } + for (i = 0; i < s->num_cpu; i++) { + sysbus_init_irq(sbd, &s->cpu[i].parent_serror); + } memory_region_init_io(&s->iomem_dist, OBJECT(s), ops, s, "gicv3_dist", 0x10000); diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h index b5585fec45..4cdeed7725 100644 --- a/include/hw/intc/arm_gic_common.h +++ b/include/hw/intc/arm_gic_common.h @@ -70,6 +70,7 @@ typedef struct GICState { qemu_irq parent_fiq[GIC_NCPU]; qemu_irq parent_virq[GIC_NCPU]; qemu_irq parent_vfiq[GIC_NCPU]; + qemu_irq parent_serror[GIC_NCPU]; qemu_irq maintenance_irq[GIC_NCPU]; /* GICD_CTLR; for a GIC with the security extensions the NS banked version diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h index 31ec9a1ae4..a025a04727 100644 --- a/include/hw/intc/arm_gicv3_common.h +++ b/include/hw/intc/arm_gicv3_common.h @@ -152,6 +152,7 @@ struct GICv3CPUState { qemu_irq parent_fiq; qemu_irq parent_virq; qemu_irq parent_vfiq; + qemu_irq parent_serror; qemu_irq maintenance_irq; /* Redistributor */