~ubuntu-branches/ubuntu/vivid/qemu/vivid

« back to all changes in this revision

Viewing changes to debian/patches/ubuntu/arm64/0010-target-arm-Provide-cpu-host-when-running-KVM.patch

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2014-02-25 22:31:43 UTC
  • mfrom: (1.8.5)
  • Revision ID: package-import@ubuntu.com-20140225223143-odhqxfc60wxrjl15
Tags: 2.0.0~rc1+dfsg-0ubuntu1
* Merge 2.0.0-rc1
* debian/rules: consolidate ppc filter entries.
* Move qemu-system-arch64 into qemu-system-arm
* debian/patches/define-trusty-machine-type.patch: define a trusty machine
  type, currently the same as pc-i440fx-2.0, to put is in a better position
  to enable live migrations from trusty onward.  (LP: #1294823)
* debian/control: build-dep on libfdt >= 1.4.0  (LP: #1295072)
* Merge latest upstream git to commit dc9528f
* Debian/rules:
  - remove -enable-uname-release=2.6.32
  - don't make the aarch64 target Ubuntu-specific.
* Remove patches which are now upstream:
  - fix-smb-security-share.patch
  - slirp-smb-redirect-port-445-too.patch 
  - linux-user-Implement-sendmmsg-syscall.patch (better version is upstream)
  - signal-added-a-wrapper-for-sigprocmask-function.patch
  - ubuntu/signal-sigsegv-protection-on-do_sigprocmask.patch
  - ubuntu/Don-t-block-SIGSEGV-at-more-places.patch
  - ubuntu/ppc-force-cpu-threads-count-to-be-power-of-2.patch
* add link for /usr/share/qemu/bios-256k.bin
* Remove all linaro patches.
* Remove all arm64/ patches.  Many but not all are upstream.
* Remove CVE-2013-4377.patch which is upstream.
* debian/control-in: don't make qemu-system-aarch64 ubuntu-specific

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
From 97d36eb8b450a0f1f01c0ae73a1c60b5a85a4e72 Mon Sep 17 00:00:00 2001
2
 
From: Peter Maydell <peter.maydell@linaro.org>
3
 
Date: Fri, 22 Nov 2013 17:17:17 +0000
4
 
Subject: [PATCH 10/49] target-arm: Provide '-cpu host' when running KVM
5
 
 
6
 
Implement '-cpu host' for ARM when we're using KVM, broadly
7
 
in line with other KVM-supporting architectures.
8
 
 
9
 
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
 
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
11
 
Message-id: 1385140638-10444-11-git-send-email-peter.maydell@linaro.org
12
 
---
13
 
 target-arm/helper.c  |   6 ++
14
 
 target-arm/kvm.c     | 224 +++++++++++++++++++++++++++++++++++++++++++++++++++
15
 
 target-arm/kvm_arm.h |  55 +++++++++++++
16
 
 3 files changed, 285 insertions(+)
17
 
 
18
 
diff --git a/target-arm/helper.c b/target-arm/helper.c
19
 
index 3445813..263dbbf 100644
20
 
--- a/target-arm/helper.c
21
 
+++ b/target-arm/helper.c
22
 
@@ -1842,6 +1842,12 @@ void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf)
23
 
     (*cpu_fprintf)(f, "Available CPUs:\n");
24
 
     g_slist_foreach(list, arm_cpu_list_entry, &s);
25
 
     g_slist_free(list);
26
 
+#ifdef CONFIG_KVM
27
 
+    /* The 'host' CPU type is dynamically registered only if KVM is
28
 
+     * enabled, so we have to special-case it here:
29
 
+     */
30
 
+    (*cpu_fprintf)(f, "  host (only available in KVM mode)\n");
31
 
+#endif
32
 
 }
33
 
 
34
 
 static void arm_cpu_add_definition(gpointer data, gpointer user_data)
35
 
diff --git a/target-arm/kvm.c b/target-arm/kvm.c
36
 
index 182db85..f865dac 100644
37
 
--- a/target-arm/kvm.c
38
 
+++ b/target-arm/kvm.c
39
 
@@ -27,12 +27,236 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
40
 
     KVM_CAP_LAST_INFO
41
 
 };
42
 
 
43
 
+bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
44
 
+                                      int *fdarray,
45
 
+                                      struct kvm_vcpu_init *init)
46
 
