master
inc 329 lines 8.88 KB
Raw
1 /*
2 * Power ISA decode for misc instructions
3 *
4 * Copyright (c) 2024, IBM Corporation.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library 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 GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 /*
21 * Memory Barrier Instructions
22 */
23
24 static bool trans_SYNC(DisasContext *ctx, arg_X_sync *a)
25 {
26 TCGBar bar = TCG_MO_ALL;
27 uint32_t l = a->l;
28 uint32_t sc = a->sc;
29
30 /*
31 * BookE uses the msync mnemonic. This means hwsync, except in the
32 * 440, where it an execution serialisation point that requires all
33 * previous storage accesses to have been performed to memory (which
34 * doesn't matter for TCG).
35 */
36 if (!(ctx->insns_flags & PPC_MEM_SYNC)) {
37 if (ctx->insns_flags & PPC_BOOKE) {
38 tcg_gen_mb(bar | TCG_BAR_SC);
39 return true;
40 }
41
42 return false;
43 }
44
45 /*
46 * In ISA v3.1, the L field grew one bit. Mask that out to ignore it in
47 * older processors. It also added the SC field, zero this to ignore
48 * it too.
49 */
50 if (!(ctx->insns_flags2 & PPC2_ISA310)) {
51 l &= 0x3;
52 sc = 0;
53 }
54
55 if (sc) {
56 /* Store syncs [stsync, stcisync, stncisync]. These ignore L. */
57 bar = TCG_MO_ST_ST;
58 } else {
59 if (((l == 1) && (ctx->insns_flags2 & PPC2_MEM_LWSYNC)) || (l == 5)) {
60 /* lwsync, or plwsync on POWER10 and later */
61 bar = TCG_MO_LD_LD | TCG_MO_LD_ST | TCG_MO_ST_ST;
62 }
63
64 /*
65 * We may need to check for a pending TLB flush.
66 *
67 * We do this on ptesync (l == 2) on ppc64 and any sync on ppc32.
68 *
69 * Additionally, this can only happen in kernel mode however so
70 * check MSR_PR as well.
71 */
72 if (((l == 2) || !(ctx->insns_flags & PPC_64B)) && !ctx->pr) {
73 gen_check_tlb_flush(ctx, true);
74 }
75 }
76
77 tcg_gen_mb(bar | TCG_BAR_SC);
78
79 return true;
80 }
81
82 static bool trans_EIEIO(DisasContext *ctx, arg_EIEIO *a)
83 {
84 TCGBar bar = TCG_MO_ALL;
85
86 /*
87 * BookE uses the mbar instruction instead of eieio, which is basically
88 * full hwsync memory barrier, but is not execution synchronising. For
89 * the purpose of TCG the distinction is not relevant.
90 */
91 if (!(ctx->insns_flags & PPC_MEM_EIEIO)) {
92 if ((ctx->insns_flags & PPC_BOOKE) ||
93 (ctx->insns_flags2 & PPC2_BOOKE206)) {
94 tcg_gen_mb(bar | TCG_BAR_SC);
95 return true;
96 }
97 return false;
98 }
99
100 /*
101 * eieio has complex semanitcs. It provides memory ordering between
102 * operations in the set:
103 * - loads from CI memory.
104 * - stores to CI memory.
105 * - stores to WT memory.
106 *
107 * It separately also orders memory for operations in the set:
108 * - stores to cacheble memory.
109 *
110 * It also serializes instructions:
111 * - dcbt and dcbst.
112 *
113 * It separately serializes:
114 * - tlbie and tlbsync.
115 *
116 * And separately serializes:
117 * - slbieg, slbiag, and slbsync.
118 *
119 * The end result is that CI memory ordering requires TCG_MO_ALL
120 * and it is not possible to special-case more relaxed ordering for
121 * cacheable accesses. TCG_BAR_SC is required to provide this
122 * serialization.
123 */
124
125 /*
126 * POWER9 has a eieio instruction variant using bit 6 as a hint to
127 * tell the CPU it is a store-forwarding barrier.
128 */
129 if (ctx->opcode & 0x2000000) {
130 /*
131 * ISA says that "Reserved fields in instructions are ignored
132 * by the processor". So ignore the bit 6 on non-POWER9 CPU but
133 * as this is not an instruction software should be using,
134 * complain to the user.
135 */
136 if (!(ctx->insns_flags2 & PPC2_ISA300)) {
137 qemu_log_mask(LOG_GUEST_ERROR, "invalid eieio using bit 6 at @"
138 TARGET_FMT_lx "\n", ctx->cia);
139 } else {
140 bar = TCG_MO_ST_LD;
141 }
142 }
143
144 tcg_gen_mb(bar | TCG_BAR_SC);
145
146 return true;
147 }
148
149 static bool trans_ATTN(DisasContext *ctx, arg_ATTN *a)
150 {
151 #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
152 gen_helper_attn(tcg_env);
153 return true;
154 #else
155 return false;
156 #endif
157 }
158
159 static bool trans_MCRF(DisasContext *ctx, arg_MCRF *a)
160 {
161 tcg_gen_mov_i32(cpu_crf[a->bf], cpu_crf[a->bfa]);
162 return true;
163 }
164
165 static bool do_mfmsr(DisasContext *ctx, arg_X_t *a)
166 {
167 REQUIRE_SV(ctx);
168 tcg_gen_mov_tl(cpu_gpr[a->rt], cpu_msr);
169 return true;
170 }
171 TRANS_FLAGS(MISC, MFMSR, do_mfmsr)
172
173 static bool do_mtmsr(DisasContext *ctx, arg_X_rs_l *a, bool is_mtmsrd)
174 {
175 REQUIRE_SV(ctx);
176 #if !defined(CONFIG_USER_ONLY)
177 TCGv t0, t1;
178 target_ulong mask;
179
180 if (is_mtmsrd) {
181 if (unlikely(!is_book3s_arch2x(ctx))) {
182 gen_invalid(ctx);
183 return true;
184 }
185 mask = ~(target_ulong)0;
186 } else {
187 mask = UINT32_MAX;
188 }
189
190 t0 = tcg_temp_new();
191 t1 = tcg_temp_new();
192 translator_io_start(&ctx->base);
193
194 if (a->l) {
195 /* L=1 form only updates EE and RI */
196 mask &= (1ULL << MSR_RI) | (1ULL << MSR_EE);
197 } else {
198 if (is_mtmsrd) {
199 /* mtmsrd does not alter HV, S, ME, or LE */
200 mask &= ~((1ULL << MSR_LE) | (1ULL << MSR_ME) |
201 (1ULL << MSR_S) | (1ULL << MSR_HV));
202 } else if (likely(!(ctx->insns_flags2 & PPC2_PPE42))) {
203 /* mtmsr does not alter S, ME, or LE */
204 mask &= ~((1ULL << MSR_LE) | (1ULL << MSR_ME) | (1ULL << MSR_S));
205 }
206 /*
207 * XXX: we need to update nip before the store if we enter
208 * power saving mode, we will exit the loop directly from
209 * ppc_store_msr
210 */
211 gen_update_nip(ctx, ctx->base.pc_next);
212 }
213
214 tcg_gen_andi_tl(t0, cpu_gpr[a->rs], mask);
215 tcg_gen_andi_tl(t1, cpu_msr, ~mask);
216 tcg_gen_or_tl(t0, t0, t1);
217
218 gen_helper_store_msr(tcg_env, t0);
219
220 /* Must stop the translation as machine state (may have) changed */
221 ctx->base.is_jmp = DISAS_EXIT_UPDATE;
222 #endif /* !CONFIG_USER_ONLY */
223 return true;
224 }
225
226 TRANS_FLAGS(MISC, MTMSR, do_mtmsr, false)
227 TRANS64(MTMSRD, do_mtmsr, true)
228
229 /*
230 * System Call and Return from Interrupt Instructions
231 */
232
233 static bool do_SC(DisasContext *ctx, arg_SC *a, uint32_t excp)
234 {
235 uint32_t lev;
236
237 /*
238 * LEV is a 7-bit field, but the top 6 bits are treated as a reserved
239 * field (i.e., ignored). ISA v3.1 changes that to 5 bits, but that is
240 * for Ultravisor which TCG does not support, so just ignore the top 6.
241 */
242 lev = a->lev & 0x1;
243 gen_exception_err(ctx, excp, lev);
244 return true;
245 }
246
247 static bool do_SCV(DisasContext *ctx, arg_SC *a)
248 {
249 #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
250 /* Set the PC back to the faulting instruction. */
251 gen_update_nip(ctx, ctx->cia);
252 gen_helper_scv(tcg_env, tcg_constant_i32(a->lev));
253
254 ctx->base.is_jmp = DISAS_NORETURN;
255 return true;
256 #else
257 gen_invalid(ctx);
258 return true;
259 #endif
260 }
261
262 /*
263 * Common helper for return-from-interrupt instructions
264 */
265 enum {
266 RFI_KIND_RFI = 0,
267 RFI_KIND_RFID = 1,
268 RFI_KIND_HRFID = 2,
269 RFI_KIND_RFSCV = 3,
270 };
271
272 static bool do_rfi(DisasContext *ctx, arg_RFID *a, int kind)
273 {
274 #if defined(CONFIG_USER_ONLY)
275 gen_priv_opc(ctx);
276 return true;
277 #else
278 void (*helper)(TCGv_ptr);
279
280 switch (kind) {
281 case RFI_KIND_RFI:
282 if (is_book3s_arch2x(ctx)) {
283 gen_invalid(ctx);
284 return true;
285 }
286 REQUIRE_SV(ctx);
287 helper = gen_helper_RFI;
288 break;
289 #if defined(TARGET_PPC64)
290 case RFI_KIND_HRFID:
291 REQUIRE_HV(ctx);
292 helper = gen_helper_HRFID;
293 break;
294 case RFI_KIND_RFID:
295 REQUIRE_SV(ctx);
296 helper = gen_helper_RFID;
297 break;
298 case RFI_KIND_RFSCV:
299 REQUIRE_SV(ctx);
300 helper = gen_helper_RFSCV;
301 break;
302 #endif
303 default:
304 gen_invalid(ctx);
305 return true;
306 }
307
308 translator_io_start(&ctx->base);
309 if (kind != RFI_KIND_HRFID) {
310 gen_update_branch_history(ctx, ctx->cia, NULL, BHRB_TYPE_NORECORD);
311 }
312 helper(tcg_env);
313 ctx->base.is_jmp = DISAS_EXIT;
314 return true;
315 #endif
316 }
317
318 #if defined(CONFIG_USER_ONLY)
319 TRANS_FLAGS(FLOW, SC, do_SC, POWERPC_EXCP_SYSCALL_USER)
320 #else
321 TRANS_FLAGS(FLOW, SC, do_SC, POWERPC_EXCP_SYSCALL)
322 #endif
323
324 TRANS64_FLAGS2(ISA300, SCV, do_SCV)
325
326 TRANS_FLAGS(FLOW, RFI, do_rfi, RFI_KIND_RFI)
327 TRANS64(RFID, do_rfi, RFI_KIND_RFID)
328 TRANS64_FLAGS(64H, HRFID, do_rfi, RFI_KIND_HRFID)
329 TRANS64_FLAGS2(ISA300, RFSCV, do_rfi, RFI_KIND_RFSCV)