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

« back to all changes in this revision

Viewing changes to debian/patches/arm64/0024-target-arm-Split-A64-from-A32-T32-gen_intermediate_c.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 f96f1df1c9b50914fb618369b747fff4ae66b72e Mon Sep 17 00:00:00 2001
2
 
From: Peter Maydell <peter.maydell@linaro.org>
3
 
Date: Tue, 17 Dec 2013 19:42:31 +0000
4
 
Subject: [PATCH 24/49] target-arm: Split A64 from A32/T32
5
 
 gen_intermediate_code_internal()
6
 
 
7
 
The A32/T32 gen_intermediate_code_internal() is complicated because it
8
 
has to deal with:
9
 
 * conditionally executed instructions
10
 
 * Thumb IT blocks
11
 
 * kernel helper page
12
 
 * M profile exception-exit special casing
13
 
 
14
 
None of these apply to A64, so putting the "this is A64 so
15
 
call the A64 decoder" check in the middle of the A32/T32
16
 
loop is confusing and means the A64 decoder's handling of
17
 
things like conditional jump and singlestepping has to take
18
 
account of the conditional-execution jumps the main loop
19
 
might emit.
20
 
 
21
 
Refactor the code to give A64 its own gen_intermediate_code_internal
22
 
function instead.
23
 
 
24
 
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
 
Reviewed-by: Richard Henderson <rth@twiddle.net>
26
 
---
27
 
 target-arm/translate-a64.c | 209 +++++++++++++++++++++++++++++++++++++++++++--
28
 
 target-arm/translate.c     |  62 ++++++--------
29
 
 target-arm/translate.h     |  20 ++++-
30
 
 3 files changed, 246 insertions(+), 45 deletions(-)
31
 
 
32
 
Index: qemu/target-arm/translate-a64.c
33
 
===================================================================
34
 
--- qemu.orig/target-arm/translate-a64.c        2014-01-10 12:08:03.444166815 -0600
35
 
+++ qemu/target-arm/translate-a64.c     2014-01-10 12:08:03.436166815 -0600
36
 
@@ -28,6 +28,8 @@
37
 
 #include "translate.h"
38
 
 #include "qemu/host-utils.h"
39
 
 
40
 
+#include "exec/gen-icount.h"
41
 
+
42
 
 #include "helper.h"
43
 
 #define GEN_HELPER 1
44
 
 #include "helper.h"
45
 
