aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorChristoffer Dall <c.dall@virtualopensystems.com>2013-01-20 18:28:06 -0500
committerChristoffer Dall <c.dall@virtualopensystems.com>2013-01-23 13:29:10 -0500
commit749cf76c5a363e1383108a914ea09530bfa0bd43 (patch)
treea1bd85e41d1a8e6eb13529681431c3aea641d202 /arch
parent9e9a367c29cebd25a356d53414612e115efdadcf (diff)
KVM: ARM: Initial skeleton to compile KVM support
Targets KVM support for Cortex A-15 processors. Contains all the framework components, make files, header files, some tracing functionality, and basic user space API. Only supported core is Cortex-A15 for now. Most functionality is in arch/arm/kvm/* or arch/arm/include/asm/kvm_*.h. Reviewed-by: Will Deacon <will.deacon@arm.com> Reviewed-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig2
-rw-r--r--arch/arm/Makefile1
-rw-r--r--arch/arm/include/asm/kvm_arm.h24
-rw-r--r--arch/arm/include/asm/kvm_asm.h58
-rw-r--r--arch/arm/include/asm/kvm_coproc.h24
-rw-r--r--arch/arm/include/asm/kvm_emulate.h50
-rw-r--r--arch/arm/include/asm/kvm_host.h114
-rw-r--r--arch/arm/include/uapi/asm/kvm.h106
-rw-r--r--arch/arm/kvm/Kconfig55
-rw-r--r--arch/arm/kvm/Makefile21
-rw-r--r--arch/arm/kvm/arm.c350
-rw-r--r--arch/arm/kvm/coproc.c23
-rw-r--r--arch/arm/kvm/emulate.c155
-rw-r--r--arch/arm/kvm/guest.c221
-rw-r--r--arch/arm/kvm/init.S19
-rw-r--r--arch/arm/kvm/interrupts.S19
-rw-r--r--arch/arm/kvm/mmu.c17
-rw-r--r--arch/arm/kvm/reset.c74
-rw-r--r--arch/arm/kvm/trace.h52
19 files changed, 1385 insertions, 0 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 67874b82a4ed..e0627cdbcda5 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2322,3 +2322,5 @@ source "security/Kconfig"
2322source "crypto/Kconfig" 2322source "crypto/Kconfig"
2323 2323
2324source "lib/Kconfig" 2324source "lib/Kconfig"
2325
2326source "arch/arm/kvm/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 30c443c406f3..4bcd2d6b0535 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -252,6 +252,7 @@ core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/
252core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ) 252core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ)
253core-$(CONFIG_VFP) += arch/arm/vfp/ 253core-$(CONFIG_VFP) += arch/arm/vfp/
254core-$(CONFIG_XEN) += arch/arm/xen/ 254core-$(CONFIG_XEN) += arch/arm/xen/
255core-$(CONFIG_KVM_ARM_HOST) += arch/arm/kvm/
255 256
256# If we have a machine-specific directory, then include it in the build. 257# If we have a machine-specific directory, then include it in the build.
257core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ 258core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
new file mode 100644
index 000000000000..dc678e193417
--- /dev/null
+++ b/arch/arm/include/asm/kvm_arm.h
@@ -0,0 +1,24 @@
1/*
2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
3 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19#ifndef __ARM_KVM_ARM_H__
20#define __ARM_KVM_ARM_H__
21
22#include <linux/types.h>
23
24#endif /* __ARM_KVM_ARM_H__ */
diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
new file mode 100644
index 000000000000..f9993e5fb695
--- /dev/null
+++ b/arch/arm/include/asm/kvm_asm.h
@@ -0,0 +1,58 @@
1/*
2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
3 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19#ifndef __ARM_KVM_ASM_H__
20#define __ARM_KVM_ASM_H__
21
22/* 0 is reserved as an invalid value. */
23#define c0_MPIDR 1 /* MultiProcessor ID Register */
24#define c0_CSSELR 2 /* Cache Size Selection Register */
25#define c1_SCTLR 3 /* System Control Register */
26#define c1_ACTLR 4 /* Auxilliary Control Register */
27#define c1_CPACR 5 /* Coprocessor Access Control */
28#define c2_TTBR0 6 /* Translation Table Base Register 0 */
29#define c2_TTBR0_high 7 /* TTBR0 top 32 bits */
30#define c2_TTBR1 8 /* Translation Table Base Register 1 */
31#define c2_TTBR1_high 9 /* TTBR1 top 32 bits */
32#define c2_TTBCR 10 /* Translation Table Base Control R. */
33#define c3_DACR 11 /* Domain Access Control Register */
34#define c5_DFSR 12 /* Data Fault Status Register */
35#define c5_IFSR 13 /* Instruction Fault Status Register */
36#define c5_ADFSR 14 /* Auxilary Data Fault Status R */
37#define c5_AIFSR 15 /* Auxilary Instrunction Fault Status R */
38#define c6_DFAR 16 /* Data Fault Address Register */
39#define c6_IFAR 17 /* Instruction Fault Address Register */
40#define c9_L2CTLR 18 /* Cortex A15 L2 Control Register */
41#define c10_PRRR 19 /* Primary Region Remap Register */
42#define c10_NMRR 20 /* Normal Memory Remap Register */
43#define c12_VBAR 21 /* Vector Base Address Register */
44#define c13_CID 22 /* Context ID Register */
45#define c13_TID_URW 23 /* Thread ID, User R/W */
46#define c13_TID_URO 24 /* Thread ID, User R/O */
47#define c13_TID_PRIV 25 /* Thread ID, Privileged */
48#define NR_CP15_REGS 26 /* Number of regs (incl. invalid) */
49
50#define ARM_EXCEPTION_RESET 0
51#define ARM_EXCEPTION_UNDEFINED 1
52#define ARM_EXCEPTION_SOFTWARE 2
53#define ARM_EXCEPTION_PREF_ABORT 3
54#define ARM_EXCEPTION_DATA_ABORT 4
55#define ARM_EXCEPTION_IRQ 5
56#define ARM_EXCEPTION_FIQ 6
57
58#endif /* __ARM_KVM_ASM_H__ */
diff --git a/arch/arm/include/asm/kvm_coproc.h b/arch/arm/include/asm/kvm_coproc.h
new file mode 100644
index 000000000000..b6d023deb426
--- /dev/null
+++ b/arch/arm/include/asm/kvm_coproc.h
@@ -0,0 +1,24 @@
1/*
2 * Copyright (C) 2012 Rusty Russell IBM Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 */
17
18#ifndef __ARM_KVM_COPROC_H__
19#define __ARM_KVM_COPROC_H__
20#include <linux/kvm_host.h>
21
22void kvm_reset_coprocs(struct kvm_vcpu *vcpu);
23
24#endif /* __ARM_KVM_COPROC_H__ */
diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
new file mode 100644
index 000000000000..17dad674b90f
--- /dev/null
+++ b/arch/arm/include/asm/kvm_emulate.h
@@ -0,0 +1,50 @@
1/*
2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
3 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19#ifndef __ARM_KVM_EMULATE_H__
20#define __ARM_KVM_EMULATE_H__
21
22#include <linux/kvm_host.h>
23#include <asm/kvm_asm.h>
24
25u32 *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num);
26u32 *vcpu_spsr(struct kvm_vcpu *vcpu);
27
28static inline u32 *vcpu_pc(struct kvm_vcpu *vcpu)
29{
30 return (u32 *)&vcpu->arch.regs.usr_regs.ARM_pc;
31}
32
33static inline u32 *vcpu_cpsr(struct kvm_vcpu *vcpu)
34{
35 return (u32 *)&vcpu->arch.regs.usr_regs.ARM_cpsr;
36}
37
38static inline bool mode_has_spsr(struct kvm_vcpu *vcpu)
39{
40 unsigned long cpsr_mode = vcpu->arch.regs.usr_regs.ARM_cpsr & MODE_MASK;
41 return (cpsr_mode > USR_MODE && cpsr_mode < SYSTEM_MODE);
42}
43
44static inline bool vcpu_mode_priv(struct kvm_vcpu *vcpu)
45{
46 unsigned long cpsr_mode = vcpu->arch.regs.usr_regs.ARM_cpsr & MODE_MASK;
47 return cpsr_mode > USR_MODE;;
48}
49
50#endif /* __ARM_KVM_EMULATE_H__ */
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
new file mode 100644
index 000000000000..0d9938a20751
--- /dev/null
+++ b/arch/arm/include/asm/kvm_host.h
@@ -0,0 +1,114 @@
1/*
2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
3 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19#ifndef __ARM_KVM_HOST_H__
20#define __ARM_KVM_HOST_H__
21
22#include <asm/kvm.h>
23#include <asm/kvm_asm.h>
24
25#define KVM_MAX_VCPUS CONFIG_KVM_ARM_MAX_VCPUS
26#define KVM_MEMORY_SLOTS 32
27#define KVM_PRIVATE_MEM_SLOTS 4
28#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
29
30#define KVM_VCPU_MAX_FEATURES 0
31
32/* We don't currently support large pages. */
33#define KVM_HPAGE_GFN_SHIFT(x) 0
34#define KVM_NR_PAGE_SIZES 1
35#define KVM_PAGES_PER_HPAGE(x) (1UL<<31)
36
37struct kvm_vcpu;
38u32 *kvm_vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num, u32 mode);
39int kvm_target_cpu(void);
40int kvm_reset_vcpu(struct kvm_vcpu *vcpu);
41void kvm_reset_coprocs(struct kvm_vcpu *vcpu);
42
43struct kvm_arch {
44 /* VTTBR value associated with below pgd and vmid */
45 u64 vttbr;
46
47 /*
48 * Anything that is not used directly from assembly code goes
49 * here.
50 */
51
52 /* The VMID generation used for the virt. memory system */
53 u64 vmid_gen;
54 u32 vmid;
55
56 /* Stage-2 page table */
57 pgd_t *pgd;
58};
59
60#define KVM_NR_MEM_OBJS 40
61
62/*
63 * We don't want allocation failures within the mmu code, so we preallocate
64 * enough memory for a single page fault in a cache.
65 */
66struct kvm_mmu_memory_cache {
67 int nobjs;
68 void *objects[KVM_NR_MEM_OBJS];
69};
70
71struct kvm_vcpu_arch {
72 struct kvm_regs regs;
73
74 int target; /* Processor target */
75 DECLARE_BITMAP(features, KVM_VCPU_MAX_FEATURES);
76
77 /* System control coprocessor (cp15) */
78 u32 cp15[NR_CP15_REGS];
79
80 /* The CPU type we expose to the VM */
81 u32 midr;
82
83 /* Exception Information */
84 u32 hsr; /* Hyp Syndrome Register */
85 u32 hxfar; /* Hyp Data/Inst Fault Address Register */
86 u32 hpfar; /* Hyp IPA Fault Address Register */
87
88 /* Interrupt related fields */
89 u32 irq_lines; /* IRQ and FIQ levels */
90
91 /* Hyp exception information */
92 u32 hyp_pc; /* PC when exception was taken from Hyp mode */
93
94 /* Cache some mmu pages needed inside spinlock regions */
95 struct kvm_mmu_memory_cache mmu_page_cache;
96};
97
98struct kvm_vm_stat {
99 u32 remote_tlb_flush;
100};
101
102struct kvm_vcpu_stat {
103 u32 halt_wakeup;
104};
105
106struct kvm_vcpu_init;
107int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
108 const struct kvm_vcpu_init *init);
109unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
110int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
111struct kvm_one_reg;
112int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
113int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
114#endif /* __ARM_KVM_HOST_H__ */
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
new file mode 100644
index 000000000000..1083327b5fcd
--- /dev/null
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -0,0 +1,106 @@
1/*
2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
3 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19#ifndef __ARM_KVM_H__
20#define __ARM_KVM_H__
21
22#include <linux/types.h>
23#include <asm/ptrace.h>
24
25#define __KVM_HAVE_GUEST_DEBUG
26
27#define KVM_REG_SIZE(id) \
28 (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
29
30/* Valid for svc_regs, abt_regs, und_regs, irq_regs in struct kvm_regs */
31#define KVM_ARM_SVC_sp svc_regs[0]
32#define KVM_ARM_SVC_lr svc_regs[1]
33#define KVM_ARM_SVC_spsr svc_regs[2]
34#define KVM_ARM_ABT_sp abt_regs[0]
35#define KVM_ARM_ABT_lr abt_regs[1]
36#define KVM_ARM_ABT_spsr abt_regs[2]
37#define KVM_ARM_UND_sp und_regs[0]
38#define KVM_ARM_UND_lr und_regs[1]
39#define KVM_ARM_UND_spsr und_regs[2]
40#define KVM_ARM_IRQ_sp irq_regs[0]
41#define KVM_ARM_IRQ_lr irq_regs[1]
42#define KVM_ARM_IRQ_spsr irq_regs[2]
43
44/* Valid only for fiq_regs in struct kvm_regs */
45#define KVM_ARM_FIQ_r8 fiq_regs[0]
46#define KVM_ARM_FIQ_r9 fiq_regs[1]
47#define KVM_ARM_FIQ_r10 fiq_regs[2]
48#define KVM_ARM_FIQ_fp fiq_regs[3]
49#define KVM_ARM_FIQ_ip fiq_regs[4]
50#define KVM_ARM_FIQ_sp fiq_regs[5]
51#define KVM_ARM_FIQ_lr fiq_regs[6]
52#define KVM_ARM_FIQ_spsr fiq_regs[7]
53
54struct kvm_regs {
55 struct pt_regs usr_regs;/* R0_usr - R14_usr, PC, CPSR */
56 __u32 svc_regs[3]; /* SP_svc, LR_svc, SPSR_svc */
57 __u32 abt_regs[3]; /* SP_abt, LR_abt, SPSR_abt */
58 __u32 und_regs[3]; /* SP_und, LR_und, SPSR_und */
59 __u32 irq_regs[3]; /* SP_irq, LR_irq, SPSR_irq */
60 __u32 fiq_regs[8]; /* R8_fiq - R14_fiq, SPSR_fiq */
61};
62
63/* Supported Processor Types */
64#define KVM_ARM_TARGET_CORTEX_A15 0
65#define KVM_ARM_NUM_TARGETS 1
66
67struct kvm_vcpu_init {
68 __u32 target;
69 __u32 features[7];
70};
71
72struct kvm_sregs {
73};
74
75struct kvm_fpu {
76};
77
78struct kvm_guest_debug_arch {
79};
80
81struct kvm_debug_exit_arch {
82};
83
84struct kvm_sync_regs {
85};
86
87struct kvm_arch_memory_slot {
88};
89
90/* If you need to interpret the index values, here is the key: */
91#define KVM_REG_ARM_COPROC_MASK 0x000000000FFF0000
92#define KVM_REG_ARM_COPROC_SHIFT 16
93#define KVM_REG_ARM_32_OPC2_MASK 0x0000000000000007
94#define KVM_REG_ARM_32_OPC2_SHIFT 0
95#define KVM_REG_ARM_OPC1_MASK 0x0000000000000078
96#define KVM_REG_ARM_OPC1_SHIFT 3
97#define KVM_REG_ARM_CRM_MASK 0x0000000000000780
98#define KVM_REG_ARM_CRM_SHIFT 7
99#define KVM_REG_ARM_32_CRN_MASK 0x0000000000007800
100#define KVM_REG_ARM_32_CRN_SHIFT 11
101
102/* Normal registers are mapped as coprocessor 16. */
103#define KVM_REG_ARM_CORE (0x0010 << KVM_REG_ARM_COPROC_SHIFT)
104#define KVM_REG_ARM_CORE_REG(name) (offsetof(struct kvm_regs, name) / 4)
105
106#endif /* __ARM_KVM_H__ */
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
new file mode 100644
index 000000000000..4a01b6fbf380
--- /dev/null
+++ b/arch/arm/kvm/Kconfig
@@ -0,0 +1,55 @@
1#
2# KVM configuration
3#
4
5source "virt/kvm/Kconfig"
6
7menuconfig VIRTUALIZATION
8 bool "Virtualization"
9 ---help---
10 Say Y here to get to see options for using your Linux host to run
11 other operating systems inside virtual machines (guests).
12 This option alone does not add any kernel code.
13
14 If you say N, all options in this submenu will be skipped and
15 disabled.
16
17if VIRTUALIZATION
18
19config KVM
20 bool "Kernel-based Virtual Machine (KVM) support"
21 select PREEMPT_NOTIFIERS
22 select ANON_INODES
23 select KVM_MMIO
24 select KVM_ARM_HOST
25 depends on ARM_VIRT_EXT && ARM_LPAE
26 ---help---
27 Support hosting virtualized guest machines. You will also
28 need to select one or more of the processor modules below.
29
30 This module provides access to the hardware capabilities through
31 a character device node named /dev/kvm.
32
33 If unsure, say N.
34
35config KVM_ARM_HOST
36 bool "KVM host support for ARM cpus."
37 depends on KVM
38 depends on MMU
39 ---help---
40 Provides host support for ARM processors.
41
42config KVM_ARM_MAX_VCPUS
43 int "Number maximum supported virtual CPUs per VM"
44 depends on KVM_ARM_HOST
45 default 4
46 help
47 Static number of max supported virtual CPUs per VM.
48
49 If you choose a high number, the vcpu structures will be quite
50 large, so only choose a reasonable number that you expect to
51 actually use.
52
53source drivers/virtio/Kconfig
54
55endif # VIRTUALIZATION
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
new file mode 100644
index 000000000000..dfc293f277b3
--- /dev/null
+++ b/arch/arm/kvm/Makefile
@@ -0,0 +1,21 @@
1#
2# Makefile for Kernel-based Virtual Machine module
3#
4
5plus_virt := $(call as-instr,.arch_extension virt,+virt)
6ifeq ($(plus_virt),+virt)
7 plus_virt_def := -DREQUIRES_VIRT=1
8endif
9
10ccflags-y += -Ivirt/kvm -Iarch/arm/kvm
11CFLAGS_arm.o := -I. $(plus_virt_def)
12CFLAGS_mmu.o := -I.
13
14AFLAGS_init.o := -Wa,-march=armv7-a$(plus_virt)
15AFLAGS_interrupts.o := -Wa,-march=armv7-a$(plus_virt)
16
17kvm-arm-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
18
19obj-y += kvm-arm.o init.o interrupts.o
20obj-y += arm.o guest.o mmu.o emulate.o reset.o
21obj-y += coproc.o
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
new file mode 100644
index 000000000000..d3506b4001aa
--- /dev/null
+++ b/arch/arm/kvm/arm.c
@@ -0,0 +1,350 @@
1/*
2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
3 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19#include <linux/errno.h>
20#include <linux/err.h>
21#include <linux/kvm_host.h>
22#include <linux/module.h>
23#include <linux/vmalloc.h>
24#include <linux/fs.h>
25#include <linux/mman.h>
26#include <linux/sched.h>
27#include <trace/events/kvm.h>
28
29#define CREATE_TRACE_POINTS
30#include "trace.h"
31
32#include <asm/unified.h>
33#include <asm/uaccess.h>
34#include <asm/ptrace.h>
35#include <asm/mman.h>
36#include <asm/cputype.h>
37
38#ifdef REQUIRES_VIRT
39__asm__(".arch_extension virt");
40#endif
41
42int kvm_arch_hardware_enable(void *garbage)
43{
44 return 0;
45}
46
47int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
48{
49 return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
50}
51
52void kvm_arch_hardware_disable(void *garbage)
53{
54}
55
56int kvm_arch_hardware_setup(void)
57{
58 return 0;
59}
60
61void kvm_arch_hardware_unsetup(void)
62{
63}
64
65void kvm_arch_check_processor_compat(void *rtn)
66{
67 *(int *)rtn = 0;
68}
69
70void kvm_arch_sync_events(struct kvm *kvm)
71{
72}
73
74int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
75{
76 if (type)
77 return -EINVAL;
78
79 return 0;
80}
81
82int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
83{
84 return VM_FAULT_SIGBUS;
85}
86
87void kvm_arch_free_memslot(struct kvm_memory_slot *free,
88 struct kvm_memory_slot *dont)
89{
90}
91
92int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages)
93{
94 return 0;
95}
96
97void kvm_arch_destroy_vm(struct kvm *kvm)
98{
99 int i;
100
101 for (i = 0; i < KVM_MAX_VCPUS; ++i) {
102 if (kvm->vcpus[i]) {
103 kvm_arch_vcpu_free(kvm->vcpus[i]);
104 kvm->vcpus[i] = NULL;
105 }
106 }
107}
108
109int kvm_dev_ioctl_check_extension(long ext)
110{
111 int r;
112 switch (ext) {
113 case KVM_CAP_USER_MEMORY:
114 case KVM_CAP_SYNC_MMU:
115 case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
116 case KVM_CAP_ONE_REG:
117 r = 1;
118 break;
119 case KVM_CAP_COALESCED_MMIO:
120 r = KVM_COALESCED_MMIO_PAGE_OFFSET;
121 break;
122 case KVM_CAP_NR_VCPUS:
123 r = num_online_cpus();
124 break;
125 case KVM_CAP_MAX_VCPUS:
126 r = KVM_MAX_VCPUS;
127 break;
128 default:
129 r = 0;
130 break;
131 }
132 return r;
133}
134
135long kvm_arch_dev_ioctl(struct file *filp,
136 unsigned int ioctl, unsigned long arg)
137{
138 return -EINVAL;
139}
140
141int kvm_arch_set_memory_region(struct kvm *kvm,
142 struct kvm_userspace_memory_region *mem,
143 struct kvm_memory_slot old,
144 int user_alloc)
145{
146 return 0;
147}
148
149int kvm_arch_prepare_memory_region(struct kvm *kvm,
150 struct kvm_memory_slot *memslot,
151 struct kvm_memory_slot old,
152 struct kvm_userspace_memory_region *mem,
153 int user_alloc)
154{
155 return 0;
156}
157
158void kvm_arch_commit_memory_region(struct kvm *kvm,
159 struct kvm_userspace_memory_region *mem,
160 struct kvm_memory_slot old,
161 int user_alloc)
162{
163}
164
165void kvm_arch_flush_shadow_all(struct kvm *kvm)
166{
167}
168
169void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
170 struct kvm_memory_slot *slot)
171{
172}
173
174struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
175{
176 int err;
177 struct kvm_vcpu *vcpu;
178
179 vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
180 if (!vcpu) {
181 err = -ENOMEM;
182 goto out;
183 }
184
185 err = kvm_vcpu_init(vcpu, kvm, id);
186 if (err)
187 goto free_vcpu;
188
189 return vcpu;
190free_vcpu:
191 kmem_cache_free(kvm_vcpu_cache, vcpu);
192out:
193 return ERR_PTR(err);
194}
195
196int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
197{
198 return 0;
199}
200
201void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
202{
203}
204
205void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
206{
207 kvm_arch_vcpu_free(vcpu);
208}
209
210int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
211{
212 return 0;
213}
214
215int __attribute_const__ kvm_target_cpu(void)
216{
217 unsigned long implementor = read_cpuid_implementor();
218 unsigned long part_number = read_cpuid_part_number();
219
220 if (implementor != ARM_CPU_IMP_ARM)
221 return -EINVAL;
222
223 switch (part_number) {
224 case ARM_CPU_PART_CORTEX_A15:
225 return KVM_ARM_TARGET_CORTEX_A15;
226 default:
227 return -EINVAL;
228 }
229}
230
231int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
232{
233 return 0;
234}
235
236void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
237{
238}
239
240void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
241{
242}
243
244void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
245{
246}
247
248int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
249 struct kvm_guest_debug *dbg)
250{
251 return -EINVAL;
252}
253
254
255int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
256 struct kvm_mp_state *mp_state)
257{
258 return -EINVAL;
259}
260
261int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
262 struct kvm_mp_state *mp_state)
263{
264 return -EINVAL;
265}
266
267int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
268{
269 return 0;
270}
271
272int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
273{
274 return -EINVAL;
275}
276
277long kvm_arch_vcpu_ioctl(struct file *filp,
278 unsigned int ioctl, unsigned long arg)
279{
280 struct kvm_vcpu *vcpu = filp->private_data;
281 void __user *argp = (void __user *)arg;
282
283 switch (ioctl) {
284 case KVM_ARM_VCPU_INIT: {
285 struct kvm_vcpu_init init;
286
287 if (copy_from_user(&init, argp, sizeof(init)))
288 return -EFAULT;
289
290 return kvm_vcpu_set_target(vcpu, &init);
291
292 }
293 case KVM_SET_ONE_REG:
294 case KVM_GET_ONE_REG: {
295 struct kvm_one_reg reg;
296 if (copy_from_user(&reg, argp, sizeof(reg)))
297 return -EFAULT;
298 if (ioctl == KVM_SET_ONE_REG)
299 return kvm_arm_set_reg(vcpu, &reg);
300 else
301 return kvm_arm_get_reg(vcpu, &reg);
302 }
303 case KVM_GET_REG_LIST: {
304 struct kvm_reg_list __user *user_list = argp;
305 struct kvm_reg_list reg_list;
306 unsigned n;
307
308 if (copy_from_user(&reg_list, user_list, sizeof(reg_list)))
309 return -EFAULT;
310 n = reg_list.n;
311 reg_list.n = kvm_arm_num_regs(vcpu);
312 if (copy_to_user(user_list, &reg_list, sizeof(reg_list)))
313 return -EFAULT;
314 if (n < reg_list.n)
315 return -E2BIG;
316 return kvm_arm_copy_reg_indices(vcpu, user_list->reg);
317 }
318 default:
319 return -EINVAL;
320 }
321}
322
323int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log)
324{
325 return -EINVAL;
326}
327
328long kvm_arch_vm_ioctl(struct file *filp,
329 unsigned int ioctl, unsigned long arg)
330{
331 return -EINVAL;
332}
333
334int kvm_arch_init(void *opaque)
335{
336 return 0;
337}
338
339/* NOP: Compiling as a module not supported */
340void kvm_arch_exit(void)
341{
342}
343
344static int arm_init(void)
345{
346 int rc = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
347 return rc;
348}
349
350module_init(arm_init);
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
new file mode 100644
index 000000000000..0c433558591c
--- /dev/null
+++ b/arch/arm/kvm/coproc.c
@@ -0,0 +1,23 @@
1/*
2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
3 * Authors: Rusty Russell <rusty@rustcorp.com.au>
4 * Christoffer Dall <c.dall@virtualopensystems.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19#include <linux/kvm_host.h>
20
21void kvm_reset_coprocs(struct kvm_vcpu *vcpu)
22{
23}
diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c
new file mode 100644
index 000000000000..3eadc25e95de
--- /dev/null
+++ b/arch/arm/kvm/emulate.c
@@ -0,0 +1,155 @@
1/*
2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
3 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19#include <asm/kvm_emulate.h>
20
21#define VCPU_NR_MODES 6
22#define VCPU_REG_OFFSET_USR 0
23#define VCPU_REG_OFFSET_FIQ 1
24#define VCPU_REG_OFFSET_IRQ 2
25#define VCPU_REG_OFFSET_SVC 3
26#define VCPU_REG_OFFSET_ABT 4
27#define VCPU_REG_OFFSET_UND 5
28#define REG_OFFSET(_reg) \
29 (offsetof(struct kvm_regs, _reg) / sizeof(u32))
30
31#define USR_REG_OFFSET(_num) REG_OFFSET(usr_regs.uregs[_num])
32
33static const unsigned long vcpu_reg_offsets[VCPU_NR_MODES][15] = {
34 /* USR/SYS Registers */
35 [VCPU_REG_OFFSET_USR] = {
36 USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
37 USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
38 USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),
39 USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),
40 USR_REG_OFFSET(12), USR_REG_OFFSET(13), USR_REG_OFFSET(14),
41 },
42
43 /* FIQ Registers */
44 [VCPU_REG_OFFSET_FIQ] = {
45 USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
46 USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
47 USR_REG_OFFSET(6), USR_REG_OFFSET(7),
48 REG_OFFSET(fiq_regs[0]), /* r8 */
49 REG_OFFSET(fiq_regs[1]), /* r9 */
50 REG_OFFSET(fiq_regs[2]), /* r10 */
51 REG_OFFSET(fiq_regs[3]), /* r11 */
52 REG_OFFSET(fiq_regs[4]), /* r12 */
53 REG_OFFSET(fiq_regs[5]), /* r13 */
54 REG_OFFSET(fiq_regs[6]), /* r14 */
55 },
56
57 /* IRQ Registers */
58 [VCPU_REG_OFFSET_IRQ] = {
59 USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
60 USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
61 USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),
62 USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),
63 USR_REG_OFFSET(12),
64 REG_OFFSET(irq_regs[0]), /* r13 */
65 REG_OFFSET(irq_regs[1]), /* r14 */
66 },
67
68 /* SVC Registers */
69 [VCPU_REG_OFFSET_SVC] = {
70 USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
71 USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
72 USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),
73 USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),
74 USR_REG_OFFSET(12),
75 REG_OFFSET(svc_regs[0]), /* r13 */
76 REG_OFFSET(svc_regs[1]), /* r14 */
77 },
78
79 /* ABT Registers */
80 [VCPU_REG_OFFSET_ABT] = {
81 USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
82 USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
83 USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),
84 USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),
85 USR_REG_OFFSET(12),
86 REG_OFFSET(abt_regs[0]), /* r13 */
87 REG_OFFSET(abt_regs[1]), /* r14 */
88 },
89
90 /* UND Registers */
91 [VCPU_REG_OFFSET_UND] = {
92 USR_REG_OFFSET(0), USR_REG_OFFSET(1), USR_REG_OFFSET(2),
93 USR_REG_OFFSET(3), USR_REG_OFFSET(4), USR_REG_OFFSET(5),
94 USR_REG_OFFSET(6), USR_REG_OFFSET(7), USR_REG_OFFSET(8),
95 USR_REG_OFFSET(9), USR_REG_OFFSET(10), USR_REG_OFFSET(11),
96 USR_REG_OFFSET(12),
97 REG_OFFSET(und_regs[0]), /* r13 */
98 REG_OFFSET(und_regs[1]), /* r14 */
99 },
100};
101
102/*
103 * Return a pointer to the register number valid in the current mode of
104 * the virtual CPU.
105 */
106u32 *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num)
107{
108 u32 *reg_array = (u32 *)&vcpu->arch.regs;
109 u32 mode = *vcpu_cpsr(vcpu) & MODE_MASK;
110
111 switch (mode) {
112 case USR_MODE...SVC_MODE:
113 mode &= ~MODE32_BIT; /* 0 ... 3 */
114 break;
115
116 case ABT_MODE:
117 mode = VCPU_REG_OFFSET_ABT;
118 break;
119
120 case UND_MODE:
121 mode = VCPU_REG_OFFSET_UND;
122 break;
123
124 case SYSTEM_MODE:
125 mode = VCPU_REG_OFFSET_USR;
126 break;
127
128 default:
129 BUG();
130 }
131
132 return reg_array + vcpu_reg_offsets[mode][reg_num];
133}
134
135/*
136 * Return the SPSR for the current mode of the virtual CPU.
137 */
138u32 *vcpu_spsr(struct kvm_vcpu *vcpu)
139{
140 u32 mode = *vcpu_cpsr(vcpu) & MODE_MASK;
141 switch (mode) {
142 case SVC_MODE:
143 return &vcpu->arch.regs.KVM_ARM_SVC_spsr;
144 case ABT_MODE:
145 return &vcpu->arch.regs.KVM_ARM_ABT_spsr;
146 case UND_MODE:
147 return &vcpu->arch.regs.KVM_ARM_UND_spsr;
148 case IRQ_MODE:
149 return &vcpu->arch.regs.KVM_ARM_IRQ_spsr;
150 case FIQ_MODE:
151 return &vcpu->arch.regs.KVM_ARM_FIQ_spsr;
152 default:
153 BUG();
154 }
155}
diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c
new file mode 100644
index 000000000000..a12eb229021d
--- /dev/null
+++ b/arch/arm/kvm/guest.c
@@ -0,0 +1,221 @@
1/*
2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
3 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19#include <linux/errno.h>
20#include <linux/err.h>
21#include <linux/kvm_host.h>
22#include <linux/module.h>
23#include <linux/vmalloc.h>
24#include <linux/fs.h>
25#include <asm/uaccess.h>
26#include <asm/kvm.h>
27#include <asm/kvm_asm.h>
28#include <asm/kvm_emulate.h>
29
30#define VM_STAT(x) { #x, offsetof(struct kvm, stat.x), KVM_STAT_VM }
31#define VCPU_STAT(x) { #x, offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU }
32
33struct kvm_stats_debugfs_item debugfs_entries[] = {
34 { NULL }
35};
36
37int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
38{
39 return 0;
40}
41
42static u64 core_reg_offset_from_id(u64 id)
43{
44 return id & ~(KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_CORE);
45}
46
47static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
48{
49 u32 __user *uaddr = (u32 __user *)(long)reg->addr;
50 struct kvm_regs *regs = &vcpu->arch.regs;
51 u64 off;
52
53 if (KVM_REG_SIZE(reg->id) != 4)
54 return -ENOENT;
55
56 /* Our ID is an index into the kvm_regs struct. */
57 off = core_reg_offset_from_id(reg->id);
58 if (off >= sizeof(*regs) / KVM_REG_SIZE(reg->id))
59 return -ENOENT;
60
61 return put_user(((u32 *)regs)[off], uaddr);
62}
63
64static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
65{
66 u32 __user *uaddr = (u32 __user *)(long)reg->addr;
67 struct kvm_regs *regs = &vcpu->arch.regs;
68 u64 off, val;
69
70 if (KVM_REG_SIZE(reg->id) != 4)
71 return -ENOENT;
72
73 /* Our ID is an index into the kvm_regs struct. */
74 off = core_reg_offset_from_id(reg->id);
75 if (off >= sizeof(*regs) / KVM_REG_SIZE(reg->id))
76 return -ENOENT;
77
78 if (get_user(val, uaddr) != 0)
79 return -EFAULT;
80
81 if (off == KVM_REG_ARM_CORE_REG(usr_regs.ARM_cpsr)) {
82 unsigned long mode = val & MODE_MASK;
83 switch (mode) {
84 case USR_MODE:
85 case FIQ_MODE:
86 case IRQ_MODE:
87 case SVC_MODE:
88 case ABT_MODE:
89 case UND_MODE:
90 break;
91 default:
92 return -EINVAL;
93 }
94 }
95
96 ((u32 *)regs)[off] = val;
97 return 0;
98}
99
100int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
101{
102 return -EINVAL;
103}
104
105int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
106{
107 return -EINVAL;
108}
109
110static unsigned long num_core_regs(void)
111{
112 return sizeof(struct kvm_regs) / sizeof(u32);
113}
114
115/**
116 * kvm_arm_num_regs - how many registers do we present via KVM_GET_ONE_REG
117 *
118 * This is for all registers.
119 */
120unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
121{
122 return num_core_regs();
123}
124
125/**
126 * kvm_arm_copy_reg_indices - get indices of all registers.
127 *
128 * We do core registers right here, then we apppend coproc regs.
129 */
130int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
131{
132 unsigned int i;
133 const u64 core_reg = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_CORE;
134
135 for (i = 0; i < sizeof(struct kvm_regs)/sizeof(u32); i++) {
136 if (put_user(core_reg | i, uindices))
137 return -EFAULT;
138 uindices++;
139 }
140
141 return 0;
142}
143
144int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
145{
146 /* We currently use nothing arch-specific in upper 32 bits */
147 if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM >> 32)
148 return -EINVAL;
149
150 /* Register group 16 means we want a core register. */
151 if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
152 return get_core_reg(vcpu, reg);
153
154 return -EINVAL;
155}
156
157int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
158{
159 /* We currently use nothing arch-specific in upper 32 bits */
160 if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM >> 32)
161 return -EINVAL;
162
163 /* Register group 16 means we set a core register. */
164 if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
165 return set_core_reg(vcpu, reg);
166
167 return -EINVAL;
168}
169
170int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
171 struct kvm_sregs *sregs)
172{
173 return -EINVAL;
174}
175
176int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
177 struct kvm_sregs *sregs)
178{
179 return -EINVAL;
180}
181
182int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
183 const struct kvm_vcpu_init *init)
184{
185 unsigned int i;
186
187 /* We can only do a cortex A15 for now. */
188 if (init->target != kvm_target_cpu())
189 return -EINVAL;
190
191 vcpu->arch.target = init->target;
192 bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES);
193
194 /* -ENOENT for unknown features, -EINVAL for invalid combinations. */
195 for (i = 0; i < sizeof(init->features) * 8; i++) {
196 if (test_bit(i, (void *)init->features)) {
197 if (i >= KVM_VCPU_MAX_FEATURES)
198 return -ENOENT;
199 set_bit(i, vcpu->arch.features);
200 }
201 }
202
203 /* Now we know what it is, we can reset it. */
204 return kvm_reset_vcpu(vcpu);
205}
206
207int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
208{
209 return -EINVAL;
210}
211
212int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
213{
214 return -EINVAL;
215}
216
217int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
218 struct kvm_translation *tr)
219{
220 return -EINVAL;
221}
diff --git a/arch/arm/kvm/init.S b/arch/arm/kvm/init.S
new file mode 100644
index 000000000000..1dc8926e26d2
--- /dev/null
+++ b/arch/arm/kvm/init.S
@@ -0,0 +1,19 @@
1/*
2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
3 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18#include <asm/asm-offsets.h>
19#include <asm/kvm_asm.h>
diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S
new file mode 100644
index 000000000000..1dc8926e26d2
--- /dev/null
+++ b/arch/arm/kvm/interrupts.S
@@ -0,0 +1,19 @@
1/*
2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
3 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18#include <asm/asm-offsets.h>
19#include <asm/kvm_asm.h>
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
new file mode 100644
index 000000000000..10ed4643269f
--- /dev/null
+++ b/arch/arm/kvm/mmu.c
@@ -0,0 +1,17 @@
1/*
2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
3 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
diff --git a/arch/arm/kvm/reset.c b/arch/arm/kvm/reset.c
new file mode 100644
index 000000000000..b80256b554cd
--- /dev/null
+++ b/arch/arm/kvm/reset.c
@@ -0,0 +1,74 @@
1/*
2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
3 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18#include <linux/compiler.h>
19#include <linux/errno.h>
20#include <linux/sched.h>
21#include <linux/kvm_host.h>
22#include <linux/kvm.h>
23
24#include <asm/unified.h>
25#include <asm/ptrace.h>
26#include <asm/cputype.h>
27#include <asm/kvm_arm.h>
28#include <asm/kvm_coproc.h>
29
30/******************************************************************************
31 * Cortex-A15 Reset Values
32 */
33
34static const int a15_max_cpu_idx = 3;
35
36static struct kvm_regs a15_regs_reset = {
37 .usr_regs.ARM_cpsr = SVC_MODE | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT,
38};
39
40
41/*******************************************************************************
42 * Exported reset function
43 */
44
45/**
46 * kvm_reset_vcpu - sets core registers and cp15 registers to reset value
47 * @vcpu: The VCPU pointer
48 *
49 * This function finds the right table above and sets the registers on the
50 * virtual CPU struct to their architectually defined reset values.
51 */
52int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
53{
54 struct kvm_regs *cpu_reset;
55
56 switch (vcpu->arch.target) {
57 case KVM_ARM_TARGET_CORTEX_A15:
58 if (vcpu->vcpu_id > a15_max_cpu_idx)
59 return -EINVAL;
60 cpu_reset = &a15_regs_reset;
61 vcpu->arch.midr = read_cpuid_id();
62 break;
63 default:
64 return -ENODEV;
65 }
66
67 /* Reset core registers */
68 memcpy(&vcpu->arch.regs, cpu_reset, sizeof(vcpu->arch.regs));
69
70 /* Reset CP15 registers */
71 kvm_reset_coprocs(vcpu);
72
73 return 0;
74}
diff --git a/arch/arm/kvm/trace.h b/arch/arm/kvm/trace.h
new file mode 100644
index 000000000000..f8869c19c0a3
--- /dev/null
+++ b/arch/arm/kvm/trace.h
@@ -0,0 +1,52 @@
1#if !defined(_TRACE_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
2#define _TRACE_KVM_H
3
4#include <linux/tracepoint.h>
5
6#undef TRACE_SYSTEM
7#define TRACE_SYSTEM kvm
8
9/*
10 * Tracepoints for entry/exit to guest
11 */
12TRACE_EVENT(kvm_entry,
13 TP_PROTO(unsigned long vcpu_pc),
14 TP_ARGS(vcpu_pc),
15
16 TP_STRUCT__entry(
17 __field( unsigned long, vcpu_pc )
18 ),
19
20 TP_fast_assign(
21 __entry->vcpu_pc = vcpu_pc;
22 ),
23
24 TP_printk("PC: 0x%08lx", __entry->vcpu_pc)
25);
26
27TRACE_EVENT(kvm_exit,
28 TP_PROTO(unsigned long vcpu_pc),
29 TP_ARGS(vcpu_pc),
30
31 TP_STRUCT__entry(
32 __field( unsigned long, vcpu_pc )
33 ),
34
35 TP_fast_assign(
36 __entry->vcpu_pc = vcpu_pc;
37 ),
38
39 TP_printk("PC: 0x%08lx", __entry->vcpu_pc)
40);
41
42
43
44#endif /* _TRACE_KVM_H */
45
46#undef TRACE_INCLUDE_PATH
47#define TRACE_INCLUDE_PATH arch/arm/kvm
48#undef TRACE_INCLUDE_FILE
49#define TRACE_INCLUDE_FILE trace
50
51/* This part must be outside protection */
52#include <trace/define_trace.h>