+{
47
 
+    int ret, kvmfd = -1, vmfd = -1, cpufd = -1;
48
 
+
49
 
+    kvmfd = qemu_open("/dev/kvm", O_RDWR);
50
 
+    if (kvmfd < 0) {
51
 
+        goto err;
52
 
+    }
53
 
+    vmfd = ioctl(kvmfd, KVM_CREATE_VM, 0);
54
 
+    if (vmfd < 0) {
55
 
+        goto err;
56
 
+    }
57
 
+    cpufd = ioctl(vmfd, KVM_CREATE_VCPU, 0);
58
 
+    if (cpufd < 0) {
59
 
+        goto err;
60
 
+    }
61
 
+
62
 
+    ret = ioctl(vmfd, KVM_ARM_PREFERRED_TARGET, init);
63
 
+    if (ret >= 0) {
64
 
+        ret = ioctl(cpufd, KVM_ARM_VCPU_INIT, init);
65
 
+        if (ret < 0) {
66
 
+            goto err;
67
 
+        }
68
 
+    } else {
69
 
+        /* Old kernel which doesn't know about the
70
 
+         * PREFERRED_TARGET ioctl: we know it will only support
71
 
+         * creating one kind of guest CPU which is its preferred
72
 
+         * CPU type.
73
 
+         */
74
 
+        while (*cpus_to_try != QEMU_KVM_ARM_TARGET_NONE) {
75
 
+            init->target = *cpus_to_try++;
76
 
+            memset(init->features, 0, sizeof(init->features));
77
 
+            ret = ioctl(cpufd, KVM_ARM_VCPU_INIT, init);
78
 
+            if (ret >= 0) {
79
 
+                break;
80
 
+            }
81
 
+        }
82
 
+        if (ret < 0) {
83
 
+            goto err;
84
 
+        }
85
 
+    }
86
 
+
87
 
+    fdarray[0] = kvmfd;
88
 
+    fdarray[1] = vmfd;
89
 
+    fdarray[2] = cpufd;
90
 
+
91
 
+    return true;
92
 
+
93
 
+err:
94
 
+    if (cpufd >= 0) {
95
 
+        close(cpufd);
96
 
+    }
97
 
+    if (vmfd >= 0) {
98
 
+        close(vmfd);
99
 
+    }
100
 
+    if (kvmfd >= 0) {
101
 
+        close(kvmfd);
102
 
+    }
103
 
+
104
 
+    return false;
105
 
+}
106
 
+
107
 
+void kvm_arm_destroy_scratch_host_vcpu(int *fdarray)
108
 
+{
109
 
+    int i;
110
 
+
111
 
+    for (i = 2; i >= 0; i--) {
112
 
+        close(fdarray[i]);
113
 
+    }
114
 
+}
115
 
+
116
 
+static inline void set_feature(uint64_t *features, int feature)
117
 
+{
118
 
+    *features |= 1ULL << feature;
119
 
+}
120
 
+
121
 
+bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
122
 