@@ -106,7 +108,42 @@ static void gen_exception_insn(DisasCont
46
 
 {
47
 
     gen_a64_set_pc_im(s->pc - offset);
48
 
     gen_exception(excp);
49
 
-    s->is_jmp = DISAS_JUMP;
50
 
+    s->is_jmp = DISAS_EXC;
51
 
+}
52
 
+
53
 
+static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
54
 
+{
55
 
+    /* No direct tb linking with singlestep or deterministic io */
56
 
+    if (s->singlestep_enabled || (s->tb->cflags & CF_LAST_IO)) {
57
 
+        return false;
58
 
+    }
59
 
+
60
 
+    /* Only link tbs from inside the same guest page */
61
 
+    if ((s->tb->pc & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
62
 
+        return false;
63
 
+    }
64
 
+
65
 
+    return true;
66
 
+}
67
 
+
68
 
+static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
69
 
+{
70
 
+    TranslationBlock *tb;
71
 
+
72
 
+    tb = s->tb;
73
 
+    if (use_goto_tb(s, n, dest)) {
74
 
+        tcg_gen_goto_tb(n);
75
 
+        gen_a64_set_pc_im(dest);
76
 
+        tcg_gen_exit_tb((tcg_target_long)tb + n);
77
 
+        s->is_jmp = DISAS_TB_JUMP;
78
 
+    } else {
79
 
+        gen_a64_set_pc_im(dest);
80
 
+        if (s->singlestep_enabled) {
81
 
+            gen_exception(EXCP_DEBUG);
82
 
+        }
83
 
+        tcg_gen_exit_tb(0);
84
 
+        s->is_jmp = DISAS_JUMP;
85
 
+    }
86
 
 }
87
 
 
88
 
 static void real_unallocated_encoding(DisasContext *s)
89
 
@@ -120,7 +157,7 @@ static void real_unallocated_encoding(Di
90
 
     real_unallocated_encoding(s); \
91
 
     } while (0)
92
 
 
93
 
-void disas_a64_insn(CPUARMState *env, DisasContext *s)
94
 
+static void disas_a64_insn(CPUARMState *env, DisasContext *s)
95
 
 {
96
 
     uint32_t insn;
97
 
 
98
 
@@ -133,9 +170,171 @@ void disas_a64_insn(CPUARMState *env, Di
99
 
         unallocated_encoding(s);
100
 
         break;
101
 
     }
102
 
+}
103
 
 
104
 
-    if (unlikely(s->singlestep_enabled) && (s->is_jmp == DISAS_TB_JUMP)) {
105
 
-        /* go through the main loop for single step */
106
 
-        s->is_jmp = DISAS_JUMP;
107
 
+void gen_intermediate_code_internal_a64(ARMCPU *cpu,
108
 
+                                        TranslationBlock *tb,
109
 
+                                        bool search_pc)
110
 
+{
111
 
+    CPUState *cs = CPU(cpu);
112
 
+    CPUARMState *env = &cpu->env;
113
 
+    DisasContext dc1, *dc = &dc1;
114
 
+    CPUBreakpoint *bp;
115
 
+    uint16_t *gen_opc_end;
116
 
+    int j, lj;
117
 
+    target_ulong pc_start;
118
 
+    target_ulong next_page_start;
119
 
+    int num_insns;
120
 
+    int max_insns;
121
 
+
122
 
+    pc_start = tb->pc;
123
 
+
124
 
+    dc->tb = tb;
125
 
+
126
 
+    gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
127
 
+
128
 
+    dc->is_jmp = DISAS_NEXT;
129
 
+    dc->pc = pc_start;
130
 
+    dc->singlestep_enabled = cs->singlestep_enabled;
131
 
+    dc->condjmp = 0;
132
 
+
133
 
+    dc->aarch64 = 1;
134
 
+    dc->thumb = 0;
135
 
+    dc->bswap_code = 0;
136
 
+    dc->condexec_mask = 0;
137
 
+    dc->condexec_cond = 0;
138
 
+#if !defined(CONFIG_USER_ONLY)
139
 
+    dc->user = 0;
140
 
+#endif
141
 
+    dc->vfp_enabled = 0;
142
 
+    dc->vec_len = 0;
143
 
+    dc->vec_stride = 0;
144
 
+
145
 
+    next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
146
 
+    lj = -1;
147
 
+    num_insns = 0;
148
 
+    max_insns = tb->cflags & CF_COUNT_MASK;
149
 
+    if (max_insns == 0) {
150
 
+        max_insns = CF_COUNT_MASK;
151
 
+    }
152
 
+
153
 
+    gen_tb_start();
154
 
+
155
 
+    tcg_clear_temp_count();
156
 
+
157
 
+    do {
158
 
+        if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
159
 
+            QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
160
 
+                if (bp->pc == dc->pc) {
161
 
+                    gen_exception_insn(dc, 0, EXCP_DEBUG);
162
 
+                    /* Advance PC so that clearing the breakpoint will
163
 
+                       invalidate this TB.  */
164
 
+                    dc->pc += 2;
165
 
+                    goto done_generating;
166
 
+                }
167
 
+            }
168
 
+        }
169
 
+
170
 
+        if (search_pc) {
171
 
+            j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
172
 
+            if (lj < j) {
173
 
+                lj++;
174
 
+                while (lj < j) {
175
 
+                    tcg_ctx.gen_opc_instr_start[lj++] = 0;
176
 
+                }
177
 
+            }
178
 
+            tcg_ctx.gen_opc_pc[lj] = dc->pc;
179
 
+            tcg_ctx.gen_opc_instr_start[lj] = 1;
180
 
+            tcg_ctx.gen_opc_icount[lj] = num_insns;
181
 
+        }
182
 
+
183
 
+        if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
184
 
+            gen_io_start();
185
 
+        }
186
 
+
187
 
+        if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
188
 
+            tcg_gen_debug_insn_start(dc->pc);
189
 
+        }
190
 
+
191
 
+        disas_a64_insn(env, dc);
192
 
+
193
 
+        if (tcg_check_temp_count()) {
194
 
+            fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
195
 
+                    dc->pc);
196
 
+        }
197
 
