|
|
1.1 root 1: /*
1.1.1.4 root 2: * QEMU generic PowerPC hardware System Emulator
3: *
4: * Copyright (c) 2003-2007 Jocelyn Mayer
5: *
1.1 root 6: * Permission is hereby granted, free of charge, to any person obtaining a copy
7: * of this software and associated documentation files (the "Software"), to deal
8: * in the Software without restriction, including without limitation the rights
9: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10: * copies of the Software, and to permit persons to whom the Software is
11: * furnished to do so, subject to the following conditions:
12: *
13: * The above copyright notice and this permission notice shall be included in
14: * all copies or substantial portions of the Software.
15: *
16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22: * THE SOFTWARE.
23: */
1.1.1.4 root 24: #include "hw.h"
25: #include "ppc.h"
26: #include "qemu-timer.h"
27: #include "sysemu.h"
28: #include "nvram.h"
1.1.1.5 root 29: #include "qemu-log.h"
1.1.1.7 root 30: #include "loader.h"
1.1.1.9 root 31: #include "kvm.h"
32: #include "kvm_ppc.h"
1.1.1.4 root 33:
34: //#define PPC_DEBUG_IRQ
35: //#define PPC_DEBUG_TB
36:
1.1.1.5 root 37: #ifdef PPC_DEBUG_IRQ
38: # define LOG_IRQ(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
39: #else
40: # define LOG_IRQ(...) do { } while (0)
41: #endif
42:
43:
44: #ifdef PPC_DEBUG_TB
45: # define LOG_TB(...) qemu_log(__VA_ARGS__)
46: #else
47: # define LOG_TB(...) do { } while (0)
48: #endif
1.1.1.4 root 49:
1.1.1.12! root 50: static void cpu_ppc_tb_stop (CPUPPCState *env);
! 51: static void cpu_ppc_tb_start (CPUPPCState *env);
1.1.1.4 root 52:
1.1.1.12! root 53: void ppc_set_irq(CPUPPCState *env, int n_IRQ, int level)
1.1.1.4 root 54: {
1.1.1.9 root 55: unsigned int old_pending = env->pending_interrupts;
56:
1.1.1.4 root 57: if (level) {
58: env->pending_interrupts |= 1 << n_IRQ;
59: cpu_interrupt(env, CPU_INTERRUPT_HARD);
60: } else {
61: env->pending_interrupts &= ~(1 << n_IRQ);
62: if (env->pending_interrupts == 0)
63: cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
64: }
1.1.1.9 root 65:
66: if (old_pending != env->pending_interrupts) {
67: #ifdef CONFIG_KVM
68: kvmppc_set_interrupt(env, n_IRQ, level);
69: #endif
70: }
71:
1.1.1.5 root 72: LOG_IRQ("%s: %p n_IRQ %d level %d => pending %08" PRIx32
1.1.1.4 root 73: "req %08x\n", __func__, env, n_IRQ, level,
74: env->pending_interrupts, env->interrupt_request);
75: }
1.1 root 76:
1.1.1.4 root 77: /* PowerPC 6xx / 7xx internal IRQ controller */
78: static void ppc6xx_set_irq (void *opaque, int pin, int level)
79: {
1.1.1.12! root 80: CPUPPCState *env = opaque;
1.1.1.4 root 81: int cur_level;
82:
1.1.1.5 root 83: LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
1.1.1.4 root 84: env, pin, level);
85: cur_level = (env->irq_input_state >> pin) & 1;
86: /* Don't generate spurious events */
87: if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
88: switch (pin) {
89: case PPC6xx_INPUT_TBEN:
90: /* Level sensitive - active high */
1.1.1.5 root 91: LOG_IRQ("%s: %s the time base\n",
1.1.1.4 root 92: __func__, level ? "start" : "stop");
93: if (level) {
94: cpu_ppc_tb_start(env);
95: } else {
96: cpu_ppc_tb_stop(env);
97: }
98: case PPC6xx_INPUT_INT:
99: /* Level sensitive - active high */
1.1.1.5 root 100: LOG_IRQ("%s: set the external IRQ state to %d\n",
1.1.1.4 root 101: __func__, level);
102: ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
103: break;
104: case PPC6xx_INPUT_SMI:
105: /* Level sensitive - active high */
1.1.1.5 root 106: LOG_IRQ("%s: set the SMI IRQ state to %d\n",
1.1.1.4 root 107: __func__, level);
108: ppc_set_irq(env, PPC_INTERRUPT_SMI, level);
109: break;
110: case PPC6xx_INPUT_MCP:
111: /* Negative edge sensitive */
112: /* XXX: TODO: actual reaction may depends on HID0 status
113: * 603/604/740/750: check HID0[EMCP]
114: */
115: if (cur_level == 1 && level == 0) {
1.1.1.5 root 116: LOG_IRQ("%s: raise machine check state\n",
1.1.1.4 root 117: __func__);
118: ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
119: }
120: break;
121: case PPC6xx_INPUT_CKSTP_IN:
122: /* Level sensitive - active low */
123: /* XXX: TODO: relay the signal to CKSTP_OUT pin */
124: /* XXX: Note that the only way to restart the CPU is to reset it */
125: if (level) {
1.1.1.5 root 126: LOG_IRQ("%s: stop the CPU\n", __func__);
1.1.1.4 root 127: env->halted = 1;
128: }
129: break;
130: case PPC6xx_INPUT_HRESET:
131: /* Level sensitive - active low */
132: if (level) {
1.1.1.5 root 133: LOG_IRQ("%s: reset the CPU\n", __func__);
1.1.1.12! root 134: cpu_interrupt(env, CPU_INTERRUPT_RESET);
1.1.1.4 root 135: }
136: break;
137: case PPC6xx_INPUT_SRESET:
1.1.1.5 root 138: LOG_IRQ("%s: set the RESET IRQ state to %d\n",
1.1.1.4 root 139: __func__, level);
140: ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
141: break;
142: default:
143: /* Unknown pin - do nothing */
1.1.1.5 root 144: LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
1.1.1.4 root 145: return;
146: }
147: if (level)
148: env->irq_input_state |= 1 << pin;
149: else
150: env->irq_input_state &= ~(1 << pin);
151: }
152: }
153:
1.1.1.12! root 154: void ppc6xx_irq_init (CPUPPCState *env)
1.1.1.4 root 155: {
156: env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env,
157: PPC6xx_INPUT_NB);
158: }
159:
160: #if defined(TARGET_PPC64)
161: /* PowerPC 970 internal IRQ controller */
162: static void ppc970_set_irq (void *opaque, int pin, int level)
163: {
1.1.1.12! root 164: CPUPPCState *env = opaque;
1.1.1.4 root 165: int cur_level;
166:
1.1.1.5 root 167: LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
1.1.1.4 root 168: env, pin, level);
169: cur_level = (env->irq_input_state >> pin) & 1;
170: /* Don't generate spurious events */
171: if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
172: switch (pin) {
173: case PPC970_INPUT_INT:
174: /* Level sensitive - active high */
1.1.1.5 root 175: LOG_IRQ("%s: set the external IRQ state to %d\n",
1.1.1.4 root 176: __func__, level);
177: ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
178: break;
179: case PPC970_INPUT_THINT:
180: /* Level sensitive - active high */
1.1.1.5 root 181: LOG_IRQ("%s: set the SMI IRQ state to %d\n", __func__,
1.1.1.4 root 182: level);
183: ppc_set_irq(env, PPC_INTERRUPT_THERM, level);
184: break;
185: case PPC970_INPUT_MCP:
186: /* Negative edge sensitive */
187: /* XXX: TODO: actual reaction may depends on HID0 status
188: * 603/604/740/750: check HID0[EMCP]
189: */
190: if (cur_level == 1 && level == 0) {
1.1.1.5 root 191: LOG_IRQ("%s: raise machine check state\n",
1.1.1.4 root 192: __func__);
193: ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
194: }
195: break;
196: case PPC970_INPUT_CKSTP:
197: /* Level sensitive - active low */
198: /* XXX: TODO: relay the signal to CKSTP_OUT pin */
199: if (level) {
1.1.1.5 root 200: LOG_IRQ("%s: stop the CPU\n", __func__);
1.1.1.4 root 201: env->halted = 1;
202: } else {
1.1.1.5 root 203: LOG_IRQ("%s: restart the CPU\n", __func__);
1.1.1.4 root 204: env->halted = 0;
1.1.1.10 root 205: qemu_cpu_kick(env);
1.1.1.4 root 206: }
207: break;
208: case PPC970_INPUT_HRESET:
209: /* Level sensitive - active low */
210: if (level) {
1.1.1.12! root 211: cpu_interrupt(env, CPU_INTERRUPT_RESET);
1.1.1.4 root 212: }
213: break;
214: case PPC970_INPUT_SRESET:
1.1.1.5 root 215: LOG_IRQ("%s: set the RESET IRQ state to %d\n",
1.1.1.4 root 216: __func__, level);
217: ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
218: break;
219: case PPC970_INPUT_TBEN:
1.1.1.5 root 220: LOG_IRQ("%s: set the TBEN state to %d\n", __func__,
1.1.1.4 root 221: level);
222: /* XXX: TODO */
223: break;
224: default:
225: /* Unknown pin - do nothing */
1.1.1.5 root 226: LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
1.1.1.4 root 227: return;
228: }
229: if (level)
230: env->irq_input_state |= 1 << pin;
231: else
232: env->irq_input_state &= ~(1 << pin);
233: }
234: }
1.1 root 235:
1.1.1.12! root 236: void ppc970_irq_init (CPUPPCState *env)
1.1.1.4 root 237: {
238: env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env,
239: PPC970_INPUT_NB);
240: }
1.1.1.10 root 241:
242: /* POWER7 internal IRQ controller */
243: static void power7_set_irq (void *opaque, int pin, int level)
244: {
1.1.1.12! root 245: CPUPPCState *env = opaque;
1.1.1.10 root 246:
247: LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
248: env, pin, level);
249:
250: switch (pin) {
251: case POWER7_INPUT_INT:
252: /* Level sensitive - active high */
253: LOG_IRQ("%s: set the external IRQ state to %d\n",
254: __func__, level);
255: ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
256: break;
257: default:
258: /* Unknown pin - do nothing */
259: LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
260: return;
261: }
262: if (level) {
263: env->irq_input_state |= 1 << pin;
264: } else {
265: env->irq_input_state &= ~(1 << pin);
266: }
267: }
268:
1.1.1.12! root 269: void ppcPOWER7_irq_init (CPUPPCState *env)
1.1.1.10 root 270: {
271: env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, env,
272: POWER7_INPUT_NB);
273: }
1.1.1.4 root 274: #endif /* defined(TARGET_PPC64) */
275:
276: /* PowerPC 40x internal IRQ controller */
277: static void ppc40x_set_irq (void *opaque, int pin, int level)
278: {
1.1.1.12! root 279: CPUPPCState *env = opaque;
1.1.1.4 root 280: int cur_level;
281:
1.1.1.5 root 282: LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
1.1.1.4 root 283: env, pin, level);
284: cur_level = (env->irq_input_state >> pin) & 1;
285: /* Don't generate spurious events */
286: if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
287: switch (pin) {
288: case PPC40x_INPUT_RESET_SYS:
289: if (level) {
1.1.1.5 root 290: LOG_IRQ("%s: reset the PowerPC system\n",
1.1.1.4 root 291: __func__);
292: ppc40x_system_reset(env);
293: }
294: break;
295: case PPC40x_INPUT_RESET_CHIP:
296: if (level) {
1.1.1.5 root 297: LOG_IRQ("%s: reset the PowerPC chip\n", __func__);
1.1.1.4 root 298: ppc40x_chip_reset(env);
299: }
300: break;
301: case PPC40x_INPUT_RESET_CORE:
302: /* XXX: TODO: update DBSR[MRR] */
303: if (level) {
1.1.1.5 root 304: LOG_IRQ("%s: reset the PowerPC core\n", __func__);
1.1.1.4 root 305: ppc40x_core_reset(env);
306: }
307: break;
308: case PPC40x_INPUT_CINT:
309: /* Level sensitive - active high */
1.1.1.5 root 310: LOG_IRQ("%s: set the critical IRQ state to %d\n",
1.1.1.4 root 311: __func__, level);
312: ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
313: break;
314: case PPC40x_INPUT_INT:
315: /* Level sensitive - active high */
1.1.1.5 root 316: LOG_IRQ("%s: set the external IRQ state to %d\n",
1.1.1.4 root 317: __func__, level);
318: ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
319: break;
320: case PPC40x_INPUT_HALT:
321: /* Level sensitive - active low */
322: if (level) {
1.1.1.5 root 323: LOG_IRQ("%s: stop the CPU\n", __func__);
1.1.1.4 root 324: env->halted = 1;
325: } else {
1.1.1.5 root 326: LOG_IRQ("%s: restart the CPU\n", __func__);
1.1.1.4 root 327: env->halted = 0;
1.1.1.10 root 328: qemu_cpu_kick(env);
1.1.1.4 root 329: }
330: break;
331: case PPC40x_INPUT_DEBUG:
332: /* Level sensitive - active high */
1.1.1.5 root 333: LOG_IRQ("%s: set the debug pin state to %d\n",
1.1.1.4 root 334: __func__, level);
335: ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
336: break;
337: default:
338: /* Unknown pin - do nothing */
1.1.1.5 root 339: LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
1.1.1.4 root 340: return;
341: }
342: if (level)
343: env->irq_input_state |= 1 << pin;
344: else
345: env->irq_input_state &= ~(1 << pin);
346: }
347: }
348:
1.1.1.12! root 349: void ppc40x_irq_init (CPUPPCState *env)
1.1.1.4 root 350: {
351: env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
352: env, PPC40x_INPUT_NB);
353: }
354:
1.1.1.5 root 355: /* PowerPC E500 internal IRQ controller */
356: static void ppce500_set_irq (void *opaque, int pin, int level)
357: {
1.1.1.12! root 358: CPUPPCState *env = opaque;
1.1.1.5 root 359: int cur_level;
360:
361: LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
362: env, pin, level);
363: cur_level = (env->irq_input_state >> pin) & 1;
364: /* Don't generate spurious events */
365: if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
366: switch (pin) {
367: case PPCE500_INPUT_MCK:
368: if (level) {
369: LOG_IRQ("%s: reset the PowerPC system\n",
370: __func__);
371: qemu_system_reset_request();
372: }
373: break;
374: case PPCE500_INPUT_RESET_CORE:
375: if (level) {
376: LOG_IRQ("%s: reset the PowerPC core\n", __func__);
377: ppc_set_irq(env, PPC_INTERRUPT_MCK, level);
378: }
379: break;
380: case PPCE500_INPUT_CINT:
381: /* Level sensitive - active high */
382: LOG_IRQ("%s: set the critical IRQ state to %d\n",
383: __func__, level);
384: ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
385: break;
386: case PPCE500_INPUT_INT:
387: /* Level sensitive - active high */
388: LOG_IRQ("%s: set the core IRQ state to %d\n",
389: __func__, level);
390: ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
391: break;
392: case PPCE500_INPUT_DEBUG:
393: /* Level sensitive - active high */
394: LOG_IRQ("%s: set the debug pin state to %d\n",
395: __func__, level);
396: ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
397: break;
398: default:
399: /* Unknown pin - do nothing */
400: LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
401: return;
402: }
403: if (level)
404: env->irq_input_state |= 1 << pin;
405: else
406: env->irq_input_state &= ~(1 << pin);
407: }
408: }
409:
1.1.1.12! root 410: void ppce500_irq_init (CPUPPCState *env)
1.1.1.5 root 411: {
412: env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
413: env, PPCE500_INPUT_NB);
414: }
1.1.1.4 root 415: /*****************************************************************************/
416: /* PowerPC time base and decrementer emulation */
1.1 root 417:
1.1.1.11 root 418: uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset)
1.1 root 419: {
420: /* TB time in tb periods */
1.1.1.7 root 421: return muldiv64(vmclk, tb_env->tb_freq, get_ticks_per_sec()) + tb_offset;
1.1 root 422: }
423:
1.1.1.12! root 424: uint64_t cpu_ppc_load_tbl (CPUPPCState *env)
1.1 root 425: {
426: ppc_tb_t *tb_env = env->tb_env;
427: uint64_t tb;
428:
1.1.1.10 root 429: if (kvm_enabled()) {
430: return env->spr[SPR_TBL];
431: }
432:
433: tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
1.1.1.5 root 434: LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
1.1 root 435:
1.1.1.8 root 436: return tb;
1.1 root 437: }
438:
1.1.1.12! root 439: static inline uint32_t _cpu_ppc_load_tbu(CPUPPCState *env)
1.1 root 440: {
441: ppc_tb_t *tb_env = env->tb_env;
442: uint64_t tb;
443:
1.1.1.10 root 444: tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
1.1.1.5 root 445: LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
1.1.1.4 root 446:
1.1 root 447: return tb >> 32;
448: }
449:
1.1.1.12! root 450: uint32_t cpu_ppc_load_tbu (CPUPPCState *env)
1.1 root 451: {
1.1.1.10 root 452: if (kvm_enabled()) {
453: return env->spr[SPR_TBU];
454: }
455:
1.1.1.4 root 456: return _cpu_ppc_load_tbu(env);
457: }
458:
1.1.1.7 root 459: static inline void cpu_ppc_store_tb(ppc_tb_t *tb_env, uint64_t vmclk,
460: int64_t *tb_offsetp, uint64_t value)
1.1.1.4 root 461: {
1.1.1.7 root 462: *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, get_ticks_per_sec());
1.1.1.5 root 463: LOG_TB("%s: tb %016" PRIx64 " offset %08" PRIx64 "\n",
1.1.1.4 root 464: __func__, value, *tb_offsetp);
1.1 root 465: }
466:
1.1.1.12! root 467: void cpu_ppc_store_tbl (CPUPPCState *env, uint32_t value)
1.1.1.4 root 468: {
469: ppc_tb_t *tb_env = env->tb_env;
470: uint64_t tb;
471:
1.1.1.10 root 472: tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
1.1.1.4 root 473: tb &= 0xFFFFFFFF00000000ULL;
1.1.1.10 root 474: cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
1.1.1.4 root 475: &tb_env->tb_offset, tb | (uint64_t)value);
476: }
477:
1.1.1.12! root 478: static inline void _cpu_ppc_store_tbu(CPUPPCState *env, uint32_t value)
1.1.1.4 root 479: {
480: ppc_tb_t *tb_env = env->tb_env;
481: uint64_t tb;
482:
1.1.1.10 root 483: tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
1.1.1.4 root 484: tb &= 0x00000000FFFFFFFFULL;
1.1.1.10 root 485: cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
1.1.1.4 root 486: &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
487: }
488:
1.1.1.12! root 489: void cpu_ppc_store_tbu (CPUPPCState *env, uint32_t value)
1.1 root 490: {
1.1.1.4 root 491: _cpu_ppc_store_tbu(env, value);
492: }
493:
1.1.1.12! root 494: uint64_t cpu_ppc_load_atbl (CPUPPCState *env)
1.1.1.4 root 495: {
1.1 root 496: ppc_tb_t *tb_env = env->tb_env;
1.1.1.4 root 497: uint64_t tb;
1.1 root 498:
1.1.1.10 root 499: tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
1.1.1.5 root 500: LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
1.1.1.4 root 501:
1.1.1.8 root 502: return tb;
1.1 root 503: }
504:
1.1.1.12! root 505: uint32_t cpu_ppc_load_atbu (CPUPPCState *env)
1.1 root 506: {
507: ppc_tb_t *tb_env = env->tb_env;
1.1.1.4 root 508: uint64_t tb;
1.1 root 509:
1.1.1.10 root 510: tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
1.1.1.5 root 511: LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
1.1.1.4 root 512:
513: return tb >> 32;
1.1 root 514: }
515:
1.1.1.12! root 516: void cpu_ppc_store_atbl (CPUPPCState *env, uint32_t value)
1.1.1.4 root 517: {
518: ppc_tb_t *tb_env = env->tb_env;
519: uint64_t tb;
520:
1.1.1.10 root 521: tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
1.1.1.4 root 522: tb &= 0xFFFFFFFF00000000ULL;
1.1.1.10 root 523: cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
1.1.1.4 root 524: &tb_env->atb_offset, tb | (uint64_t)value);
525: }
526:
1.1.1.12! root 527: void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value)
1.1.1.4 root 528: {
529: ppc_tb_t *tb_env = env->tb_env;
530: uint64_t tb;
531:
1.1.1.10 root 532: tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
1.1.1.4 root 533: tb &= 0x00000000FFFFFFFFULL;
1.1.1.10 root 534: cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
1.1.1.4 root 535: &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
536: }
537:
1.1.1.12! root 538: static void cpu_ppc_tb_stop (CPUPPCState *env)
1.1.1.4 root 539: {
540: ppc_tb_t *tb_env = env->tb_env;
541: uint64_t tb, atb, vmclk;
542:
543: /* If the time base is already frozen, do nothing */
544: if (tb_env->tb_freq != 0) {
1.1.1.10 root 545: vmclk = qemu_get_clock_ns(vm_clock);
1.1.1.4 root 546: /* Get the time base */
547: tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset);
548: /* Get the alternate time base */
549: atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset);
550: /* Store the time base value (ie compute the current offset) */
551: cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
552: /* Store the alternate time base value (compute the current offset) */
553: cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
554: /* Set the time base frequency to zero */
555: tb_env->tb_freq = 0;
556: /* Now, the time bases are frozen to tb_offset / atb_offset value */
557: }
558: }
559:
1.1.1.12! root 560: static void cpu_ppc_tb_start (CPUPPCState *env)
1.1.1.4 root 561: {
562: ppc_tb_t *tb_env = env->tb_env;
563: uint64_t tb, atb, vmclk;
564:
565: /* If the time base is not frozen, do nothing */
566: if (tb_env->tb_freq == 0) {
1.1.1.10 root 567: vmclk = qemu_get_clock_ns(vm_clock);
1.1.1.4 root 568: /* Get the time base from tb_offset */
569: tb = tb_env->tb_offset;
570: /* Get the alternate time base from atb_offset */
571: atb = tb_env->atb_offset;
572: /* Restore the tb frequency from the decrementer frequency */
573: tb_env->tb_freq = tb_env->decr_freq;
574: /* Store the time base value */
575: cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
576: /* Store the alternate time base value */
577: cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
578: }
579: }
580:
1.1.1.12! root 581: static inline uint32_t _cpu_ppc_load_decr(CPUPPCState *env, uint64_t next)
1.1 root 582: {
583: ppc_tb_t *tb_env = env->tb_env;
584: uint32_t decr;
585: int64_t diff;
586:
1.1.1.10 root 587: diff = next - qemu_get_clock_ns(vm_clock);
1.1.1.11 root 588: if (diff >= 0) {
1.1.1.7 root 589: decr = muldiv64(diff, tb_env->decr_freq, get_ticks_per_sec());
1.1.1.11 root 590: } else if (tb_env->flags & PPC_TIMER_BOOKE) {
591: decr = 0;
592: } else {
1.1.1.7 root 593: decr = -muldiv64(-diff, tb_env->decr_freq, get_ticks_per_sec());
1.1.1.11 root 594: }
1.1.1.5 root 595: LOG_TB("%s: %08" PRIx32 "\n", __func__, decr);
1.1.1.4 root 596:
1.1 root 597: return decr;
598: }
599:
1.1.1.12! root 600: uint32_t cpu_ppc_load_decr (CPUPPCState *env)
1.1.1.4 root 601: {
602: ppc_tb_t *tb_env = env->tb_env;
603:
1.1.1.10 root 604: if (kvm_enabled()) {
605: return env->spr[SPR_DECR];
606: }
607:
1.1.1.6 root 608: return _cpu_ppc_load_decr(env, tb_env->decr_next);
1.1.1.4 root 609: }
610:
1.1.1.12! root 611: uint32_t cpu_ppc_load_hdecr (CPUPPCState *env)
1.1.1.4 root 612: {
613: ppc_tb_t *tb_env = env->tb_env;
614:
1.1.1.6 root 615: return _cpu_ppc_load_decr(env, tb_env->hdecr_next);
1.1.1.4 root 616: }
617:
1.1.1.12! root 618: uint64_t cpu_ppc_load_purr (CPUPPCState *env)
1.1.1.4 root 619: {
620: ppc_tb_t *tb_env = env->tb_env;
621: uint64_t diff;
622:
1.1.1.10 root 623: diff = qemu_get_clock_ns(vm_clock) - tb_env->purr_start;
1.1.1.4 root 624:
1.1.1.7 root 625: return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, get_ticks_per_sec());
1.1.1.4 root 626: }
627:
1.1 root 628: /* When decrementer expires,
629: * all we need to do is generate or queue a CPU exception
630: */
1.1.1.12! root 631: static inline void cpu_ppc_decr_excp(CPUPPCState *env)
1.1.1.4 root 632: {
633: /* Raise it */
1.1.1.5 root 634: LOG_TB("raise decrementer exception\n");
1.1.1.4 root 635: ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
636: }
637:
1.1.1.12! root 638: static inline void cpu_ppc_hdecr_excp(CPUPPCState *env)
1.1 root 639: {
640: /* Raise it */
1.1.1.5 root 641: LOG_TB("raise decrementer exception\n");
1.1.1.4 root 642: ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1);
1.1 root 643: }
644:
1.1.1.12! root 645: static void __cpu_ppc_store_decr (CPUPPCState *env, uint64_t *nextp,
1.1.1.4 root 646: struct QEMUTimer *timer,
1.1.1.12! root 647: void (*raise_excp)(CPUPPCState *),
1.1.1.4 root 648: uint32_t decr, uint32_t value,
649: int is_excp)
1.1 root 650: {
651: ppc_tb_t *tb_env = env->tb_env;
652: uint64_t now, next;
653:
1.1.1.5 root 654: LOG_TB("%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__,
1.1.1.4 root 655: decr, value);
1.1.1.11 root 656:
657: if (kvm_enabled()) {
658: /* KVM handles decrementer exceptions, we don't need our own timer */
659: return;
660: }
661:
1.1.1.10 root 662: now = qemu_get_clock_ns(vm_clock);
1.1.1.7 root 663: next = now + muldiv64(value, get_ticks_per_sec(), tb_env->decr_freq);
1.1.1.11 root 664: if (is_excp) {
1.1.1.4 root 665: next += *nextp - now;
1.1.1.11 root 666: }
667: if (next == now) {
1.1.1.4 root 668: next++;
1.1.1.11 root 669: }
1.1.1.4 root 670: *nextp = next;
1.1 root 671: /* Adjust timer */
1.1.1.4 root 672: qemu_mod_timer(timer, next);
1.1.1.11 root 673:
674: /* If we set a negative value and the decrementer was positive, raise an
675: * exception.
1.1 root 676: */
1.1.1.11 root 677: if ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED)
678: && (value & 0x80000000)
679: && !(decr & 0x80000000)) {
1.1.1.4 root 680: (*raise_excp)(env);
1.1.1.11 root 681: }
1.1.1.4 root 682: }
683:
1.1.1.12! root 684: static inline void _cpu_ppc_store_decr(CPUPPCState *env, uint32_t decr,
1.1.1.7 root 685: uint32_t value, int is_excp)
1.1.1.4 root 686: {
687: ppc_tb_t *tb_env = env->tb_env;
688:
689: __cpu_ppc_store_decr(env, &tb_env->decr_next, tb_env->decr_timer,
690: &cpu_ppc_decr_excp, decr, value, is_excp);
1.1 root 691: }
692:
1.1.1.12! root 693: void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value)
1.1 root 694: {
695: _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
696: }
697:
698: static void cpu_ppc_decr_cb (void *opaque)
699: {
700: _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
701: }
702:
1.1.1.12! root 703: static inline void _cpu_ppc_store_hdecr(CPUPPCState *env, uint32_t hdecr,
1.1.1.7 root 704: uint32_t value, int is_excp)
1.1.1.4 root 705: {
706: ppc_tb_t *tb_env = env->tb_env;
707:
708: if (tb_env->hdecr_timer != NULL) {
709: __cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer,
710: &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
711: }
712: }
713:
1.1.1.12! root 714: void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value)
1.1.1.4 root 715: {
716: _cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0);
717: }
718:
719: static void cpu_ppc_hdecr_cb (void *opaque)
720: {
721: _cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1);
722: }
723:
1.1.1.12! root 724: void cpu_ppc_store_purr (CPUPPCState *env, uint64_t value)
1.1.1.4 root 725: {
726: ppc_tb_t *tb_env = env->tb_env;
727:
728: tb_env->purr_load = value;
1.1.1.10 root 729: tb_env->purr_start = qemu_get_clock_ns(vm_clock);
1.1.1.4 root 730: }
731:
732: static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
733: {
1.1.1.12! root 734: CPUPPCState *env = opaque;
1.1.1.4 root 735: ppc_tb_t *tb_env = env->tb_env;
736:
737: tb_env->tb_freq = freq;
738: tb_env->decr_freq = freq;
739: /* There is a bug in Linux 2.4 kernels:
740: * if a decrementer exception is pending when it enables msr_ee at startup,
741: * it's not ready to handle it...
742: */
743: _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
744: _cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
745: cpu_ppc_store_purr(env, 0x0000000000000000ULL);
746: }
747:
1.1 root 748: /* Set up (once) timebase frequency (in Hz) */
1.1.1.12! root 749: clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
1.1 root 750: {
751: ppc_tb_t *tb_env;
752:
1.1.1.11 root 753: tb_env = g_malloc0(sizeof(ppc_tb_t));
1.1 root 754: env->tb_env = tb_env;
1.1.1.11 root 755: tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
1.1.1.4 root 756: /* Create new timer */
1.1.1.10 root 757: tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_decr_cb, env);
1.1.1.4 root 758: if (0) {
759: /* XXX: find a suitable condition to enable the hypervisor decrementer
760: */
1.1.1.10 root 761: tb_env->hdecr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_hdecr_cb, env);
1.1.1.4 root 762: } else {
763: tb_env->hdecr_timer = NULL;
764: }
765: cpu_ppc_set_tb_clk(env, freq);
766:
767: return &cpu_ppc_set_tb_clk;
768: }
769:
770: /* Specific helpers for POWER & PowerPC 601 RTC */
1.1.1.5 root 771: #if 0
1.1.1.12! root 772: static clk_setup_cb cpu_ppc601_rtc_init (CPUPPCState *env)
1.1.1.4 root 773: {
774: return cpu_ppc_tb_init(env, 7812500);
775: }
1.1.1.5 root 776: #endif
1.1.1.4 root 777:
1.1.1.12! root 778: void cpu_ppc601_store_rtcu (CPUPPCState *env, uint32_t value)
1.1.1.4 root 779: {
780: _cpu_ppc_store_tbu(env, value);
781: }
782:
1.1.1.12! root 783: uint32_t cpu_ppc601_load_rtcu (CPUPPCState *env)
1.1.1.4 root 784: {
785: return _cpu_ppc_load_tbu(env);
786: }
787:
1.1.1.12! root 788: void cpu_ppc601_store_rtcl (CPUPPCState *env, uint32_t value)
1.1.1.4 root 789: {
790: cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
791: }
792:
1.1.1.12! root 793: uint32_t cpu_ppc601_load_rtcl (CPUPPCState *env)
1.1.1.4 root 794: {
795: return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
796: }
797:
798: /*****************************************************************************/
1.1.1.11 root 799: /* PowerPC 40x timers */
1.1.1.4 root 800:
801: /* PIT, FIT & WDT */
1.1.1.11 root 802: typedef struct ppc40x_timer_t ppc40x_timer_t;
803: struct ppc40x_timer_t {
1.1.1.4 root 804: uint64_t pit_reload; /* PIT auto-reload value */
805: uint64_t fit_next; /* Tick for next FIT interrupt */
806: struct QEMUTimer *fit_timer;
807: uint64_t wdt_next; /* Tick for next WDT interrupt */
808: struct QEMUTimer *wdt_timer;
1.1.1.9 root 809:
810: /* 405 have the PIT, 440 have a DECR. */
811: unsigned int decr_excp;
1.1.1.4 root 812: };
813:
814: /* Fixed interval timer */
815: static void cpu_4xx_fit_cb (void *opaque)
816: {
1.1.1.12! root 817: CPUPPCState *env;
1.1.1.4 root 818: ppc_tb_t *tb_env;
1.1.1.11 root 819: ppc40x_timer_t *ppc40x_timer;
1.1.1.4 root 820: uint64_t now, next;
821:
822: env = opaque;
823: tb_env = env->tb_env;
1.1.1.11 root 824: ppc40x_timer = tb_env->opaque;
1.1.1.10 root 825: now = qemu_get_clock_ns(vm_clock);
1.1.1.4 root 826: switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
827: case 0:
828: next = 1 << 9;
829: break;
830: case 1:
831: next = 1 << 13;
832: break;
833: case 2:
834: next = 1 << 17;
835: break;
836: case 3:
837: next = 1 << 21;
838: break;
839: default:
840: /* Cannot occur, but makes gcc happy */
841: return;
1.1 root 842: }
1.1.1.7 root 843: next = now + muldiv64(next, get_ticks_per_sec(), tb_env->tb_freq);
1.1.1.4 root 844: if (next == now)
845: next++;
1.1.1.11 root 846: qemu_mod_timer(ppc40x_timer->fit_timer, next);
1.1.1.4 root 847: env->spr[SPR_40x_TSR] |= 1 << 26;
848: if ((env->spr[SPR_40x_TCR] >> 23) & 0x1)
849: ppc_set_irq(env, PPC_INTERRUPT_FIT, 1);
1.1.1.7 root 850: LOG_TB("%s: ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
851: (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
852: env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
1.1.1.4 root 853: }
1.1 root 854:
1.1.1.4 root 855: /* Programmable interval timer */
1.1.1.12! root 856: static void start_stop_pit (CPUPPCState *env, ppc_tb_t *tb_env, int is_excp)
1.1.1.4 root 857: {
1.1.1.11 root 858: ppc40x_timer_t *ppc40x_timer;
1.1.1.4 root 859: uint64_t now, next;
860:
1.1.1.11 root 861: ppc40x_timer = tb_env->opaque;
862: if (ppc40x_timer->pit_reload <= 1 ||
1.1.1.4 root 863: !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
864: (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
865: /* Stop PIT */
1.1.1.5 root 866: LOG_TB("%s: stop PIT\n", __func__);
1.1.1.4 root 867: qemu_del_timer(tb_env->decr_timer);
868: } else {
1.1.1.5 root 869: LOG_TB("%s: start PIT %016" PRIx64 "\n",
1.1.1.11 root 870: __func__, ppc40x_timer->pit_reload);
1.1.1.10 root 871: now = qemu_get_clock_ns(vm_clock);
1.1.1.11 root 872: next = now + muldiv64(ppc40x_timer->pit_reload,
1.1.1.7 root 873: get_ticks_per_sec(), tb_env->decr_freq);
1.1.1.4 root 874: if (is_excp)
875: next += tb_env->decr_next - now;
876: if (next == now)
877: next++;
878: qemu_mod_timer(tb_env->decr_timer, next);
879: tb_env->decr_next = next;
880: }
881: }
882:
883: static void cpu_4xx_pit_cb (void *opaque)
884: {
1.1.1.12! root 885: CPUPPCState *env;
1.1.1.4 root 886: ppc_tb_t *tb_env;
1.1.1.11 root 887: ppc40x_timer_t *ppc40x_timer;
1.1.1.4 root 888:
889: env = opaque;
890: tb_env = env->tb_env;
1.1.1.11 root 891: ppc40x_timer = tb_env->opaque;
1.1.1.4 root 892: env->spr[SPR_40x_TSR] |= 1 << 27;
893: if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
1.1.1.11 root 894: ppc_set_irq(env, ppc40x_timer->decr_excp, 1);
1.1.1.4 root 895: start_stop_pit(env, tb_env, 1);
1.1.1.7 root 896: LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " "
897: "%016" PRIx64 "\n", __func__,
898: (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
899: (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
900: env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
1.1.1.11 root 901: ppc40x_timer->pit_reload);
1.1.1.4 root 902: }
903:
904: /* Watchdog timer */
905: static void cpu_4xx_wdt_cb (void *opaque)
906: {
1.1.1.12! root 907: CPUPPCState *env;
1.1.1.4 root 908: ppc_tb_t *tb_env;
1.1.1.11 root 909: ppc40x_timer_t *ppc40x_timer;
1.1.1.4 root 910: uint64_t now, next;
911:
912: env = opaque;
913: tb_env = env->tb_env;
1.1.1.11 root 914: ppc40x_timer = tb_env->opaque;
1.1.1.10 root 915: now = qemu_get_clock_ns(vm_clock);
1.1.1.4 root 916: switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
917: case 0:
918: next = 1 << 17;
919: break;
920: case 1:
921: next = 1 << 21;
922: break;
923: case 2:
924: next = 1 << 25;
925: break;
926: case 3:
927: next = 1 << 29;
928: break;
929: default:
930: /* Cannot occur, but makes gcc happy */
931: return;
932: }
1.1.1.7 root 933: next = now + muldiv64(next, get_ticks_per_sec(), tb_env->decr_freq);
1.1.1.4 root 934: if (next == now)
935: next++;
1.1.1.7 root 936: LOG_TB("%s: TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
937: env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
1.1.1.4 root 938: switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
939: case 0x0:
940: case 0x1:
1.1.1.11 root 941: qemu_mod_timer(ppc40x_timer->wdt_timer, next);
942: ppc40x_timer->wdt_next = next;
1.1.1.4 root 943: env->spr[SPR_40x_TSR] |= 1 << 31;
944: break;
945: case 0x2:
1.1.1.11 root 946: qemu_mod_timer(ppc40x_timer->wdt_timer, next);
947: ppc40x_timer->wdt_next = next;
1.1.1.4 root 948: env->spr[SPR_40x_TSR] |= 1 << 30;
949: if ((env->spr[SPR_40x_TCR] >> 27) & 0x1)
950: ppc_set_irq(env, PPC_INTERRUPT_WDT, 1);
951: break;
952: case 0x3:
953: env->spr[SPR_40x_TSR] &= ~0x30000000;
954: env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
955: switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
956: case 0x0:
957: /* No reset */
958: break;
959: case 0x1: /* Core reset */
960: ppc40x_core_reset(env);
961: break;
962: case 0x2: /* Chip reset */
963: ppc40x_chip_reset(env);
964: break;
965: case 0x3: /* System reset */
966: ppc40x_system_reset(env);
967: break;
968: }
969: }
970: }
971:
1.1.1.12! root 972: void store_40x_pit (CPUPPCState *env, target_ulong val)
1.1.1.4 root 973: {
974: ppc_tb_t *tb_env;
1.1.1.11 root 975: ppc40x_timer_t *ppc40x_timer;
1.1.1.4 root 976:
977: tb_env = env->tb_env;
1.1.1.11 root 978: ppc40x_timer = tb_env->opaque;
1.1.1.7 root 979: LOG_TB("%s val" TARGET_FMT_lx "\n", __func__, val);
1.1.1.11 root 980: ppc40x_timer->pit_reload = val;
1.1.1.4 root 981: start_stop_pit(env, tb_env, 0);
982: }
983:
1.1.1.12! root 984: target_ulong load_40x_pit (CPUPPCState *env)
1.1.1.4 root 985: {
986: return cpu_ppc_load_decr(env);
987: }
988:
1.1.1.11 root 989: static void ppc_40x_set_tb_clk (void *opaque, uint32_t freq)
1.1.1.4 root 990: {
1.1.1.12! root 991: CPUPPCState *env = opaque;
1.1.1.4 root 992: ppc_tb_t *tb_env = env->tb_env;
993:
1.1.1.5 root 994: LOG_TB("%s set new frequency to %" PRIu32 "\n", __func__,
1.1.1.4 root 995: freq);
996: tb_env->tb_freq = freq;
997: tb_env->decr_freq = freq;
998: /* XXX: we should also update all timers */
999: }
1000:
1.1.1.12! root 1001: clk_setup_cb ppc_40x_timers_init (CPUPPCState *env, uint32_t freq,
1.1.1.9 root 1002: unsigned int decr_excp)
1.1.1.4 root 1003: {
1004: ppc_tb_t *tb_env;
1.1.1.11 root 1005: ppc40x_timer_t *ppc40x_timer;
1.1.1.4 root 1006:
1.1.1.11 root 1007: tb_env = g_malloc0(sizeof(ppc_tb_t));
1.1.1.4 root 1008: env->tb_env = tb_env;
1.1.1.11 root 1009: tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
1010: ppc40x_timer = g_malloc0(sizeof(ppc40x_timer_t));
1.1.1.4 root 1011: tb_env->tb_freq = freq;
1012: tb_env->decr_freq = freq;
1.1.1.11 root 1013: tb_env->opaque = ppc40x_timer;
1.1.1.5 root 1014: LOG_TB("%s freq %" PRIu32 "\n", __func__, freq);
1.1.1.11 root 1015: if (ppc40x_timer != NULL) {
1.1.1.4 root 1016: /* We use decr timer for PIT */
1.1.1.10 root 1017: tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_4xx_pit_cb, env);
1.1.1.11 root 1018: ppc40x_timer->fit_timer =
1.1.1.10 root 1019: qemu_new_timer_ns(vm_clock, &cpu_4xx_fit_cb, env);
1.1.1.11 root 1020: ppc40x_timer->wdt_timer =
1.1.1.10 root 1021: qemu_new_timer_ns(vm_clock, &cpu_4xx_wdt_cb, env);
1.1.1.11 root 1022: ppc40x_timer->decr_excp = decr_excp;
1.1.1.4 root 1023: }
1024:
1.1.1.11 root 1025: return &ppc_40x_set_tb_clk;
1.1.1.4 root 1026: }
1027:
1028: /*****************************************************************************/
1029: /* Embedded PowerPC Device Control Registers */
1030: typedef struct ppc_dcrn_t ppc_dcrn_t;
1031: struct ppc_dcrn_t {
1032: dcr_read_cb dcr_read;
1033: dcr_write_cb dcr_write;
1034: void *opaque;
1035: };
1036:
1037: /* XXX: on 460, DCR addresses are 32 bits wide,
1038: * using DCRIPR to get the 22 upper bits of the DCR address
1039: */
1040: #define DCRN_NB 1024
1041: struct ppc_dcr_t {
1042: ppc_dcrn_t dcrn[DCRN_NB];
1043: int (*read_error)(int dcrn);
1044: int (*write_error)(int dcrn);
1045: };
1046:
1.1.1.8 root 1047: int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
1.1.1.4 root 1048: {
1049: ppc_dcrn_t *dcr;
1050:
1051: if (dcrn < 0 || dcrn >= DCRN_NB)
1052: goto error;
1053: dcr = &dcr_env->dcrn[dcrn];
1054: if (dcr->dcr_read == NULL)
1055: goto error;
1056: *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
1057:
1058: return 0;
1059:
1060: error:
1061: if (dcr_env->read_error != NULL)
1062: return (*dcr_env->read_error)(dcrn);
1063:
1064: return -1;
1065: }
1066:
1.1.1.8 root 1067: int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
1.1.1.4 root 1068: {
1069: ppc_dcrn_t *dcr;
1070:
1071: if (dcrn < 0 || dcrn >= DCRN_NB)
1072: goto error;
1073: dcr = &dcr_env->dcrn[dcrn];
1074: if (dcr->dcr_write == NULL)
1075: goto error;
1076: (*dcr->dcr_write)(dcr->opaque, dcrn, val);
1077:
1078: return 0;
1079:
1080: error:
1081: if (dcr_env->write_error != NULL)
1082: return (*dcr_env->write_error)(dcrn);
1083:
1084: return -1;
1085: }
1086:
1.1.1.12! root 1087: int ppc_dcr_register (CPUPPCState *env, int dcrn, void *opaque,
1.1.1.4 root 1088: dcr_read_cb dcr_read, dcr_write_cb dcr_write)
1089: {
1090: ppc_dcr_t *dcr_env;
1091: ppc_dcrn_t *dcr;
1092:
1093: dcr_env = env->dcr_env;
1094: if (dcr_env == NULL)
1095: return -1;
1096: if (dcrn < 0 || dcrn >= DCRN_NB)
1097: return -1;
1098: dcr = &dcr_env->dcrn[dcrn];
1099: if (dcr->opaque != NULL ||
1100: dcr->dcr_read != NULL ||
1101: dcr->dcr_write != NULL)
1102: return -1;
1103: dcr->opaque = opaque;
1104: dcr->dcr_read = dcr_read;
1105: dcr->dcr_write = dcr_write;
1106:
1107: return 0;
1108: }
1109:
1.1.1.12! root 1110: int ppc_dcr_init (CPUPPCState *env, int (*read_error)(int dcrn),
1.1.1.4 root 1111: int (*write_error)(int dcrn))
1112: {
1113: ppc_dcr_t *dcr_env;
1114:
1.1.1.11 root 1115: dcr_env = g_malloc0(sizeof(ppc_dcr_t));
1.1.1.4 root 1116: dcr_env->read_error = read_error;
1117: dcr_env->write_error = write_error;
1118: env->dcr_env = dcr_env;
1119:
1120: return 0;
1.1 root 1121: }
1122:
1123: /*****************************************************************************/
1124: /* Debug port */
1125: void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
1126: {
1127: addr &= 0xF;
1128: switch (addr) {
1129: case 0:
1130: printf("%c", val);
1131: break;
1132: case 1:
1133: printf("\n");
1134: fflush(stdout);
1135: break;
1136: case 2:
1.1.1.4 root 1137: printf("Set loglevel to %04" PRIx32 "\n", val);
1.1 root 1138: cpu_set_log(val | 0x100);
1139: break;
1140: }
1141: }
1142:
1143: /*****************************************************************************/
1144: /* NVRAM helpers */
1.1.1.4 root 1145: static inline uint32_t nvram_read (nvram_t *nvram, uint32_t addr)
1146: {
1.1.1.12! root 1147: return (*nvram->read_fn)(nvram->opaque, addr);
1.1.1.4 root 1148: }
1149:
1150: static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
1.1 root 1151: {
1.1.1.4 root 1152: (*nvram->write_fn)(nvram->opaque, addr, val);
1.1 root 1153: }
1154:
1.1.1.4 root 1155: void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value)
1.1 root 1156: {
1.1.1.4 root 1157: nvram_write(nvram, addr, value);
1.1 root 1158: }
1159:
1.1.1.4 root 1160: uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr)
1.1 root 1161: {
1.1.1.4 root 1162: return nvram_read(nvram, addr);
1.1 root 1163: }
1164:
1.1.1.4 root 1165: void NVRAM_set_word (nvram_t *nvram, uint32_t addr, uint16_t value)
1166: {
1167: nvram_write(nvram, addr, value >> 8);
1168: nvram_write(nvram, addr + 1, value & 0xFF);
1169: }
1170:
1171: uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr)
1.1 root 1172: {
1173: uint16_t tmp;
1174:
1.1.1.4 root 1175: tmp = nvram_read(nvram, addr) << 8;
1176: tmp |= nvram_read(nvram, addr + 1);
1177:
1.1 root 1178: return tmp;
1179: }
1180:
1.1.1.4 root 1181: void NVRAM_set_lword (nvram_t *nvram, uint32_t addr, uint32_t value)
1.1 root 1182: {
1.1.1.4 root 1183: nvram_write(nvram, addr, value >> 24);
1184: nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
1185: nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
1186: nvram_write(nvram, addr + 3, value & 0xFF);
1.1 root 1187: }
1188:
1.1.1.4 root 1189: uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
1.1 root 1190: {
1191: uint32_t tmp;
1192:
1.1.1.4 root 1193: tmp = nvram_read(nvram, addr) << 24;
1194: tmp |= nvram_read(nvram, addr + 1) << 16;
1195: tmp |= nvram_read(nvram, addr + 2) << 8;
1196: tmp |= nvram_read(nvram, addr + 3);
1197:
1.1 root 1198: return tmp;
1199: }
1200:
1.1.1.4 root 1201: void NVRAM_set_string (nvram_t *nvram, uint32_t addr,
1.1.1.5 root 1202: const char *str, uint32_t max)
1.1 root 1203: {
1204: int i;
1205:
1206: for (i = 0; i < max && str[i] != '\0'; i++) {
1.1.1.4 root 1207: nvram_write(nvram, addr + i, str[i]);
1.1 root 1208: }
1.1.1.4 root 1209: nvram_write(nvram, addr + i, str[i]);
1210: nvram_write(nvram, addr + max - 1, '\0');
1.1 root 1211: }
1212:
1.1.1.4 root 1213: int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max)
1.1 root 1214: {
1215: int i;
1216:
1217: memset(dst, 0, max);
1218: for (i = 0; i < max; i++) {
1219: dst[i] = NVRAM_get_byte(nvram, addr + i);
1220: if (dst[i] == '\0')
1221: break;
1222: }
1223:
1224: return i;
1225: }
1226:
1227: static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
1228: {
1229: uint16_t tmp;
1230: uint16_t pd, pd1, pd2;
1231:
1232: tmp = prev >> 8;
1233: pd = prev ^ value;
1234: pd1 = pd & 0x000F;
1235: pd2 = ((pd >> 4) & 0x000F) ^ pd1;
1236: tmp ^= (pd1 << 3) | (pd1 << 8);
1237: tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
1238:
1239: return tmp;
1240: }
1241:
1.1.1.5 root 1242: static uint16_t NVRAM_compute_crc (nvram_t *nvram, uint32_t start, uint32_t count)
1.1 root 1243: {
1244: uint32_t i;
1245: uint16_t crc = 0xFFFF;
1246: int odd;
1247:
1248: odd = count & 1;
1249: count &= ~1;
1250: for (i = 0; i != count; i++) {
1.1.1.4 root 1251: crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
1.1 root 1252: }
1253: if (odd) {
1.1.1.4 root 1254: crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
1.1 root 1255: }
1256:
1257: return crc;
1258: }
1259:
1260: #define CMDLINE_ADDR 0x017ff000
1261:
1.1.1.4 root 1262: int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
1.1.1.5 root 1263: const char *arch,
1.1 root 1264: uint32_t RAM_size, int boot_device,
1265: uint32_t kernel_image, uint32_t kernel_size,
1266: const char *cmdline,
1267: uint32_t initrd_image, uint32_t initrd_size,
1268: uint32_t NVRAM_image,
1269: int width, int height, int depth)
1270: {
1271: uint16_t crc;
1272:
1273: /* Set parameters for Open Hack'Ware BIOS */
1274: NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
1275: NVRAM_set_lword(nvram, 0x10, 0x00000002); /* structure v2 */
1276: NVRAM_set_word(nvram, 0x14, NVRAM_size);
1277: NVRAM_set_string(nvram, 0x20, arch, 16);
1278: NVRAM_set_lword(nvram, 0x30, RAM_size);
1279: NVRAM_set_byte(nvram, 0x34, boot_device);
1280: NVRAM_set_lword(nvram, 0x38, kernel_image);
1281: NVRAM_set_lword(nvram, 0x3C, kernel_size);
1282: if (cmdline) {
1283: /* XXX: put the cmdline in NVRAM too ? */
1.1.1.7 root 1284: pstrcpy_targphys("cmdline", CMDLINE_ADDR, RAM_size - CMDLINE_ADDR, cmdline);
1.1 root 1285: NVRAM_set_lword(nvram, 0x40, CMDLINE_ADDR);
1286: NVRAM_set_lword(nvram, 0x44, strlen(cmdline));
1287: } else {
1288: NVRAM_set_lword(nvram, 0x40, 0);
1289: NVRAM_set_lword(nvram, 0x44, 0);
1290: }
1291: NVRAM_set_lword(nvram, 0x48, initrd_image);
1292: NVRAM_set_lword(nvram, 0x4C, initrd_size);
1293: NVRAM_set_lword(nvram, 0x50, NVRAM_image);
1294:
1295: NVRAM_set_word(nvram, 0x54, width);
1296: NVRAM_set_word(nvram, 0x56, height);
1297: NVRAM_set_word(nvram, 0x58, depth);
1298: crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
1.1.1.4 root 1299: NVRAM_set_word(nvram, 0xFC, crc);
1.1 root 1300:
1301: return 0;
1302: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.