From patchwork Tue Nov 20 13:31:07 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 12991 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 5C24F23E01 for ; Tue, 20 Nov 2012 13:31:25 +0000 (UTC) Received: from mail-ia0-f180.google.com (mail-ia0-f180.google.com [209.85.210.180]) by fiordland.canonical.com (Postfix) with ESMTP id C2C3CA1912C for ; Tue, 20 Nov 2012 13:31:24 +0000 (UTC) Received: by mail-ia0-f180.google.com with SMTP id t4so1694273iag.11 for ; Tue, 20 Nov 2012 05:31:24 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:from:to:cc :subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=73ewVZqmZ2X7f4JP7NLXRUIuqfRRO4YltDutEYc7wQI=; b=jK/VbIY7O3WV+VZ9bDDIfrXwHrCRmXNntKtpnDsAM6h436x2OVUke0X5Dj4nkAW/1u a1ajGX2LTT2bVbvAz0Xi0CcAuUYdyIZclWd2W4mjMPLAgSVDD99JzJb7m3HuLu2DyFcq 3Bqygh9MMbTZ7rSuqOA8s1hsB9XK7IV07i+u7tiHRzcKyRGmC8o00L7VZ3kTtiLjGky5 w5nhfXI3GrTijDsZ2qw6YGovpi5GTLhWnltGmlrWTiO/IKjmdLAh+JoK29/JspPEhkCT eJlK6sjVr94WocdtfSMOpIRxuBLYxGkIG7YqGPUQlipfV6DrZUITrmUS3gN0Iv4uHONC o7Wg== Received: by 10.43.46.2 with SMTP id um2mr13825162icb.18.1353418284567; Tue, 20 Nov 2012 05:31:24 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.50.67.148 with SMTP id n20csp317802igt; Tue, 20 Nov 2012 05:31:22 -0800 (PST) Received: by 10.180.7.130 with SMTP id j2mr14457752wia.17.1353418281349; Tue, 20 Nov 2012 05:31:21 -0800 (PST) Received: from mnementh.archaic.org.uk (1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.1.0.0.b.8.0.1.0.0.2.ip6.arpa. [2001:8b0:1d0::1]) by mx.google.com with ESMTPS id du8si11936752wib.19.2012.11.20.05.31.20 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 20 Nov 2012 05:31:21 -0800 (PST) Received-SPF: neutral (google.com: 2001:8b0:1d0::1 is neither permitted nor denied by best guess record for domain of pm215@archaic.org.uk) client-ip=2001:8b0:1d0::1; Authentication-Results: mx.google.com; spf=neutral (google.com: 2001:8b0:1d0::1 is neither permitted nor denied by best guess record for domain of pm215@archaic.org.uk) smtp.mail=pm215@archaic.org.uk Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.72) (envelope-from ) id 1Tanuw-0006Dm-TW; Tue, 20 Nov 2012 13:31:10 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Cc: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, patches@linaro.org, Blue Swirl , =?UTF-8?q?Andreas=20F=C3=A4rber?= , Avi Kivity , Marcelo Tosatti Subject: [RFC v4 5/8] target-arm: Use MemoryListener to identify GIC base address for KVM Date: Tue, 20 Nov 2012 13:31:07 +0000 Message-Id: <1353418270-23881-6-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1353418270-23881-1-git-send-email-peter.maydell@linaro.org> References: <1353418270-23881-1-git-send-email-peter.maydell@linaro.org> X-Gm-Message-State: ALoCoQkyOS9aL44QFc9/wYjp15Oy3CreZ9UEDhtFQoeLPzZ4/+p9wQU9SEkXbkdBEIr9nt1jQBx0 When using an in-kernel GIC with KVM, we need to tell the kernel where the GIC's memory mapped registers live. Do this by registering a MemoryListener which tracks where the board model maps the A15's private peripherals, so we can finish the GIC initialisation when the GIC is actually mapped. Signed-off-by: Peter Maydell --- target-arm/kvm.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++ target-arm/kvm_arm.h | 32 +++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 target-arm/kvm_arm.h diff --git a/target-arm/kvm.c b/target-arm/kvm.c index 4217ad6..ff3007b 100644 --- a/target-arm/kvm.c +++ b/target-arm/kvm.c @@ -19,6 +19,7 @@ #include "qemu-timer.h" #include "sysemu.h" #include "kvm.h" +#include "kvm_arm.h" #include "cpu.h" #include "hw/arm-misc.h" @@ -62,6 +63,88 @@ int kvm_arch_init_vcpu(CPUARMState *env) return ret; } +/* We track all the KVM devices which need their memory addresses + * passing to the kernel in a list of these structures. + * When board init is complete we run through the list and + * tell the kernel the base addresses of the memory regions. + * We use a MemoryListener to track mapping and unmapping of + * the regions during board creation, so the board models don't + * need to do anything special for the KVM case. + */ +typedef struct KVMDevice { + struct kvm_device_address kda; + MemoryRegion *mr; + QSLIST_ENTRY(KVMDevice) entries; +} KVMDevice; + +static QSLIST_HEAD(kvm_devices_head, KVMDevice) kvm_devices_head; + +static void kvm_arm_devlistener_add(MemoryListener *listener, + MemoryRegionSection *section) +{ + KVMDevice *kd; + QSLIST_FOREACH(kd, &kvm_devices_head, entries) { + if (section->mr == kd->mr) { + kd->kda.addr = section->offset_within_address_space; + } + } +} + +static void kvm_arm_devlistener_del(MemoryListener *listener, + MemoryRegionSection *section) +{ + KVMDevice *kd; + QSLIST_FOREACH(kd, &kvm_devices_head, entries) { + if (section->mr == kd->mr) { + kd->kda.addr = -1; + } + } +} + +static MemoryListener devlistener = { + .region_add = kvm_arm_devlistener_add, + .region_del = kvm_arm_devlistener_del, +}; + +static void kvm_arm_machine_init_done(Notifier *notifier, void *data) +{ + KVMDevice *kd, *tkd; + memory_listener_unregister(&devlistener); + QSLIST_FOREACH_SAFE(kd, &kvm_devices_head, entries, tkd) { + if (kd->kda.addr != -1) { + if (kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ADDRESS, &kd->kda) < 0) { + fprintf(stderr, "KVM_SET_DEVICE_ADDRESS failed: %s\n", + strerror(errno)); + abort(); + } + } + g_free(kd); + } +} + +static Notifier notify = { + .notify = kvm_arm_machine_init_done, +}; + +void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid) +{ + KVMDevice *kd; + + if (!kvm_irqchip_in_kernel()) { + return; + } + + if (QSLIST_EMPTY(&kvm_devices_head)) { + memory_listener_register(&devlistener, NULL); + qemu_add_machine_init_done_notifier(¬ify); + } + kd = g_new0(KVMDevice, 1); + kd->mr = mr; + kd->kda.id = devid; + kd->kda.addr = -1; + QSLIST_INSERT_HEAD(&kvm_devices_head, kd, entries); +} + typedef struct Reg { uint64_t id; int offset; diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h new file mode 100644 index 0000000..2f61d00 --- /dev/null +++ b/target-arm/kvm_arm.h @@ -0,0 +1,32 @@ +/* + * QEMU KVM support -- ARM specific functions. + * + * Copyright (c) 2012 Linaro Limited + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef QEMU_KVM_ARM_H +#define QEMU_KVM_ARM_H + +#include "kvm.h" +#include "memory.h" + +/** + * kvm_arm_register_device: + * @mr: memory region for this device + * @devid: the KVM device ID + * + * Remember the memory region @mr, and when it is mapped by the + * machine model, tell the kernel that base address using the + * KVM_SET_DEVICE_ADDRESS ioctl. @devid should be the ID of + * the device as defined by KVM_SET_DEVICE_ADDRESS. + * The machine model may map and unmap the device multiple times; + * the kernel will only be told the final address at the point + * where machine init is complete. + */ +void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid); + +#endif