~ubuntu-branches/ubuntu/trusty/qemu/trusty

« back to all changes in this revision

Viewing changes to debian/patches/ubuntu/arm64/0019-target-arm-Add-minimal-KVM-AArch64-support.patch

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2014-02-04 12:13:08 UTC
  • mfrom: (10.1.45 sid)
  • Revision ID: package-import@ubuntu.com-20140204121308-1xq92lrfs75agw2g
Tags: 1.7.0+dfsg-3ubuntu1~ppa1
* Merge 1.7.0+dfsg-3 from debian.  Remaining changes:
  - debian/patches/ubuntu:
    * expose-vmx_qemu64cpu.patch
    * linaro (omap3) and arm64 patches
    * ubuntu/target-ppc-add-stubs-for-kvm-breakpoints: fix FTBFS
      on ppc
    * ubuntu/CVE-2013-4377.patch: fix denial of service via virtio
  - debian/qemu-system-x86.modprobe: set kvm_intel nested=1 options
  - debian/control:
    * add arm64 to Architectures
    * add qemu-common and qemu-system-aarch64 packages
  - debian/qemu-system-common.install: add debian/tmp/usr/lib
  - debian/qemu-system-common.preinst: add kvm group
  - debian/qemu-system-common.postinst: remove acl placed by udev,
    and add udevadm trigger.
  - qemu-system-x86.links: add eepro100.rom, remove pxe-virtio,
    pxe-e1000 and pxe-rtl8139.
  - add qemu-system-x86.qemu-kvm.upstart and .default
  - qemu-user-static.postinst-in: remove arm64 binfmt
  - debian/rules:
    * allow parallel build
    * add aarch64 to system_targets and sys_systems
    * add qemu-kvm-spice links
    * install qemu-system-x86.modprobe
  - add debian/qemu-system-common.links for OVMF.fd link
* Remove kvm-img, kvm-nbd, kvm-ifup and kvm-ifdown symlinks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
From 39bcaed680a5967ae0d6aef96b98e7b8e8f6da60 Mon Sep 17 00:00:00 2001
 
2
From: "Mian M. Hamayun" <m.hamayun@virtualopensystems.com>
 
3
Date: Tue, 17 Dec 2013 19:42:30 +0000
 
4
Subject: [PATCH 19/49] target-arm: Add minimal KVM AArch64 support
 
5
 
 
6
Add the bare minimum set of functions needed for control of an
 
7
AArch64 KVM vcpu:
 
8
 * CPU initialization
 
9
 * minimal get/put register functions which only handle the
 
10
   basic state of the CPU
 
11
 
 
12
Signed-off-by: Mian M. Hamayun <m.hamayun@virtualopensystems.com>
 
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
 
14
Message-id: 1385645602-18662-4-git-send-email-peter.maydell@linaro.org
 
15
[PMM: significantly overhauled; most notably:
 
16
 * code lives in kvm64.c rather than using #ifdefs
 
17
 * support '-cpu host' rather than implicitly using whatever the
 
18
   host's CPU is regardless of what the user requests
 
19
 * fix bug attempting to get/set nonexistent X[31]
 
20
 * fix bug writing 64 bit kernel pstate into uint32_t env field
 
21
]
 
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
 
23
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
 
24
---
 
25
 target-arm/Makefile.objs |   1 +
 
26
 target-arm/kvm.c         |   4 +
 
27
 target-arm/kvm64.c       | 204 +++++++++++++++++++++++++++++++++++++++++++++++
 
28
 3 files changed, 209 insertions(+)
 
29
 create mode 100644 target-arm/kvm64.c
 
30
 
 
31
diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
 
32
index c9f7944..bc23563 100644
 
33
--- a/target-arm/Makefile.objs
 
34
+++ b/target-arm/Makefile.objs
 
35
@@ -2,6 +2,7 @@ obj-y += arm-semi.o
 
36
 obj-$(CONFIG_SOFTMMU) += machine.o
 
37
 obj-$(CONFIG_KVM) += kvm.o
 
38
 obj-$(call land,$(CONFIG_KVM),$(call lnot,$(TARGET_AARCH64))) += kvm32.o
 
39
+obj-$(call land,$(CONFIG_KVM),$(TARGET_AARCH64)) += kvm64.o
 
40
 obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
 
41
 obj-y += translate.o op_helper.o helper.o cpu.o
 
42
 obj-y += neon_helper.o iwmmxt_helper.o
 
43
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
 
44
index 5cdb3b9..1d2688d 100644
 
45
--- a/target-arm/kvm.c
 
46
+++ b/target-arm/kvm.c
 
