qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v3 00/11] AARCH64 support on machvirt machine model using KVM
@ 2013-09-27 10:10 Mian M. Hamayun
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 01/11] ARM: arm64 kvm headers from kernel arm64-kvm tree Mian M. Hamayun
                   ` (10 more replies)
  0 siblings, 11 replies; 20+ messages in thread
From: Mian M. Hamayun @ 2013-09-27 10:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, agraf, tech, kvmarm, afaerber

From: "Mian M. Hamayun" <m.hamayun@virtualopensystems.com>

This is the v3 of patch series that implements KVM support in QEMU for the ARMv8
Cortex A57 CPU. It depends on the recently mainlined AArch64 preparation patch
series and machvirt patches version v7, and uses the already available KVM 
in-kernel GIC support. 
This implementation supports both 64-bit and 32-bit guests on AARCH64.

As a reference, KVM Tool and the AArch64 bootwrapper were used, as well as
public documentation from ARM. The following work has been tested with SMP
capabilities for both 64 and 32-bit guests, under ARMv8 Fast and Foundation 
Models (Open Embedded userspace with an emulated MMC).

The v1 of this patch series related to AArch64 CPU model for Versatile Express
was sponsored by Huawei, and developed in collaboration between Huawei
Technologies Duesseldorf GmbH - European Research Center Munich (ERC) and
Virtual Open Systems.

A working tree of this implementation is available on the "kvm-aarch64-v3"
branch of the following github repository.

https://github.com/virtualopensystems/qemu/tree/kvm-aarch64-v3

Summary of Changes:

Changes v2 -> v3
 * Based on AArch64 Preparation Patchset (mainlined) and machvirt patch version v7
 * 32 and 64-bit KVM hooks have been separated into kvm_32.c and kvm_64.c, whereas
   common code resides in kvm.c
 * SMP support is now implemented using PSCI method instead of the boot injection
   mechanism, as implemented in the previous versions
 * 32-bit SMP guest support is now available

Changes v1 -> v2
 * Based on AArch64 Preparation Patchset V5 and machvirt patches.
 * Implemented for Machvirt Machine Model.
 * Architecture-specific CPU initialization code improved. Removed hardcoding
   from register set/get loops and introduced CPU target type array to find
   appropriate ARMv8 CPU type supported by KVM.
 * Disable the PSCI method in case of AArch64 and use the spin-table method
   instead for booting secondary CPUs.
 * 32-bit guest support still missing

v1
 * Based on AArch64 Preparation Patchset V4
 * Implemented for Versatile Express Machine Model
 * Support for SMP using bootcode injection
 * No 32-bit guest support

John Rigby (2):
  ARM: arm64 kvm headers from kernel arm64-kvm tree
  AARCH64: add a57core

Mian M. Hamayun (9):
  AARCH64: Add A57 CPU to default AArch64 configuration and enable KVM
  AARCH64: Separate 32-bit specific code from common KVM hooks
  AARCH64: Add AARCH64 CPU initialization, get and put registers support
  target-arm: Parameterize the bootloader selection and setup mechanism
  AARCH64: Add boot support for aarch64 processor
  AARCH64: Enable SMP support for aarch64 processors using PSCI method
  AARCH64: Enable configure support for 32-bit guests on AARCH64
  AARCH64: Add flags and boot parameters for 32-bit guests on AARCH64
  AARCH64: Add 32-bit mode selection parameter

 configure                           |   3 +-
 default-configs/aarch64-softmmu.mak |   1 +
 hw/arm/boot.c                       | 147 ++++++++++++--
 hw/arm/virt.c                       |   8 +
 hw/cpu/Makefile.objs                |   1 +
 hw/cpu/a57mpcore.c                  | 122 ++++++++++++
 linux-headers/asm-arm64/kvm.h       | 168 ++++++++++++++++
 linux-headers/asm-arm64/kvm_para.h  |   1 +
 linux-headers/linux/kvm.h           |   1 +
 qemu-options.hx                     |   8 +
 target-arm/Makefile.objs            |   5 +
 target-arm/cpu.c                    |  18 +-
 target-arm/kvm.c                    | 363 ----------------------------------
 target-arm/kvm_32.c                 | 382 ++++++++++++++++++++++++++++++++++++
 target-arm/kvm_64.c                 | 146 ++++++++++++++
 vl.c                                |   4 +
 16 files changed, 997 insertions(+), 381 deletions(-)
 create mode 100644 hw/cpu/a57mpcore.c
 create mode 100644 linux-headers/asm-arm64/kvm.h
 create mode 100644 linux-headers/asm-arm64/kvm_para.h
 create mode 100644 target-arm/kvm_32.c
 create mode 100644 target-arm/kvm_64.c

-- 
1.8.1.2

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v3 01/11] ARM: arm64 kvm headers from kernel arm64-kvm tree
  2013-09-27 10:10 [Qemu-devel] [PATCH v3 00/11] AARCH64 support on machvirt machine model using KVM Mian M. Hamayun
@ 2013-09-27 10:10 ` Mian M. Hamayun
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 02/11] AARCH64: add a57core Mian M. Hamayun
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Mian M. Hamayun @ 2013-09-27 10:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, agraf, tech, kvmarm, afaerber

From: John Rigby <john.rigby@linaro.org>

Also add the KVM_REG_ARM64 register type to linux/kvm header file.

Signed-off-by: John Rigby <john.rigby@linaro.org>
Signed-off-by: Mian M. Hamayun <m.hamayun@virtualopensystems.com>
---
 linux-headers/asm-arm64/kvm.h      | 168 +++++++++++++++++++++++++++++++++++++
 linux-headers/asm-arm64/kvm_para.h |   1 +
 linux-headers/linux/kvm.h          |   1 +
 3 files changed, 170 insertions(+)
 create mode 100644 linux-headers/asm-arm64/kvm.h
 create mode 100644 linux-headers/asm-arm64/kvm_para.h

diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h
new file mode 100644
index 0000000..5031f42
--- /dev/null
+++ b/linux-headers/asm-arm64/kvm.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2012,2013 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * Derived from arch/arm/include/uapi/asm/kvm.h:
+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University
+ * Author: Christoffer Dall <c.dall@virtualopensystems.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARM_KVM_H__
+#define __ARM_KVM_H__
+
+#define KVM_SPSR_EL1	0
+#define KVM_SPSR_SVC	KVM_SPSR_EL1
+#define KVM_SPSR_ABT	1
+#define KVM_SPSR_UND	2
+#define KVM_SPSR_IRQ	3
+#define KVM_SPSR_FIQ	4
+#define KVM_NR_SPSR	5
+
+#ifndef __ASSEMBLY__
+#include <asm/types.h>
+#include <asm/ptrace.h>
+
+#define __KVM_HAVE_GUEST_DEBUG
+#define __KVM_HAVE_IRQ_LINE
+
+#define KVM_REG_SIZE(id)						\
+	(1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
+
+struct kvm_regs {
+	struct user_pt_regs regs;	/* sp = sp_el0 */
+
+	__u64	sp_el1;
+	__u64	elr_el1;
+
+	__u64	spsr[KVM_NR_SPSR];
+
+	struct user_fpsimd_state fp_regs;
+};
+
+/* Supported Processor Types */
+#define KVM_ARM_TARGET_AEM_V8		0
+#define KVM_ARM_TARGET_FOUNDATION_V8	1
+#define KVM_ARM_TARGET_CORTEX_A57	2
+
+#define KVM_ARM_NUM_TARGETS		3
+
+/* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
+#define KVM_ARM_DEVICE_TYPE_SHIFT	0
+#define KVM_ARM_DEVICE_TYPE_MASK	(0xffff << KVM_ARM_DEVICE_TYPE_SHIFT)
+#define KVM_ARM_DEVICE_ID_SHIFT		16
+#define KVM_ARM_DEVICE_ID_MASK		(0xffff << KVM_ARM_DEVICE_ID_SHIFT)
+
+/* Supported device IDs */
+#define KVM_ARM_DEVICE_VGIC_V2		0
+
+/* Supported VGIC address types  */
+#define KVM_VGIC_V2_ADDR_TYPE_DIST	0
+#define KVM_VGIC_V2_ADDR_TYPE_CPU	1
+
+#define KVM_VGIC_V2_DIST_SIZE		0x1000
+#define KVM_VGIC_V2_CPU_SIZE		0x2000
+
+#define KVM_ARM_VCPU_POWER_OFF		0 /* CPU is started in OFF state */
+#define KVM_ARM_VCPU_EL1_32BIT		1 /* CPU running a 32bit VM */
+
+struct kvm_vcpu_init {
+	__u32 target;
+	__u32 features[7];
+};
+
+struct kvm_sregs {
+};
+
+struct kvm_fpu {
+};
+
+struct kvm_guest_debug_arch {
+};
+
+struct kvm_debug_exit_arch {
+};
+
+struct kvm_sync_regs {
+};
+
+struct kvm_arch_memory_slot {
+};
+
+/* If you need to interpret the index values, here is the key: */
+#define KVM_REG_ARM_COPROC_MASK		0x000000000FFF0000
+#define KVM_REG_ARM_COPROC_SHIFT	16
+
+/* Normal registers are mapped as coprocessor 16. */
+#define KVM_REG_ARM_CORE		(0x0010 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM_CORE_REG(name)	(offsetof(struct kvm_regs, name) / sizeof(__u32))
+
+/* Some registers need more space to represent values. */
+#define KVM_REG_ARM_DEMUX		(0x0011 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM_DEMUX_ID_MASK	0x000000000000FF00
+#define KVM_REG_ARM_DEMUX_ID_SHIFT	8
+#define KVM_REG_ARM_DEMUX_ID_CCSIDR	(0x00 << KVM_REG_ARM_DEMUX_ID_SHIFT)
+#define KVM_REG_ARM_DEMUX_VAL_MASK	0x00000000000000FF
+#define KVM_REG_ARM_DEMUX_VAL_SHIFT	0
+
+/* AArch64 system registers */
+#define KVM_REG_ARM64_SYSREG		(0x0013 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM64_SYSREG_OP0_MASK	0x000000000000c000
+#define KVM_REG_ARM64_SYSREG_OP0_SHIFT	14
+#define KVM_REG_ARM64_SYSREG_OP1_MASK	0x0000000000003800
+#define KVM_REG_ARM64_SYSREG_OP1_SHIFT	11
+#define KVM_REG_ARM64_SYSREG_CRN_MASK	0x0000000000000780
+#define KVM_REG_ARM64_SYSREG_CRN_SHIFT	7
+#define KVM_REG_ARM64_SYSREG_CRM_MASK	0x0000000000000078
+#define KVM_REG_ARM64_SYSREG_CRM_SHIFT	3
+#define KVM_REG_ARM64_SYSREG_OP2_MASK	0x0000000000000007
+#define KVM_REG_ARM64_SYSREG_OP2_SHIFT	0
+
+/* KVM_IRQ_LINE irq field index values */
+#define KVM_ARM_IRQ_TYPE_SHIFT		24
+#define KVM_ARM_IRQ_TYPE_MASK		0xff
+#define KVM_ARM_IRQ_VCPU_SHIFT		16
+#define KVM_ARM_IRQ_VCPU_MASK		0xff
+#define KVM_ARM_IRQ_NUM_SHIFT		0
+#define KVM_ARM_IRQ_NUM_MASK		0xffff
+
+/* irq_type field */
+#define KVM_ARM_IRQ_TYPE_CPU		0
+#define KVM_ARM_IRQ_TYPE_SPI		1
+#define KVM_ARM_IRQ_TYPE_PPI		2
+
+/* out-of-kernel GIC cpu interrupt injection irq_number field */
+#define KVM_ARM_IRQ_CPU_IRQ		0
+#define KVM_ARM_IRQ_CPU_FIQ		1
+
+/* Highest supported SPI, from VGIC_NR_IRQS */
+#define KVM_ARM_IRQ_GIC_MAX		127
+
+/* PSCI interface */
+#define KVM_PSCI_FN_BASE		0x95c1ba5e
+#define KVM_PSCI_FN(n)			(KVM_PSCI_FN_BASE + (n))
+
+#define KVM_PSCI_FN_CPU_SUSPEND		KVM_PSCI_FN(0)
+#define KVM_PSCI_FN_CPU_OFF		KVM_PSCI_FN(1)
+#define KVM_PSCI_FN_CPU_ON		KVM_PSCI_FN(2)
+#define KVM_PSCI_FN_MIGRATE		KVM_PSCI_FN(3)
+
+#define KVM_PSCI_RET_SUCCESS		0
+#define KVM_PSCI_RET_NI			((unsigned long)-1)
+#define KVM_PSCI_RET_INVAL		((unsigned long)-2)
+#define KVM_PSCI_RET_DENIED		((unsigned long)-3)
+
+#endif
+
+#endif /* __ARM_KVM_H__ */
diff --git a/linux-headers/asm-arm64/kvm_para.h b/linux-headers/asm-arm64/kvm_para.h
new file mode 100644
index 0000000..14fab8f
--- /dev/null
+++ b/linux-headers/asm-arm64/kvm_para.h
@@ -0,0 +1 @@
+#include <asm-generic/kvm_para.h>
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index c614070..4200779 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -783,6 +783,7 @@ struct kvm_dirty_tlb {
 #define KVM_REG_IA64		0x3000000000000000ULL
 #define KVM_REG_ARM		0x4000000000000000ULL
 #define KVM_REG_S390		0x5000000000000000ULL
+#define KVM_REG_ARM64		0x6000000000000000ULL
 
 #define KVM_REG_SIZE_SHIFT	52
 #define KVM_REG_SIZE_MASK	0x00f0000000000000ULL
-- 
1.8.1.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v3 02/11] AARCH64: add a57core
  2013-09-27 10:10 [Qemu-devel] [PATCH v3 00/11] AARCH64 support on machvirt machine model using KVM Mian M. Hamayun
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 01/11] ARM: arm64 kvm headers from kernel arm64-kvm tree Mian M. Hamayun
@ 2013-09-27 10:10 ` Mian M. Hamayun
  2013-09-27 15:53   ` Andreas Färber
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 03/11] AARCH64: Add A57 CPU to default AArch64 configuration and enable KVM Mian M. Hamayun
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 20+ messages in thread
From: Mian M. Hamayun @ 2013-09-27 10:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, agraf, tech, kvmarm, afaerber

