qemu

Форк
0
/
cpu_loop.c 
223 строки · 7.9 Кб
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 = get_task_state(cs);
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

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.