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