From: John Rigby <john.rigby@linaro.org>

Just an copy of a15 with a57 substituting a15 for now.

Signed-off-by: John Rigby <john.rigby@linaro.org>
Signed-off-by: Mian M. Hamayun <m.hamayun@virtualopensystems.com>
---
 hw/cpu/Makefile.objs |   1 +
 hw/cpu/a57mpcore.c   | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++
 target-arm/cpu.c     |   9 ++++
 3 files changed, 132 insertions(+)
 create mode 100644 hw/cpu/a57mpcore.c

diff --git a/hw/cpu/Makefile.objs b/hw/cpu/Makefile.objs
index df287c1..22e9567 100644
--- a/hw/cpu/Makefile.objs
+++ b/hw/cpu/Makefile.objs
@@ -1,5 +1,6 @@
 obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o
 obj-$(CONFIG_A9MPCORE) += a9mpcore.o
 obj-$(CONFIG_A15MPCORE) += a15mpcore.o
+obj-$(CONFIG_A57MPCORE) += a57mpcore.o
 obj-$(CONFIG_ICC_BUS) += icc_bus.o
 
diff --git a/hw/cpu/a57mpcore.c b/hw/cpu/a57mpcore.c
new file mode 100644
index 0000000..4be277f
--- /dev/null
+++ b/hw/cpu/a57mpcore.c
@@ -0,0 +1,122 @@
+/*
+ * Cortex-A57MPCore internal peripheral emulation.
+ *
+ * Copyright (c) 2012 Linaro Limited.
+ * Written by Peter Maydell.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/sysbus.h"
+#include "sysemu/kvm.h"
+
+/* A57MP private memory region.  */
+
+#define TYPE_A57MPCORE_PRIV "a57mpcore_priv"
+#define A57MPCORE_PRIV(obj) \
+    OBJECT_CHECK(A57MPPrivState, (obj), TYPE_A57MPCORE_PRIV)
+
+typedef struct A57MPPrivState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
+    uint32_t num_cpu;
+    uint32_t num_irq;
+    MemoryRegion container;
+    DeviceState *gic;
+} A57MPPrivState;
+
+static void a57mp_priv_set_irq(void *opaque, int irq, int level)
+{
+    A57MPPrivState *s = (A57MPPrivState *)opaque;
+    qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
+}
+
+static int a57mp_priv_init(SysBusDevice *dev)
+{
+    A57MPPrivState *s = A57MPCORE_PRIV(dev);
+    SysBusDevice *busdev;
+    const char *gictype = "arm_gic";
+
+    if (kvm_irqchip_in_kernel()) {
+        gictype = "kvm-arm-gic";
+    }
+
+    s->gic = qdev_create(NULL, gictype);
+    qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
+    qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
+    qdev_prop_set_uint32(s->gic, "revision", 2);
+    qdev_init_nofail(s->gic);
+    busdev = SYS_BUS_DEVICE(s->gic);
+
+    /* Pass through outbound IRQ lines from the GIC */
+    sysbus_pass_irq(dev, busdev);
+
+    /* Pass through inbound GPIO lines to the GIC */
+    qdev_init_gpio_in(DEVICE(dev), a57mp_priv_set_irq, s->num_irq - 32);
+
+    /* Memory map (addresses are offsets from PERIPHBASE):
+     *  0x0000-0x0fff -- reserved
+     *  0x1000-0x1fff -- GIC Distributor
+     *  0x2000-0x2fff -- GIC CPU interface
+     *  0x4000-0x4fff -- GIC virtual interface control (not modelled)
+     *  0x5000-0x5fff -- GIC virtual interface control (not modelled)
+     *  0x6000-0x7fff -- GIC virtual CPU interface (not modelled)
+     */
+    memory_region_init(&s->container, OBJECT(s),
+                       "a57mp-priv-container", 0x8000);
+    memory_region_add_subregion(&s->container, 0x1000,
+                                sysbus_mmio_get_region(busdev, 0));
+    memory_region_add_subregion(&s->container, 0x2000,
+                                sysbus_mmio_get_region(busdev, 1));
+
+    sysbus_init_mmio(dev, &s->container);
+    return 0;
+}
+
+static Property a57mp_priv_properties[] = {
+    DEFINE_PROP_UINT32("num-cpu", A57MPPrivState, num_cpu, 1),
+    /* The Cortex-A57MP may have anything from 0 to 224 external interrupt
+     * IRQ lines (with another 32 internal). We default to 128+32, which
+     * is the number provided by the Cortex-A57MP test chip in the
+     * Versatile Express A57 development board.
+     * Other boards may differ and should set this property appropriately.
+     */
+    DEFINE_PROP_UINT32("num-irq", A57MPPrivState, num_irq, 160),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void a57mp_priv_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+    k->init = a57mp_priv_init;
+    dc->props = a57mp_priv_properties;
+    /* We currently have no savable state */
+}
+
+static const TypeInfo a57mp_priv_info = {
+    .name  = TYPE_A57MPCORE_PRIV,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size  = sizeof(A57MPPrivState),
+    .class_init = a57mp_priv_class_init,
+};
+
+static void a57mp_register_types(void)
+{
+    type_register_static(&a57mp_priv_info);
+}
+
+type_init(a57mp_register_types)
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index d40f2a7..5d811b9 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -684,6 +684,14 @@ static void cortex_a15_initfn(Object *obj)
     define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
 }
 
+static void cortex_a57_initfn(Object *obj)
+{
+    ARMCPU *cpu = ARM_CPU(obj);
+    set_feature(&cpu->env, ARM_FEATURE_V8);
+    set_feature(&cpu->env, ARM_FEATURE_AARCH64);
+    /* TODO: See if we need to set some more features for ARMv8 ? */
+}
+
 static void ti925t_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
