From patchwork Thu Nov 28 13:33:18 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 21838 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pd0-f199.google.com (mail-pd0-f199.google.com [209.85.192.199]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id B93CB23FCB for ; Thu, 28 Nov 2013 13:33:37 +0000 (UTC) Received: by mail-pd0-f199.google.com with SMTP id r10sf21468672pdi.6 for ; Thu, 28 Nov 2013 05:33:37 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=40/iv5C8lctzefaKM+y3C5isE/J/DiGvZ7Vp+eFtugw=; b=gG6HuumKVjcFDDPPiFgwLQePriWEl3rSdjE7mI63W+9XPMlCT5YmAshZIUG4NS4OLy PDRg9m7EuIIKbknDfDZWUrH1itCBrIdwffsF8HpNMQgKWDy/k3KWYzSgReA+GqUwOovP FkPuxqIEJKJbJ0d0gg75nLpUeNVyau8NIBM4vQUDw9S5cretOR5wI0EhF7tHp9795iit +7Xr1OspcBo9ggv+2P1l4D/ZMHlIuQ9TpAwQRtrXM9zy8qJ9uaIeqh3rE2OXS8gbXXq7 WRNlQEepT49tzUbDYvQBtub1UCjFcmyUpDWHoxcdjtBlz9dgn8p5/FlCQCMMXa22aUsg vAyA== X-Gm-Message-State: ALoCoQnKYKI0ZyvvGkxHJve7x7YJbLi1UGOc5nbANMKsuOSBlaxlz6r+f2GpWMsKkU9u3CIEUCEk X-Received: by 10.66.220.163 with SMTP id px3mr793413pac.38.1385645616980; Thu, 28 Nov 2013 05:33:36 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.97.201 with SMTP id ec9ls558044qeb.60.gmail; Thu, 28 Nov 2013 05:33:36 -0800 (PST) X-Received: by 10.220.17.131 with SMTP id s3mr15494605vca.20.1385645616853; Thu, 28 Nov 2013 05:33:36 -0800 (PST) Received: from mail-vc0-f182.google.com (mail-vc0-f182.google.com [209.85.220.182]) by mx.google.com with ESMTPS id td8si22859576vdc.131.2013.11.28.05.33.36 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 28 Nov 2013 05:33:36 -0800 (PST) Received-SPF: neutral (google.com: 209.85.220.182 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.182; Received: by mail-vc0-f182.google.com with SMTP id lc6so5942486vcb.13 for ; Thu, 28 Nov 2013 05:33:36 -0800 (PST) X-Received: by 10.220.199.5 with SMTP id eq5mr38572354vcb.16.1385645616687; Thu, 28 Nov 2013 05:33:36 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp15927vcz; Thu, 28 Nov 2013 05:33:36 -0800 (PST) X-Received: by 10.194.11.38 with SMTP id n6mr37457878wjb.25.1385645614548; Thu, 28 Nov 2013 05:33:34 -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 iz4si8179533wic.19.2013.11.28.05.33.34 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Thu, 28 Nov 2013 05:33:34 -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; Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1Vm1ic-0004rf-Rp; Thu, 28 Nov 2013 13:33:22 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, kvmarm@lists.cs.columbia.edu, "Mian M. Hamayun" , afaerber@suse.de, agraf@suse.de Subject: [PATCH 3/7] target-arm: Add minimal KVM AArch64 support Date: Thu, 28 Nov 2013 13:33:18 +0000 Message-Id: <1385645602-18662-4-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1385645602-18662-1-git-send-email-peter.maydell@linaro.org> References: <1385645602-18662-1-git-send-email-peter.maydell@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: peter.maydell@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.182 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: "Mian M. Hamayun" Add the bare minimum set of functions needed for control of an AArch64 KVM vcpu: * CPU initialization * minimal get/put register functions which only handle the basic state of the CPU Signed-off-by: Mian M. Hamayun [PMM: significantly overhauled; most notably: * code lives in kvm64.c rather than using #ifdefs * support '-cpu host' rather than implicitly using whatever the host's CPU is regardless of what the user requests * fix bug attempting to get/set nonexistent X[31] * fix bug writing 64 bit kernel pstate into uint32_t env field ] Signed-off-by: Peter Maydell Reviewed-by: Christoffer Dall --- target-arm/Makefile.objs | 1 + target-arm/kvm.c | 4 + target-arm/kvm64.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 209 insertions(+) create mode 100644 target-arm/kvm64.c diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs index d1db77c..5493a4c 100644 --- a/target-arm/Makefile.objs +++ b/target-arm/Makefile.objs @@ -7,3 +7,4 @@ obj-y += neon_helper.o iwmmxt_helper.o obj-y += gdbstub.o obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o gdbstub64.o obj-$(call land,$(CONFIG_KVM),$(call lnot,$(TARGET_AARCH64))) += kvm32.o +obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o diff --git a/target-arm/kvm.c b/target-arm/kvm.c index 5cdb3b9..1d2688d 100644 --- a/target-arm/kvm.c +++ b/target-arm/kvm.c @@ -128,7 +128,11 @@ static void kvm_arm_host_cpu_initfn(Object *obj) static const TypeInfo host_arm_cpu_type_info = { .name = TYPE_ARM_HOST_CPU, +#ifdef TARGET_AARCH64 + .parent = TYPE_AARCH64_CPU, +#else .parent = TYPE_ARM_CPU, +#endif .instance_init = kvm_arm_host_cpu_initfn, .class_init = kvm_arm_host_cpu_class_init, .class_size = sizeof(ARMHostCPUClass), diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c new file mode 100644 index 0000000..599db5d --- /dev/null +++ b/target-arm/kvm64.c @@ -0,0 +1,204 @@ +/* + * ARM implementation of KVM hooks, 64 bit specific code + * + * Copyright Mian-M. Hamayun 2013, Virtual Open Systems + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include +#include +#include +#include + +#include + +#include "qemu-common.h" +#include "qemu/timer.h" +#include "sysemu/sysemu.h" +#include "sysemu/kvm.h" +#include "kvm_arm.h" +#include "cpu.h" +#include "hw/arm/arm.h" + +static inline void set_feature(uint64_t *features, int feature) +{ + *features |= 1ULL << feature; +} + +bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc) +{ + /* Identify the feature bits corresponding to the host CPU, and + * fill out the ARMHostCPUClass fields accordingly. To do this + * we have to create a scratch VM, create a single CPU inside it, + * and then query that CPU for the relevant ID registers. + * For AArch64 we currently don't care about ID registers at + * all; we just want to know the CPU type. + */ + int fdarray[3]; + uint64_t features = 0; + /* Old kernels may not know about the PREFERRED_TARGET ioctl: however + * we know these will only support creating one kind of guest CPU, + * which is its preferred CPU type. Fortunately these old kernels + * support only a very limited number of CPUs. + */ + static const uint32_t cpus_to_try[] = { + KVM_ARM_TARGET_AEM_V8, + KVM_ARM_TARGET_FOUNDATION_V8, + KVM_ARM_TARGET_CORTEX_A57, + QEMU_KVM_ARM_TARGET_NONE + }; + struct kvm_vcpu_init init; + + if (!kvm_arm_create_scratch_host_vcpu(cpus_to_try, fdarray, &init)) { + return false; + } + + ahcc->target = init.target; + ahcc->dtb_compatible = "arm,arm-v7"; + + kvm_arm_destroy_scratch_host_vcpu(fdarray); + + /* We can assume any KVM supporting CPU is at least a v8 + * with VFPv4+Neon; this in turn implies most of the other + * feature bits. + */ + set_feature(&features, ARM_FEATURE_V8); + set_feature(&features, ARM_FEATURE_VFP4); + set_feature(&features, ARM_FEATURE_NEON); + set_feature(&features, ARM_FEATURE_AARCH64); + + ahcc->features = features; + + return true; +} + +int kvm_arch_init_vcpu(CPUState *cs) +{ + ARMCPU *cpu = ARM_CPU(cs); + struct kvm_vcpu_init init; + int ret; + + if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE || + !arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { + fprintf(stderr, "KVM is not supported for this guest CPU type\n"); + return -EINVAL; + } + + init.target = cpu->kvm_target; + memset(init.features, 0, sizeof(init.features)); + if (cpu->start_powered_off) { + init.features[0] = 1 << KVM_ARM_VCPU_POWER_OFF; + } + ret = kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_INIT, &init); + + /* TODO : support for save/restore/reset of system regs via tuple list */ + + return ret; +} + +#define AARCH64_CORE_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \ + KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x)) + +int kvm_arch_put_registers(CPUState *cs, int level) +{ + struct kvm_one_reg reg; + uint64_t val; + int i; + int ret; + + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + + for (i = 0; i < 31; i++) { + reg.id = AARCH64_CORE_REG(regs.regs[i]); + reg.addr = (uintptr_t) &env->xregs[i]; + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret) { + return ret; + } + } + + reg.id = AARCH64_CORE_REG(regs.sp); + reg.addr = (uintptr_t) &env->xregs[31]; + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret) { + return ret; + } + + /* Note that KVM thinks pstate is 64 bit but we use a uint32_t */ + val = pstate_read(env); + reg.id = AARCH64_CORE_REG(regs.pstate); + reg.addr = (uintptr_t) &val; + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret) { + return ret; + } + + reg.id = AARCH64_CORE_REG(regs.pc); + reg.addr = (uintptr_t) &env->pc; + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret) { + return ret; + } + + /* TODO: + * SP_EL1 + * ELR_EL1 + * SPSR[] + * FP state + * system registers + */ + return ret; +} + +int kvm_arch_get_registers(CPUState *cs) +{ + struct kvm_one_reg reg; + uint64_t val; + int i; + int ret; + + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + + for (i = 0; i < 31; i++) { + reg.id = AARCH64_CORE_REG(regs.regs[i]); + reg.addr = (uintptr_t) &env->xregs[i]; + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret) { + return ret; + } + } + + reg.id = AARCH64_CORE_REG(regs.sp); + reg.addr = (uintptr_t) &env->xregs[31]; + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret) { + return ret; + } + + reg.id = AARCH64_CORE_REG(regs.pstate); + reg.addr = (uintptr_t) &val; + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret) { + return ret; + } + pstate_write(env, val); + + reg.id = AARCH64_CORE_REG(regs.pc); + reg.addr = (uintptr_t) &env->pc; + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret) { + return ret; + } + + /* TODO: other registers */ + return ret; +} + +void kvm_arch_reset_vcpu(CPUState *cs) +{ +}