+
198
 
+        /* Translation stops when a conditional branch is encountered.
199
 
+         * Otherwise the subsequent code could get translated several times.
200
 
+         * Also stop translation when a page boundary is reached.  This
201
 
+         * ensures prefetch aborts occur at the right place.
202
 
+         */
203
 
+        num_insns++;
204
 
+    } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
205
 
+             !cs->singlestep_enabled &&
206
 
+             !singlestep &&
207
 
+             dc->pc < next_page_start &&
208
 
+             num_insns < max_insns);
209
 
+
210
 
+    if (tb->cflags & CF_LAST_IO) {
211
 
+        gen_io_end();
212
 
+    }
213
 
+
214
 
+    if (unlikely(cs->singlestep_enabled) && dc->is_jmp != DISAS_EXC) {
215
 
+        /* Note that this means single stepping WFI doesn't halt the CPU.
216
 
+         * For conditional branch insns this is harmless unreachable code as
217
 
+         * gen_goto_tb() has already handled emitting the debug exception
218
 
+         * (and thus a tb-jump is not possible when singlestepping).
219
 
+         */
220
 
+        assert(dc->is_jmp != DISAS_TB_JUMP);
221
 
+        if (dc->is_jmp != DISAS_JUMP) {
222
 
+            gen_a64_set_pc_im(dc->pc);
223
 
+        }
224
 
+        gen_exception(EXCP_DEBUG);
225
 
+    } else {
226
 
+        switch (dc->is_jmp) {
227
 
+        case DISAS_NEXT:
228
 
+            gen_goto_tb(dc, 1, dc->pc);
229
 
+            break;
230
 
+        default:
231
 
+        case DISAS_JUMP:
232
 
+        case DISAS_UPDATE:
233
 
+            /* indicate that the hash table must be used to find the next TB */
234
 
+            tcg_gen_exit_tb(0);
235
 
+            break;
236
 
+        case DISAS_TB_JUMP:
237
 
+        case DISAS_EXC:
238
 
+        case DISAS_SWI:
239
 
+            break;
240
 
+        case DISAS_WFI:
241
 
+            /* This is a special case because we don't want to just halt the CPU
242
 
+             * if trying to debug across a WFI.
243
 
+             */
244
 
+            gen_helper_wfi(cpu_env);
245
 
+            break;
246
 
+        }
247
 
+    }
248
 
+
249
 
+done_generating:
250
 
+    gen_tb_end(tb, num_insns);
251
 
+    *tcg_ctx.gen_opc_ptr = INDEX_op_end;
252
 
+
253
 
+#ifdef DEBUG_DISAS
254
 
+    if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
255
 
+        qemu_log("----------------\n");
256
 
+        qemu_log("IN: %s\n", lookup_symbol(pc_start));
257
 
+        log_target_disas(env, pc_start, dc->pc - pc_start,
258
 
+                         dc->thumb | (dc->bswap_code << 1));
259
 
+        qemu_log("\n");
260
 
+    }
261
 
+#endif
262
 