@@ -872,6 +880,7 @@ static const ARMCPUInfo arm_cpus[] = {
     { .name = "cortex-a8",   .initfn = cortex_a8_initfn },
     { .name = "cortex-a9",   .initfn = cortex_a9_initfn },
     { .name = "cortex-a15",  .initfn = cortex_a15_initfn },
+    { .name = "cortex-a57",  .initfn = cortex_a57_initfn },
     { .name = "ti925t",      .initfn = ti925t_initfn },
     { .name = "sa1100",      .initfn = sa1100_initfn },
     { .name = "sa1110",      .initfn = sa1110_initfn },
-- 
1.8.1.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v3 03/11] AARCH64: Add A57 CPU to default AArch64 configuration and enable KVM
  2013-09-27 10:10 [Qemu-devel] [PATCH v3 00/11] AARCH64 support on machvirt machine model using KVM Mian M. Hamayun
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 01/11] ARM: arm64 kvm headers from kernel arm64-kvm tree Mian M. Hamayun
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 02/11] AARCH64: add a57core Mian M. Hamayun
@ 2013-09-27 10:10 ` Mian M. Hamayun
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 04/11] AARCH64: Separate 32-bit specific code from common KVM hooks Mian M. Hamayun
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Mian M. Hamayun @ 2013-09-27 10:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, agraf, tech, kvmarm, afaerber

From: "Mian M. Hamayun" <m.hamayun@virtualopensystems.com>

Introduce the A57 cpu to the default AArch64 configuration and enable KVM for
64-bit guests only.

Signed-off-by: Mian M. Hamayun <m.hamayun@virtualopensystems.com>
---
 configure                           | 2 +-
 default-configs/aarch64-softmmu.mak | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/configure b/configure
index 2b83936..7298b69 100755
--- a/configure
+++ b/configure
@@ -4481,7 +4481,7 @@ case "$target_name" in
   *)
 esac
 case "$target_name" in
-  arm|i386|x86_64|ppcemb|ppc|ppc64|s390x)
+  arm|aarch64|i386|x86_64|ppcemb|ppc|ppc64|s390x)
     # Make sure the target and host cpus are compatible
     if test "$kvm" = "yes" -a "$target_softmmu" = "yes" -a \
       \( "$target_name" = "$cpu" -o \
diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak
index 175362f..0eb3d96 100644
--- a/default-configs/aarch64-softmmu.mak
+++ b/default-configs/aarch64-softmmu.mak
@@ -37,6 +37,7 @@ CONFIG_USB_MUSB=y
 CONFIG_ARM11MPCORE=y
 CONFIG_A9MPCORE=y
 CONFIG_A15MPCORE=y
+CONFIG_A57MPCORE=y
 
 CONFIG_ARM_GIC=y
 CONFIG_ARM_GIC_KVM=$(CONFIG_KVM)
-- 
1.8.1.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v3 04/11] AARCH64: Separate 32-bit specific code from common KVM hooks
  2013-09-27 10:10 [Qemu-devel] [PATCH v3 00/11] AARCH64 support on machvirt machine model using KVM Mian M. Hamayun
                   ` (2 preceding siblings ...)
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 03/11] AARCH64: Add A57 CPU to default AArch64 configuration and enable KVM Mian M. Hamayun
@ 2013-09-27 10:10 ` Mian M. Hamayun
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 05/11] AARCH64: Add AARCH64 CPU initialization, get and put registers support Mian M. Hamayun
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Mian M. Hamayun @ 2013-09-27 10:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, agraf, tech, kvmarm, afaerber

From: "Mian M. Hamayun" <m.hamayun@virtualopensystems.com>

This commit separates the 32-bit (ARMv7) specific KVM hooks from
the common code. It also adds the stub functions for 64-bit (ARMv8).

The makefile objects are also tweaked accordingly to compile code
either of ARMv7 or ARMv8 depending on the AARCH64 variable.

Signed-off-by: Mian M. Hamayun <m.hamayun@virtualopensystems.com>
---
 target-arm/Makefile.objs |   5 +
 target-arm/kvm.c         | 363 --------------------------------------------
 target-arm/kvm_32.c      | 382 +++++++++++++++++++++++++++++++++++++++++++++++
 target-arm/kvm_64.c      |  39 +++++
 4 files changed, 426 insertions(+), 363 deletions(-)
 create mode 100644 target-arm/kvm_32.c
 create mode 100644 target-arm/kvm_64.c

diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
index 6453f5c..4b37d29 100644
--- a/target-arm/Makefile.objs
+++ b/target-arm/Makefile.objs
@@ -1,6 +1,11 @@
 obj-y += arm-semi.o
 obj-$(CONFIG_SOFTMMU) += machine.o
 obj-$(CONFIG_KVM) += kvm.o
+ifeq ($(TARGET_AARCH64),y)
+obj-$(CONFIG_KVM) += kvm_64.o
+else
+obj-$(CONFIG_KVM) += kvm_32.o
+endif
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
 obj-y += translate.o op_helper.o helper.o cpu.o
 obj-y += neon_helper.o iwmmxt_helper.o
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index b92e00d..8e608c9 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -50,130 +50,6 @@ unsigned long kvm_arch_vcpu_id(CPUState *cpu)
     return cpu->cpu_index;
 }
 
-static bool reg_syncs_via_tuple_list(uint64_t regidx)
-{
-    /* Return true if the regidx is a register we should synchronize
-     * via the cpreg_tuples array (ie is not a core reg we sync by
-     * hand in kvm_arch_get/put_registers())
-     */
-    switch (regidx & KVM_REG_ARM_COPROC_MASK) {
-    case KVM_REG_ARM_CORE:
-    case KVM_REG_ARM_VFP:
-        return false;
-    default:
-        return true;
-    }
-}
-
-static int compare_u64(const void *a, const void *b)
-{
-    return *(uint64_t *)a - *(uint64_t *)b;
-}
-
-int kvm_arch_init_vcpu(CPUState *cs)
-{
-    struct kvm_vcpu_init init;
-    int i, ret, arraylen;
-    uint64_t v;
-    struct kvm_one_reg r;
-    struct kvm_reg_list rl;
-    struct kvm_reg_list *rlp;
-    ARMCPU *cpu = ARM_CPU(cs);
-
-    init.target = KVM_ARM_TARGET_CORTEX_A15;
-    memset(init.features, 0, sizeof(init.features));
-    ret = kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_INIT, &init);
-    if (ret) {
-        return ret;
-    }
-    /* Query the kernel to make sure it supports 32 VFP
-     * registers: QEMU's "cortex-a15" CPU is always a
-     * VFP-D32 core. The simplest way to do this is just
-     * to attempt to read register d31.
-     */
-    r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP | 31;
-    r.addr = (uintptr_t)(&v);
-    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
-    if (ret == -ENOENT) {
-        return -EINVAL;
-    }
-
-    /* Populate the cpreg list based on the kernel's idea
-     * of what registers exist (and throw away the TCG-created list).
-     */
-    rl.n = 0;
-    ret = kvm_vcpu_ioctl(cs, KVM_GET_REG_LIST, &rl);
-    if (ret != -E2BIG) {
-        return ret;
-    }
-    rlp = g_malloc(sizeof(struct kvm_reg_list) + rl.n * sizeof(uint64_t));
-    rlp->n = rl.n;
-    ret = kvm_vcpu_ioctl(cs, KVM_GET_REG_LIST, rlp);
-    if (ret) {
-        goto out;
-    }
-    /* Sort the list we get back from the kernel, since cpreg_tuples
-     * must be in strictly ascending order.
-     */
-    qsort(&rlp->reg, rlp->n, sizeof(rlp->reg[0]), compare_u64);
-
-    for (i = 0, arraylen = 0; i < rlp->n; i++) {
-        if (!reg_syncs_via_tuple_list(rlp->reg[i])) {
-            continue;
-        }
-        switch (rlp->reg[i] & KVM_REG_SIZE_MASK) {
-        case KVM_REG_SIZE_U32:
-        case KVM_REG_SIZE_U64:
-            break;
-        default:
-            fprintf(stderr, "Can't handle size of register in kernel list\n");
-            ret = -EINVAL;
-            goto out;
-        }
-
-        arraylen++;
-    }
-
-    cpu->cpreg_indexes = g_renew(uint64_t, cpu->cpreg_indexes, arraylen);
-    cpu->cpreg_values = g_renew(uint64_t, cpu->cpreg_values, arraylen);
-    cpu->cpreg_vmstate_indexes = g_renew(uint64_t, cpu->cpreg_vmstate_indexes,
-                                         arraylen);
-    cpu->cpreg_vmstate_values = g_renew(uint64_t, cpu->cpreg_vmstate_values,
-                                        arraylen);
-    cpu->cpreg_array_len = arraylen;
-    cpu->cpreg_vmstate_array_len = arraylen;
-
-    for (i = 0, arraylen = 0; i < rlp->n; i++) {
-        uint64_t regidx = rlp->reg[i];
-        if (!reg_syncs_via_tuple_list(regidx)) {
-            continue;
-        }
-        cpu->cpreg_indexes[arraylen] = regidx;
-        arraylen++;
-    }
-    assert(cpu->cpreg_array_len == arraylen);
-
-    if (!write_kvmstate_to_list(cpu)) {
-        /* Shouldn't happen unless kernel is inconsistent about
-         * what registers exist.
-         */
-        fprintf(stderr, "Initial read of kernel register state failed\n");
-        ret = -EINVAL;
-        goto out;
-    }
-
-    /* Save a copy of the initial register values so that we can
-     * feed it back to the kernel on VCPU reset.
-     */
-    cpu->cpreg_reset_values = g_memdup(cpu->cpreg_values,
-                                       cpu->cpreg_array_len *
-                                       sizeof(cpu->cpreg_values[0]));
-
-out:
-    g_free(rlp);
-    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
@@ -334,232 +210,6 @@ bool write_list_to_kvmstate(ARMCPU *cpu)
     return ok;
 }
 
-typedef struct Reg {
-    uint64_t id;
-    int offset;
-} Reg;
-
-#define COREREG(KERNELNAME, QEMUFIELD)                       \
-    {                                                        \
-        KVM_REG_ARM | KVM_REG_SIZE_U32 |                     \
-        KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \
-        offsetof(CPUARMState, QEMUFIELD)                     \
-    }
-
-#define VFPSYSREG(R)                                       \
-    {                                                      \
-        KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP | \
-        KVM_REG_ARM_VFP_##R,                               \
-        offsetof(CPUARMState, vfp.xregs[ARM_VFP_##R])      \
-    }
-
-static const Reg regs[] = {
-    /* R0_usr .. R14_usr */
-    COREREG(usr_regs.uregs[0], regs[0]),
-    COREREG(usr_regs.uregs[1], regs[1]),
-    COREREG(usr_regs.uregs[2], regs[2]),
-    COREREG(usr_regs.uregs[3], regs[3]),
-    COREREG(usr_regs.uregs[4], regs[4]),
-    COREREG(usr_regs.uregs[5], regs[5]),
-    COREREG(usr_regs.uregs[6], regs[6]),
-    COREREG(usr_regs.uregs[7], regs[7]),
-    COREREG(usr_regs.uregs[8], usr_regs[0]),
-    COREREG(usr_regs.uregs[9], usr_regs[1]),
-    COREREG(usr_regs.uregs[10], usr_regs[2]),
-    COREREG(usr_regs.uregs[11], usr_regs[3]),
-    COREREG(usr_regs.uregs[12], usr_regs[4]),
-    COREREG(usr_regs.uregs[13], banked_r13[0]),
-    COREREG(usr_regs.uregs[14], banked_r14[0]),
-    /* R13, R14, SPSR for SVC, ABT, UND, IRQ banks */
-    COREREG(svc_regs[0], banked_r13[1]),
-    COREREG(svc_regs[1], banked_r14[1]),
-    COREREG(svc_regs[2], banked_spsr[1]),
-    COREREG(abt_regs[0], banked_r13[2]),
-    COREREG(abt_regs[1], banked_r14[2]),
-    COREREG(abt_regs[2], banked_spsr[2]),
-    COREREG(und_regs[0], banked_r13[3]),
-    COREREG(und_regs[1], banked_r14[3]),
-    COREREG(und_regs[2], banked_spsr[3]),
-    COREREG(irq_regs[0], banked_r13[4]),
-    COREREG(irq_regs[1], banked_r14[4]),
-    COREREG(irq_regs[2], banked_spsr[4]),
-    /* R8_fiq .. R14_fiq and SPSR_fiq */
-    COREREG(fiq_regs[0], fiq_regs[0]),
-    COREREG(fiq_regs[1], fiq_regs[1]),
-    COREREG(fiq_regs[2], fiq_regs[2]),
-    COREREG(fiq_regs[3], fiq_regs[3]),
-    COREREG(fiq_regs[4], fiq_regs[4]),
-    COREREG(fiq_regs[5], banked_r13[5]),
-    COREREG(fiq_regs[6], banked_r14[5]),
-    COREREG(fiq_regs[7], banked_spsr[5]),
-    /* R15 */
-    COREREG(usr_regs.uregs[15], regs[15]),
-    /* VFP system registers */
-    VFPSYSREG(FPSID),
-    VFPSYSREG(MVFR1),
-    VFPSYSREG(MVFR0),
-    VFPSYSREG(FPEXC),
-    VFPSYSREG(FPINST),
-    VFPSYSREG(FPINST2),
-};
-
-int kvm_arch_put_registers(CPUState *cs, int level)
-{
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
-    struct kvm_one_reg r;
-    int mode, bn;
-    int ret, i;
-    uint32_t cpsr, fpscr;
-
-    /* Make sure the banked regs are properly set */
-    mode = env->uncached_cpsr & CPSR_M;
-    bn = bank_number(mode);
-    if (mode == ARM_CPU_MODE_FIQ) {
-        memcpy(env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
-    } else {
-        memcpy(env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
-    }
-    env->banked_r13[bn] = env->regs[13];
-    env->banked_r14[bn] = env->regs[14];
-    env->banked_spsr[bn] = env->spsr;
-
-    /* Now we can safely copy stuff down to the kernel */
-    for (i = 0; i < ARRAY_SIZE(regs); i++) {
-        r.id = regs[i].id;
-        r.addr = (uintptr_t)(env) + regs[i].offset;
-        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
-        if (ret) {
-            return ret;
-        }
-    }
-
-    /* Special cases which aren't a single CPUARMState field */
-    cpsr = cpsr_read(env);
-    r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 |
-        KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr);
-    r.addr = (uintptr_t)(&cpsr);
-    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
-    if (ret) {
-        return ret;
-    }
-
-    /* VFP registers */
-    r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
-    for (i = 0; i < 32; i++) {
-        r.addr = (uintptr_t)(&env->vfp.regs[i]);
-        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
-        if (ret) {
-            return ret;
-        }
-        r.id++;
-    }
-
-    r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP |
-        KVM_REG_ARM_VFP_FPSCR;
-    fpscr = vfp_get_fpscr(env);
-    r.addr = (uintptr_t)&fpscr;
-    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
-    if (ret) {
-        return ret;
-    }
-
-    /* Note that we do not call write_cpustate_to_list()
-     * here, so we are only writing the tuple list back to
-     * KVM. This is safe because nothing can change the
-     * CPUARMState cp15 fields (in particular gdb accesses cannot)
-     * and so there are no changes to sync. In fact syncing would
-     * be wrong at this point: for a constant register where TCG and
-     * KVM disagree about its value, the preceding write_list_to_cpustate()
-     * would not have had any effect on the CPUARMState value (since the
-     * register is read-only), and a write_cpustate_to_list() here would
-     * then try to write the TCG value back into KVM -- this would either
-     * fail or incorrectly change the value the guest sees.
-     *
-     * If we ever want to allow the user to modify cp15 registers via
-     * the gdb stub, we would need to be more clever here (for instance
-     * tracking the set of registers kvm_arch_get_registers() successfully
-     * managed to update the CPUARMState with, and only allowing those
-     * to be written back up into the kernel).
-     */
-    if (!write_list_to_kvmstate(cpu)) {
-        return EINVAL;
-    }
-
-    return ret;
-}
-
-int kvm_arch_get_registers(CPUState *cs)
-{
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
-    struct kvm_one_reg r;
-    int mode, bn;
-    int ret, i;
-    uint32_t cpsr, fpscr;
-
-    for (i = 0; i < ARRAY_SIZE(regs); i++) {
-        r.id = regs[i].id;
-        r.addr = (uintptr_t)(env) + regs[i].offset;
-        ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
-        if (ret) {
-            return ret;
-        }
-    }
-
-    /* Special cases which aren't a single CPUARMState field */
-    r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 |
-        KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr);
-    r.addr = (uintptr_t)(&cpsr);
-    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
-    if (ret) {
-        return ret;
-    }
-    cpsr_write(env, cpsr, 0xffffffff);
-
-    /* Make sure the current mode regs are properly set */
-    mode = env->uncached_cpsr & CPSR_M;
-    bn = bank_number(mode);
-    if (mode == ARM_CPU_MODE_FIQ) {
-        memcpy(env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
-    } else {
-        memcpy(env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
-    }
-    env->regs[13] = env->banked_r13[bn];
-    env->regs[14] = env->banked_r14[bn];
-    env->spsr = env->banked_spsr[bn];
-
-    /* VFP registers */
-    r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
-    for (i = 0; i < 32; i++) {
-        r.addr = (uintptr_t)(&env->vfp.regs[i]);
-        ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
-        if (ret) {
-            return ret;
-        }
-        r.id++;
-    }
-
-    r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP |
-        KVM_REG_ARM_VFP_FPSCR;
-    r.addr = (uintptr_t)&fpscr;
-    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
-    if (ret) {
-        return ret;
-    }
-    vfp_set_fpscr(env, fpscr);
-
-    if (!write_kvmstate_to_list(cpu)) {
-        return EINVAL;
-    }
-    /* Note that it's OK to have registers which aren't in CPUState,
-     * so we can ignore a failure return here.
-     */
-    write_list_to_cpustate(cpu);
-
-    return 0;
-}
-
 void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
 {
 }
@@ -573,19 +223,6 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
     return 0;
 }
 
-void kvm_arch_reset_vcpu(CPUState *cs)
-{
-    /* Feed the kernel back its initial register state */
-    ARMCPU *cpu = ARM_CPU(cs);
-
-    memmove(cpu->cpreg_values, cpu->cpreg_reset_values,
-            cpu->cpreg_array_len * sizeof(cpu->cpreg_values[0]));
-
-    if (!write_list_to_kvmstate(cpu)) {
-        abort();
-    }
-}
-
 bool kvm_arch_stop_on_emulation_error(CPUState *cs)
 {
     return true;
diff --git a/target-arm/kvm_32.c b/target-arm/kvm_32.c
new file mode 100644
index 0000000..b67ea94
--- /dev/null
+++ b/target-arm/kvm_32.c
@@ -0,0 +1,382 @@
+/*
+ * ARM implementation of KVM hooks
+ *
+ * Copyright Christoffer Dall 2009-2010
+ *
+ * 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 <stdio.h>
+#include <sys/types.h>
+
+#include <linux/kvm.h>
+
+#include "qemu-common.h"
+#include "sysemu/kvm.h"
+#include "kvm_arm.h"
+
+static bool reg_syncs_via_tuple_list(uint64_t regidx)
+{
+    /* Return true if the regidx is a register we should synchronize
+     * via the cpreg_tuples array (ie is not a core reg we sync by
+     * hand in kvm_arch_get/put_registers())
+     */
+    switch (regidx & KVM_REG_ARM_COPROC_MASK) {
+    case KVM_REG_ARM_CORE:
+    case KVM_REG_ARM_VFP:
+        return false;
+    default:
+        return true;
+    }
+}
+
+static int compare_u64(const void *a, const void *b)
+{
+    return *(uint64_t *)a - *(uint64_t *)b;
+}
+
+int kvm_arch_init_vcpu(CPUState *cs)
+{
+    struct kvm_vcpu_init init;
+    int i, ret, arraylen;
+    uint64_t v;
+    struct kvm_one_reg r;
+    struct kvm_reg_list rl;
+    struct kvm_reg_list *rlp;
+    ARMCPU *cpu = ARM_CPU(cs);
+
+    init.target = KVM_ARM_TARGET_CORTEX_A15;
+    memset(init.features, 0, sizeof(init.features));
+    ret = kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_INIT, &init);
+    if (ret) {
+        return ret;
+    }
+    /* Query the kernel to make sure it supports 32 VFP
+     * registers: QEMU's "cortex-a15" CPU is always a
+     * VFP-D32 core. The simplest way to do this is just
+     * to attempt to read register d31.
+     */
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP | 31;
+    r.addr = (uintptr_t)(&v);
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
+    if (ret == -ENOENT) {
+        return -EINVAL;
+    }
+
+    /* Populate the cpreg list based on the kernel's idea
+     * of what registers exist (and throw away the TCG-created list).
+     */
+    rl.n = 0;
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_REG_LIST, &rl);
+    if (ret != -E2BIG) {
+        return ret;
+    }
+    rlp = g_malloc(sizeof(struct kvm_reg_list) + rl.n * sizeof(uint64_t));
+    rlp->n = rl.n;
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_REG_LIST, rlp);
+    if (ret) {
+        goto out;
+    }
+    /* Sort the list we get back from the kernel, since cpreg_tuples
+     * must be in strictly ascending order.
+     */
+    qsort(&rlp->reg, rlp->n, sizeof(rlp->reg[0]), compare_u64);
+
+    for (i = 0, arraylen = 0; i < rlp->n; i++) {
+        if (!reg_syncs_via_tuple_list(rlp->reg[i])) {
+            continue;
+        }
+        switch (rlp->reg[i] & KVM_REG_SIZE_MASK) {
+        case KVM_REG_SIZE_U32:
+        case KVM_REG_SIZE_U64:
+            break;
+        default:
+            fprintf(stderr, "Can't handle size of register in kernel list\n");
+            ret = -EINVAL;
+            goto out;
+        }
+
+        arraylen++;
+    }
+
+    cpu->cpreg_indexes = g_renew(uint64_t, cpu->cpreg_indexes, arraylen);
+    cpu->cpreg_values = g_renew(uint64_t, cpu->cpreg_values, arraylen);
+    cpu->cpreg_vmstate_indexes = g_renew(uint64_t, cpu->cpreg_vmstate_indexes,
+                                         arraylen);
+    cpu->cpreg_vmstate_values = g_renew(uint64_t, cpu->cpreg_vmstate_values,
+                                        arraylen);
+    cpu->cpreg_array_len = arraylen;
+    cpu->cpreg_vmstate_array_len = arraylen;
+
+    for (i = 0, arraylen = 0; i < rlp->n; i++) {
+        uint64_t regidx = rlp->reg[i];
+        if (!reg_syncs_via_tuple_list(regidx)) {
+            continue;
+        }
+        cpu->cpreg_indexes[arraylen] = regidx;
+        arraylen++;
+    }
+    assert(cpu->cpreg_array_len == arraylen);
+
+    if (!write_kvmstate_to_list(cpu)) {
+        /* Shouldn't happen unless kernel is inconsistent about
+         * what registers exist.
+         */
+        fprintf(stderr, "Initial read of kernel register state failed\n");
+        ret = -EINVAL;
+        goto out;
+    }
+
+    /* Save a copy of the initial register values so that we can
+     * feed it back to the kernel on VCPU reset.
+     */
+    cpu->cpreg_reset_values = g_memdup(cpu->cpreg_values,
+                                       cpu->cpreg_array_len *
+                                       sizeof(cpu->cpreg_values[0]));
+
+out:
+    g_free(rlp);
+    return ret;
+}
+
+typedef struct Reg {
+    uint64_t id;
+    int offset;
+} Reg;
+
+#define COREREG(KERNELNAME, QEMUFIELD)                       \
+    {                                                        \
+        KVM_REG_ARM | KVM_REG_SIZE_U32 |                     \
+        KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(KERNELNAME), \
+        offsetof(CPUARMState, QEMUFIELD)                     \
+    }
+
+#define VFPSYSREG(R)                                       \
+    {                                                      \
+        KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP | \
+        KVM_REG_ARM_VFP_##R,                               \
+        offsetof(CPUARMState, vfp.xregs[ARM_VFP_##R])      \
+    }
+
+static const Reg regs[] = {
+    /* R0_usr .. R14_usr */
+    COREREG(usr_regs.uregs[0], regs[0]),
+    COREREG(usr_regs.uregs[1], regs[1]),
+    COREREG(usr_regs.uregs[2], regs[2]),
+    COREREG(usr_regs.uregs[3], regs[3]),
+    COREREG(usr_regs.uregs[4], regs[4]),
+    COREREG(usr_regs.uregs[5], regs[5]),
+    COREREG(usr_regs.uregs[6], regs[6]),
+    COREREG(usr_regs.uregs[7], regs[7]),
+    COREREG(usr_regs.uregs[8], usr_regs[0]),
+    COREREG(usr_regs.uregs[9], usr_regs[1]),
+    COREREG(usr_regs.uregs[10], usr_regs[2]),
+    COREREG(usr_regs.uregs[11], usr_regs[3]),
+    COREREG(usr_regs.uregs[12], usr_regs[4]),
+    COREREG(usr_regs.uregs[13], banked_r13[0]),
+    COREREG(usr_regs.uregs[14], banked_r14[0]),
+    /* R13, R14, SPSR for SVC, ABT, UND, IRQ banks */
+    COREREG(svc_regs[0], banked_r13[1]),
+    COREREG(svc_regs[1], banked_r14[1]),
+    COREREG(svc_regs[2], banked_spsr[1]),
+    COREREG(abt_regs[0], banked_r13[2]),
+    COREREG(abt_regs[1], banked_r14[2]),
+    COREREG(abt_regs[2], banked_spsr[2]),
+    COREREG(und_regs[0], banked_r13[3]),
+    COREREG(und_regs[1], banked_r14[3]),
+    COREREG(und_regs[2], banked_spsr[3]),
+    COREREG(irq_regs[0], banked_r13[4]),
+    COREREG(irq_regs[1], banked_r14[4]),
+    COREREG(irq_regs[2], banked_spsr[4]),
+    /* R8_fiq .. R14_fiq and SPSR_fiq */
+    COREREG(fiq_regs[0], fiq_regs[0]),
+    COREREG(fiq_regs[1], fiq_regs[1]),
+    COREREG(fiq_regs[2], fiq_regs[2]),
+    COREREG(fiq_regs[3], fiq_regs[3]),
+    COREREG(fiq_regs[4], fiq_regs[4]),
+    COREREG(fiq_regs[5], banked_r13[5]),
+    COREREG(fiq_regs[6], banked_r14[5]),
+    COREREG(fiq_regs[7], banked_spsr[5]),
+    /* R15 */
+    COREREG(usr_regs.uregs[15], regs[15]),
+    /* VFP system registers */
+    VFPSYSREG(FPSID),
+    VFPSYSREG(MVFR1),
+    VFPSYSREG(MVFR0),
+    VFPSYSREG(FPEXC),
+    VFPSYSREG(FPINST),
+    VFPSYSREG(FPINST2),
+};
+
+int kvm_arch_put_registers(CPUState *cs, int level)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+    struct kvm_one_reg r;
+    int mode, bn;
+    int ret, i;
+    uint32_t cpsr, fpscr;
+
+    /* Make sure the banked regs are properly set */
+    mode = env->uncached_cpsr & CPSR_M;
+    bn = bank_number(mode);
+    if (mode == ARM_CPU_MODE_FIQ) {
+        memcpy(env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
+    } else {
+        memcpy(env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
+    }
+    env->banked_r13[bn] = env->regs[13];
+    env->banked_r14[bn] = env->regs[14];
+    env->banked_spsr[bn] = env->spsr;
+
+    /* Now we can safely copy stuff down to the kernel */
+    for (i = 0; i < ARRAY_SIZE(regs); i++) {
+        r.id = regs[i].id;
+        r.addr = (uintptr_t)(env) + regs[i].offset;
+        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
+        if (ret) {
+            return ret;
+        }
+    }
+
+    /* Special cases which aren't a single CPUARMState field */
+    cpsr = cpsr_read(env);
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 |
+        KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr);
+    r.addr = (uintptr_t)(&cpsr);
+    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
+    if (ret) {
+        return ret;
+    }
+
+    /* VFP registers */
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
+    for (i = 0; i < 32; i++) {
+        r.addr = (uintptr_t)(&env->vfp.regs[i]);
+        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
+        if (ret) {
+            return ret;
+        }
+        r.id++;
+    }
+
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP |
+        KVM_REG_ARM_VFP_FPSCR;
+    fpscr = vfp_get_fpscr(env);
+    r.addr = (uintptr_t)&fpscr;
+    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
+    if (ret) {
+        return ret;
+    }
+
+    /* Note that we do not call write_cpustate_to_list()
+     * here, so we are only writing the tuple list back to
+     * KVM. This is safe because nothing can change the
+     * CPUARMState cp15 fields (in particular gdb accesses cannot)
+     * and so there are no changes to sync. In fact syncing would
+     * be wrong at this point: for a constant register where TCG and
+     * KVM disagree about its value, the preceding write_list_to_cpustate()
+     * would not have had any effect on the CPUARMState value (since the
+     * register is read-only), and a write_cpustate_to_list() here would
+     * then try to write the TCG value back into KVM -- this would either
+     * fail or incorrectly change the value the guest sees.
+     *
+     * If we ever want to allow the user to modify cp15 registers via
+     * the gdb stub, we would need to be more clever here (for instance
+     * tracking the set of registers kvm_arch_get_registers() successfully
+     * managed to update the CPUARMState with, and only allowing those
+     * to be written back up into the kernel).
+     */
+    if (!write_list_to_kvmstate(cpu)) {
+        return EINVAL;
+    }
+
+    return ret;
+}
+
+int kvm_arch_get_registers(CPUState *cs)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+    struct kvm_one_reg r;
+    int mode, bn;
+    int ret, i;
+    uint32_t cpsr, fpscr;
+
+    for (i = 0; i < ARRAY_SIZE(regs); i++) {
+        r.id = regs[i].id;
+        r.addr = (uintptr_t)(env) + regs[i].offset;
+        ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
+        if (ret) {
+            return ret;
+        }
+    }
+
+    /* Special cases which aren't a single CPUARMState field */
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 |
+        KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr);
+    r.addr = (uintptr_t)(&cpsr);
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
+    if (ret) {
+        return ret;
+    }
+    cpsr_write(env, cpsr, 0xffffffff);
+
+    /* Make sure the current mode regs are properly set */
+    mode = env->uncached_cpsr & CPSR_M;
+    bn = bank_number(mode);
+    if (mode == ARM_CPU_MODE_FIQ) {
+        memcpy(env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
+    } else {
+        memcpy(env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
+    }
+    env->regs[13] = env->banked_r13[bn];
+    env->regs[14] = env->banked_r14[bn];
+    env->spsr = env->banked_spsr[bn];
+
+    /* VFP registers */
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
+    for (i = 0; i < 32; i++) {
+        r.addr = (uintptr_t)(&env->vfp.regs[i]);
+        ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
+        if (ret) {
+            return ret;
+        }
+        r.id++;
+    }
+
+    r.id = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_VFP |
+        KVM_REG_ARM_VFP_FPSCR;
+    r.addr = (uintptr_t)&fpscr;
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
+    if (ret) {
+        return ret;
+    }
+    vfp_set_fpscr(env, fpscr);
+
+    if (!write_kvmstate_to_list(cpu)) {
+        return EINVAL;
+    }
+    /* Note that it's OK to have registers which aren't in CPUState,
+     * so we can ignore a failure return here.
+     */
+    write_list_to_cpustate(cpu);
+
+    return 0;
+}
+
+void kvm_arch_reset_vcpu(CPUState *cs)
+{
+    /* Feed the kernel back its initial register state */
+    ARMCPU *cpu = ARM_CPU(cs);
+
+    memmove(cpu->cpreg_values, cpu->cpreg_reset_values,
+            cpu->cpreg_array_len * sizeof(cpu->cpreg_values[0]));
+
+    if (!write_list_to_kvmstate(cpu)) {
+        abort();
+    }
+}
+
diff --git a/target-arm/kvm_64.c b/target-arm/kvm_64.c
new file mode 100644
index 0000000..a6af968
--- /dev/null
+++ b/target-arm/kvm_64.c
@@ -0,0 +1,39 @@
+/*
+ * ARM implementation of KVM hooks for AARCH64
+ *
+ * Copyright Christoffer Dall 2009-2010
+ *           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 <stdio.h>
+#include <sys/types.h>
+
+#include <linux/kvm.h>
+
+#include "qemu-common.h"
+#include "sysemu/kvm.h"
+#include "kvm_arm.h"
+
+int kvm_arch_init_vcpu(CPUState *cs)
+{
+    return 0;
+}
+
+int kvm_arch_put_registers(CPUState *cs, int level)
+{
+    return 0;
+}
+
+int kvm_arch_get_registers(CPUState *cs)
+{
+    return 0;
+}
+
+void kvm_arch_reset_vcpu(CPUState *cs)
+{
+}
+
-- 
1.8.1.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v3 05/11] AARCH64: Add AARCH64 CPU initialization, get and put registers support
  2013-09-27 10:10 [Qemu-devel] [PATCH v3 00/11] AARCH64 support on machvirt machine model using KVM Mian M. Hamayun
                   ` (3 preceding siblings ...)
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 04/11] AARCH64: Separate 32-bit specific code from common KVM hooks Mian M. Hamayun
@ 2013-09-27 10:10 ` Mian M. Hamayun
  2013-11-26 22:24   ` Peter Maydell
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 06/11] target-arm: Parameterize the bootloader selection and setup mechanism Mian M. Hamayun
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 20+ messages in thread
From: Mian M. Hamayun @ 2013-09-27 10:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, agraf, tech, kvmarm, afaerber

