* [Qemu-devel] [RFC v4 1/8] linux-headers: Add ARM KVM headers (not for upstream)
2012-11-20 13:31 [Qemu-devel] [RFC v4 0/8] QEMU: Support KVM on ARM Peter Maydell
@ 2012-11-20 13:31 ` Peter Maydell
2012-11-20 13:31 ` [Qemu-devel] [RFC v4 2/8] ARM: KVM: Add support for KVM on ARM architecture Peter Maydell
` (6 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Peter Maydell @ 2012-11-20 13:31 UTC (permalink / raw)
To: qemu-devel
Cc: kvm, patches, Marcelo Tosatti, kvmarm, Blue Swirl, Avi Kivity,
Andreas Färber
This commit adds the ARM KVM headers. This is not to go to QEMU
upstream -- the correct path there is that the KVM code will be
committed to a mainline upstream kernel, and then upstream QEMU
can do a bulk header update from the upstream kernel, which will
allow us to drop this temporary commit.
This is the result of running update-headers on Christoffer's
kvm-arm-v14-vgic-timers branch (commit 68d116f).
This commit currently also includes some non-ARM header changes
which hopefully will have made it into QEMU upstream by the time
we submit this for merging.
---
| 137 ++++++++++++++++++++++++++++++++++
| 1 +
| 4 +
| 59 +++++++++++++++
| 7 +-
| 34 +++++++--
6 files changed, 234 insertions(+), 8 deletions(-)
create mode 100644 linux-headers/asm-arm/kvm.h
create mode 100644 linux-headers/asm-arm/kvm_para.h
create mode 100644 linux-headers/asm-generic/kvm_para.h
--git a/linux-headers/asm-arm/kvm.h b/linux-headers/asm-arm/kvm.h
new file mode 100644
index 0000000..b1c7871
--- /dev/null
+++ b/linux-headers/asm-arm/kvm.h
@@ -0,0 +1,137 @@
+/*
+ * 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, write to the Free Software
+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __ARM_KVM_H__
+#define __ARM_KVM_H__
+
+#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 pt_regs usr_regs;/* R0_usr - R14_usr, PC, CPSR */
+ __u32 svc_regs[3]; /* SP_svc, LR_svc, SPSR_svc */
+ __u32 abt_regs[3]; /* SP_abt, LR_abt, SPSR_abt */
+ __u32 und_regs[3]; /* SP_und, LR_und, SPSR_und */
+ __u32 irq_regs[3]; /* SP_irq, LR_irq, SPSR_irq */
+ __u32 fiq_regs[8]; /* R8_fiq - R14_fiq, SPSR_fiq */
+};
+
+/* Supported Processor Types */
+#define KVM_ARM_TARGET_CORTEX_A15 0
+#define KVM_ARM_NUM_TARGETS 1
+
+/* KVM_SET_DEVICE_ADDRESS ioctl id encoding */
+#define KVM_DEVICE_TYPE_SHIFT 0
+#define KVM_DEVICE_TYPE_MASK (0xffff << KVM_DEVICE_TYPE_SHIFT)
+#define KVM_DEVICE_ID_SHIFT 16
+#define KVM_DEVICE_ID_MASK (0xffff << KVM_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
+
+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
+#define KVM_REG_ARM_32_OPC2_MASK 0x0000000000000007
+#define KVM_REG_ARM_32_OPC2_SHIFT 0
+#define KVM_REG_ARM_OPC1_MASK 0x0000000000000078
+#define KVM_REG_ARM_OPC1_SHIFT 3
+#define KVM_REG_ARM_CRM_MASK 0x0000000000000780
+#define KVM_REG_ARM_CRM_SHIFT 7
+#define KVM_REG_ARM_32_CRN_MASK 0x0000000000007800
+#define KVM_REG_ARM_32_CRN_SHIFT 11
+
+/* 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) / 4)
+
+/* 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
+
+/* VFP registers: we could overload CP10 like ARM does, but that's ugly. */
+#define KVM_REG_ARM_VFP (0x0012 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM_VFP_MASK 0x000000000000FFFF
+#define KVM_REG_ARM_VFP_BASE_REG 0x0
+#define KVM_REG_ARM_VFP_FPSID 0x1000
+#define KVM_REG_ARM_VFP_FPSCR 0x1001
+#define KVM_REG_ARM_VFP_MVFR1 0x1006
+#define KVM_REG_ARM_VFP_MVFR0 0x1007
+#define KVM_REG_ARM_VFP_FPEXC 0x1008
+#define KVM_REG_ARM_VFP_FPINST 0x1009
+#define KVM_REG_ARM_VFP_FPINST2 0x100A
+
+
+/* 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
+
+#endif /* __ARM_KVM_H__ */
--git a/linux-headers/asm-arm/kvm_para.h b/linux-headers/asm-arm/kvm_para.h
new file mode 100644
index 0000000..14fab8f
--- /dev/null
+++ b/linux-headers/asm-arm/kvm_para.h
@@ -0,0 +1 @@
+#include <asm-generic/kvm_para.h>
--git a/linux-headers/asm-generic/kvm_para.h b/linux-headers/asm-generic/kvm_para.h
new file mode 100644
index 0000000..486f0af
--- /dev/null
+++ b/linux-headers/asm-generic/kvm_para.h
@@ -0,0 +1,4 @@
+/*
+ * There isn't anything here, but the file must not be empty or patch
+ * will delete it.
+ */
--git a/linux-headers/asm-powerpc/kvm.h b/linux-headers/asm-powerpc/kvm.h
index 1bea4d8..b89ae4d 100644
--- a/linux-headers/asm-powerpc/kvm.h
+++ b/linux-headers/asm-powerpc/kvm.h
@@ -221,6 +221,12 @@ struct kvm_sregs {
__u32 dbsr; /* KVM_SREGS_E_UPDATE_DBSR */
__u32 dbcr[3];
+ /*
+ * iac/dac registers are 64bit wide, while this API
+ * interface provides only lower 32 bits on 64 bit
+ * processors. ONE_REG interface is added for 64bit
+ * iac/dac registers.
+ */
__u32 iac[4];
__u32 dac[2];
__u32 dvc[2];
@@ -326,5 +332,58 @@ struct kvm_book3e_206_tlb_params {
};
#define KVM_REG_PPC_HIOR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x1)
+#define KVM_REG_PPC_IAC1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x2)
+#define KVM_REG_PPC_IAC2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3)
+#define KVM_REG_PPC_IAC3 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x4)
+#define KVM_REG_PPC_IAC4 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x5)
+#define KVM_REG_PPC_DAC1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x6)
+#define KVM_REG_PPC_DAC2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x7)
+#define KVM_REG_PPC_DABR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8)
+#define KVM_REG_PPC_DSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x9)
+#define KVM_REG_PPC_PURR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa)
+#define KVM_REG_PPC_SPURR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb)
+#define KVM_REG_PPC_DAR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc)
+#define KVM_REG_PPC_DSISR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd)
+#define KVM_REG_PPC_AMR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xe)
+#define KVM_REG_PPC_UAMOR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xf)
+
+#define KVM_REG_PPC_MMCR0 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x10)
+#define KVM_REG_PPC_MMCR1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x11)
+#define KVM_REG_PPC_MMCRA (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x12)
+
+#define KVM_REG_PPC_PMC1 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x18)
+#define KVM_REG_PPC_PMC2 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x19)
+#define KVM_REG_PPC_PMC3 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1a)
+#define KVM_REG_PPC_PMC4 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1b)
+#define KVM_REG_PPC_PMC5 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1c)
+#define KVM_REG_PPC_PMC6 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1d)
+#define KVM_REG_PPC_PMC7 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1e)
+#define KVM_REG_PPC_PMC8 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1f)
+
+/* 32 floating-point registers */
+#define KVM_REG_PPC_FPR0 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x20)
+#define KVM_REG_PPC_FPR(n) (KVM_REG_PPC_FPR0 + (n))
+#define KVM_REG_PPC_FPR31 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3f)
+
+/* 32 VMX/Altivec vector registers */
+#define KVM_REG_PPC_VR0 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x40)
+#define KVM_REG_PPC_VR(n) (KVM_REG_PPC_VR0 + (n))
+#define KVM_REG_PPC_VR31 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x5f)
+
+/* 32 double-width FP registers for VSX */
+/* High-order halves overlap with FP regs */
+#define KVM_REG_PPC_VSR0 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x60)
+#define KVM_REG_PPC_VSR(n) (KVM_REG_PPC_VSR0 + (n))
+#define KVM_REG_PPC_VSR31 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x7f)
+
+/* FP and vector status/control registers */
+#define KVM_REG_PPC_FPSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x80)
+#define KVM_REG_PPC_VSCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x81)
+
+/* Virtual processor areas */
+/* For SLB & DTL, address in high (first) half, length in low half */
+#define KVM_REG_PPC_VPA_ADDR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x82)
+#define KVM_REG_PPC_VPA_SLB (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x83)
+#define KVM_REG_PPC_VPA_DTL (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x84)
#endif /* __LINUX_KVM_POWERPC_H */
--git a/linux-headers/asm-powerpc/kvm_para.h b/linux-headers/asm-powerpc/kvm_para.h
index 5e04383..ed0e025 100644
--- a/linux-headers/asm-powerpc/kvm_para.h
+++ b/linux-headers/asm-powerpc/kvm_para.h
@@ -75,9 +75,10 @@ struct kvm_vcpu_arch_shared {
};
#define KVM_SC_MAGIC_R0 0x4b564d21 /* "KVM!" */
-#define HC_VENDOR_KVM (42 << 16)
-#define HC_EV_SUCCESS 0
-#define HC_EV_UNIMPLEMENTED 12
+
+#define KVM_HCALL_TOKEN(num) _EV_HCALL_TOKEN(EV_KVM_VENDOR_ID, num)
+
+#include <uapi/asm/epapr_hcalls.h>
#define KVM_FEATURE_MAGIC_PAGE 1
--git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index 81d2feb..c819d4c 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -115,6 +115,7 @@ struct kvm_irq_level {
* ACPI gsi notion of irq.
* For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47..
* For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23..
+ * For ARM: See Documentation/virtual/kvm/api.txt
*/
union {
__u32 irq;
@@ -167,10 +168,15 @@ struct kvm_pit_config {
#define KVM_EXIT_OSI 18
#define KVM_EXIT_PAPR_HCALL 19
#define KVM_EXIT_S390_UCONTROL 20
+#define KVM_EXIT_WATCHDOG 21
/* For KVM_EXIT_INTERNAL_ERROR */
-#define KVM_INTERNAL_ERROR_EMULATION 1
-#define KVM_INTERNAL_ERROR_SIMUL_EX 2
+/* Emulate instruction failed. */
+#define KVM_INTERNAL_ERROR_EMULATION 1
+/* Encounter unexpected simultaneous exceptions. */
+#define KVM_INTERNAL_ERROR_SIMUL_EX 2
+/* Encounter unexpected vm-exit due to delivery event. */
+#define KVM_INTERNAL_ERROR_DELIVERY_EV 3
/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
struct kvm_run {
@@ -477,6 +483,8 @@ struct kvm_ppc_smmu_info {
struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
};
+#define KVM_PPC_PVINFO_FLAGS_EV_IDLE (1<<0)
+
#define KVMIO 0xAE
/* machine type bits, to be used as argument to KVM_CREATE_VM */
@@ -626,6 +634,8 @@ struct kvm_ppc_smmu_info {
#define KVM_CAP_READONLY_MEM 81
#endif
#define KVM_CAP_IRQFD_RESAMPLE 82
+#define KVM_CAP_PPC_BOOKE_WATCHDOG 83
+#define KVM_CAP_SET_DEVICE_ADDR 84
#ifdef KVM_CAP_IRQ_ROUTING
@@ -755,6 +765,11 @@ struct kvm_dirty_tlb {
#define KVM_REG_SIZE_U512 0x0060000000000000ULL
#define KVM_REG_SIZE_U1024 0x0070000000000000ULL
+struct kvm_reg_list {
+ __u64 n; /* number of regs */
+ __u64 reg[0];
+};
+
struct kvm_one_reg {
__u64 id;
__u64 addr;
@@ -768,6 +783,11 @@ struct kvm_msi {
__u8 pad[16];
};
+struct kvm_device_address {
+ __u64 id;
+ __u64 addr;
+};
+
/*
* ioctls for VM fds
*/
@@ -848,6 +868,11 @@ struct kvm_s390_ucas_mapping {
#define KVM_PPC_GET_SMMU_INFO _IOR(KVMIO, 0xa6, struct kvm_ppc_smmu_info)
/* Available with KVM_CAP_PPC_ALLOC_HTAB */
#define KVM_PPC_ALLOCATE_HTAB _IOWR(KVMIO, 0xa7, __u32)
+#define KVM_CREATE_SPAPR_TCE _IOW(KVMIO, 0xa8, struct kvm_create_spapr_tce)
+/* Available with KVM_CAP_RMA */
+#define KVM_ALLOCATE_RMA _IOR(KVMIO, 0xa9, struct kvm_allocate_rma)
+/* Available with KVM_CAP_SET_DEVICE_ADDR */
+#define KVM_SET_DEVICE_ADDRESS _IOW(KVMIO, 0xaa, struct kvm_device_address)
/*
* ioctls for vcpu fds
@@ -911,9 +936,6 @@ struct kvm_s390_ucas_mapping {
/* Available with KVM_CAP_XCRS */
#define KVM_GET_XCRS _IOR(KVMIO, 0xa6, struct kvm_xcrs)
#define KVM_SET_XCRS _IOW(KVMIO, 0xa7, struct kvm_xcrs)
-#define KVM_CREATE_SPAPR_TCE _IOW(KVMIO, 0xa8, struct kvm_create_spapr_tce)
-/* Available with KVM_CAP_RMA */
-#define KVM_ALLOCATE_RMA _IOR(KVMIO, 0xa9, struct kvm_allocate_rma)
/* Available with KVM_CAP_SW_TLB */
#define KVM_DIRTY_TLB _IOW(KVMIO, 0xaa, struct kvm_dirty_tlb)
/* Available with KVM_CAP_ONE_REG */
@@ -921,6 +943,8 @@ struct kvm_s390_ucas_mapping {
#define KVM_SET_ONE_REG _IOW(KVMIO, 0xac, struct kvm_one_reg)
/* VM is being stopped by host */
#define KVM_KVMCLOCK_CTRL _IO(KVMIO, 0xad)
+#define KVM_ARM_VCPU_INIT _IOW(KVMIO, 0xae, struct kvm_vcpu_init)
+#define KVM_GET_REG_LIST _IOWR(KVMIO, 0xb0, struct kvm_reg_list)
#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0)
#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [RFC v4 2/8] ARM: KVM: Add support for KVM on ARM architecture
2012-11-20 13:31 [Qemu-devel] [RFC v4 0/8] QEMU: Support KVM on ARM Peter Maydell
2012-11-20 13:31 ` [Qemu-devel] [RFC v4 1/8] linux-headers: Add ARM KVM headers (not for upstream) Peter Maydell
@ 2012-11-20 13:31 ` Peter Maydell
2012-11-20 13:31 ` [Qemu-devel] [RFC v4 3/8] ARM KVM: save and load VFP registers from kernel Peter Maydell
` (5 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Peter Maydell @ 2012-11-20 13:31 UTC (permalink / raw)
To: qemu-devel
Cc: kvm, patches, Marcelo Tosatti, kvmarm, Blue Swirl, Avi Kivity,
Andreas Färber
From: Christoffer Dall <cdall@cs.columbia.edu>
Add basic support for KVM on ARM architecture.
Signed-off-by: Christoffer Dall <cdall@cs.columbia.edu>
[PMM: Minor tweaks and code cleanup, switch to ONE_REG]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
hw/arm_pic.c | 26 ++++
target-arm/Makefile.objs | 1 +
target-arm/cpu.h | 1 +
target-arm/helper.c | 2 +-
target-arm/kvm.c | 327 ++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 356 insertions(+), 1 deletion(-)
create mode 100644 target-arm/kvm.c
diff --git a/hw/arm_pic.c b/hw/arm_pic.c
index ffb4d41..874bbaf 100644
--- a/hw/arm_pic.c
+++ b/hw/arm_pic.c
@@ -9,6 +9,7 @@
#include "hw.h"
#include "arm-misc.h"
+#include "kvm.h"
/* Input 0 is IRQ and input 1 is FIQ. */
static void arm_pic_cpu_handler(void *opaque, int irq, int level)
@@ -34,7 +35,32 @@ static void arm_pic_cpu_handler(void *opaque, int irq, int level)
}
}
+static void kvm_arm_pic_cpu_handler(void *opaque, int irq, int level)
+{
+#ifdef CONFIG_KVM
+ ARMCPU *cpu = opaque;
+ CPUARMState *env = &cpu->env;
+ int kvm_irq = KVM_ARM_IRQ_TYPE_CPU << KVM_ARM_IRQ_TYPE_SHIFT;
+
+ switch (irq) {
+ case ARM_PIC_CPU_IRQ:
+ kvm_irq |= KVM_ARM_IRQ_CPU_IRQ;
+ break;
+ case ARM_PIC_CPU_FIQ:
+ kvm_irq |= KVM_ARM_IRQ_CPU_FIQ;
+ break;
+ default:
+ hw_error("kvm_arm_pic_cpu_handler: Bad interrupt line %d\n", irq);
+ }
+ kvm_irq |= env->cpu_index << KVM_ARM_IRQ_VCPU_SHIFT;
+ kvm_set_irq(kvm_state, kvm_irq, level ? 1 : 0);
+#endif
+}
+
qemu_irq *arm_pic_init_cpu(ARMCPU *cpu)
{
+ if (kvm_enabled()) {
+ return qemu_allocate_irqs(kvm_arm_pic_cpu_handler, cpu, 2);
+ }
return qemu_allocate_irqs(arm_pic_cpu_handler, cpu, 2);
}
diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
index b6f1a9e..d89b57c 100644
--- a/target-arm/Makefile.objs
+++ b/target-arm/Makefile.objs
@@ -1,4 +1,5 @@
obj-y += arm-semi.o
obj-$(CONFIG_SOFTMMU) += machine.o
+obj-$(CONFIG_KVM) += kvm.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/cpu.h b/target-arm/cpu.h
index e4ff918..44b5b4f 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -236,6 +236,7 @@ ARMCPU *cpu_arm_init(const char *cpu_model);
void arm_translate_init(void);
int cpu_arm_exec(CPUARMState *s);
void do_interrupt(CPUARMState *);
+int bank_number(CPUARMState *env, int mode);
void switch_mode(CPUARMState *, int);
uint32_t do_arm_semihosting(CPUARMState *env);
diff --git a/target-arm/helper.c b/target-arm/helper.c
index ab8b734..6760d76 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1614,7 +1614,7 @@ uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode)
#else
/* Map CPU modes onto saved register banks. */
-static inline int bank_number(CPUARMState *env, int mode)
+int bank_number(CPUARMState *env, int mode)
{
switch (mode) {
case ARM_CPU_MODE_USR:
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
new file mode 100644
index 0000000..8e4b989
--- /dev/null
+++ b/target-arm/kvm.c
@@ -0,0 +1,327 @@
+/*
+ * 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 <sys/ioctl.h>
+#include <sys/mman.h>
+
+#include <linux/kvm.h>
+
+#include "qemu-common.h"
+#include "qemu-timer.h"
+#include "sysemu.h"
+#include "kvm.h"
+#include "cpu.h"
+#include "hw/arm-misc.h"
+
+const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+ KVM_CAP_LAST_INFO
+};
+
+int kvm_arch_init(KVMState *s)
+{
+ /* For ARM interrupt delivery is always asynchronous,
+ * whether we are using an in-kernel VGIC or not.
+ */
+ kvm_async_interrupts_allowed = true;
+ return 0;
+}
+
+int kvm_arch_init_vcpu(CPUARMState *env)
+{
+ struct kvm_vcpu_init init;
+
+ init.target = KVM_ARM_TARGET_CORTEX_A15;
+ memset(init.features, 0, sizeof(init.features));
+ return kvm_vcpu_ioctl(env, KVM_ARM_VCPU_INIT, &init);
+}
+
+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 CP15REG(CRN, CRM, OPC1, OPC2, QEMUFIELD) \
+ { \
+ KVM_REG_ARM | KVM_REG_SIZE_U32 | \
+ (15 << KVM_REG_ARM_COPROC_SHIFT) | \
+ ((CRN) << KVM_REG_ARM_32_CRN_SHIFT) | \
+ ((CRM) << KVM_REG_ARM_CRM_SHIFT) | \
+ ((OPC1) << KVM_REG_ARM_OPC1_SHIFT) | \
+ ((OPC2) << KVM_REG_ARM_32_OPC2_SHIFT), \
+ offsetof(CPUARMState, QEMUFIELD) \
+ }
+
+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]),
+ /* A non-comprehensive set of cp15 registers.
+ * TODO: drive this from the cp_regs hashtable instead.
+ */
+ CP15REG(1, 0, 0, 0, cp15.c1_sys), /* SCTLR */
+ CP15REG(2, 0, 0, 2, cp15.c2_control), /* TTBCR */
+ CP15REG(3, 0, 0, 0, cp15.c3), /* DACR */
+};
+
+int kvm_arch_put_registers(CPUARMState *env, int level)
+{
+ struct kvm_one_reg r;
+ int mode, bn;
+ int ret, i;
+ uint32_t cpsr;
+ uint64_t ttbr;
+
+ /* Make sure the banked regs are properly set */
+ mode = env->uncached_cpsr & CPSR_M;
+ bn = bank_number(env, 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(env, 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(env, KVM_SET_ONE_REG, &r);
+ if (ret) {
+ return ret;
+ }
+
+ /* TTBR0: cp15 crm=2 opc1=0 */
+ ttbr = ((uint64_t)env->cp15.c2_base0_hi << 32) | env->cp15.c2_base0;
+ r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | (15 << KVM_REG_ARM_COPROC_SHIFT) |
+ (2 << KVM_REG_ARM_CRM_SHIFT) | (0 << KVM_REG_ARM_OPC1_SHIFT);
+ r.addr = (uintptr_t)(&ttbr);
+ ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, &r);
+ if (ret) {
+ return ret;
+ }
+
+ /* TTBR1: cp15 crm=2 opc1=1 */
+ ttbr = ((uint64_t)env->cp15.c2_base1_hi << 32) | env->cp15.c2_base1;
+ r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | (15 << KVM_REG_ARM_COPROC_SHIFT) |
+ (2 << KVM_REG_ARM_CRM_SHIFT) | (1 << KVM_REG_ARM_OPC1_SHIFT);
+ r.addr = (uintptr_t)(&ttbr);
+ ret = kvm_vcpu_ioctl(env, KVM_SET_ONE_REG, &r);
+
+ return ret;
+}
+
+int kvm_arch_get_registers(CPUARMState *env)
+{
+ struct kvm_one_reg r;
+ int mode, bn;
+ int ret, i;
+ uint32_t cpsr;
+ uint64_t ttbr;
+
+ 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(env, 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(env, KVM_GET_ONE_REG, &r);
+ if (ret) {
+ return ret;
+ }
+ cpsr_write(env, cpsr, 0xffffffff);
+
+ /* TTBR0: cp15 crm=2 opc1=0 */
+ r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | (15 << KVM_REG_ARM_COPROC_SHIFT) |
+ (2 << KVM_REG_ARM_CRM_SHIFT) | (0 << KVM_REG_ARM_OPC1_SHIFT);
+ r.addr = (uintptr_t)(&ttbr);
+ ret = kvm_vcpu_ioctl(env, KVM_GET_ONE_REG, &r);
+ if (ret) {
+ return ret;
+ }
+ env->cp15.c2_base0_hi = ttbr >> 32;
+ env->cp15.c2_base0 = ttbr;
+
+ /* TTBR1: cp15 crm=2 opc1=1 */
+ r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | (15 << KVM_REG_ARM_COPROC_SHIFT) |
+ (2 << KVM_REG_ARM_CRM_SHIFT) | (1 << KVM_REG_ARM_OPC1_SHIFT);
+ r.addr = (uintptr_t)(&ttbr);
+ ret = kvm_vcpu_ioctl(env, KVM_GET_ONE_REG, &r);
+ if (ret) {
+ return ret;
+ }
+ env->cp15.c2_base1_hi = ttbr >> 32;
+ env->cp15.c2_base1 = ttbr;
+
+ /* Make sure the current mode regs are properly set */
+ mode = env->uncached_cpsr & CPSR_M;
+ bn = bank_number(env, 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];
+
+ /* The main GET_ONE_REG loop above set c2_control, but we need to
+ * update some extra cached precomputed values too.
+ * When this is driven from the cp_regs hashtable then this ugliness
+ * can disappear because we'll use the access function which sets
+ * these values automatically.
+ */
+ env->cp15.c2_mask = ~(0xffffffffu >> env->cp15.c2_control);
+ env->cp15.c2_base_mask = ~(0x3fffu >> env->cp15.c2_control);
+
+ return 0;
+}
+
+void kvm_arch_pre_run(CPUARMState *env, struct kvm_run *run)
+{
+}
+
+void kvm_arch_post_run(CPUARMState *env, struct kvm_run *run)
+{
+}
+
+int kvm_arch_handle_exit(CPUARMState *env, struct kvm_run *run)
+{
+ int ret = 0;
+
+ return ret;
+}
+
+void kvm_arch_reset_vcpu(CPUARMState *env)
+{
+}
+
+bool kvm_arch_stop_on_emulation_error(CPUARMState *env)
+{
+ return true;
+}
+
+int kvm_arch_process_async_events(CPUARMState *env)
+{
+ return 0;
+}
+
+int kvm_arch_on_sigbus_vcpu(CPUARMState *env, int code, void *addr)
+{
+ return 1;
+}
+
+int kvm_arch_on_sigbus(int code, void *addr)
+{
+ return 1;
+}
+
+void kvm_arch_update_guest_debug(CPUARMState *env, struct kvm_guest_debug *dbg)
+{
+ qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
+}
+
+int kvm_arch_insert_sw_breakpoint(CPUARMState *env,
+ struct kvm_sw_breakpoint *bp)
+{
+ qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
+ return -EINVAL;
+}
+
+int kvm_arch_insert_hw_breakpoint(target_ulong addr,
+ target_ulong len, int type)
+{
+ qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
+ return -EINVAL;
+}
+
+int kvm_arch_remove_hw_breakpoint(target_ulong addr,
+ target_ulong len, int type)
+{
+ qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
+ return -EINVAL;
+}
+
+int kvm_arch_remove_sw_breakpoint(CPUARMState *env,
+ struct kvm_sw_breakpoint *bp)
+{
+ qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
+ return -EINVAL;
+}
+
+void kvm_arch_remove_all_hw_breakpoints(void)
+{
+ qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
+}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [RFC v4 3/8] ARM KVM: save and load VFP registers from kernel
2012-11-20 13:31 [Qemu-devel] [RFC v4 0/8] QEMU: Support KVM on ARM Peter Maydell
2012-11-20 13:31 ` [Qemu-devel] [RFC v4 1/8] linux-headers: Add ARM KVM headers (not for upstream) Peter Maydell
2012-11-20 13:31 ` [Qemu-devel] [RFC v4 2/8] ARM: KVM: Add support for KVM on ARM architecture Peter Maydell
@ 2012-11-20 13:31 ` Peter Maydell
2012-11-20 13:31 ` [Qemu-devel] [RFC v4 4/8] hw/arm_gic: Add presave/postload hooks Peter Maydell
` (4 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Peter Maydell @ 2012-11-20 13:31 UTC (permalink / raw)
To: qemu-devel
Cc: kvm, patches, Marcelo Tosatti, kvmarm, Blue Swirl, Avi Kivity,
Andreas Färber
Add support for saving and restoring VFP register state from the
kernel. This includes a check that the KVM-created CPU has full
VFP support (as the TCG Cortex-A15 model always does), since for
the moment ARM QEMU doesn't have any way to tweak optional features
on created CPUs.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target-arm/kvm.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 75 insertions(+), 3 deletions(-)
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index 8e4b989..4217ad6 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -38,10 +38,28 @@ int kvm_arch_init(KVMState *s)
int kvm_arch_init_vcpu(CPUARMState *env)
{
struct kvm_vcpu_init init;
+ int ret;
+ uint64_t v;
+ struct kvm_one_reg r;
init.target = KVM_ARM_TARGET_CORTEX_A15;
memset(init.features, 0, sizeof(init.features));
- return kvm_vcpu_ioctl(env, KVM_ARM_VCPU_INIT, &init);
+ ret = kvm_vcpu_ioctl(env, 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(env, KVM_GET_ONE_REG, &r);
+ if (ret == ENOENT) {
+ return EINVAL;
+ }
+ return ret;
}
typedef struct Reg {
@@ -67,6 +85,13 @@ typedef struct Reg {
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]),
@@ -114,6 +139,13 @@ static const Reg regs[] = {
CP15REG(1, 0, 0, 0, cp15.c1_sys), /* SCTLR */
CP15REG(2, 0, 0, 2, cp15.c2_control), /* TTBCR */
CP15REG(3, 0, 0, 0, cp15.c3), /* DACR */
+ /* VFP system registers */
+ VFPSYSREG(FPSID),
+ VFPSYSREG(MVFR1),
+ VFPSYSREG(MVFR0),
+ VFPSYSREG(FPEXC),
+ VFPSYSREG(FPINST),
+ VFPSYSREG(FPINST2),
};
int kvm_arch_put_registers(CPUARMState *env, int level)
@@ -121,7 +153,7 @@ int kvm_arch_put_registers(CPUARMState *env, int level)
struct kvm_one_reg r;
int mode, bn;
int ret, i;
- uint32_t cpsr;
+ uint32_t cpsr, fpscr;
uint64_t ttbr;
/* Make sure the banked regs are properly set */
@@ -172,6 +204,26 @@ int kvm_arch_put_registers(CPUARMState *env, int level)
(2 << KVM_REG_ARM_CRM_SHIFT) | (1 << KVM_REG_ARM_OPC1_SHIFT);
r.addr = (uintptr_t)(&ttbr);
ret = kvm_vcpu_ioctl(env, 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(env, 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(env, KVM_SET_ONE_REG, &r);
return ret;
}
@@ -181,7 +233,7 @@ int kvm_arch_get_registers(CPUARMState *env)
struct kvm_one_reg r;
int mode, bn;
int ret, i;
- uint32_t cpsr;
+ uint32_t cpsr, fpscr;
uint64_t ttbr;
for (i = 0; i < ARRAY_SIZE(regs); i++) {
@@ -246,6 +298,26 @@ int kvm_arch_get_registers(CPUARMState *env)
env->cp15.c2_mask = ~(0xffffffffu >> env->cp15.c2_control);
env->cp15.c2_base_mask = ~(0x3fffu >> env->cp15.c2_control);
+ /* 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(env, 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(env, KVM_GET_ONE_REG, &r);
+ if (ret) {
+ return ret;
+ }
+ vfp_set_fpscr(env, fpscr);
+
return 0;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [RFC v4 4/8] hw/arm_gic: Add presave/postload hooks
2012-11-20 13:31 [Qemu-devel] [RFC v4 0/8] QEMU: Support KVM on ARM Peter Maydell
` (2 preceding siblings ...)
2012-11-20 13:31 ` [Qemu-devel] [RFC v4 3/8] ARM KVM: save and load VFP registers from kernel Peter Maydell
@ 2012-11-20 13:31 ` Peter Maydell
2012-11-20 13:31 ` [Qemu-devel] [RFC v4 5/8] target-arm: Use MemoryListener to identify GIC base address for KVM Peter Maydell
` (3 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Peter Maydell @ 2012-11-20 13:31 UTC (permalink / raw)
To: qemu-devel
Cc: kvm, patches, Marcelo Tosatti, kvmarm, Blue Swirl, Avi Kivity,
Andreas Färber
Add presave/postload hooks to the ARM GIC common base class.
These will be used by the KVM in-kernel GIC subclass to sync
state between kernel and userspace when migrating.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Andreas Färber <afaerber@suse.de>
---
hw/arm_gic_common.c | 10 ++++++++++
hw/arm_gic_internal.h | 2 ++
2 files changed, 12 insertions(+)
diff --git a/hw/arm_gic_common.c b/hw/arm_gic_common.c
index 8369309..961b44c 100644
--- a/hw/arm_gic_common.c
+++ b/hw/arm_gic_common.c
@@ -23,9 +23,14 @@
static void gic_save(QEMUFile *f, void *opaque)
{
GICState *s = (GICState *)opaque;
+ ARMGICCommonClass *c = ARM_GIC_COMMON_GET_CLASS(s);
int i;
int j;
+ if (c->pre_save) {
+ c->pre_save(s);
+ }
+
qemu_put_be32(f, s->enabled);
for (i = 0; i < s->num_cpu; i++) {
qemu_put_be32(f, s->cpu_enabled[i]);
@@ -57,6 +62,7 @@ static void gic_save(QEMUFile *f, void *opaque)
static int gic_load(QEMUFile *f, void *opaque, int version_id)
{
GICState *s = (GICState *)opaque;
+ ARMGICCommonClass *c = ARM_GIC_COMMON_GET_CLASS(s);
int i;
int j;
@@ -91,6 +97,10 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
s->irq_state[i].trigger = qemu_get_byte(f);
}
+ if (c->post_load) {
+ c->post_load(s);
+ }
+
return 0;
}
diff --git a/hw/arm_gic_internal.h b/hw/arm_gic_internal.h
index 699352c..3640be0 100644
--- a/hw/arm_gic_internal.h
+++ b/hw/arm_gic_internal.h
@@ -118,6 +118,8 @@ void gic_init_irqs_and_distributor(GICState *s, int num_irq);
typedef struct ARMGICCommonClass {
SysBusDeviceClass parent_class;
+ void (*pre_save)(GICState *s);
+ void (*post_load)(GICState *s);
} ARMGICCommonClass;
#define TYPE_ARM_GIC "arm_gic"
--
1.7.9.5
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [RFC v4 5/8] target-arm: Use MemoryListener to identify GIC base address for KVM
2012-11-20 13:31 [Qemu-devel] [RFC v4 0/8] QEMU: Support KVM on ARM Peter Maydell
` (3 preceding siblings ...)
2012-11-20 13:31 ` [Qemu-devel] [RFC v4 4/8] hw/arm_gic: Add presave/postload hooks Peter Maydell
@ 2012-11-20 13:31 ` Peter Maydell
2012-11-20 13:31 ` [Qemu-devel] [RFC v4 6/8] hw/kvm/arm_gic: Implement support for KVM in-kernel ARM GIC Peter Maydell
` (2 subsequent siblings)
7 siblings, 0 replies; 13+ messages in thread
From: Peter Maydell @ 2012-11-20 13:31 UTC (permalink / raw)
To: qemu-devel
Cc: kvm, patches, Marcelo Tosatti, kvmarm, Blue Swirl, Avi Kivity,
Andreas Färber
When using an in-kernel GIC with KVM, we need to tell the kernel where
the GIC's memory mapped registers live. Do this by registering a
MemoryListener which tracks where the board model maps the A15's
private peripherals, so we can finish the GIC initialisation
when the GIC is actually mapped.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target-arm/kvm.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++
target-arm/kvm_arm.h | 32 +++++++++++++++++++
2 files changed, 115 insertions(+)
create mode 100644 target-arm/kvm_arm.h
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
index 4217ad6..ff3007b 100644
--- a/target-arm/kvm.c
+++ b/target-arm/kvm.c
@@ -19,6 +19,7 @@
#include "qemu-timer.h"
#include "sysemu.h"
#include "kvm.h"
+#include "kvm_arm.h"
#include "cpu.h"
#include "hw/arm-misc.h"
@@ -62,6 +63,88 @@ int kvm_arch_init_vcpu(CPUARMState *env)
return ret;
}
+/* We track all the KVM devices which need their memory addresses
+ * passing to the kernel in a list of these structures.
+ * When board init is complete we run through the list and
+ * tell the kernel the base addresses of the memory regions.
+ * We use a MemoryListener to track mapping and unmapping of
+ * the regions during board creation, so the board models don't
+ * need to do anything special for the KVM case.
+ */
+typedef struct KVMDevice {
+ struct kvm_device_address kda;
+ MemoryRegion *mr;
+ QSLIST_ENTRY(KVMDevice) entries;
+} KVMDevice;
+
+static QSLIST_HEAD(kvm_devices_head, KVMDevice) kvm_devices_head;
+
+static void kvm_arm_devlistener_add(MemoryListener *listener,
+ MemoryRegionSection *section)
+{
+ KVMDevice *kd;
+ QSLIST_FOREACH(kd, &kvm_devices_head, entries) {
+ if (section->mr == kd->mr) {
+ kd->kda.addr = section->offset_within_address_space;
+ }
+ }
+}
+
+static void kvm_arm_devlistener_del(MemoryListener *listener,
+ MemoryRegionSection *section)
+{
+ KVMDevice *kd;
+ QSLIST_FOREACH(kd, &kvm_devices_head, entries) {
+ if (section->mr == kd->mr) {
+ kd->kda.addr = -1;
+ }
+ }
+}
+
+static MemoryListener devlistener = {
+ .region_add = kvm_arm_devlistener_add,
+ .region_del = kvm_arm_devlistener_del,
+};
+
+static void kvm_arm_machine_init_done(Notifier *notifier, void *data)
+{
+ KVMDevice *kd, *tkd;
+ memory_listener_unregister(&devlistener);
+ QSLIST_FOREACH_SAFE(kd, &kvm_devices_head, entries, tkd) {
+ if (kd->kda.addr != -1) {
+ if (kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ADDRESS, &kd->kda) < 0) {
+ fprintf(stderr, "KVM_SET_DEVICE_ADDRESS failed: %s\n",
+ strerror(errno));
+ abort();
+ }
+ }
+ g_free(kd);
+ }
+}
+
+static Notifier notify = {
+ .notify = kvm_arm_machine_init_done,
+};
+
+void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid)
+{
+ KVMDevice *kd;
+
+ if (!kvm_irqchip_in_kernel()) {
+ return;
+ }
+
+ if (QSLIST_EMPTY(&kvm_devices_head)) {
+ memory_listener_register(&devlistener, NULL);
+ qemu_add_machine_init_done_notifier(¬ify);
+ }
+ kd = g_new0(KVMDevice, 1);
+ kd->mr = mr;
+ kd->kda.id = devid;
+ kd->kda.addr = -1;
+ QSLIST_INSERT_HEAD(&kvm_devices_head, kd, entries);
+}
+
typedef struct Reg {
uint64_t id;
int offset;
diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h
new file mode 100644
index 0000000..2f61d00
--- /dev/null
+++ b/target-arm/kvm_arm.h
@@ -0,0 +1,32 @@
+/*
+ * QEMU KVM support -- ARM specific functions.
+ *
+ * Copyright (c) 2012 Linaro Limited
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef QEMU_KVM_ARM_H
+#define QEMU_KVM_ARM_H
+
+#include "kvm.h"
+#include "memory.h"
+
+/**
+ * kvm_arm_register_device:
+ * @mr: memory region for this device
+ * @devid: the KVM device ID
+ *
+ * Remember the memory region @mr, and when it is mapped by the
+ * machine model, tell the kernel that base address using the
+ * KVM_SET_DEVICE_ADDRESS ioctl. @devid should be the ID of
+ * the device as defined by KVM_SET_DEVICE_ADDRESS.
+ * The machine model may map and unmap the device multiple times;
+ * the kernel will only be told the final address at the point
+ * where machine init is complete.
+ */
+void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid);
+
+#endif
--
1.7.9.5
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [RFC v4 6/8] hw/kvm/arm_gic: Implement support for KVM in-kernel ARM GIC
2012-11-20 13:31 [Qemu-devel] [RFC v4 0/8] QEMU: Support KVM on ARM Peter Maydell
` (4 preceding siblings ...)
2012-11-20 13:31 ` [Qemu-devel] [RFC v4 5/8] target-arm: Use MemoryListener to identify GIC base address for KVM Peter Maydell
@ 2012-11-20 13:31 ` Peter Maydell
2012-11-20 13:31 ` [Qemu-devel] [RFC v4 7/8] configure: Enable KVM on ARM Peter Maydell
2012-11-20 13:31 ` [Qemu-devel] [RFC v4 8/8] oslib-posix: Align to permit transparent hugepages on ARM Linux Peter Maydell
7 siblings, 0 replies; 13+ messages in thread
From: Peter Maydell @ 2012-11-20 13:31 UTC (permalink / raw)
To: qemu-devel
Cc: kvm, patches, Marcelo Tosatti, kvmarm, Blue Swirl, Avi Kivity,
Andreas Färber
Implement support for using the KVM in-kernel GIC for ARM.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
hw/a15mpcore.c | 8 ++-
hw/arm/Makefile.objs | 1 +
hw/kvm/arm_gic.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 177 insertions(+), 1 deletion(-)
create mode 100644 hw/kvm/arm_gic.c
diff --git a/hw/a15mpcore.c b/hw/a15mpcore.c
index fc0a02a..31158f9 100644
--- a/hw/a15mpcore.c
+++ b/hw/a15mpcore.c
@@ -19,6 +19,7 @@
*/
#include "sysbus.h"
+#include "kvm.h"
/* A15MP private memory region. */
@@ -40,8 +41,13 @@ static int a15mp_priv_init(SysBusDevice *dev)
{
A15MPPrivState *s = FROM_SYSBUS(A15MPPrivState, dev);
SysBusDevice *busdev;
+ const char *gictype = "arm-gic";
- s->gic = qdev_create(NULL, "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);
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 6d049e7..38b10a8 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -31,5 +31,6 @@ obj-y += collie.o
obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
obj-y += kzm.o
obj-$(CONFIG_FDT) += ../device_tree.o
+obj-$(CONFIG_KVM) += kvm/arm_gic.o
obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/kvm/arm_gic.c b/hw/kvm/arm_gic.c
new file mode 100644
index 0000000..0ad1b8b
--- /dev/null
+++ b/hw/kvm/arm_gic.c
@@ -0,0 +1,169 @@
+/*
+ * ARM Generic Interrupt Controller using KVM in-kernel support
+ *
+ * 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 "kvm.h"
+#include "kvm_arm.h"
+#include "hw/arm_gic_internal.h"
+
+#define TYPE_KVM_ARM_GIC "kvm-arm-gic"
+#define KVM_ARM_GIC(obj) \
+ OBJECT_CHECK(GICState, (obj), TYPE_KVM_ARM_GIC)
+#define KVM_ARM_GIC_CLASS(klass) \
+ OBJECT_CLASS_CHECK(KVMARMGICClass, (klass), TYPE_KVM_ARM_GIC)
+#define KVM_ARM_GIC_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(KVMARMGICClass, (obj), TYPE_KVM_ARM_GIC)
+
+typedef struct KVMARMGICClass {
+ ARMGICCommonClass parent_class;
+ int (*parent_init)(SysBusDevice *dev);
+ void (*parent_reset)(DeviceState *dev);
+} KVMARMGICClass;
+
+static void kvm_arm_gic_set_irq(void *opaque, int irq, int level)
+{
+ /* Meaning of the 'irq' parameter:
+ * [0..N-1] : external interrupts
+ * [N..N+31] : PPI (internal) interrupts for CPU 0
+ * [N+32..N+63] : PPI (internal interrupts for CPU 1
+ * ...
+ * Convert this to the kernel's desired encoding, which
+ * has separate fields in the irq number for type,
+ * CPU number and interrupt number.
+ */
+ GICState *s = (GICState *)opaque;
+ int kvm_irq, irqtype, cpu;
+
+ if (irq < (s->num_irq - GIC_INTERNAL)) {
+ /* External interrupt. The kernel numbers these like the GIC
+ * hardware, with external interrupt IDs starting after the
+ * internal ones.
+ */
+ irqtype = KVM_ARM_IRQ_TYPE_SPI;
+ cpu = 0;
+ irq += GIC_INTERNAL;
+ } else {
+ /* Internal interrupt: decode into (cpu, interrupt id) */
+ irqtype = KVM_ARM_IRQ_TYPE_PPI;
+ irq -= (s->num_irq - GIC_INTERNAL);
+ cpu = irq / GIC_INTERNAL;
+ irq %= GIC_INTERNAL;
+ }
+ kvm_irq = (irqtype << KVM_ARM_IRQ_TYPE_SHIFT)
+ | (cpu << KVM_ARM_IRQ_VCPU_SHIFT) | irq;
+
+ kvm_set_irq(kvm_state, kvm_irq, !!level);
+}
+
+static void kvm_arm_gic_put(GICState *s)
+{
+ /* TODO: there isn't currently a kernel interface to set the GIC state */
+}
+
+static void kvm_arm_gic_get(GICState *s)
+{
+ /* TODO: there isn't currently a kernel interface to get the GIC state */
+}
+
+static void kvm_arm_gic_reset(DeviceState *dev)
+{
+ GICState *s = ARM_GIC_COMMON(dev);
+ KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
+ kgc->parent_reset(dev);
+ kvm_arm_gic_put(s);
+}
+
+static int kvm_arm_gic_init(SysBusDevice *dev)
+{
+ /* Device instance init function for the GIC sysbus device */
+ int i;
+ GICState *s = FROM_SYSBUS(GICState, dev);
+ KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
+
+ kgc->parent_init(dev);
+
+ i = s->num_irq - GIC_INTERNAL;
+ /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
+ * GPIO array layout is thus:
+ * [0..N-1] SPIs
+ * [N..N+31] PPIs for CPU 0
+ * [N+32..N+63] PPIs for CPU 1
+ * ...
+ */
+ i += (GIC_INTERNAL * s->num_cpu);
+ qdev_init_gpio_in(&s->busdev.qdev, kvm_arm_gic_set_irq, i);
+ /* We never use our outbound IRQ lines but provide them so that
+ * we maintain the same interface as the non-KVM GIC.
+ */
+ for (i = 0; i < s->num_cpu; i++) {
+ sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
+ }
+ /* Distributor */
+ memory_region_init_reservation(&s->iomem, "kvm-gic_dist", 0x1000);
+ sysbus_init_mmio(dev, &s->iomem);
+ kvm_arm_register_device(&s->iomem,
+ (KVM_ARM_DEVICE_VGIC_V2 << KVM_DEVICE_ID_SHIFT) |
+ KVM_VGIC_V2_ADDR_TYPE_DIST);
+ /* CPU interface for current core. Unlike arm_gic, we don't
+ * provide the "interface for core #N" memory regions, because
+ * cores with a VGIC don't have those.
+ */
+ memory_region_init_reservation(&s->cpuiomem[0], "kvm-gic_cpu", 0x1000);
+ sysbus_init_mmio(dev, &s->cpuiomem[0]);
+ kvm_arm_register_device(&s->cpuiomem[0],
+ (KVM_ARM_DEVICE_VGIC_V2 << KVM_DEVICE_ID_SHIFT) |
+ KVM_VGIC_V2_ADDR_TYPE_CPU);
+ /* TODO: we should tell the kernel at some point the address
+ * of the private peripheral base. However we don't currently have
+ * any convenient infrastructure to do that, and in any case the
+ * kernel doesn't yet implement an ioctl to let us tell it.
+ */
+ return 0;
+}
+
+static void kvm_arm_gic_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
+ ARMGICCommonClass *agcc = ARM_GIC_COMMON_CLASS(klass);
+ KVMARMGICClass *kgc = KVM_ARM_GIC_CLASS(klass);
+ agcc->pre_save = kvm_arm_gic_get;
+ agcc->post_load = kvm_arm_gic_put;
+ kgc->parent_init = sbc->init;
+ kgc->parent_reset = dc->reset;
+ sbc->init = kvm_arm_gic_init;
+ dc->reset = kvm_arm_gic_reset;
+ dc->no_user = 1;
+}
+
+static const TypeInfo kvm_arm_gic_info = {
+ .name = TYPE_KVM_ARM_GIC,
+ .parent = TYPE_ARM_GIC_COMMON,
+ .instance_size = sizeof(GICState),
+ .class_init = kvm_arm_gic_class_init,
+ .class_size = sizeof(KVMARMGICClass),
+};
+
+static void kvm_arm_gic_register_types(void)
+{
+ type_register_static(&kvm_arm_gic_info);
+}
+
+type_init(kvm_arm_gic_register_types)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [RFC v4 7/8] configure: Enable KVM on ARM
2012-11-20 13:31 [Qemu-devel] [RFC v4 0/8] QEMU: Support KVM on ARM Peter Maydell
` (5 preceding siblings ...)
2012-11-20 13:31 ` [Qemu-devel] [RFC v4 6/8] hw/kvm/arm_gic: Implement support for KVM in-kernel ARM GIC Peter Maydell
@ 2012-11-20 13:31 ` Peter Maydell
2012-11-20 13:31 ` [Qemu-devel] [RFC v4 8/8] oslib-posix: Align to permit transparent hugepages on ARM Linux Peter Maydell
7 siblings, 0 replies; 13+ messages in thread
From: Peter Maydell @ 2012-11-20 13:31 UTC (permalink / raw)
To: qemu-devel
Cc: kvm, patches, Marcelo Tosatti, kvmarm, Blue Swirl, Avi Kivity,
Andreas Färber
Enable KVM on ARM hosts, now that all the necessary components
for it exist.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
configure | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/configure b/configure
index 780b19a..2438d6d 100755
--- a/configure
+++ b/configure
@@ -3927,7 +3927,7 @@ case "$target_arch2" in
echo "CONFIG_NO_XEN=y" >> $config_target_mak
esac
case "$target_arch2" in
- i386|x86_64|ppcemb|ppc|ppc64|s390x)
+ arm|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_arch2" = "$cpu" -o \
--
1.7.9.5
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [RFC v4 8/8] oslib-posix: Align to permit transparent hugepages on ARM Linux
2012-11-20 13:31 [Qemu-devel] [RFC v4 0/8] QEMU: Support KVM on ARM Peter Maydell
` (6 preceding siblings ...)
2012-11-20 13:31 ` [Qemu-devel] [RFC v4 7/8] configure: Enable KVM on ARM Peter Maydell
@ 2012-11-20 13:31 ` Peter Maydell
2012-11-20 13:54 ` [Qemu-devel] [kvmarm] " Alexander Graf
7 siblings, 1 reply; 13+ messages in thread
From: Peter Maydell @ 2012-11-20 13:31 UTC (permalink / raw)
To: qemu-devel
Cc: kvm, patches, Marcelo Tosatti, kvmarm, Blue Swirl, Avi Kivity,
Andreas Färber
ARM Linux (like x86-64 Linux) can use transparent hugepages for
KVM if memory blocks are 2MiB aligned; set QEMU_VMALLOC_ALIGN
accordingly.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
oslib-posix.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/oslib-posix.c b/oslib-posix.c
index 9db9c3d..d25b52a 100644
--- a/oslib-posix.c
+++ b/oslib-posix.c
@@ -35,7 +35,7 @@
extern int daemon(int, int);
#endif
-#if defined(__linux__) && defined(__x86_64__)
+#if defined(__linux__) && (defined(__x86_64__) || defined(__arm__))
/* Use 2 MiB alignment so transparent hugepages can be used by KVM.
Valgrind does not support alignments larger than 1 MiB,
therefore we need special code which handles running on Valgrind. */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [kvmarm] [RFC v4 8/8] oslib-posix: Align to permit transparent hugepages on ARM Linux
2012-11-20 13:31 ` [Qemu-devel] [RFC v4 8/8] oslib-posix: Align to permit transparent hugepages on ARM Linux Peter Maydell
@ 2012-11-20 13:54 ` Alexander Graf
2012-11-20 13:55 ` Christoffer Dall
0 siblings, 1 reply; 13+ messages in thread
From: Alexander Graf @ 2012-11-20 13:54 UTC (permalink / raw)
To: Peter Maydell
Cc: kvm, patches, Marcelo Tosatti, qemu-devel, Andreas Färber,
Blue Swirl, kvmarm
On 11/20/2012 02:31 PM, Peter Maydell wrote:
> ARM Linux (like x86-64 Linux) can use transparent hugepages for
> KVM if memory blocks are 2MiB aligned; set QEMU_VMALLOC_ALIGN
> accordingly.
>
> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
> ---
> oslib-posix.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/oslib-posix.c b/oslib-posix.c
> index 9db9c3d..d25b52a 100644
> --- a/oslib-posix.c
> +++ b/oslib-posix.c
> @@ -35,7 +35,7 @@
> extern int daemon(int, int);
> #endif
>
> -#if defined(__linux__)&& defined(__x86_64__)
> +#if defined(__linux__)&& (defined(__x86_64__) || defined(__arm__))
Why not just drop the arch specific bit?
Alex
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [kvmarm] [RFC v4 8/8] oslib-posix: Align to permit transparent hugepages on ARM Linux
2012-11-20 13:54 ` [Qemu-devel] [kvmarm] " Alexander Graf
@ 2012-11-20 13:55 ` Christoffer Dall
2012-11-20 14:37 ` Alexander Graf
0 siblings, 1 reply; 13+ messages in thread
From: Christoffer Dall @ 2012-11-20 13:55 UTC (permalink / raw)
To: Alexander Graf
Cc: Peter Maydell, kvm, patches, Marcelo Tosatti, qemu-devel,
Andreas Färber, Blue Swirl, kvmarm
On Tue, Nov 20, 2012 at 8:54 AM, Alexander Graf <agraf@suse.de> wrote:
> On 11/20/2012 02:31 PM, Peter Maydell wrote:
>>
>> ARM Linux (like x86-64 Linux) can use transparent hugepages for
>> KVM if memory blocks are 2MiB aligned; set QEMU_VMALLOC_ALIGN
>> accordingly.
>>
>> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
>> ---
>> oslib-posix.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/oslib-posix.c b/oslib-posix.c
>> index 9db9c3d..d25b52a 100644
>> --- a/oslib-posix.c
>> +++ b/oslib-posix.c
>> @@ -35,7 +35,7 @@
>> extern int daemon(int, int);
>> #endif
>>
>> -#if defined(__linux__)&& defined(__x86_64__)
>> +#if defined(__linux__)&& (defined(__x86_64__) || defined(__arm__))
>
>
> Why not just drop the arch specific bit?
>
>
other archs have other alignment requirements, iirc.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [kvmarm] [RFC v4 8/8] oslib-posix: Align to permit transparent hugepages on ARM Linux
2012-11-20 13:55 ` Christoffer Dall
@ 2012-11-20 14:37 ` Alexander Graf
2012-11-20 14:48 ` Peter Maydell
0 siblings, 1 reply; 13+ messages in thread
From: Alexander Graf @ 2012-11-20 14:37 UTC (permalink / raw)
To: Christoffer Dall
Cc: Peter Maydell, kvm, patches, Marcelo Tosatti, qemu-devel,
Andreas Färber, Blue Swirl, kvmarm
On 11/20/2012 02:55 PM, Christoffer Dall wrote:
> On Tue, Nov 20, 2012 at 8:54 AM, Alexander Graf<agraf@suse.de> wrote:
>> On 11/20/2012 02:31 PM, Peter Maydell wrote:
>>> ARM Linux (like x86-64 Linux) can use transparent hugepages for
>>> KVM if memory blocks are 2MiB aligned; set QEMU_VMALLOC_ALIGN
>>> accordingly.
>>>
>>> Signed-off-by: Peter Maydell<peter.maydell@linaro.org>
>>> ---
>>> oslib-posix.c | 2 +-
>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/oslib-posix.c b/oslib-posix.c
>>> index 9db9c3d..d25b52a 100644
>>> --- a/oslib-posix.c
>>> +++ b/oslib-posix.c
>>> @@ -35,7 +35,7 @@
>>> extern int daemon(int, int);
>>> #endif
>>>
>>> -#if defined(__linux__)&& defined(__x86_64__)
>>> +#if defined(__linux__)&& (defined(__x86_64__) || defined(__arm__))
>>
>> Why not just drop the arch specific bit?
>>
>>
> other archs have other alignment requirements, iirc.
Ah, sorry, missed the rest of the lines around this one :). Yeah, should
be ok then.
Alex
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [kvmarm] [RFC v4 8/8] oslib-posix: Align to permit transparent hugepages on ARM Linux
2012-11-20 14:37 ` Alexander Graf
@ 2012-11-20 14:48 ` Peter Maydell
0 siblings, 0 replies; 13+ messages in thread
From: Peter Maydell @ 2012-11-20 14:48 UTC (permalink / raw)
To: Alexander Graf
Cc: Christoffer Dall, kvm, patches, Marcelo Tosatti, qemu-devel,
Andreas Färber, Blue Swirl, kvmarm
On 20 November 2012 14:37, Alexander Graf <agraf@suse.de> wrote:
> On 11/20/2012 02:55 PM, Christoffer Dall wrote:
>> On Tue, Nov 20, 2012 at 8:54 AM, Alexander Graf<agraf@suse.de> wrote:
>>> On 11/20/2012 02:31 PM, Peter Maydell wrote:
>>>> ARM Linux (like x86-64 Linux) can use transparent hugepages for
>>>> KVM if memory blocks are 2MiB aligned; set QEMU_VMALLOC_ALIGN
>>>> accordingly.
>>>> -#if defined(__linux__)&& defined(__x86_64__)
>>>> +#if defined(__linux__)&& (defined(__x86_64__) || defined(__arm__))
>>>
>>>
>>> Why not just drop the arch specific bit?
>> other archs have other alignment requirements, iirc.
>
> Ah, sorry, missed the rest of the lines around this one :).
> Yeah, should be ok then.
Yeah. Ideally the kernel would provide a mechanism so we can
ask at runtime what the preferred alignment is. (Or it could
just automatically provide it for suitably large allocations.)
In the absence of that this is just following along with the
current style.
-- PMM
^ permalink raw reply [flat|nested] 13+ messages in thread