+    if (search_pc) {
263
 
+        j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
264
 
+        lj++;
265
 
+        while (lj <= j) {
266
 
+            tcg_ctx.gen_opc_instr_start[lj++] = 0;
267
 
+        }
268
 
+    } else {
269
 
+        tb->size = dc->pc - pc_start;
270
 
+        tb->icount = num_insns;
271
 
     }
272
 
 }
273
 
Index: qemu/target-arm/translate.c
274
 
===================================================================
275
 
--- qemu.orig/target-arm/translate.c    2014-01-10 12:07:58.348166701 -0600
276
 
+++ qemu/target-arm/translate.c 2014-01-10 12:14:18.576175248 -0600
277
 
@@ -50,18 +50,18 @@
278
 
 #include "translate.h"
279
 
 static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
280
 
 
281
 
-#if defined(CONFIG_USER_ONLY)
282
 
-#define IS_USER(s) 1
283
 
-#else
284
 
-#define IS_USER(s) (s->user)
285
 
-#endif
286
 
-
287
 
 /* These instructions trap after executing, so defer them until after the
288
 
    conditional execution state has been updated.  */
289
 
 #define DISAS_WFI 4
290
 
 #define DISAS_SWI 5
291
 
 #define DISAS_SMC 6
292
 
 
293
 
+#if defined(CONFIG_USER_ONLY)
294
 
+#define IS_USER(s) 1
295
 
+#else
296
 
+#define IS_USER(s) (s->user)
297
 
+#endif
298
 
+
299
 
 TCGv_ptr cpu_env;
300
 
 /* We reuse the same 64-bit temporaries for efficiency.  */
301
 
 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
302
 
@@ -907,11 +907,7 @@ static inline void gen_smc(CPUARMState *
303
 
 
304
 
 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
305
 
 {
306
 
-    if (s->aarch64) {
307
 
-        gen_a64_set_pc_im(val);
308
 
-    } else {
309
 
-        tcg_gen_movi_i32(cpu_R[15], val);
310
 
-    }
311
 
+    tcg_gen_movi_i32(cpu_R[15], val);
312
 
 }
313
 
 
314
 
 /* Force a TB lookup after an instruction that changes the CPU state.  */
315
 
@@ -10235,6 +10231,15 @@ static inline void gen_intermediate_code
316
 
     int max_insns;
317
 
 
318
 
     /* generate intermediate code */
319
 
+
320
 
+    /* The A64 decoder has its own top level loop, because it doesn't need
321
 
+     * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
322
 
+     */
323
 
+    if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
324
 
+        gen_intermediate_code_internal_a64(cpu, tb, search_pc);
325
 
+        return;
326
 
+    }
327
 
+
328
 
     pc_start = tb->pc;
329
 
 
330
 
     dc->tb = tb;
331
 
@@ -10246,31 +10251,18 @@ static inline void gen_intermediate_code
332
 
     dc->singlestep_enabled = cs->singlestep_enabled;
333
 
     dc->condjmp = 0;
334
 
 
335
 
-    if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
336
 
-        dc->aarch64 = 1;
337
 
-        dc->thumb = 0;
338
 
-        dc->bswap_code = 0;
339
 
-        dc->condexec_mask = 0;
340
 
-        dc->condexec_cond = 0;
341
 
-#if !defined(CONFIG_USER_ONLY)
342
 
-        dc->user = 0;
343
 
-#endif
344
 
-        dc->vfp_enabled = 0;
345
 
-        dc->vec_len = 0;
346
 
-        dc->vec_stride = 0;
347
 
-    } else {
348
 
-        dc->aarch64 = 0;
349
 
-        dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
350
 
-        dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
351
 
-        dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
352
 
-        dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
353
 
+    dc->aarch64 = 0;
354
 
+    dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
355
 
+    dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
356
 
+    dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
357
 
+    dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
358
 
 #if !defined(CONFIG_USER_ONLY)
359
 
-        dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
360
 
+    dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
361
 
 #endif
362
 
-        dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
363
 
-        dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
364
 
-        dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
365
 
-    }
366
 