From: "Mian M. Hamayun" <m.hamayun@virtualopensystems.com>

The cpu init function tries to initialize with all possible cpu types, as
KVM does not provide a means to detect the real cpu type and simply refuses
to initialize on cpu type mis-match. By using the loop based init function,
we avoid the need to modify code if the underlying platform is different,
such as Fast Models instead of Foundation Models.

Get and Put Registers deal with the basic state of AARCH64 CPUs.

Signed-off-by: Mian M. Hamayun <m.hamayun@virtualopensystems.com>
---
 target-arm/kvm_64.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 103 insertions(+), 3 deletions(-)

diff --git a/target-arm/kvm_64.c b/target-arm/kvm_64.c
index a6af968..9685727 100644
--- a/target-arm/kvm_64.c
+++ b/target-arm/kvm_64.c
@@ -18,19 +18,119 @@
 #include "sysemu/kvm.h"
 #include "kvm_arm.h"
 
+#define AARCH64_CORE_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
+                            KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
+
+static uint32_t kvm_arm_targets[KVM_ARM_NUM_TARGETS] = {
+    KVM_ARM_TARGET_AEM_V8,
+    KVM_ARM_TARGET_FOUNDATION_V8,
+    KVM_ARM_TARGET_CORTEX_A57
+};
+
 int kvm_arch_init_vcpu(CPUState *cs)
 {
-    return 0;
+    struct kvm_vcpu_init init;
+    int ret, i;
+
+    memset(init.features, 0, sizeof(init.features));
+    /* Find an appropriate target CPU type.
+     * KVM does not provide means to detect the host CPU type on aarch64,
+     * and simply refuses to initialize, if the CPU type mis-matches;
+     * so we try each possible CPU type on aarch64 before giving up! */
+    for (i = 0; i < KVM_ARM_NUM_TARGETS; ++i) {
+        init.target = kvm_arm_targets[i];
+        ret = kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_INIT, &init);
+        if (!ret)
+            break;
+    }
+
+    return ret;
 }
 
 int kvm_arch_put_registers(CPUState *cs, int level)
 {
-    return 0;
+    struct kvm_one_reg reg;
+    int i;
+    int ret;
+
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+
+    for (i = 0; i < ARRAY_SIZE(env->xregs); 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, &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, &reg);
+    if (ret) {
+        return ret;
+    }
+
+    reg.id = AARCH64_CORE_REG(regs.pstate);
+    reg.addr = (uintptr_t) &env->pstate;
+    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &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, &reg);
+    if (ret) {
+        return ret;
+    }
+
+    /* TODO: Set Rest of Registers */
+    return ret;
 }
 
 int kvm_arch_get_registers(CPUState *cs)
 {
-    return 0;
+    struct kvm_one_reg reg;
+    int i;
+    int ret;
+
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+
+    for (i = 0; i < ARRAY_SIZE(env->xregs); 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, &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, &reg);
+    if (ret) {
+        return ret;
+    }
+
+    reg.id = AARCH64_CORE_REG(regs.pstate);
+    reg.addr = (uintptr_t) &env->pstate;
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+    if (ret) {
+        return ret;
+    }
+
+    reg.id = AARCH64_CORE_REG(regs.pc);
+    reg.addr = (uintptr_t) &env->pc;
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+    if (ret) {
+        return ret;
+    }
+
+    /* TODO: Set Rest of Registers */
+    return ret;
 }
 
 void kvm_arch_reset_vcpu(CPUState *cs)
