aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kvm
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/arm/kvm
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/arm/kvm')
-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
11 files changed, 1006 insertions, 0 deletions
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>