+    dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
367
 
+    dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
368
 
+    dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
369
 
+
370
 
     cpu_F0s = tcg_temp_new_i32();
371
 
     cpu_F1s = tcg_temp_new_i32();
372
 
     cpu_F0d = tcg_temp_new_i64();
373
 
@@ -10332,7 +10324,7 @@ static inline void gen_intermediate_code
374
 
     do {
375
 
 #ifdef CONFIG_USER_ONLY
376
 
         /* Intercept jump to the magic kernel page.  */
377
 
-        if (!dc->aarch64 && dc->pc >= 0xffff0000) {
378
 
+        if (dc->pc >= 0xffff0000) {
379
 
             /* We always get here via a jump, so know we are not in a
380
 
                conditional execution block.  */
381
 
             gen_exception(EXCP_KERNEL_TRAP);
382
 
@@ -10380,9 +10372,7 @@ static inline void gen_intermediate_code
383
 
             tcg_gen_debug_insn_start(dc->pc);
384
 
         }
385
 
 
386
 
-        if (dc->aarch64) {
387
 
-            disas_a64_insn(env, dc);
388
 
-        } else if (dc->thumb) {
389
 
+        if (dc->thumb) {
390
 
             disas_thumb_insn(env, dc);
391
 
             if (dc->condexec_mask) {
392
 
                 dc->condexec_cond = (dc->condexec_cond & 0xe)
393
 
@@ -10584,8 +10574,9 @@ void restore_state_to_opc(CPUARMState *e
394
 
 {
395
 
     if (is_a64(env)) {
396
 
         env->pc = tcg_ctx.gen_opc_pc[pc_pos];
397
 
+        env->condexec_bits = 0;
398
 
     } else {
399
 
         env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
400
 
+        env->condexec_bits = gen_opc_condexec_bits[pc_pos];
401
 
     }
402
 
-    env->condexec_bits = gen_opc_condexec_bits[pc_pos];
403
 
 }
404
 
Index: qemu/target-arm/translate.h
405
 
===================================================================
406
 
--- qemu.orig/target-arm/translate.h    2014-01-10 12:08:03.444166815 -0600
407
 
+++ qemu/target-arm/translate.h 2014-01-10 12:08:03.440166815 -0600
408
 
@@ -28,16 +28,32 @@ typedef struct DisasContext {
409
 
 
410
 
 extern TCGv_ptr cpu_env;
411
 
 
412
 
+/* target-specific extra values for is_jmp */
413
 
+/* These instructions trap after executing, so the A32/T32 decoder must
414
 
+ * defer them until after the conditional execution state has been updated.
415
 
+ * WFI also needs special handling when single-stepping.
416
 
+ */
417
 
+#define DISAS_WFI 4
418
 
+#define DISAS_SWI 5
419
 
+/* For instructions which unconditionally cause an exception we can skip
420
 
+ * emitting unreachable code at the end of the TB in the A64 decoder
421
 
+ */
422
 
+#define DISAS_EXC 6
423
 
+
424
 
 #ifdef TARGET_AARCH64
425
 
 void a64_translate_init(void);
426
 
-void disas_a64_insn(CPUARMState *env, DisasContext *s);
427
 
+void gen_intermediate_code_internal_a64(ARMCPU *cpu,
428
 
+                                        TranslationBlock *tb,
429
 
+                                        bool search_pc);
430
 
 void gen_a64_set_pc_im(uint64_t val);
431
 
 #else
432
 
 static inline void a64_translate_init(void)
433
 
 {
434
 
 }
435
 
 
436
 
-static inline void disas_a64_insn(CPUARMState *env, DisasContext *s)
437
 
+static inline void gen_intermediate_code_internal_a64(ARMCPU *cpu,
438
 
+                                                      TranslationBlock *tb,
439
 
+                                                      bool search_pc)
440
 
 {
441
 
 }
442