+{
123
 
+    /* Identify the feature bits corresponding to the host CPU, and
124
 
+     * fill out the ARMHostCPUClass fields accordingly. To do this
125
 
+     * we have to create a scratch VM, create a single CPU inside it,
126
 
+     * and then query that CPU for the relevant ID registers.
127
 
+     */
128
 
+    int i, ret, fdarray[3];
129
 
+    uint32_t midr, id_pfr0, id_isar0, mvfr1;
130
 
+    uint64_t features = 0;
131
 
+    /* Old kernels may not know about the PREFERRED_TARGET ioctl: however
132
 
+     * we know these will only support creating one kind of guest CPU,
133
 
+     * which is its preferred CPU type.
134
 
+     */
135
 
+    static const uint32_t cpus_to_try[] = {
136
 
+        QEMU_KVM_ARM_TARGET_CORTEX_A15,
137
 
+        QEMU_KVM_ARM_TARGET_NONE
138
 
+    };
139
 
+    struct kvm_vcpu_init init;
140
 
+    struct kvm_one_reg idregs[] = {
141
 
+        {
142
 
+            .id = KVM_REG_ARM | KVM_REG_SIZE_U32
143
 
+            | ENCODE_CP_REG(15, 0, 0, 0, 0, 0),
144
 
+            .addr = (uintptr_t)&midr,
145
 
+        },
146
 
+        {
147
 
+            .id = KVM_REG_ARM | KVM_REG_SIZE_U32
148
 
+            | ENCODE_CP_REG(15, 0, 0, 1, 0, 0),
149
 
+            .addr = (uintptr_t)&id_pfr0,
150
 
+        },
151
 
+        {
152
 
+            .id = KVM_REG_ARM | KVM_REG_SIZE_U32
153
 
+            | ENCODE_CP_REG(15, 0, 0, 2, 0, 0),
154
 
+            .addr = (uintptr_t)&id_isar0,
155
 
+        },
156
 
+        {
157
 
+            .id = KVM_REG_ARM | KVM_REG_SIZE_U32
158
 
+            | KVM_REG_ARM_VFP | KVM_REG_ARM_VFP_MVFR1,
159
 
+            .addr = (uintptr_t)&mvfr1,
160
 
+        },
161
 
+    };
162
 
+
163
 
+    if (!kvm_arm_create_scratch_host_vcpu(cpus_to_try, fdarray, &init)) {
164
 
+        return false;
165
 
+    }
166
 
+
167
 
+    ahcc->target = init.target;
168
 
+
169
 
+    /* This is not strictly blessed by the device tree binding docs yet,
170
 
+     * but in practice the kernel does not care about this string so
171
 
+     * there is no point maintaining an KVM_ARM_TARGET_* -> string table.
172
 
+     */
173
 
+    ahcc->dtb_compatible = "arm,arm-v7";
174
 
+
175
 
+    for (i = 0; i < ARRAY_SIZE(idregs); i++) {
176
 
+        ret = ioctl(fdarray[2], KVM_GET_ONE_REG, &idregs[i]);
177
 
+        if (ret) {
178
 
+            break;
179
 
+        }
180
 
+    }
181
 
+
182
 
+    kvm_arm_destroy_scratch_host_vcpu(fdarray);
183
 
+
184
 
+    if (ret) {
185
 
+        return false;
186
 
+    }
187
 
+
188
 
+    /* Now we've retrieved all the register information we can
189
 
+     * set the feature bits based on the ID register fields.
190
 
+     * We can assume any KVM supporting CPU is at least a v7
191
 
+     * with VFPv3, LPAE and the generic timers; this in turn implies
192
 
+     * most of the other feature bits, but a few must be tested.
193
 
+     */
194
 
+    set_feature(&features, ARM_FEATURE_V7);
195
 
+    set_feature(&features, ARM_FEATURE_VFP3);
196
 
+    set_feature(&features, ARM_FEATURE_LPAE);
197
 
+    set_feature(&features, ARM_FEATURE_GENERIC_TIMER);
198
 
+
199
 
+    switch (extract32(id_isar0, 24, 4)) {
200
 
+    case 1:
201
 
+        set_feature(&features, ARM_FEATURE_THUMB_DIV);
202
 
+        break;
203
 
+    case 2:
204
 
+        set_feature(&features, ARM_FEATURE_ARM_DIV);
205
 
+        set_feature(&features, ARM_FEATURE_THUMB_DIV);
206
 
+        break;
207
 
+    default:
208
 
+        break;
209
 
+    }
210
 
+
211
 
+    if (extract32(id_pfr0, 12, 4) == 1) {
212
 
+        set_feature(&features, ARM_FEATURE_THUMB2EE);
213
 
+    }
214
 
+    if (extract32(mvfr1, 20, 4) == 1) {
215
 
+        set_feature(&features, ARM_FEATURE_VFP_FP16);
216
 
+    }
217
 
+    if (extract32(mvfr1, 12, 4) == 1) {
218
 
+        set_feature(&features, ARM_FEATURE_NEON);
219
 
+    }
220
 
+    if (extract32(mvfr1, 28, 4) == 1) {
221
 
+        /* FMAC support implies VFPv4 */
222
 
+        set_feature(&features, ARM_FEATURE_VFP4);
223
 
+    }
224
 
+
225
 
+    ahcc->features = features;
226
 
+
227
 
+    return true;
228
 
+}
229
 
+
230
 
+static void kvm_arm_host_cpu_class_init(ObjectClass *oc, void *data)
231
 
+{
232
 
+    ARMHostCPUClass *ahcc = ARM_HOST_CPU_CLASS(oc);
233
 
+
234
 
+    /* All we really need to set up for the 'host' CPU
235
 
+     * is the feature bits -- we rely on the fact that the
236
 
+     * various ID register values in ARMCPU are only used for
237
 
+     * TCG CPUs.
238
 
+     */
239
 
+    if (!kvm_arm_get_host_cpu_features(ahcc)) {
240
 
+        fprintf(stderr, "Failed to retrieve host CPU features!\n");
241
 
+        abort();
242
 
+    }
243
 
+}
244
 
+
245
 
+static void kvm_arm_host_cpu_initfn(Object *obj)
246
 
