From patchwork Fri Nov 28 13:06:39 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: PranavkumarSawargaonkar X-Patchwork-Id: 41697 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wi0-f199.google.com (mail-wi0-f199.google.com [209.85.212.199]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 61D69244C2 for ; Fri, 28 Nov 2014 13:08:06 +0000 (UTC) Received: by mail-wi0-f199.google.com with SMTP id bs8sf4261926wib.6 for ; Fri, 28 Nov 2014 05:08:05 -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:date :message-id:cc:subject:precedence:list-id:list-unsubscribe :list-archive:list-post:list-help:list-subscribe:errors-to:sender :x-original-sender:x-original-authentication-results:mailing-list; bh=2p1Ot/ypEm5+UVySuz57CXDNQxTYBRhS5a3VvKkKpjQ=; b=jJXQTpbjc2B90KVLN6NykmXwqc2prq3+Kwe2/WvTqhVGaL+ugXSYAI8Lgwy8vmCIpP kMIXiTyk1ArHXw7RIx0nHvsjPX4cKnEbegoyRLLP3jq3lm2mSWVW25AOa3d9/P7cq/Mw 7Xgpav5VmbP+qvZMp8WEPYl4IvjYwWklT1nXr3KI+PzPKjAdS5zg3bDX6Q8l9AFfB/fq EVRFReutHwc10pRRs+kdFJnKKITVmE9jQVOUXYSak/8ezWLPsB49vmGJml2GlZ2IBBwW +rkK4M/lCGLtpZp9C7oHUXsLNySOpj1oDilgAa7SOH1V07bU0kH+fVGp06f61E2CjqMJ r+vw== X-Gm-Message-State: ALoCoQm9BRzEnMcn7evQSDQwOCRYjOFXtBwc5Aez3mfExnaLhtyeAAus/b2cUgXcQElzwJYvvE3e X-Received: by 10.194.133.39 with SMTP id oz7mr3826333wjb.3.1417180085657; Fri, 28 Nov 2014 05:08:05 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.234.228 with SMTP id uh4ls953397lac.108.gmail; Fri, 28 Nov 2014 05:08:05 -0800 (PST) X-Received: by 10.152.1.131 with SMTP id 3mr678335lam.89.1417180085481; Fri, 28 Nov 2014 05:08:05 -0800 (PST) Received: from mail-la0-f42.google.com (mail-la0-f42.google.com. [209.85.215.42]) by mx.google.com with ESMTPS id n4si9985876lan.14.2014.11.28.05.08.05 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 28 Nov 2014 05:08:05 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.42 as permitted sender) client-ip=209.85.215.42; Received: by mail-la0-f42.google.com with SMTP id s18so5712356lam.15 for ; Fri, 28 Nov 2014 05:08:05 -0800 (PST) X-Received: by 10.112.52.37 with SMTP id q5mr43199616lbo.32.1417180085275; Fri, 28 Nov 2014 05:08:05 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.184.201 with SMTP id ew9csp87855lbc; Fri, 28 Nov 2014 05:08:04 -0800 (PST) X-Received: by 10.140.22.201 with SMTP id 67mr61606091qgn.16.1417180083848; Fri, 28 Nov 2014 05:08:03 -0800 (PST) Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id j4si11802910qai.6.2014.11.28.05.08.03 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Fri, 28 Nov 2014 05:08:03 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Received: from localhost ([::1]:44196 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XuLHG-0000nQ-Sm for patch@linaro.org; Fri, 28 Nov 2014 08:08:02 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45647) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XuLGS-00007w-H1 for qemu-devel@nongnu.org; Fri, 28 Nov 2014 08:07:18 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XuLGM-0006J4-Pw for qemu-devel@nongnu.org; Fri, 28 Nov 2014 08:07:12 -0500 Received: from mail-pa0-f45.google.com ([209.85.220.45]:46837) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XuLGM-0006Iw-Hn for qemu-devel@nongnu.org; Fri, 28 Nov 2014 08:07:06 -0500 Received: by mail-pa0-f45.google.com with SMTP id lj1so6838901pab.4 for ; Fri, 28 Nov 2014 05:07:05 -0800 (PST) X-Received: by 10.66.124.136 with SMTP id mi8mr74379892pab.105.1417180025641; Fri, 28 Nov 2014 05:07:05 -0800 (PST) Received: from pnqlab006.amcc.com ([182.73.239.130]) by mx.google.com with ESMTPSA id cq6sm9998183pad.30.2014.11.28.05.07.02 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 28 Nov 2014 05:07:04 -0800 (PST) From: Pranavkumar Sawargaonkar To: qemu-devel@nongnu.org Date: Fri, 28 Nov 2014 18:36:39 +0530 Message-Id: <1417179999-10061-1-git-send-email-pranavkumar@linaro.org> X-Mailer: git-send-email 1.7.9.5 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.85.220.45 Cc: peter.maydell@linaro.org, patches@apm.com, alex.bennee@linaro.org, kvmarm@lists.cs.columbia.edu, christoffer.dall@linaro.org, Pranavkumar Sawargaonkar Subject: [Qemu-devel] [PATCH] target-arm: ARM64: Adding EL1 AARCH32 guest support for KVM. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: pranavkumar@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.42 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 In KVM ARM64 one can choose to run guest in 32bit mode i.e EL1 in AARCH32 mode. This patch adds qemu support for running guest EL1 in AARCH32 mode with virt as a machine model. This patch also adds a support to run Image (along with zImage) for arm32. One can specify about 32bit kernel Image by using -cpu host,el1_aarch32 argument. e.g. "./qemu/aarch64-softmmu/qemu-system-aarch64 -nographic -display none \ -serial stdio -kernel ./Image -m 512 -M virt -cpu host,el1_aarch32 \ -initrd rootfs.img -append "console=ttyAMA0 root=/dev/ram" -enable-kvm" Signed-off-by: Pranavkumar Sawargaonkar --- hw/arm/boot.c | 44 ++++++++++++++++++++++++++++---- hw/arm/virt.c | 30 +++++++++++++++++++++- target-arm/cpu.c | 5 ++-- target-arm/cpu.h | 2 ++ target-arm/kvm64.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 146 insertions(+), 8 deletions(-) diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 0014c34..da8cdc8 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -476,6 +476,32 @@ static void do_cpu_reset(void *opaque) } } +static int check_load_zimage(const char *filename) +{ + int fd; + uint8_t buf[40]; + uint32_t *p = (uint32_t *) &buf[36]; + + fd = open(filename, O_RDONLY | O_BINARY); + if (fd < 0) { + perror(filename); + return -1; + } + + memset(buf, 0, sizeof(buf)); + if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { + close(fd); + return -1; + } + + /* Check for zImage magic number */ + if (*p == 0x016F2818) { + return 1; + } + + return 0; +} + void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) { CPUState *cs; @@ -515,15 +541,23 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) return; } - if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { + if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && + (!cpu->env.el1_aarch32)) { primary_loader = bootloader_aarch64; kernel_load_offset = KERNEL64_LOAD_ADDR; elf_machine = EM_AARCH64; } else { - primary_loader = bootloader; - kernel_load_offset = KERNEL_LOAD_ADDR; - elf_machine = EM_ARM; - } + if (check_load_zimage(info->kernel_filename)) { + primary_loader = bootloader; + kernel_load_offset = KERNEL_LOAD_ADDR; + elf_machine = EM_ARM; + } else { + primary_loader = bootloader; + /* Assuming we are loading Image hence aligning it to 0x8000 */ + kernel_load_offset = KERNEL_LOAD_ADDR - 0x8000; + elf_machine = EM_ARM; + } + } info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb"); diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 314e55b..64213e6 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -204,7 +204,8 @@ static void fdt_add_psci_node(const VirtBoardInfo *vbi) qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp)); cpu_off_fn = QEMU_PSCI_0_2_FN_CPU_OFF; - if (arm_feature(&armcpu->env, ARM_FEATURE_AARCH64)) { + if (arm_feature(&armcpu->env, ARM_FEATURE_AARCH64) && + (!armcpu->env.el1_aarch32)) { cpu_suspend_fn = QEMU_PSCI_0_2_FN64_CPU_SUSPEND; cpu_on_fn = QEMU_PSCI_0_2_FN64_CPU_ON; migrate_fn = QEMU_PSCI_0_2_FN64_MIGRATE; @@ -527,6 +528,24 @@ static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size) return board->fdt; } +#if defined(TARGET_AARCH64) && !defined(CONFIG_USER_ONLY) +static void check_special_cpu_model_flags(const char *cpu_model, + Object *cpuobj) +{ + ARMCPU *cpu = ARM_CPU(cpuobj); + + if (!cpu) { + return; + } + + if (strcmp(cpu_model, "host,el1_aarch32") == 0) { + cpu->env.el1_aarch32 = 1; + } else { + cpu->env.el1_aarch32 = 0; + } +} +#endif + static void machvirt_init(MachineState *machine) { qemu_irq pic[NUM_IRQS]; @@ -540,6 +559,12 @@ static void machvirt_init(MachineState *machine) cpu_model = "cortex-a15"; } +#if defined(TARGET_AARCH64) && !defined(CONFIG_USER_ONLY) + if (strcmp(cpu_model, "host,el1_aarch32") == 0) { + cpu_model = "host"; + } +#endif + vbi = find_machine_info(cpu_model); if (!vbi) { @@ -578,6 +603,9 @@ static void machvirt_init(MachineState *machine) object_property_set_int(cpuobj, vbi->memmap[VIRT_CPUPERIPHS].base, "reset-cbar", &error_abort); } +#if defined(TARGET_AARCH64) && !defined(CONFIG_USER_ONLY) + check_special_cpu_model_flags(machine->cpu_model, cpuobj); +#endif object_property_set_bool(cpuobj, true, "realized", NULL); } diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 5ce7350..37dfe30 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -103,7 +103,7 @@ static void arm_cpu_reset(CPUState *s) env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q'; } - if (arm_feature(env, ARM_FEATURE_AARCH64)) { + if (arm_feature(env, ARM_FEATURE_AARCH64) && (!env->el1_aarch32)) { /* 64 bit CPUs always start in 64 bit mode */ env->aarch64 = 1; #if defined(CONFIG_USER_ONLY) @@ -394,7 +394,8 @@ static void arm_cpu_post_init(Object *obj) &error_abort); } - if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) { + if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64) && + (!cpu->env.el1_aarch32)) { qdev_property_add_static(DEVICE(obj), &arm_cpu_rvbar_property, &error_abort); } diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 7f80090..d2f8eda 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -343,6 +343,8 @@ typedef struct CPUARMState { /* Internal CPU feature flags. */ uint64_t features; + uint32_t el1_aarch32; /* 1 If CPU is in aarch64 state and el1 is aarch32 */ + void *nvic; const struct arm_boot_info *boot_info; } CPUARMState; diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c index c615286..03e6dcc 100644 --- a/target-arm/kvm64.c +++ b/target-arm/kvm64.c @@ -97,6 +97,15 @@ int kvm_arch_init_vcpu(CPUState *cs) cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_PSCI_0_2; } + if ((cpu->env.el1_aarch32)) { + if ((kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_EL1_32BIT))) { + cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_EL1_32BIT; + } else { + fprintf(stderr, "KVM is not supporting EL1 AARCH32 mode\n"); + return -1; + } + } + /* Do KVM_ARM_VCPU_INIT ioctl */ ret = kvm_arm_vcpu_init(cs); if (ret) { @@ -111,6 +120,35 @@ int kvm_arch_init_vcpu(CPUState *cs) #define AARCH64_CORE_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \ KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x)) + +static int kvm_arch32_put_registers(CPUState *cs, int level) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + struct kvm_one_reg reg; + int ret; + int i; + + for (i = 0; i < 16; i++) { + reg.id = AARCH64_CORE_REG(regs.regs[i]); + reg.addr = (uintptr_t) &env->regs[i]; + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret) { + return ret; + } + } + + /* PC will be set in env->regs[15] */ + reg.addr = (uintptr_t) &env->regs[15]; + reg.id = AARCH64_CORE_REG(regs.pc); + ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®); + if (ret) { + return ret; + } + + return ret; +} + int kvm_arch_put_registers(CPUState *cs, int level) { struct kvm_one_reg reg; @@ -121,6 +159,10 @@ int kvm_arch_put_registers(CPUState *cs, int level) ARMCPU *cpu = ARM_CPU(cs); CPUARMState *env = &cpu->env; + if (env->el1_aarch32) { + return kvm_arch32_put_registers(cs, level); + } + for (i = 0; i < 31; i++) { reg.id = AARCH64_CORE_REG(regs.regs[i]); reg.addr = (uintptr_t) &env->xregs[i]; @@ -188,6 +230,33 @@ int kvm_arch_put_registers(CPUState *cs, int level) return ret; } +static int kvm_arch32_get_registers(CPUState *cs) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + struct kvm_one_reg reg; + int ret; + int i; + + for (i = 0; i < 16; i++) { + reg.id = AARCH64_CORE_REG(regs.regs[i]); + reg.addr = (uintptr_t) &env->regs[i]; + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret) { + return ret; + } + } + + reg.addr = (uintptr_t) &env->regs[15]; + reg.id = AARCH64_CORE_REG(regs.pc); + ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®); + if (ret) { + return ret; + } + + return ret; +} + int kvm_arch_get_registers(CPUState *cs) { struct kvm_one_reg reg; @@ -198,6 +267,10 @@ int kvm_arch_get_registers(CPUState *cs) ARMCPU *cpu = ARM_CPU(cs); CPUARMState *env = &cpu->env; + if (env->el1_aarch32) { + return kvm_arch32_get_registers(cs); + } + for (i = 0; i < 31; i++) { reg.id = AARCH64_CORE_REG(regs.regs[i]); reg.addr = (uintptr_t) &env->xregs[i];