47
@@ -128,7 +128,11 @@ static void kvm_arm_host_cpu_initfn(Object *obj)
 
48
 
 
49
 static const TypeInfo host_arm_cpu_type_info = {
 
50
     .name = TYPE_ARM_HOST_CPU,
 
51
+#ifdef TARGET_AARCH64
 
52
+    .parent = TYPE_AARCH64_CPU,
 
53
+#else
 
54
     .parent = TYPE_ARM_CPU,
 
55
+#endif
 
56
     .instance_init = kvm_arm_host_cpu_initfn,
 
57
     .class_init = kvm_arm_host_cpu_class_init,
 
58
     .class_size = sizeof(ARMHostCPUClass),
 
59
diff --git a/target-arm/kvm64.c b/target-arm/kvm64.c
 
60
new file mode 100644
 
61
index 0000000..1b7ca90
 
62
--- /dev/null
 
63
+++ b/target-arm/kvm64.c
 
64
@@ -0,0 +1,204 @@
 
65
+/*
 
66
+ * ARM implementation of KVM hooks, 64 bit specific code
 
67
+ *
 
68
+ * Copyright Mian-M. Hamayun 2013, Virtual Open Systems
 
69
+ *
 
70
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
 
71
+ * See the COPYING file in the top-level directory.
 
72
+ *
 
73
+ */
 
74
+
 
75
+#include <stdio.h>
 
76
+#include <sys/types.h>
 
77
+#include <sys/ioctl.h>
 
78
+#include <sys/mman.h>
 
79
+
 
80
+#include <linux/kvm.h>
 
81
+
 
82
+#include "qemu-common.h"
 
83
+#include "qemu/timer.h"
 
84
+#include "sysemu/sysemu.h"
 
85
+#include "sysemu/kvm.h"
 
86
+#include "kvm_arm.h"
 
87
+#include "cpu.h"
 
88
+#include "hw/arm/arm.h"
 
89
+
 
90
+static inline void set_feature(uint64_t *features, int feature)
 
91
+{
 
92
+    *features |= 1ULL << feature;
 
93
+}
 
94
+
 
95
+bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
 
96
+{
 
97
+    /* Identify the feature bits corresponding to the host CPU, and
 
98
+     * fill out the ARMHostCPUClass fields accordingly. To do this
 
99
+     * we have to create a scratch VM, create a single CPU inside it,
 
100
+     * and then query that CPU for the relevant ID registers.
 
101
+     * For AArch64 we currently don't care about ID registers at
 
102
+     * all; we just want to know the CPU type.
 
103
+     */
 
104
+    int fdarray[3];
 
105
+    uint64_t features = 0;
 
106
+    /* Old kernels may not know about the PREFERRED_TARGET ioctl: however
 
107
+     * we know these will only support creating one kind of guest CPU,
 
108
+     * which is its preferred CPU type. Fortunately these old kernels
 
109
+     * support only a very limited number of CPUs.
 
110
+     */
 
111
+    static const uint32_t cpus_to_try[] = {
 
112
+        KVM_ARM_TARGET_AEM_V8,
 
113
+        KVM_ARM_TARGET_FOUNDATION_V8,
 
114
+        KVM_ARM_TARGET_CORTEX_A57,
 
115
+        QEMU_KVM_ARM_TARGET_NONE
 
116
+    };
 
117
+    struct kvm_vcpu_init init;
 
118
+
 
119
+    if (!kvm_arm_create_scratch_host_vcpu(cpus_to_try, fdarray, &init)) {
 
120
+        return false;
 
121
+    }
 
122
+
 
123
+    ahcc->target = init.target;
 
124
+    ahcc->dtb_compatible = "arm,arm-v8";
 
125
+
 
126
+    kvm_arm_destroy_scratch_host_vcpu(fdarray);
 
127
+
 
128
+   /* We can assume any KVM supporting CPU is at least a v8
 
129
+     * with VFPv4+Neon; this in turn implies most of the other
 
130
+     * feature bits.
 
131
+     */
 
132
+    set_feature(&features, ARM_FEATURE_V8);
 
133
+    set_feature(&features, ARM_FEATURE_VFP4);
 
134
+    set_feature(&features, ARM_FEATURE_NEON);
 
135
+    set_feature(&features, ARM_FEATURE_AARCH64);
 
136
+
 
137
+    ahcc->features = features;
 
138
+
 
139
+    return true;
 
140
+}
 
141
+
 
142
+int kvm_arch_init_vcpu(CPUState *cs)
 
143
+{
 
144
+    ARMCPU *cpu = ARM_CPU(cs);
 
145
+    struct kvm_vcpu_init init;
 
146
+    int ret;
 
147
+
 
148
+    if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE ||
 
149
+        !arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
 
150
+        fprintf(stderr, "KVM is not supported for this guest CPU type\n");
 
151
+        return -EINVAL;
 
152
+    }
 
153
+
 
154
+    init.target = cpu->kvm_target;
 
155
+    memset(init.features, 0, sizeof(init.features));
 
156
+    if (cpu->start_powered_off) {
 
157
+        init.features[0] = 1 << KVM_ARM_VCPU_POWER_OFF;
 
158
+    }
 
159
+    ret = kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_INIT, &init);
 