+{
247
 
+    ARMHostCPUClass *ahcc = ARM_HOST_CPU_GET_CLASS(obj);
248
 
+    ARMCPU *cpu = ARM_CPU(obj);
249
 
+    CPUARMState *env = &cpu->env;
250
 
+
251
 
+    cpu->kvm_target = ahcc->target;
252
 
+    cpu->dtb_compatible = ahcc->dtb_compatible;
253
 
+    env->features = ahcc->features;
254
 
+}
255
 
+
256
 
+static const TypeInfo host_arm_cpu_type_info = {
257
 
+    .name = TYPE_ARM_HOST_CPU,
258
 
+    .parent = TYPE_ARM_CPU,
259
 
+    .instance_init = kvm_arm_host_cpu_initfn,
260
 
+    .class_init = kvm_arm_host_cpu_class_init,
261
 
+    .class_size = sizeof(ARMHostCPUClass),
262
 
+};
263
 
+
264
 
 int kvm_arch_init(KVMState *s)
265
 
 {
266
 
     /* For ARM interrupt delivery is always asynchronous,
267
 
      * whether we are using an in-kernel VGIC or not.
268
 
      */
269
 
     kvm_async_interrupts_allowed = true;
270
 
+
271
 
+    type_register_static(&host_arm_cpu_type_info);
272
 
+
273
 
     return 0;
274
 
 }
275
 
 
276
 
diff --git a/target-arm/kvm_arm.h b/target-arm/kvm_arm.h
277
 
index 5d14887..cd3d13c 100644
278
 
--- a/target-arm/kvm_arm.h
279
 
+++ b/target-arm/kvm_arm.h
280
 
@@ -62,4 +62,59 @@ bool write_list_to_kvmstate(ARMCPU *cpu);
281
 
  */
282
 
 bool write_kvmstate_to_list(ARMCPU *cpu);
283
 
 
284
 
+#ifdef CONFIG_KVM
285
 
+/**
286
 
+ * kvm_arm_create_scratch_host_vcpu:
287
 
+ * @cpus_to_try: array of QEMU_KVM_ARM_TARGET_* values (terminated with
288
 
+ * QEMU_KVM_ARM_TARGET_NONE) to try as fallback if the kernel does not
289
 
+ * know the PREFERRED_TARGET ioctl
290
 
+ * @fdarray: filled in with kvmfd, vmfd, cpufd file descriptors in that order
291
 
+ * @init: filled in with the necessary values for creating a host vcpu
292
 
+ *
293
 
+ * Create a scratch vcpu in its own VM of the type preferred by the host
294
 
+ * kernel (as would be used for '-cpu host'), for purposes of probing it
295
 
+ * for capabilities.
296
 
+ *
297
 
+ * Returns: true on success (and fdarray and init are filled in),
298
 
+ * false on failure (and fdarray and init are not valid).
299
 
+ */
300
 
+bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
301
 
+                                      int *fdarray,
302
 
+                                      struct kvm_vcpu_init *init);
303
 
+
304
 
+/**
305
 
+ * kvm_arm_destroy_scratch_host_vcpu:
306
 
+ * @fdarray: array of fds as set up by kvm_arm_create_scratch_host_vcpu
307
 
+ *
308
 
+ * Tear down the scratch vcpu created by kvm_arm_create_scratch_host_vcpu.
309
 
+ */
310
 
+void kvm_arm_destroy_scratch_host_vcpu(int *fdarray);
311
 
+
312
 
+#define TYPE_ARM_HOST_CPU "host-" TYPE_ARM_CPU
313
 
+#define ARM_HOST_CPU_CLASS(klass) \
314
 
+    OBJECT_CLASS_CHECK(ARMHostCPUClass, (klass), TYPE_ARM_HOST_CPU)
315
 
+#define ARM_HOST_CPU_GET_CLASS(obj) \
316
 
+    OBJECT_GET_CLASS(ARMHostCPUClass, (obj), TYPE_ARM_HOST_CPU)
317
 
+
318
 
+typedef struct ARMHostCPUClass {
319
 
+    /*< private >*/
320
 
+    ARMCPUClass parent_class;
321
 
+    /*< public >*/
322
 
+
323
 
+    uint64_t features;
324
 
+    uint32_t target;
325
 
+    const char *dtb_compatible;
326
 
+} ARMHostCPUClass;
327
 
+
328
 
+/**
329
 
+ * kvm_arm_get_host_cpu_features:
330
 
+ * @ahcc: ARMHostCPUClass to fill in
331
 
+ *
332
 
+ * Probe the capabilities of the host kernel's preferred CPU and fill
333
 
+ * in the ARMHostCPUClass struct accordingly.
334
 
+ */
335
 
+bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc);
336
 
+
337
 
+#endif
338
 
+
339
 
 #endif
340
 
1.8.5.2
341