kvm: qemu: report paravirt features on cpuid
[kvm-userspace.git] / qemu / target-alpha / helper.c
blobfd39f5f8936b7de09fc8af547d398821e5cba1d1
1 /*
2 * Alpha emulation cpu helpers for qemu.
4 * Copyright (c) 2007 Jocelyn Mayer
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 of the License, or (at your option) any later version.
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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <stdio.h>
25 #include "cpu.h"
26 #include "exec-all.h"
28 #if defined(CONFIG_USER_ONLY)
30 int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
31 int mmu_idx, int is_softmmu)
33 if (rw == 2)
34 env->exception_index = EXCP_ITB_MISS;
35 else
36 env->exception_index = EXCP_DFAULT;
37 env->ipr[IPR_EXC_ADDR] = address;
39 return 1;
42 target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
44 return addr;
47 void do_interrupt (CPUState *env)
49 env->exception_index = -1;
52 #else
54 target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
56 return -1;
59 int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
60 int mmu_idx, int is_softmmu)
62 uint32_t opc;
64 if (rw == 2) {
65 /* Instruction translation buffer miss */
66 env->exception_index = EXCP_ITB_MISS;
67 } else {
68 if (env->ipr[IPR_EXC_ADDR] & 1)
69 env->exception_index = EXCP_DTB_MISS_PAL;
70 else
71 env->exception_index = EXCP_DTB_MISS_NATIVE;
72 opc = (ldl_code(env->pc) >> 21) << 4;
73 if (rw) {
74 opc |= 0x9;
75 } else {
76 opc |= 0x4;
78 env->ipr[IPR_MM_STAT] = opc;
81 return 1;
84 int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp)
86 uint64_t hwpcb;
87 int ret = 0;
89 hwpcb = env->ipr[IPR_PCBB];
90 switch (iprn) {
91 case IPR_ASN:
92 if (env->features & FEATURE_ASN)
93 *valp = env->ipr[IPR_ASN];
94 else
95 *valp = 0;
96 break;
97 case IPR_ASTEN:
98 *valp = ((int64_t)(env->ipr[IPR_ASTEN] << 60)) >> 60;
99 break;
100 case IPR_ASTSR:
101 *valp = ((int64_t)(env->ipr[IPR_ASTSR] << 60)) >> 60;
102 break;
103 case IPR_DATFX:
104 /* Write only */
105 ret = -1;
106 break;
107 case IPR_ESP:
108 if (env->features & FEATURE_SPS)
109 *valp = env->ipr[IPR_ESP];
110 else
111 *valp = ldq_raw(hwpcb + 8);
112 break;
113 case IPR_FEN:
114 *valp = ((int64_t)(env->ipr[IPR_FEN] << 63)) >> 63;
115 break;
116 case IPR_IPIR:
117 /* Write-only */
118 ret = -1;
119 break;
120 case IPR_IPL:
121 *valp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59;
122 break;
123 case IPR_KSP:
124 if (!(env->ipr[IPR_EXC_ADDR] & 1)) {
125 ret = -1;
126 } else {
127 if (env->features & FEATURE_SPS)
128 *valp = env->ipr[IPR_KSP];
129 else
130 *valp = ldq_raw(hwpcb + 0);
132 break;
133 case IPR_MCES:
134 *valp = ((int64_t)(env->ipr[IPR_MCES] << 59)) >> 59;
135 break;
136 case IPR_PERFMON:
137 /* Implementation specific */
138 *valp = 0;
139 break;
140 case IPR_PCBB:
141 *valp = ((int64_t)env->ipr[IPR_PCBB] << 16) >> 16;
142 break;
143 case IPR_PRBR:
144 *valp = env->ipr[IPR_PRBR];
145 break;
146 case IPR_PTBR:
147 *valp = env->ipr[IPR_PTBR];
148 break;
149 case IPR_SCBB:
150 *valp = (int64_t)((int32_t)env->ipr[IPR_SCBB]);
151 break;
152 case IPR_SIRR:
153 /* Write-only */
154 ret = -1;
155 break;
156 case IPR_SISR:
157 *valp = (int64_t)((int16_t)env->ipr[IPR_SISR]);
158 case IPR_SSP:
159 if (env->features & FEATURE_SPS)
160 *valp = env->ipr[IPR_SSP];
161 else
162 *valp = ldq_raw(hwpcb + 16);
163 break;
164 case IPR_SYSPTBR:
165 if (env->features & FEATURE_VIRBND)
166 *valp = env->ipr[IPR_SYSPTBR];
167 else
168 ret = -1;
169 break;
170 case IPR_TBCHK:
171 if ((env->features & FEATURE_TBCHK)) {
172 /* XXX: TODO */
173 *valp = 0;
174 ret = -1;
175 } else {
176 ret = -1;
178 break;
179 case IPR_TBIA:
180 /* Write-only */
181 ret = -1;
182 break;
183 case IPR_TBIAP:
184 /* Write-only */
185 ret = -1;
186 break;
187 case IPR_TBIS:
188 /* Write-only */
189 ret = -1;
190 break;
191 case IPR_TBISD:
192 /* Write-only */
193 ret = -1;
194 break;
195 case IPR_TBISI:
196 /* Write-only */
197 ret = -1;
198 break;
199 case IPR_USP:
200 if (env->features & FEATURE_SPS)
201 *valp = env->ipr[IPR_USP];
202 else
203 *valp = ldq_raw(hwpcb + 24);
204 break;
205 case IPR_VIRBND:
206 if (env->features & FEATURE_VIRBND)
207 *valp = env->ipr[IPR_VIRBND];
208 else
209 ret = -1;
210 break;
211 case IPR_VPTB:
212 *valp = env->ipr[IPR_VPTB];
213 break;
214 case IPR_WHAMI:
215 *valp = env->ipr[IPR_WHAMI];
216 break;
217 default:
218 /* Invalid */
219 ret = -1;
220 break;
223 return ret;
226 int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp)
228 uint64_t hwpcb, tmp64;
229 uint8_t tmp8;
230 int ret = 0;
232 hwpcb = env->ipr[IPR_PCBB];
233 switch (iprn) {
234 case IPR_ASN:
235 /* Read-only */
236 ret = -1;
237 break;
238 case IPR_ASTEN:
239 tmp8 = ((int8_t)(env->ipr[IPR_ASTEN] << 4)) >> 4;
240 *oldvalp = tmp8;
241 tmp8 &= val & 0xF;
242 tmp8 |= (val >> 4) & 0xF;
243 env->ipr[IPR_ASTEN] &= ~0xF;
244 env->ipr[IPR_ASTEN] |= tmp8;
245 ret = 1;
246 break;
247 case IPR_ASTSR:
248 tmp8 = ((int8_t)(env->ipr[IPR_ASTSR] << 4)) >> 4;
249 *oldvalp = tmp8;
250 tmp8 &= val & 0xF;
251 tmp8 |= (val >> 4) & 0xF;
252 env->ipr[IPR_ASTSR] &= ~0xF;
253 env->ipr[IPR_ASTSR] |= tmp8;
254 ret = 1;
255 case IPR_DATFX:
256 env->ipr[IPR_DATFX] &= ~0x1;
257 env->ipr[IPR_DATFX] |= val & 1;
258 tmp64 = ldq_raw(hwpcb + 56);
259 tmp64 &= ~0x8000000000000000ULL;
260 tmp64 |= (val & 1) << 63;
261 stq_raw(hwpcb + 56, tmp64);
262 break;
263 case IPR_ESP:
264 if (env->features & FEATURE_SPS)
265 env->ipr[IPR_ESP] = val;
266 else
267 stq_raw(hwpcb + 8, val);
268 break;
269 case IPR_FEN:
270 env->ipr[IPR_FEN] = val & 1;
271 tmp64 = ldq_raw(hwpcb + 56);
272 tmp64 &= ~1;
273 tmp64 |= val & 1;
274 stq_raw(hwpcb + 56, tmp64);
275 break;
276 case IPR_IPIR:
277 /* XXX: TODO: Send IRQ to CPU #ir[16] */
278 break;
279 case IPR_IPL:
280 *oldvalp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59;
281 env->ipr[IPR_IPL] &= ~0x1F;
282 env->ipr[IPR_IPL] |= val & 0x1F;
283 /* XXX: may issue an interrupt or ASR _now_ */
284 ret = 1;
285 break;
286 case IPR_KSP:
287 if (!(env->ipr[IPR_EXC_ADDR] & 1)) {
288 ret = -1;
289 } else {
290 if (env->features & FEATURE_SPS)
291 env->ipr[IPR_KSP] = val;
292 else
293 stq_raw(hwpcb + 0, val);
295 break;
296 case IPR_MCES:
297 env->ipr[IPR_MCES] &= ~((val & 0x7) | 0x18);
298 env->ipr[IPR_MCES] |= val & 0x18;
299 break;
300 case IPR_PERFMON:
301 /* Implementation specific */
302 *oldvalp = 0;
303 ret = 1;
304 break;
305 case IPR_PCBB:
306 /* Read-only */
307 ret = -1;
308 break;
309 case IPR_PRBR:
310 env->ipr[IPR_PRBR] = val;
311 break;
312 case IPR_PTBR:
313 /* Read-only */
314 ret = -1;
315 break;
316 case IPR_SCBB:
317 env->ipr[IPR_SCBB] = (uint32_t)val;
318 break;
319 case IPR_SIRR:
320 if (val & 0xF) {
321 env->ipr[IPR_SISR] |= 1 << (val & 0xF);
322 /* XXX: request a software interrupt _now_ */
324 break;
325 case IPR_SISR:
326 /* Read-only */
327 ret = -1;
328 break;
329 case IPR_SSP:
330 if (env->features & FEATURE_SPS)
331 env->ipr[IPR_SSP] = val;
332 else
333 stq_raw(hwpcb + 16, val);
334 break;
335 case IPR_SYSPTBR:
336 if (env->features & FEATURE_VIRBND)
337 env->ipr[IPR_SYSPTBR] = val;
338 else
339 ret = -1;
340 case IPR_TBCHK:
341 /* Read-only */
342 ret = -1;
343 break;
344 case IPR_TBIA:
345 tlb_flush(env, 1);
346 break;
347 case IPR_TBIAP:
348 tlb_flush(env, 1);
349 break;
350 case IPR_TBIS:
351 tlb_flush_page(env, val);
352 break;
353 case IPR_TBISD:
354 tlb_flush_page(env, val);
355 break;
356 case IPR_TBISI:
357 tlb_flush_page(env, val);
358 break;
359 case IPR_USP:
360 if (env->features & FEATURE_SPS)
361 env->ipr[IPR_USP] = val;
362 else
363 stq_raw(hwpcb + 24, val);
364 break;
365 case IPR_VIRBND:
366 if (env->features & FEATURE_VIRBND)
367 env->ipr[IPR_VIRBND] = val;
368 else
369 ret = -1;
370 break;
371 case IPR_VPTB:
372 env->ipr[IPR_VPTB] = val;
373 break;
374 case IPR_WHAMI:
375 /* Read-only */
376 ret = -1;
377 break;
378 default:
379 /* Invalid */
380 ret = -1;
381 break;
384 return ret;
387 void do_interrupt (CPUState *env)
389 int excp;
391 env->ipr[IPR_EXC_ADDR] = env->pc | 1;
392 excp = env->exception_index;
393 env->exception_index = 0;
394 env->error_code = 0;
395 /* XXX: disable interrupts and memory mapping */
396 if (env->ipr[IPR_PAL_BASE] != -1ULL) {
397 /* We use native PALcode */
398 env->pc = env->ipr[IPR_PAL_BASE] + excp;
399 } else {
400 /* We use emulated PALcode */
401 call_pal(env);
402 /* Emulate REI */
403 env->pc = env->ipr[IPR_EXC_ADDR] & ~7;
404 env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
405 /* XXX: re-enable interrupts and memory mapping */
408 #endif
410 void cpu_dump_state (CPUState *env, FILE *f,
411 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
412 int flags)
414 static unsigned char *linux_reg_names[] = {
415 "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ",
416 "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ",
417 "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ",
418 "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero",
420 int i;
422 cpu_fprintf(f, " PC " TARGET_FMT_lx " PS " TARGET_FMT_lx "\n",
423 env->pc, env->ps);
424 for (i = 0; i < 31; i++) {
425 cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i,
426 linux_reg_names[i], env->ir[i]);
427 if ((i % 3) == 2)
428 cpu_fprintf(f, "\n");
430 cpu_fprintf(f, "\n");
431 for (i = 0; i < 31; i++) {
432 cpu_fprintf(f, "FIR%02d " TARGET_FMT_lx " ", i,
433 *((uint64_t *)(&env->fir[i])));
434 if ((i % 3) == 2)
435 cpu_fprintf(f, "\n");
437 cpu_fprintf(f, "FT " TARGET_FMT_lx " " TARGET_FMT_lx " " TARGET_FMT_lx,
438 *((uint64_t *)(&env->ft0)), *((uint64_t *)(&env->ft1)),
439 *((uint64_t *)(&env->ft2)));
440 cpu_fprintf(f, "\nMEM " TARGET_FMT_lx " %d %d\n",
441 ldq_raw(0x000000004007df60ULL),
442 (uint8_t *)(&env->ft0), (uint8_t *)(&env->fir[0]));
445 void cpu_dump_EA (target_ulong EA)
447 FILE *f;
449 if (logfile)
450 f = logfile;
451 else
452 f = stdout;
453 fprintf(f, "Memory access at address " TARGET_FMT_lx "\n", EA);