From patchwork Fri Feb 22 19:04:22 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 15036 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 6A81723E4C for ; Fri, 22 Feb 2013 19:04:39 +0000 (UTC) Received: from mail-vc0-f173.google.com (mail-vc0-f173.google.com [209.85.220.173]) by fiordland.canonical.com (Postfix) with ESMTP id DC822A18C87 for ; Fri, 22 Feb 2013 19:04:38 +0000 (UTC) Received: by mail-vc0-f173.google.com with SMTP id fy27so616102vcb.4 for ; Fri, 22 Feb 2013 11:04:38 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-forwarded-to:x-forwarded-for:delivered-to:x-received :received-spf:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references:x-gm-message-state; bh=feX1N/MQFNfvqkwmKzWABBGeQ9mkGNQgtqu8+3//JXs=; b=gCo3sCqVbYibHo4yKd3Y/EUpFHqoZ61+W6sF1fAwrqXXMPFCdKQYydFEyBw4AxYJsV Y1st2PEpOrh7CaIh+yUTOh+Z0oQWeI9CuxO0Z+0CRk5aCe+GDKfRSikLxzi7FCFrypoy Nzg6+RgilKfIlJAgVFRo6JoX9Ofp3Tl22yu9YOkyfqYriLZno7IPLv9BBHzuC48SfBWi Ag++nNjPqXQL2uzs2RDMAyRvB+ULGFoI0SfLVLNwonI83vaHAPFtvJ3jspSFDcMhL25Q +GvOUzUUO9P08fsu5dSnI1sEsH5KuLtSFXO857syXqihD5qDQgsyOFaI4pXU33VjrFDP n9xw== X-Received: by 10.220.39.69 with SMTP id f5mr4109820vce.45.1361559878333; Fri, 22 Feb 2013 11:04:38 -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.58.145.101 with SMTP id st5csp103652veb; Fri, 22 Feb 2013 11:04:37 -0800 (PST) X-Received: by 10.14.204.3 with SMTP id g3mr9222068eeo.27.1361559873976; Fri, 22 Feb 2013 11:04:33 -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 4si6317033eee.241.2013.02.22.11.04.33 (version=TLSv1 cipher=RC4-SHA bits=128/128); Fri, 22 Feb 2013 11:04:33 -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 1U8xuz-0005mB-9o; Fri, 22 Feb 2013 19:04:25 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, kvm@vger.kernel.org, Marcelo Tosatti , kvmarm@lists.cs.columbia.edu, Blue Swirl , =?UTF-8?q?Andreas=20F=C3=A4rber?= , Gleb Natapov , Christoffer Dall , Paolo Bonzini Subject: [PATCH v6 6/9] target-arm: Use MemoryListener to identify GIC base address for KVM Date: Fri, 22 Feb 2013 19:04:22 +0000 Message-Id: <1361559865-22168-7-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1361559865-22168-1-git-send-email-peter.maydell@linaro.org> References: <1361559865-22168-1-git-send-email-peter.maydell@linaro.org> X-Gm-Message-State: ALoCoQlSyr9nxFrUw/jdEH5bf82DrQ1x74mqUk77e4HLTkgNbgRGrOkFb+mdbzCo9RzDCWO9ZFNH 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 Reviewed-by: Paolo Bonzini --- target-arm/kvm.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++ target-arm/kvm_arm.h | 32 +++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 target-arm/kvm_arm.h diff --git a/target-arm/kvm.c b/target-arm/kvm.c index 5cd9086..c0f2d86 100644 --- a/target-arm/kvm.c +++ b/target-arm/kvm.c @@ -19,6 +19,7 @@ #include "qemu/timer.h" #include "sysemu/sysemu.h" #include "sysemu/kvm.h" +#include "kvm_arm.h" #include "cpu.h" #include "hw/arm-misc.h" @@ -67,6 +68,89 @@ int kvm_arch_init_vcpu(CPUState *cs) 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_arm_device_addr 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_ARM_SET_DEVICE_ADDR, + &kd->kda) < 0) { + fprintf(stderr, "KVM_ARM_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..b1c54ff --- /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 "sysemu/kvm.h" +#include "exec/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