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