-- 
1.8.1.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v3 06/11] target-arm: Parameterize the bootloader selection and setup mechanism
  2013-09-27 10:10 [Qemu-devel] [PATCH v3 00/11] AARCH64 support on machvirt machine model using KVM Mian M. Hamayun
                   ` (4 preceding siblings ...)
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 05/11] AARCH64: Add AARCH64 CPU initialization, get and put registers support Mian M. Hamayun
@ 2013-09-27 10:10 ` Mian M. Hamayun
  2013-11-25 21:17   ` Peter Maydell
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 07/11] AARCH64: Add boot support for aarch64 processor Mian M. Hamayun
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 20+ messages in thread
From: Mian M. Hamayun @ 2013-09-27 10:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, agraf, tech, kvmarm, afaerber

From: "Mian M. Hamayun" <m.hamayun@virtualopensystems.com>

This commit replaces the constant indices used in bootloaders, such as for
specifying the Board ID and kernel arguments with variable parameters.
This change is used as mechanism to minimize code changes for different
bootloaders, for example different bootloaders will be used for different
architectures (ARMv7 vs. ARMv8).

Similary pointers are introduced to select appropriate bootloaders for boot
and secondary cpus.

Signed-off-by: Mian M. Hamayun <m.hamayun@virtualopensystems.com>
---
 hw/arm/boot.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 66 insertions(+), 15 deletions(-)

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 967397b..4c1170e 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -18,10 +18,9 @@
 #include "qemu/config-file.h"
 
 #define KERNEL_ARGS_ADDR 0x100
-#define KERNEL_LOAD_ADDR 0x00010000
 
 /* The worlds second smallest bootloader.  Set r0-r2, then jump to kernel.  */
-static uint32_t bootloader[] = {
+static uint32_t bootloader_arm32[] = {
   0xe3a00000, /* mov     r0, #0 */
   0xe59f1004, /* ldr     r1, [pc, #4] */
   0xe59f2004, /* ldr     r2, [pc, #4] */
@@ -48,7 +47,7 @@ static uint32_t bootloader[] = {
 #define DSB_INSN 0xf57ff04f
 #define CP15_DSB_INSN 0xee070f9a /* mcr cp15, 0, r0, c7, c10, 4 */
 
-static uint32_t smpboot[] = {
+static uint32_t smpboot_arm32[] = {
   0xe59f2028, /* ldr r2, gic_cpu_if */
   0xe59f0028, /* ldr r0, startaddr */
   0xe3a01001, /* mov r1, #1 */
@@ -65,13 +64,60 @@ static uint32_t smpboot[] = {
   0           /* bootreg: Boot register address is held here */
 };
 
+/*
+ * The bootloaders to be used are referenced by the following pointers
+ * An appropriate bootloader is selected depending on the architecture
+ * i.e. ARMv7, ARMv8 (AARCH64 and AARCH32)
+ */
+static uint32_t *bootloader = NULL;
+static uint32_t  bootloader_array_size = 0;
+
+static uint32_t *smpboot = NULL;
+static uint32_t  smpboot_array_size = 0;
+
+/*
+ * An index gives the location in the bootloader array, where we put the board
+ * ID, kernel arguments and kernel entry addresses. These are different for
+ * ARMv7 and ARMv8 bootloaders defined above.
+ */
+static uint32_t kernel_boardid_index = 0;
+static uint32_t kernel_args_index    = 0;
+static uint32_t kernel_entry_index   = 0;
+
+/*
+ * Similarly, the kernel loading address also depends on the architecture,
+ * i.e. its different for ARMv7, ARMv8 (AARCH64 and AARCH32)
+ */
+static uint32_t kernel_load_addr = 0x0;
+
+static void setup_boot_env_32(void)
+{
+    bootloader = bootloader_arm32;
+    bootloader_array_size = ARRAY_SIZE(bootloader_arm32);
+    smpboot = smpboot_arm32;
+    smpboot_array_size = ARRAY_SIZE(smpboot_arm32);
+
+    kernel_boardid_index = bootloader_array_size - 3;
+    kernel_args_index    = bootloader_array_size - 2;
+    kernel_entry_index   = bootloader_array_size - 1;
+    return;
+}
+
+static void setup_boot_env(ARMCPU *cpu)
+{
+    /* ARMv7 */
+    kernel_load_addr = 0x00010000;
+    setup_boot_env_32();
+    return;
+}
+
 static void default_write_secondary(ARMCPU *cpu,
                                     const struct arm_boot_info *info)
 {
     int n;
-    smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
-    smpboot[ARRAY_SIZE(smpboot) - 2] = info->gic_cpu_if_addr;
-    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
+    smpboot[smpboot_array_size - 1] = info->smp_bootreg_addr;
+    smpboot[smpboot_array_size - 2] = info->gic_cpu_if_addr;
+    for (n = 0; n < smpboot_array_size; n++) {
         /* Replace DSB with the pre-v7 DSB if necessary. */
         if (!arm_feature(&cpu->env, ARM_FEATURE_V7) &&
             smpboot[n] == DSB_INSN) {
@@ -79,7 +125,8 @@ static void default_write_secondary(ARMCPU *cpu,
         }
         smpboot[n] = tswap32(smpboot[n]);
     }
-    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
+    rom_add_blob_fixed("smpboot", smpboot,
+                       smpboot_array_size * sizeof(uint32_t),
                        info->smp_loader_start);
 }
 
@@ -360,6 +407,9 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
     hwaddr entry;
     int big_endian;
 
+    /* Select the bootloader to use and setup array indices, kernel entry etc */
+    setup_boot_env(cpu);
+
     /* Load the kernel.  */
     if (!info->kernel_filename) {
         fprintf(stderr, "Kernel image must be specified\n");
@@ -406,9 +456,9 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
                                   &is_linux);
     }
     if (kernel_size < 0) {
-        entry = info->loader_start + KERNEL_LOAD_ADDR;
+        entry = info->loader_start + kernel_load_addr;
         kernel_size = load_image_targphys(info->kernel_filename, entry,
-                                          info->ram_size - KERNEL_LOAD_ADDR);
+                                          info->ram_size - kernel_load_addr);
         is_linux = 1;
     }
     if (kernel_size < 0) {
@@ -439,7 +489,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
         }
         info->initrd_size = initrd_size;
 
-        bootloader[4] = info->board_id;
+        bootloader[kernel_boardid_index] = info->board_id;
 
         /* for device tree boot, we pass the DTB directly in r2. Otherwise
          * we point to the kernel args.
@@ -454,9 +504,9 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
             if (load_dtb(dtb_start, info)) {
                 exit(1);
             }
-            bootloader[5] = dtb_start;
+            bootloader[kernel_args_index] = dtb_start;
         } else {
-            bootloader[5] = info->loader_start + KERNEL_ARGS_ADDR;
+            bootloader[kernel_args_index] = info->loader_start + KERNEL_ARGS_ADDR;
             if (info->ram_size >= (1ULL << 32)) {
                 fprintf(stderr, "qemu: RAM size must be less than 4GB to boot"
                         " Linux kernel using ATAGS (try passing a device tree"
@@ -464,11 +514,12 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
                 exit(1);
             }
         }
-        bootloader[6] = entry;
-        for (n = 0; n < sizeof(bootloader) / 4; n++) {
+        bootloader[kernel_entry_index] = entry;
+        for (n = 0; n < bootloader_array_size; n++) {
             bootloader[n] = tswap32(bootloader[n]);
         }
-        rom_add_blob_fixed("bootloader", bootloader, sizeof(bootloader),
+        rom_add_blob_fixed("bootloader", bootloader,
+                           bootloader_array_size * sizeof(uint32_t),
                            info->loader_start);
         if (info->nb_cpus > 1) {
             info->write_secondary_boot(cpu, info);
-- 
1.8.1.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v3 07/11] AARCH64: Add boot support for aarch64 processor
  2013-09-27 10:10 [Qemu-devel] [PATCH v3 00/11] AARCH64 support on machvirt machine model using KVM Mian M. Hamayun
                   ` (5 preceding siblings ...)
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 06/11] target-arm: Parameterize the bootloader selection and setup mechanism Mian M. Hamayun
@ 2013-09-27 10:10 ` Mian M. Hamayun
  2013-11-25 23:51   ` Peter Maydell
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 08/11] AARCH64: Enable SMP support for aarch64 processors using PSCI method Mian M. Hamayun
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 20+ messages in thread
From: Mian M. Hamayun @ 2013-09-27 10:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, agraf, tech, kvmarm, afaerber

From: "Mian M. Hamayun" <m.hamayun@virtualopensystems.com>

This commit adds support for booting a single AArch64 CPU by setting
appropriate registers. The bootloader includes placehoders for Board-ID
that are used to implement uniform indexing across different bootloaders.
We also introduce Cortex-A57 to virt platform.

Signed-off-by: Mian M. Hamayun <m.hamayun@virtualopensystems.com>
---
 hw/arm/boot.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/arm/virt.c |  8 ++++++++
 2 files changed, 65 insertions(+)

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 4c1170e..0471eb8 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -19,6 +19,23 @@
 
 #define KERNEL_ARGS_ADDR 0x100
 
+#ifdef TARGET_AARCH64
+static uint32_t bootloader_arm64[] = {
+    0x580000c0, 	/* ldr	x0, 18 ; Load the lower 32-bits of DTB */
+    0xaa1f03e1, 	/* mov	x1, xzr */
+    0xaa1f03e2, 	/* mov	x2, xzr */
+    0xaa1f03e3, 	/* mov	x3, xzr */
+    0x58000084, 	/* ldr	x4, 20 ; Load the lower 32-bits of kernel entry */
+    0xd61f0080, 	/* br	x4     ; Jump to the kernel entry point */
+    0x00000000, 	/* .word @DTB Lower 32-bits */
+    0x00000000, 	/* .word @DTB Higher 32-bits */
+    0x00000000, 	/* .word @Kernel Entry Lower 32-bits */
+    0x00000000,  	/* .word @Kernel Entry Higher 32-bits */
+    0x00000000, 	/* .word @Board ID Lower 32-bits -- Placeholder */
+    0x00000000  	/* .word @Board ID Higher 32-bits -- Placeholder */
+};
+#endif
+
 /* The worlds second smallest bootloader.  Set r0-r2, then jump to kernel.  */
 static uint32_t bootloader_arm32[] = {
   0xe3a00000, /* mov     r0, #0 */
@@ -103,11 +120,37 @@ static void setup_boot_env_32(void)
     return;
 }
 
+#ifdef TARGET_AARCH64
+static void setup_boot_env_64(void)
+{
+    bootloader = bootloader_arm64;
+    bootloader_array_size = ARRAY_SIZE(bootloader_arm64);
+
+    kernel_args_index    = bootloader_array_size - 6;
+    kernel_entry_index   = bootloader_array_size - 4;
+    kernel_boardid_index = bootloader_array_size - 2;
+    return;
+}
+#endif
+
 static void setup_boot_env(ARMCPU *cpu)
 {
+#ifdef TARGET_AARCH64
+    CPUARMState *env = &cpu->env;
+    if(env->aarch64) {
+        /* AARCH64 Mode */
+        kernel_load_addr = 0x00080000;
+        setup_boot_env_64();
+    }
+    else {
+        /* AARCH32 Mode */
+        /* TODO: Specify Kernel Load Address for AARCH32 */
+    }
+#else
     /* ARMv7 */
     kernel_load_addr = 0x00010000;
     setup_boot_env_32();
+#endif
     return;
 }
 