160
+
 
161
+    /* TODO : support for save/restore/reset of system regs via tuple list */
 
162
+
 
163
+    return ret;
 
164
+}
 
165
+
 
166
+#define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
 
167
+                 KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
 
168
+
 
169
+int kvm_arch_put_registers(CPUState *cs, int level)
 
170
+{
 
171
+    struct kvm_one_reg reg;
 
172
+    uint64_t val;
 
173
+    int i;
 
174
+    int ret;
 
175
+
 
176
+    ARMCPU *cpu = ARM_CPU(cs);
 
177
+    CPUARMState *env = &cpu->env;
 
178
+
 
179
+    for (i = 0; i < 31; i++) {
 
180
+        reg.id = AARCH64_CORE_REG(regs.regs[i]);
 
181
+        reg.addr = (uintptr_t) &env->xregs[i];
 
182
+        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
 
183
+        if (ret) {
 
184
+            return ret;
 
185
+        }
 
186
+    }
 
187
+
 
188
+    reg.id = AARCH64_CORE_REG(regs.sp);
 
189
+    reg.addr = (uintptr_t) &env->xregs[31];
 
190
+    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
 
191
+    if (ret) {
 
192
+        return ret;
 
193
+    }
 
194
+
 
195
+    /* Note that KVM thinks pstate is 64 bit but we use a uint32_t */
 
196
+    val = pstate_read(env);
 
197
+    reg.id = AARCH64_CORE_REG(regs.pstate);
 
198
+    reg.addr = (uintptr_t) &val;
 
199
+    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
 
200
+    if (ret) {
 
201
+        return ret;
 
202
+    }
 
203
+
 
204
+    reg.id = AARCH64_CORE_REG(regs.pc);
 
205
+    reg.addr = (uintptr_t) &env->pc;
 
206
+    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
 
207
+    if (ret) {
 
208
+        return ret;
 
209
+    }
 
210
+
 
211
+    /* TODO:
 
212
+     * SP_EL1
 
213
+     * ELR_EL1
 
214
+     * SPSR[]
 
215
+     * FP state
 
216
+     * system registers
 
217
+     */
 
218
+    return ret;
 
219
+}
 
220
+
 
221
+int kvm_arch_get_registers(CPUState *cs)
 
222
+{
 
223
+    struct kvm_one_reg reg;
 
224
+    uint64_t val;
 
225
+    int i;
 
226
+    int ret;
 
227
+
 
228
+    ARMCPU *cpu = ARM_CPU(cs);
 
229
+    CPUARMState *env = &cpu->env;
 
230
+
 
231
+    for (i = 0; i < 31; i++) {
 
232
+        reg.id = AARCH64_CORE_REG(regs.regs[i]);
 
233
+        reg.addr = (uintptr_t) &env->xregs[i];
 
234
+        ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
 
235
+        if (ret) {
 
236
+            return ret;
 
237
+        }
 
238
+    }
 
239
+
 
240
+    reg.id = AARCH64_CORE_REG(regs.sp);
 
241
+    reg.addr = (uintptr_t) &env->xregs[31];
 
242
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
 
243
+    if (ret) {
 
244
+        return ret;
 
245
+    }
 
246
+
 
247
+    reg.id = AARCH64_CORE_REG(regs.pstate);
 
248
+    reg.addr = (uintptr_t) &val;
 
249
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
 
250
+    if (ret) {
 
251
+        return ret;
 
252
+    }
 
253
+    pstate_write(env, val);
 
254
+
 
255
+    reg.id = AARCH64_CORE_REG(regs.pc);
 
256
+    reg.addr = (uintptr_t) &env->pc;
 
257
+    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
 
258
+    if (ret) {
 
259
+        return ret;
 
260
+    }
 
261
+
 
262
+    /* TODO: other registers */
 
263
+    return ret;
 
264
+}
 
265
+
 
266
+void kvm_arch_reset_vcpu(CPUState *cs)
 
267
+{
 
268
+}
 
269
-- 
 
270
1.8.5.2
 
271