xref: /qemu/linux-user/aarch64/cpu_loop.c (revision 372b69f503d47eb6619a98cac2ab5a6a569e3483)
1  /*
2   *  qemu user cpu loop
3   *
4   *  Copyright (c) 2003-2008 Fabrice Bellard
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 as published by
8   *  the Free Software Foundation; either version 2 of the License, or
9   *  (at your option) any later version.
10   *
11   *  This program is distributed in the hope that it will be useful,
12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   *  GNU General Public License for more details.
15   *
16   *  You should have received a copy of the GNU General Public License
17   *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18   */
19  
20  #include "qemu/osdep.h"
21  #include "qemu.h"
22  #include "user-internals.h"
23  #include "cpu_loop-common.h"
24  #include "signal-common.h"
25  #include "qemu/guest-random.h"
26  #include "semihosting/common-semi.h"
27  #include "target/arm/syndrome.h"
28  #include "target/arm/cpu-features.h"
29  
30  #define get_user_code_u32(x, gaddr, env)                \
31      ({ abi_long __r = get_user_u32((x), (gaddr));       \
32          if (!__r && bswap_code(arm_sctlr_b(env))) {     \
33              (x) = bswap32(x);                           \
34          }                                               \
35          __r;                                            \
36      })
37  
38  #define get_user_code_u16(x, gaddr, env)                \
39      ({ abi_long __r = get_user_u16((x), (gaddr));       \
40          if (!__r && bswap_code(arm_sctlr_b(env))) {     \
41              (x) = bswap16(x);                           \
42          }                                               \
43          __r;                                            \
44      })
45  
46  #define get_user_data_u32(x, gaddr, env)                \
47      ({ abi_long __r = get_user_u32((x), (gaddr));       \
48          if (!__r && arm_cpu_bswap_data(env)) {          \
49              (x) = bswap32(x);                           \
50          }                                               \
51          __r;                                            \
52      })
53  
54  #define get_user_data_u16(x, gaddr, env)                \
55      ({ abi_long __r = get_user_u16((x), (gaddr));       \
56          if (!__r && arm_cpu_bswap_data(env)) {          \
57              (x) = bswap16(x);                           \
58          }                                               \
59          __r;                                            \
60      })
61  
62  #define put_user_data_u32(x, gaddr, env)                \
63      ({ typeof(x) __x = (x);                             \
64          if (arm_cpu_bswap_data(env)) {                  \
65              __x = bswap32(__x);                         \
66          }                                               \
67          put_user_u32(__x, (gaddr));                     \
68      })
69  
70  #define put_user_data_u16(x, gaddr, env)                \
71      ({ typeof(x) __x = (x);                             \
72          if (arm_cpu_bswap_data(env)) {                  \
73              __x = bswap16(__x);                         \
74          }                                               \
75          put_user_u16(__x, (gaddr));                     \
76      })
77  
78  /* AArch64 main loop */
79  void cpu_loop(CPUARMState *env)
80  {
81      CPUState *cs = env_cpu(env);
82      int trapnr, ec, fsc, si_code, si_signo;
83      abi_long ret;
84  
85      for (;;) {
86          cpu_exec_start(cs);
87          trapnr = cpu_exec(cs);
88          cpu_exec_end(cs);
89          process_queued_cpu_work(cs);
90  
91          switch (trapnr) {
92          case EXCP_SWI:
93              /* On syscall, PSTATE.ZA is preserved, PSTATE.SM is cleared. */
94              aarch64_set_svcr(env, 0, R_SVCR_SM_MASK);
95              ret = do_syscall(env,
96                               env->xregs[8],
97                               env->xregs[0],
98                               env->xregs[1],
99                               env->xregs[2],
100                               env->xregs[3],
101                               env->xregs[4],
102                               env->xregs[5],
103                               0, 0);
104              if (ret == -QEMU_ERESTARTSYS) {
105                  env->pc -= 4;
106              } else if (ret != -QEMU_ESIGRETURN) {
107                  env->xregs[0] = ret;
108              }
109              break;
110          case EXCP_INTERRUPT:
111              /* just indicate that signals should be handled asap */
112              break;
113          case EXCP_UDEF:
114              force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->pc);
115              break;
116          case EXCP_PREFETCH_ABORT:
117          case EXCP_DATA_ABORT:
118              ec = syn_get_ec(env->exception.syndrome);
119              switch (ec) {
120              case EC_DATAABORT:
121              case EC_INSNABORT:
122                  /* Both EC have the same format for FSC, or close enough. */
123                  fsc = extract32(env->exception.syndrome, 0, 6);
124                  switch (fsc) {
125                  case 0x04 ... 0x07: /* Translation fault, level {0-3} */
126                      si_signo = TARGET_SIGSEGV;
127                      si_code = TARGET_SEGV_MAPERR;
128                      break;
129                  case 0x09 ... 0x0b: /* Access flag fault, level {1-3} */
130                  case 0x0d ... 0x0f: /* Permission fault, level {1-3} */
131                      si_signo = TARGET_SIGSEGV;
132                      si_code = TARGET_SEGV_ACCERR;
133                      break;
134                  case 0x11: /* Synchronous Tag Check Fault */
135                      si_signo = TARGET_SIGSEGV;
136                      si_code = TARGET_SEGV_MTESERR;
137                      break;
138                  case 0x21: /* Alignment fault */
139                      si_signo = TARGET_SIGBUS;
140                      si_code = TARGET_BUS_ADRALN;
141                      break;
142                  default:
143                      g_assert_not_reached();
144                  }
145                  break;
146              case EC_PCALIGNMENT:
147                  si_signo = TARGET_SIGBUS;
148                  si_code = TARGET_BUS_ADRALN;
149                  break;
150              default:
151                  g_assert_not_reached();
152              }
153              force_sig_fault(si_signo, si_code, env->exception.vaddress);
154              break;
155          case EXCP_DEBUG:
156          case EXCP_BKPT:
157              force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
158              break;
159          case EXCP_SEMIHOST:
160              do_common_semihosting(cs);
161              env->pc += 4;
162              break;
163          case EXCP_YIELD:
164              /* nothing to do here for user-mode, just resume guest code */
165              break;
166          case EXCP_ATOMIC:
167              cpu_exec_step_atomic(cs);
168              break;
169          default:
170              EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
171              abort();
172          }
173  
174          /* Check for MTE asynchronous faults */
175          if (unlikely(env->cp15.tfsr_el[0])) {
176              env->cp15.tfsr_el[0] = 0;
177              force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MTEAERR, 0);
178          }
179  
180          process_pending_signals(env);
181          /* Exception return on AArch64 always clears the exclusive monitor,
182           * so any return to running guest code implies this.
183           */
184          env->exclusive_addr = -1;
185      }
186  }
187  
188  void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
189  {
190      ARMCPU *cpu = env_archcpu(env);
191      CPUState *cs = env_cpu(env);
192      TaskState *ts = cs->opaque;
193      struct image_info *info = ts->info;
194      int i;
195  
196      if (!(arm_feature(env, ARM_FEATURE_AARCH64))) {
197          fprintf(stderr,
198                  "The selected ARM CPU does not support 64 bit mode\n");
199          exit(EXIT_FAILURE);
200      }
201  
202      for (i = 0; i < 31; i++) {
203          env->xregs[i] = regs->regs[i];
204      }
205      env->pc = regs->pc;
206      env->xregs[31] = regs->sp;
207  #if TARGET_BIG_ENDIAN
208      env->cp15.sctlr_el[1] |= SCTLR_E0E;
209      for (i = 1; i < 4; ++i) {
210          env->cp15.sctlr_el[i] |= SCTLR_EE;
211      }
212      arm_rebuild_hflags(env);
213  #endif
214  
215      if (cpu_isar_feature(aa64_pauth, cpu)) {
216          qemu_guest_getrandom_nofail(&env->keys, sizeof(env->keys));
217      }
218  
219      ts->stack_base = info->start_stack;
220      ts->heap_base = info->brk;
221      /* This will be filled in on the first SYS_HEAPINFO call.  */
222      ts->heap_limit = 0;
223  }
224