@@ -380,8 +423,22 @@ static void do_cpu_reset(void *opaque)
             env->regs[15] = info->entry & 0xfffffffe;
             env->thumb = info->entry & 1;
         } else {
+#ifdef TARGET_AARCH64
+            if(env->aarch64) {
+                env->pstate = PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | PSR_MODE_EL1h;
+            } else {
+                hw_error("AArch32 mode is currently not supported\n");
+            }
+            env->xregs[0] =  0;
+            env->xregs[1] = -1;
+#endif
             if (CPU(cpu) == first_cpu) {
+#ifdef TARGET_AARCH64
+                env->xregs[2] = bootloader[kernel_args_index];
+                env->pc = info->loader_start;
+#else
                 env->regs[15] = info->loader_start;
+#endif
                 if (!info->dtb_filename) {
                     if (old_param) {
                         set_kernel_args_old(info);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 448a0e5..8043fd4 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -118,6 +118,14 @@ static VirtBoardInfo machines[] = {
         .memmap = a15memmap,
         .irqmap = a15irqmap,
     },
+    {
+        .cpu_model = "cortex-a57",
+        .cpu_compatible = "arm,arm-v8",
+        .qdevname = "a57mpcore_priv",
+        .gic_compatible = "arm,cortex-a15-gic",
+        .memmap = a15memmap,
+        .irqmap = a15irqmap,
+    },
 };
 
 static VirtBoardInfo *find_machine_info(const char *cpu)
-- 
1.8.1.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v3 08/11] AARCH64: Enable SMP support for aarch64 processors using PSCI method
  2013-09-27 10:10 [Qemu-devel] [PATCH v3 00/11] AARCH64 support on machvirt machine model using KVM Mian M. Hamayun
                   ` (6 preceding siblings ...)
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 07/11] AARCH64: Add boot support for aarch64 processor Mian M. Hamayun
@ 2013-09-27 10:10 ` Mian M. Hamayun
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 09/11] AARCH64: Enable configure support for 32-bit guests on AARCH64 Mian M. Hamayun
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Mian M. Hamayun @ 2013-09-27 10:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, agraf, tech, kvmarm, afaerber

From: "Mian M. Hamayun" <m.hamayun@virtualopensystems.com>

We enable SMP support for aarch64 processors using the PSCI method,
by setting the appropriate CPU feature flags at initilializtion time.

Secondary boot code for non-aarch64 processors is disabled in case
of compilation for aarch64.

Signed-off-by: Mian M. Hamayun <m.hamayun@virtualopensystems.com>
---
 hw/arm/boot.c       | 4 ++++
 target-arm/kvm_64.c | 7 +++++++
 2 files changed, 11 insertions(+)

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 0471eb8..ddafd3b 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -157,6 +157,7 @@ static void setup_boot_env(ARMCPU *cpu)
 static void default_write_secondary(ARMCPU *cpu,
                                     const struct arm_boot_info *info)
 {
+#ifndef TARGET_AARCH64
     int n;
     smpboot[smpboot_array_size - 1] = info->smp_bootreg_addr;
     smpboot[smpboot_array_size - 2] = info->gic_cpu_if_addr;
@@ -171,15 +172,18 @@ static void default_write_secondary(ARMCPU *cpu,
     rom_add_blob_fixed("smpboot", smpboot,
                        smpboot_array_size * sizeof(uint32_t),
                        info->smp_loader_start);
+#endif
 }
 
 static void default_reset_secondary(ARMCPU *cpu,
                                     const struct arm_boot_info *info)
 {
+#ifndef TARGET_AARCH64
     CPUARMState *env = &cpu->env;
 
     stl_phys_notdirty(info->smp_bootreg_addr, 0);
     env->regs[15] = info->smp_loader_start;
+#endif
 }
 
 #define WRITE_WORD(p, value) do { \
diff --git a/target-arm/kvm_64.c b/target-arm/kvm_64.c
index 9685727..146b7c4 100644
--- a/target-arm/kvm_64.c
+++ b/target-arm/kvm_64.c
@@ -27,12 +27,19 @@ static uint32_t kvm_arm_targets[KVM_ARM_NUM_TARGETS] = {
     KVM_ARM_TARGET_CORTEX_A57
 };
 
+#define ARM_VCPU_FEATURE_FLAGS(cpuid, is_aarch32)  		\
+((!!(cpuid) << KVM_ARM_VCPU_POWER_OFF) | (is_aarch32 << KVM_ARM_VCPU_EL1_32BIT))
+
 int kvm_arch_init_vcpu(CPUState *cs)
 {
     struct kvm_vcpu_init init;
     int ret, i;
 
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+
     memset(init.features, 0, sizeof(init.features));
+    init.features[0] = ARM_VCPU_FEATURE_FLAGS(cs->cpu_index, !env->aarch64);
     /* Find an appropriate target CPU type.
      * KVM does not provide means to detect the host CPU type on aarch64,
      * and simply refuses to initialize, if the CPU type mis-matches;
-- 
1.8.1.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v3 09/11] AARCH64: Enable configure support for 32-bit guests on AARCH64
  2013-09-27 10:10 [Qemu-devel] [PATCH v3 00/11] AARCH64 support on machvirt machine model using KVM Mian M. Hamayun
                   ` (7 preceding siblings ...)
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 08/11] AARCH64: Enable SMP support for aarch64 processors using PSCI method Mian M. Hamayun
@ 2013-09-27 10:10 ` Mian M. Hamayun
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 10/11] AARCH64: Add flags and boot parameters " Mian M. Hamayun
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 11/11] AARCH64: Add 32-bit mode selection parameter Mian M. Hamayun
  10 siblings, 0 replies; 20+ messages in thread
From: Mian M. Hamayun @ 2013-09-27 10:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, agraf, tech, kvmarm, afaerber

From: "Mian M. Hamayun" <m.hamayun@virtualopensystems.com>

Signed-off-by: Mian M. Hamayun <m.hamayun@virtualopensystems.com>
---
 configure | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configure b/configure
index 7298b69..dbaf56f 100755
--- a/configure
+++ b/configure
@@ -4485,6 +4485,7 @@ case "$target_name" in
     # Make sure the target and host cpus are compatible
     if test "$kvm" = "yes" -a "$target_softmmu" = "yes" -a \
       \( "$target_name" = "$cpu" -o \
+      \( "$target_name" = "arm" -a "$cpu" = "aarch64" \) -o \
       \( "$target_name" = "ppcemb" -a "$cpu" = "ppc" \) -o \
       \( "$target_name" = "ppc64"  -a "$cpu" = "ppc" \) -o \
       \( "$target_name" = "ppc"    -a "$cpu" = "ppc64" \) -o \
-- 
1.8.1.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v3 10/11] AARCH64: Add flags and boot parameters for 32-bit guests on AARCH64
  2013-09-27 10:10 [Qemu-devel] [PATCH v3 00/11] AARCH64 support on machvirt machine model using KVM Mian M. Hamayun
                   ` (8 preceding siblings ...)
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 09/11] AARCH64: Enable configure support for 32-bit guests on AARCH64 Mian M. Hamayun
@ 2013-09-27 10:10 ` Mian M. Hamayun
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 11/11] AARCH64: Add 32-bit mode selection parameter Mian M. Hamayun
  10 siblings, 0 replies; 20+ messages in thread
From: Mian M. Hamayun @ 2013-09-27 10:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, agraf, tech, kvmarm, afaerber

From: "Mian M. Hamayun" <m.hamayun@virtualopensystems.com>

This commit adds the necessary flags and kernel load address to enable
booting of 32-bit guests on AArch64 processors.

The actual enable/disable mechanism is not included in this commit,
which should tweak the value of env->aarch64 variable for this purpose.

Signed-off-by: Mian M. Hamayun <m.hamayun@virtualopensystems.com>
---
 hw/arm/boot.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index ddafd3b..2cfa9bf 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -20,6 +20,10 @@
 #define KERNEL_ARGS_ADDR 0x100
 
 #ifdef TARGET_AARCH64
+#define COMPAT_PSR_F_BIT    0x00000040
+#define COMPAT_PSR_I_BIT    0x00000080
+#define COMPAT_PSR_MODE_SVC 0x00000013
+
 static uint32_t bootloader_arm64[] = {
     0x580000c0, 	/* ldr	x0, 18 ; Load the lower 32-bits of DTB */
     0xaa1f03e1, 	/* mov	x1, xzr */
@@ -144,7 +148,8 @@ static void setup_boot_env(ARMCPU *cpu)
     }
     else {
         /* AARCH32 Mode */
-        /* TODO: Specify Kernel Load Address for AARCH32 */
+        kernel_load_addr = 0x00008000;
+        setup_boot_env_32();
     }
 #else
     /* ARMv7 */
@@ -431,7 +436,7 @@ static void do_cpu_reset(void *opaque)
             if(env->aarch64) {
                 env->pstate = PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | PSR_MODE_EL1h;
             } else {
-                hw_error("AArch32 mode is currently not supported\n");
+                env->pstate = COMPAT_PSR_I_BIT | COMPAT_PSR_F_BIT | COMPAT_PSR_MODE_SVC;
             }
             env->xregs[0] =  0;
             env->xregs[1] = -1;
-- 
1.8.1.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v3 11/11] AARCH64: Add 32-bit mode selection parameter
  2013-09-27 10:10 [Qemu-devel] [PATCH v3 00/11] AARCH64 support on machvirt machine model using KVM Mian M. Hamayun
                   ` (9 preceding siblings ...)
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 10/11] AARCH64: Add flags and boot parameters " Mian M. Hamayun
@ 2013-09-27 10:10 ` Mian M. Hamayun
  10 siblings, 0 replies; 20+ messages in thread
From: Mian M. Hamayun @ 2013-09-27 10:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, agraf, tech, kvmarm, afaerber

From: "Mian M. Hamayun" <m.hamayun@virtualopensystems.com>

This commit introduces a commandline argument to select the
AARCH64 or AARCH32 mode for processor initilization.

Signed-off-by: Mian M. Hamayun <m.hamayun@virtualopensystems.com>
---
 qemu-options.hx  | 8 ++++++++
 target-arm/cpu.c | 9 +++++++--
 vl.c             | 4 ++++
 3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index 5dc8b75..a2dab99 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -72,6 +72,14 @@ STEXI
 Select CPU model (@code{-cpu help} for list and additional feature selection)
 ETEXI
 
+DEF("aarch32-mode", 0, QEMU_OPTION_aarch32_mode, \
+    "-aarch32-mode   enable aarch32 mode support on aarch64\n", QEMU_ARCH_ARM)
+STEXI
+@item -aarch32-mode
+@findex -aarch32-mode
+Enable aarch32 guest support on aarch64.
+ETEXI
+
 DEF("smp", HAS_ARG, QEMU_OPTION_smp,
     "-smp [cpus=]n[,maxcpus=cpus][,cores=cores][,threads=threads][,sockets=sockets]\n"
     "                set the number of CPUs to 'n' [default=1]\n"
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 5d811b9..56e8e56 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -27,6 +27,8 @@
 #include "sysemu/sysemu.h"
 #include "sysemu/kvm.h"
 
+extern int aarch32_mode;
+
 static void arm_cpu_set_pc(CPUState *cs, vaddr value)
 {
     ARMCPU *cpu = ARM_CPU(cs);
@@ -85,8 +87,11 @@ static void arm_cpu_reset(CPUState *s)
     }
 
     if (arm_feature(env, ARM_FEATURE_AARCH64)) {
-        /* 64 bit CPUs always start in 64 bit mode */
-        env->aarch64 = 1;
+        if(aarch32_mode) {
+            env->aarch64 = 0;  /* Boot a 32-bit Guest */
+        } else {
+            env->aarch64 = 1;  /* Boot a 64-bit Guest */
+        }
     }
 
 #if defined(CONFIG_USER_ONLY)
diff --git a/vl.c b/vl.c
index 4e709d5..e0f2cf3 100644
--- a/vl.c
+++ b/vl.c
@@ -207,6 +207,7 @@ CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
 CharDriverState *sclp_hds[MAX_SCLP_CONSOLES];
 int win2k_install_hack = 0;
 int singlestep = 0;
+int aarch32_mode = 0;
 int smp_cpus = 1;
 int max_cpus = 0;
 int smp_cores = 1;
@@ -3113,6 +3114,9 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_dtb:
                 qemu_opts_set(qemu_find_opts("machine"), 0, "dtb", optarg);
                 break;
+            case QEMU_OPTION_aarch32_mode:
+                aarch32_mode = 1;
+                break;
             case QEMU_OPTION_cdrom:
                 drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS);
                 break;
-- 
1.8.1.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v3 02/11] AARCH64: add a57core
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 02/11] AARCH64: add a57core Mian M. Hamayun
@ 2013-09-27 15:53   ` Andreas Färber
  2013-09-28  0:16     ` Peter Maydell
  0 siblings, 1 reply; 20+ messages in thread
From: Andreas Färber @ 2013-09-27 15:53 UTC (permalink / raw)
  To: Mian M. Hamayun; +Cc: peter.maydell, tech, kvmarm, qemu-devel, agraf

Hi,

Am 27.09.2013 12:10, schrieb Mian M. Hamayun:
> From: John Rigby <john.rigby@linaro.org>
> 
> Just an copy of a15 with a57 substituting a15 for now.
> 
> Signed-off-by: John Rigby <john.rigby@linaro.org>
> Signed-off-by: Mian M. Hamayun <m.hamayun@virtualopensystems.com>
> ---
>  hw/cpu/Makefile.objs |   1 +
>  hw/cpu/a57mpcore.c   | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  target-arm/cpu.c     |   9 ++++
>  3 files changed, 132 insertions(+)
>  create mode 100644 hw/cpu/a57mpcore.c

I had previously gently nack'ed this patch - conversions are still
queued on qom-next currently though. Having PMM's kernel load patches
now, I'll try if I can still get this posted today.

In particular use of QOM realize and embedding of child device with
avoidance of child instantiation during realization.

Regards,
Andreas

> 
> diff --git a/hw/cpu/Makefile.objs b/hw/cpu/Makefile.objs
> index df287c1..22e9567 100644
> --- a/hw/cpu/Makefile.objs
> +++ b/hw/cpu/Makefile.objs
> @@ -1,5 +1,6 @@
>  obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o
>  obj-$(CONFIG_A9MPCORE) += a9mpcore.o
>  obj-$(CONFIG_A15MPCORE) += a15mpcore.o
> +obj-$(CONFIG_A57MPCORE) += a57mpcore.o
>  obj-$(CONFIG_ICC_BUS) += icc_bus.o
>  
> diff --git a/hw/cpu/a57mpcore.c b/hw/cpu/a57mpcore.c
> new file mode 100644
> index 0000000..4be277f
> --- /dev/null
> +++ b/hw/cpu/a57mpcore.c
> @@ -0,0 +1,122 @@
> +/*
> + * Cortex-A57MPCore internal peripheral emulation.
> + *
> + * Copyright (c) 2012 Linaro Limited.
> + * Written by Peter Maydell.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "hw/sysbus.h"
> +#include "sysemu/kvm.h"
> +
> +/* A57MP private memory region.  */
> +
> +#define TYPE_A57MPCORE_PRIV "a57mpcore_priv"
> +#define A57MPCORE_PRIV(obj) \
> +    OBJECT_CHECK(A57MPPrivState, (obj), TYPE_A57MPCORE_PRIV)
> +
> +typedef struct A57MPPrivState {
> +    /*< private >*/
> +    SysBusDevice parent_obj;
> +    /*< public >*/
> +
> +    uint32_t num_cpu;
> +    uint32_t num_irq;
> +    MemoryRegion container;
> +    DeviceState *gic;
> +} A57MPPrivState;
> +
> +static void a57mp_priv_set_irq(void *opaque, int irq, int level)
> +{
> +    A57MPPrivState *s = (A57MPPrivState *)opaque;
> +    qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level);
> +}
> +
> +static int a57mp_priv_init(SysBusDevice *dev)
> +{
> +    A57MPPrivState *s = A57MPCORE_PRIV(dev);
> +    SysBusDevice *busdev;
> +    const char *gictype = "arm_gic";
> +
> +    if (kvm_irqchip_in_kernel()) {
> +        gictype = "kvm-arm-gic";
> +    }
> +
> +    s->gic = qdev_create(NULL, gictype);
> +    qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
> +    qdev_prop_set_uint32(s->gic, "num-irq", s->num_irq);
> +    qdev_prop_set_uint32(s->gic, "revision", 2);
> +    qdev_init_nofail(s->gic);
> +    busdev = SYS_BUS_DEVICE(s->gic);
> +
> +    /* Pass through outbound IRQ lines from the GIC */
> +    sysbus_pass_irq(dev, busdev);
> +
> +    /* Pass through inbound GPIO lines to the GIC */
> +    qdev_init_gpio_in(DEVICE(dev), a57mp_priv_set_irq, s->num_irq - 32);
> +
> +    /* Memory map (addresses are offsets from PERIPHBASE):
> +     *  0x0000-0x0fff -- reserved
> +     *  0x1000-0x1fff -- GIC Distributor
> +     *  0x2000-0x2fff -- GIC CPU interface
> +     *  0x4000-0x4fff -- GIC virtual interface control (not modelled)
> +     *  0x5000-0x5fff -- GIC virtual interface control (not modelled)
> +     *  0x6000-0x7fff -- GIC virtual CPU interface (not modelled)
> +     */
> +    memory_region_init(&s->container, OBJECT(s),
> +                       "a57mp-priv-container", 0x8000);
> +    memory_region_add_subregion(&s->container, 0x1000,
> +                                sysbus_mmio_get_region(busdev, 0));
> +    memory_region_add_subregion(&s->container, 0x2000,
> +                                sysbus_mmio_get_region(busdev, 1));
> +
> +    sysbus_init_mmio(dev, &s->container);
> +    return 0;
> +}
> +
> +static Property a57mp_priv_properties[] = {
> +    DEFINE_PROP_UINT32("num-cpu", A57MPPrivState, num_cpu, 1),
> +    /* The Cortex-A57MP may have anything from 0 to 224 external interrupt
> +     * IRQ lines (with another 32 internal). We default to 128+32, which
> +     * is the number provided by the Cortex-A57MP test chip in the
> +     * Versatile Express A57 development board.
> +     * Other boards may differ and should set this property appropriately.
> +     */
> +    DEFINE_PROP_UINT32("num-irq", A57MPPrivState, num_irq, 160),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void a57mp_priv_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
> +    k->init = a57mp_priv_init;
> +    dc->props = a57mp_priv_properties;
> +    /* We currently have no savable state */
> +}
> +
> +static const TypeInfo a57mp_priv_info = {
> +    .name  = TYPE_A57MPCORE_PRIV,
> +    .parent = TYPE_SYS_BUS_DEVICE,
> +    .instance_size  = sizeof(A57MPPrivState),
> +    .class_init = a57mp_priv_class_init,
> +};
> +
> +static void a57mp_register_types(void)
> +{
> +    type_register_static(&a57mp_priv_info);
> +}
> +
> +type_init(a57mp_register_types)
> diff --git a/target-arm/cpu.c b/target-arm/cpu.c
> index d40f2a7..5d811b9 100644
> --- a/target-arm/cpu.c
> +++ b/target-arm/cpu.c
> @@ -684,6 +684,14 @@ static void cortex_a15_initfn(Object *obj)
>      define_arm_cp_regs(cpu, cortexa15_cp_reginfo);
>  }
>  
> +static void cortex_a57_initfn(Object *obj)
> +{
> +    ARMCPU *cpu = ARM_CPU(obj);
> +    set_feature(&cpu->env, ARM_FEATURE_V8);
> +    set_feature(&cpu->env, ARM_FEATURE_AARCH64);
> +    /* TODO: See if we need to set some more features for ARMv8 ? */
> +}
> +
>  static void ti925t_initfn(Object *obj)
>  {
>      ARMCPU *cpu = ARM_CPU(obj);
> @@ -872,6 +880,7 @@ static const ARMCPUInfo arm_cpus[] = {
>      { .name = "cortex-a8",   .initfn = cortex_a8_initfn },
>      { .name = "cortex-a9",   .initfn = cortex_a9_initfn },
>      { .name = "cortex-a15",  .initfn = cortex_a15_initfn },
> +    { .name = "cortex-a57",  .initfn = cortex_a57_initfn },
>      { .name = "ti925t",      .initfn = ti925t_initfn },
>      { .name = "sa1100",      .initfn = sa1100_initfn },
>      { .name = "sa1110",      .initfn = sa1110_initfn },
> 


-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v3 02/11] AARCH64: add a57core
  2013-09-27 15:53   ` Andreas Färber
@ 2013-09-28  0:16     ` Peter Maydell
  2013-09-30 15:53       ` Mian M. Hamayun
  0 siblings, 1 reply; 20+ messages in thread
From: Peter Maydell @ 2013-09-28  0:16 UTC (permalink / raw)
  To: Andreas Färber
  Cc: tech@virtualopensystems.com, kvmarm@lists.cs.columbia.edu,
	QEMU Developers, Mian M. Hamayun, Alexander Graf

On 28 September 2013 00:53, Andreas Färber <afaerber@suse.de> wrote:
> Hi,
>
> Am 27.09.2013 12:10, schrieb Mian M. Hamayun:
>> From: John Rigby <john.rigby@linaro.org>
>>
>> Just an copy of a15 with a57 substituting a15 for now.

> I had previously gently nack'ed this patch - conversions are still
> queued on qom-next currently though. Having PMM's kernel load patches
> now, I'll try if I can still get this posted today.

It's also already had a strong nak from me because it's not
really an A57 model. We should be using 'cpu host'
until there's a public TRM for a real A57 model.

-- PMM

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v3 02/11] AARCH64: add a57core
  2013-09-28  0:16     ` Peter Maydell
@ 2013-09-30 15:53       ` Mian M. Hamayun
  2013-09-30 18:09         ` Andreas Färber
  2013-10-01  0:55         ` Peter Maydell
  0 siblings, 2 replies; 20+ messages in thread
From: Mian M. Hamayun @ 2013-09-30 15:53 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Alexander Graf, tech@virtualopensystems.com,
	kvmarm@lists.cs.columbia.edu, Andreas Färber,
	QEMU Developers


On 28/09/2013 02:16, Peter Maydell wrote:
> On 28 September 2013 00:53, Andreas Färber <afaerber@suse.de> wrote:
>> Hi,
>>
>> Am 27.09.2013 12:10, schrieb Mian M. Hamayun:
>>> From: John Rigby <john.rigby@linaro.org>
>>>
>>> Just an copy of a15 with a57 substituting a15 for now.
>> I had previously gently nack'ed this patch - conversions are still
>> queued on qom-next currently though. Having PMM's kernel load patches
>> now, I'll try if I can still get this posted today.
> It's also already had a strong nak from me because it's not
> really an A57 model. We should be using 'cpu host'
> until there's a public TRM for a real A57 model.
>
> -- PMM

I agree with your concerns and feedback but as I remember from our last
KVM/ARM telco, we agreed that I should not wait for the -cpu host support
to become available and post the next patch series anyways.

Also there are multiple patches under review for providing the -cpu host
or equivalent support in QEMU and/or KVM such as the one posted by Peter
Maydell and another CPU=Host patch from Anup Patel. We will update our patch
series, once we have consensus on which implementation to actually use for
providing the -cpu host support.

--
Hamayun

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v3 02/11] AARCH64: add a57core
  2013-09-30 15:53       ` Mian M. Hamayun
@ 2013-09-30 18:09         ` Andreas Färber
  2013-10-01  0:55         ` Peter Maydell
  1 sibling, 0 replies; 20+ messages in thread
From: Andreas Färber @ 2013-09-30 18:09 UTC (permalink / raw)
  To: m.hamayun
  Cc: Peter Maydell, tech@virtualopensystems.com,
	kvmarm@lists.cs.columbia.edu, QEMU Developers, Alexander Graf

Am 30.09.2013 17:53, schrieb Mian M. Hamayun:
> On 28/09/2013 02:16, Peter Maydell wrote:
>> On 28 September 2013 00:53, Andreas Färber <afaerber@suse.de> wrote:
>>> Am 27.09.2013 12:10, schrieb Mian M. Hamayun:
>>>> From: John Rigby <john.rigby@linaro.org>
>>>>
>>>> Just an copy of a15 with a57 substituting a15 for now.
>>> I had previously gently nack'ed this patch - conversions are still
>>> queued on qom-next currently though. Having PMM's kernel load patches
>>> now, I'll try if I can still get this posted today.
>> It's also already had a strong nak from me because it's not
>> really an A57 model. We should be using 'cpu host'
>> until there's a public TRM for a real A57 model.
> 
> I agree with your concerns and feedback but as I remember from our last
> KVM/ARM telco, we agreed that I should not wait for the -cpu host support
> to become available and post the next patch series anyways.

In such a case please use "RFC" rather than "PATCH" to clarify that it
is known not yet ready for applying. :-)

Andreas

> Also there are multiple patches under review for providing the -cpu host
> or equivalent support in QEMU and/or KVM such as the one posted by Peter
> Maydell and another CPU=Host patch from Anup Patel. We will update our
> patch
> series, once we have consensus on which implementation to actually use for
> providing the -cpu host support.
> 
> -- 
> Hamayun

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v3 02/11] AARCH64: add a57core
  2013-09-30 15:53       ` Mian M. Hamayun
  2013-09-30 18:09         ` Andreas Färber
@ 2013-10-01  0:55         ` Peter Maydell
  1 sibling, 0 replies; 20+ messages in thread
From: Peter Maydell @ 2013-10-01  0:55 UTC (permalink / raw)
  To: Mian M. Hamayun
  Cc: Alexander Graf, tech@virtualopensystems.com,
	kvmarm@lists.cs.columbia.edu, Andreas Färber,
	QEMU Developers

On 1 October 2013 00:53, Mian M. Hamayun
<m.hamayun@virtualopensystems.com> wrote:
> Also there are multiple patches under review for providing the -cpu host
> or equivalent support in QEMU and/or KVM such as the one posted by Peter
> Maydell and another CPU=Host patch from Anup Patel.

Yeah, I agree it's a bit up in the air at the moment API wise
but I think we've more or less converged on a decision.

https://git.linaro.org/gitweb?p=people/pmaydell/qemu-arm.git;a=shortlog;h=refs/heads/aarch64-kvm
has the QEMU side stuff as I currently have it, and it doesn't
depend on the kernel patches being committed.

-- PMM

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v3 06/11] target-arm: Parameterize the bootloader selection and setup mechanism
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 06/11] target-arm: Parameterize the bootloader selection and setup mechanism Mian M. Hamayun
@ 2013-11-25 21:17   ` Peter Maydell
  0 siblings, 0 replies; 20+ messages in thread
From: Peter Maydell @ 2013-11-25 21:17 UTC (permalink / raw)
  To: Mian M. Hamayun
  Cc: Alexander Graf, tech@virtualopensystems.com, QEMU Developers,
	Andreas Färber, kvmarm@lists.cs.columbia.edu

On 27 September 2013 11:10, Mian M. Hamayun
<m.hamayun@virtualopensystems.com> wrote:
> From: "Mian M. Hamayun" <m.hamayun@virtualopensystems.com>
>
> This commit replaces the constant indices used in bootloaders, such as for
> specifying the Board ID and kernel arguments with variable parameters.
> This change is used as mechanism to minimize code changes for different
> bootloaders, for example different bootloaders will be used for different
> architectures (ARMv7 vs. ARMv8).
>
> Similary pointers are introduced to select appropriate bootloaders for boot
> and secondary cpus.

So I think parameterizing this a bit is good, but I don't think this
code is quite the right approach...

> Signed-off-by: Mian M. Hamayun <m.hamayun@virtualopensystems.com>
> ---
>  hw/arm/boot.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++-----------
>  1 file changed, 66 insertions(+), 15 deletions(-)
>
> diff --git a/hw/arm/boot.c b/hw/arm/boot.c
> index 967397b..4c1170e 100644
> --- a/hw/arm/boot.c
> +++ b/hw/arm/boot.c
> @@ -18,10 +18,9 @@
>  #include "qemu/config-file.h"
>
>  #define KERNEL_ARGS_ADDR 0x100
> -#define KERNEL_LOAD_ADDR 0x00010000
>
>  /* The worlds second smallest bootloader.  Set r0-r2, then jump to kernel.  */
> -static uint32_t bootloader[] = {
> +static uint32_t bootloader_arm32[] = {
>    0xe3a00000, /* mov     r0, #0 */
>    0xe59f1004, /* ldr     r1, [pc, #4] */
>    0xe59f2004, /* ldr     r2, [pc, #4] */
> @@ -48,7 +47,7 @@ static uint32_t bootloader[] = {
>  #define DSB_INSN 0xf57ff04f
>  #define CP15_DSB_INSN 0xee070f9a /* mcr cp15, 0, r0, c7, c10, 4 */
>
> -static uint32_t smpboot[] = {
> +static uint32_t smpboot_arm32[] = {
>    0xe59f2028, /* ldr r2, gic_cpu_if */
>    0xe59f0028, /* ldr r0, startaddr */
>    0xe3a01001, /* mov r1, #1 */
> @@ -65,13 +64,60 @@ static uint32_t smpboot[] = {
>    0           /* bootreg: Boot register address is held here */
>  };
>
> +/*
> + * The bootloaders to be used are referenced by the following pointers
> + * An appropriate bootloader is selected depending on the architecture
> + * i.e. ARMv7, ARMv8 (AARCH64 and AARCH32)
> + */
> +static uint32_t *bootloader = NULL;
> +static uint32_t  bootloader_array_size = 0;
> +
> +static uint32_t *smpboot = NULL;
> +static uint32_t  smpboot_array_size = 0;
> +
> +/*
> + * An index gives the location in the bootloader array, where we put the board
> + * ID, kernel arguments and kernel entry addresses. These are different for
> + * ARMv7 and ARMv8 bootloaders defined above.
> + */
> +static uint32_t kernel_boardid_index = 0;
> +static uint32_t kernel_args_index    = 0;
> +static uint32_t kernel_entry_index   = 0;
> +
> +/*
> + * Similarly, the kernel loading address also depends on the architecture,
> + * i.e. its different for ARMv7, ARMv8 (AARCH64 and AARCH32)
> + */
> +static uint32_t kernel_load_addr = 0x0;
> +
> +static void setup_boot_env_32(void)
> +{
> +    bootloader = bootloader_arm32;
> +    bootloader_array_size = ARRAY_SIZE(bootloader_arm32);
> +    smpboot = smpboot_arm32;
> +    smpboot_array_size = ARRAY_SIZE(smpboot_arm32);
> +
> +    kernel_boardid_index = bootloader_array_size - 3;
> +    kernel_args_index    = bootloader_array_size - 2;
> +    kernel_entry_index   = bootloader_array_size - 1;
> +    return;
> +}

...you wind up with a per-loader function which sets a bunch
of globals, so the information relating to that loader is more
scattered than necessary. Also, if we find that we need something
other than boardid/args/entrypoint to be patched in, we need to
update every loader. And we're fixing up the secondary boot
loader separately from the primary cpu loader, just because
it happens to need slightly different things doing to it.

My suggestion would be that we have a struct defining
a loader:

typedef struct ARMInsnList {
    uint32_t insn;
    uint32_t fixup;
};

and then have each loader be an array ARMInsnList[];

fixup is one of a set of constants defining what if any action
to take on that word:
#define FIXUP_NONE 0      /* do nothing */
#define FIXUP_TERMINATOR 1 /* end of list */
#define FIXUP_BOARDID 2   /* replace with board ID */
#define FIXUP_ARGPTR 3    /* replace with arg pointer */
#define FIXUP_ENTRYPOINT 4  /* replace with entry point */
#define FIXUP_DSB 5           /* if pre-v7, replace with cp15 DSB */
#define FIXUP_GIC_CPUIF 6 /* replace with GIC CPU i/f address */

and so on. The 32 bit loader then looks something like:

static const ARMInsnList bootloader_arm32[] = {
  { 0xe3a00000 } , /* mov     r0, #0 */
  { 0xe59f1004 }, /* ldr     r1, [pc, #4] */
  { 0xe59f2004 }, /* ldr     r2, [pc, #4] */
  { 0xe59ff004 }, /* ldr     pc, [pc, #4] */
  { 0, FIXUP_BOARDID },
  { 0, FIXUP_ARGPTR },
  { 0, FIXUP_ENTRYPOINT },
  { 0, FIXUP_TERMINATOR }
};

(note that since we made FIXUP_NONE 0 we can omit it as
the struct initialization will default to that.)

Then we can have a common bit of code that does the
"create the fixed up instructions based on the list of
insns and fixups"; it can figure out the length from the
presence of the terminator, and it will be able to handle
both the primary and secondary loaders, with scope for
more flexibility if we need it via further fixup types. (It'll
need to allocate an array to fill in since the insns aren't
consecutive in an ARMInsnList but that's not a big deal.)

I'll have a go at writing up a patch for this this evening...

-- PMM

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v3 07/11] AARCH64: Add boot support for aarch64 processor
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 07/11] AARCH64: Add boot support for aarch64 processor Mian M. Hamayun
@ 2013-11-25 23:51   ` Peter Maydell
  0 siblings, 0 replies; 20+ messages in thread
From: Peter Maydell @ 2013-11-25 23:51 UTC (permalink / raw)
  To: Mian M. Hamayun
  Cc: Alexander Graf, tech@virtualopensystems.com, QEMU Developers,
	Andreas Färber, kvmarm@lists.cs.columbia.edu

On 27 September 2013 11:10, Mian M. Hamayun
<m.hamayun@virtualopensystems.com> wrote:
> From: "Mian M. Hamayun" <m.hamayun@virtualopensystems.com>
>
> This commit adds support for booting a single AArch64 CPU by setting
> appropriate registers. The bootloader includes placehoders for Board-ID
> that are used to implement uniform indexing across different bootloaders.
> We also introduce Cortex-A57 to virt platform.

Hi; apologies for not getting round to a closer look at this patch earlier.
The changes are mostly fairly minor so my current plan is to put a version
of this patch in the set I'm hoping to send out later this week...

> Signed-off-by: Mian M. Hamayun <m.hamayun@virtualopensystems.com>
> ---
>  hw/arm/boot.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/arm/virt.c |  8 ++++++++
>  2 files changed, 65 insertions(+)
>
> diff --git a/hw/arm/boot.c b/hw/arm/boot.c
> index 4c1170e..0471eb8 100644
> --- a/hw/arm/boot.c
> +++ b/hw/arm/boot.c
> @@ -19,6 +19,23 @@
>
>  #define KERNEL_ARGS_ADDR 0x100
>
> +#ifdef TARGET_AARCH64
> +static uint32_t bootloader_arm64[] = {
> +    0x580000c0,        /* ldr  x0, 18 ; Load the lower 32-bits of DTB */
> +    0xaa1f03e1,        /* mov  x1, xzr */
> +    0xaa1f03e2,        /* mov  x2, xzr */
> +    0xaa1f03e3,        /* mov  x3, xzr */
> +    0x58000084,        /* ldr  x4, 20 ; Load the lower 32-bits of kernel entry */
> +    0xd61f0080,        /* br   x4     ; Jump to the kernel entry point */
> +    0x00000000,        /* .word @DTB Lower 32-bits */
> +    0x00000000,        /* .word @DTB Higher 32-bits */
> +    0x00000000,        /* .word @Kernel Entry Lower 32-bits */
> +    0x00000000,        /* .word @Kernel Entry Higher 32-bits */
> +    0x00000000,        /* .word @Board ID Lower 32-bits -- Placeholder */
> +    0x00000000         /* .word @Board ID Higher 32-bits -- Placeholder */
> +};
> +#endif
> +
>  /* The worlds second smallest bootloader.  Set r0-r2, then jump to kernel.  */
>  static uint32_t bootloader_arm32[] = {
>    0xe3a00000, /* mov     r0, #0 */
> @@ -103,11 +120,37 @@ static void setup_boot_env_32(void)
>      return;
>  }
>
> +#ifdef TARGET_AARCH64
> +static void setup_boot_env_64(void)
> +{
> +    bootloader = bootloader_arm64;
> +    bootloader_array_size = ARRAY_SIZE(bootloader_arm64);
> +
> +    kernel_args_index    = bootloader_array_size - 6;
> +    kernel_entry_index   = bootloader_array_size - 4;
> +    kernel_boardid_index = bootloader_array_size - 2;
> +    return;
> +}
> +#endif
> +
>  static void setup_boot_env(ARMCPU *cpu)
>  {
> +#ifdef TARGET_AARCH64

You don't need this ifdef -- env->aarch64 exists on 32 bit builds
and is always zero, so just doing a runtime check should be fine.

> +    CPUARMState *env = &cpu->env;
> +    if(env->aarch64) {
> +        /* AARCH64 Mode */
> +        kernel_load_addr = 0x00080000;

This offset should ideally be pulled out of the decompressed image header.

> +        setup_boot_env_64();
> +    }
> +    else {
> +        /* AARCH32 Mode */
> +        /* TODO: Specify Kernel Load Address for AARCH32 */
> +    }
> +#else
>      /* ARMv7 */
>      kernel_load_addr = 0x00010000;
>      setup_boot_env_32();
> +#endif
>      return;
>  }
>
> @@ -380,8 +423,22 @@ static void do_cpu_reset(void *opaque)
>              env->regs[15] = info->entry & 0xfffffffe;
>              env->thumb = info->entry & 1;
>          } else {
> +#ifdef TARGET_AARCH64
> +            if(env->aarch64) {
> +                env->pstate = PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | PSR_MODE_EL1h;
> +            } else {
> +                hw_error("AArch32 mode is currently not supported\n");

TARGET_AARCH64 doesn't necessarily mean this is a 64
bit CPU; this ifdef breaks 32 bit CPUs in an aarch64-softmmu binary.

> +            }
> +            env->xregs[0] =  0;
> +            env->xregs[1] = -1;
> +#endif
>              if (CPU(cpu) == first_cpu) {
> +#ifdef TARGET_AARCH64
> +                env->xregs[2] = bootloader[kernel_args_index];

Why are we setting X[2] here? The bootloader code is going
to immediately clear it... Similarly X[0] and X[1] above.

> +                env->pc = info->loader_start;
> +#else
>                  env->regs[15] = info->loader_start;

This ifdef should be an "if (aarch64)" runtime check too.

> +#endif
>                  if (!info->dtb_filename) {
>                      if (old_param) {
>                          set_kernel_args_old(info);
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 448a0e5..8043fd4 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -118,6 +118,14 @@ static VirtBoardInfo machines[] = {
>          .memmap = a15memmap,
>          .irqmap = a15irqmap,
>      },
> +    {
> +        .cpu_model = "cortex-a57",
> +        .cpu_compatible = "arm,arm-v8",
> +        .qdevname = "a57mpcore_priv",
> +        .gic_compatible = "arm,cortex-a15-gic",
> +        .memmap = a15memmap,
> +        .irqmap = a15irqmap,
> +    },
>  };

This hunk shouldn't really be in this patch I think.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v3 05/11] AARCH64: Add AARCH64 CPU initialization, get and put registers support
  2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 05/11] AARCH64: Add AARCH64 CPU initialization, get and put registers support Mian M. Hamayun
@ 2013-11-26 22:24   ` Peter Maydell
  0 siblings, 0 replies; 20+ messages in thread
From: Peter Maydell @ 2013-11-26 22:24 UTC (permalink / raw)
  To: Mian M. Hamayun
  Cc: Alexander Graf, tech@virtualopensystems.com, QEMU Developers,
	Andreas Färber, kvmarm@lists.cs.columbia.edu

On 27 September 2013 11:10, Mian M. Hamayun
<m.hamayun@virtualopensystems.com> wrote:
> From: "Mian M. Hamayun" <m.hamayun@virtualopensystems.com>
>
> The cpu init function tries to initialize with all possible cpu types, as
> KVM does not provide a means to detect the real cpu type and simply refuses
> to initialize on cpu type mis-match. By using the loop based init function,
> we avoid the need to modify code if the underlying platform is different,
> such as Fast Models instead of Foundation Models.
>
> Get and Put Registers deal with the basic state of AARCH64 CPUs.

Hi; this is another review mail mostly to flag up a few things I'm
fixing up as I go along with these patches.

>  int kvm_arch_put_registers(CPUState *cs, int level)
>  {
> -    return 0;
> +    struct kvm_one_reg reg;
> +    int i;
> +    int ret;
> +
> +    ARMCPU *cpu = ARM_CPU(cs);
> +    CPUARMState *env = &cpu->env;
> +
> +    for (i = 0; i < ARRAY_SIZE(env->xregs); i++) {

This upper bound using ARRAY_SIZE means we'll try
to do a read/write of xregs[31], which isn't a core register
(it's SP for QEMU, as you can see below).

> +        reg.id = AARCH64_CORE_REG(regs.regs[i]);
> +        reg.addr = (uintptr_t) &env->xregs[i];
> +        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &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, &reg);
> +    if (ret) {
> +        return ret;
> +    }

> +    reg.id = AARCH64_CORE_REG(regs.pstate);
> +    reg.addr = (uintptr_t) &env->pstate;

This will tell the kernel to read/write 64 bits of data into
env->pstate, which is a uint32_t. We need to use a local
uint64_t to pass the data through.

(I don't know why the kernel thinks PSTATE is a 64 bit
register...)

thanks
-- PMM

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2013-11-26 22:24 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-27 10:10 [Qemu-devel] [PATCH v3 00/11] AARCH64 support on machvirt machine model using KVM Mian M. Hamayun
2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 01/11] ARM: arm64 kvm headers from kernel arm64-kvm tree Mian M. Hamayun
2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 02/11] AARCH64: add a57core Mian M. Hamayun
2013-09-27 15:53   ` Andreas Färber
2013-09-28  0:16     ` Peter Maydell
2013-09-30 15:53       ` Mian M. Hamayun
2013-09-30 18:09         ` Andreas Färber
2013-10-01  0:55         ` Peter Maydell
2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 03/11] AARCH64: Add A57 CPU to default AArch64 configuration and enable KVM Mian M. Hamayun
2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 04/11] AARCH64: Separate 32-bit specific code from common KVM hooks Mian M. Hamayun
2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 05/11] AARCH64: Add AARCH64 CPU initialization, get and put registers support Mian M. Hamayun
2013-11-26 22:24   ` Peter Maydell
2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 06/11] target-arm: Parameterize the bootloader selection and setup mechanism Mian M. Hamayun
2013-11-25 21:17   ` Peter Maydell
2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 07/11] AARCH64: Add boot support for aarch64 processor Mian M. Hamayun
2013-11-25 23:51   ` Peter Maydell
2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 08/11] AARCH64: Enable SMP support for aarch64 processors using PSCI method Mian M. Hamayun
2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 09/11] AARCH64: Enable configure support for 32-bit guests on AARCH64 Mian M. Hamayun
2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 10/11] AARCH64: Add flags and boot parameters " Mian M. Hamayun
2013-09-27 10:10 ` [Qemu-devel] [PATCH v3 11/11] AARCH64: Add 32-bit mode selection parameter Mian M. Hamayun

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).