Statistics
| Branch: | Revision:

root / hw / ppc.c @ 7b62a955

History | View | Annotate | Download (40 kB)

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

    
26
//#define PPC_DEBUG_IRQ
27
//#define PPC_DEBUG_TB
28

    
29
extern FILE *logfile;
30
extern int loglevel;
31

    
32
static void cpu_ppc_tb_stop (CPUState *env);
33
static void cpu_ppc_tb_start (CPUState *env);
34

    
35
static void ppc_set_irq (CPUState *env, int n_IRQ, int level)
36
{
37
    if (level) {
38
        env->pending_interrupts |= 1 << n_IRQ;
39
        cpu_interrupt(env, CPU_INTERRUPT_HARD);
40
    } else {
41
        env->pending_interrupts &= ~(1 << n_IRQ);
42
        if (env->pending_interrupts == 0)
43
            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
44
    }
45
#if defined(PPC_DEBUG_IRQ)
46
    if (loglevel & CPU_LOG_INT) {
47
        fprintf(logfile, "%s: %p n_IRQ %d level %d => pending %08x req %08x\n",
48
                __func__, env, n_IRQ, level,
49
                env->pending_interrupts, env->interrupt_request);
50
    }
51
#endif
52
}
53

    
54
/* PowerPC 6xx / 7xx internal IRQ controller */
55
static void ppc6xx_set_irq (void *opaque, int pin, int level)
56
{
57
    CPUState *env = opaque;
58
    int cur_level;
59

    
60
#if defined(PPC_DEBUG_IRQ)
61
    if (loglevel & CPU_LOG_INT) {
62
        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
63
                env, pin, level);
64
    }
65
#endif
66
    cur_level = (env->irq_input_state >> pin) & 1;
67
    /* Don't generate spurious events */
68
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
69
        switch (pin) {
70
        case PPC6xx_INPUT_TBEN:
71
            /* Level sensitive - active high */
72
#if defined(PPC_DEBUG_IRQ)
73
            if (loglevel & CPU_LOG_INT) {
74
                fprintf(logfile, "%s: %s the time base\n",
75
                        __func__, level ? "start" : "stop");
76
            }
77
#endif
78
            if (level) {
79
                cpu_ppc_tb_start(env);
80
            } else {
81
                cpu_ppc_tb_stop(env);
82
            }
83
        case PPC6xx_INPUT_INT:
84
            /* Level sensitive - active high */
85
#if defined(PPC_DEBUG_IRQ)
86
            if (loglevel & CPU_LOG_INT) {
87
                fprintf(logfile, "%s: set the external IRQ state to %d\n",
88
                        __func__, level);
89
            }
90
#endif
91
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
92
            break;
93
        case PPC6xx_INPUT_SMI:
94
            /* Level sensitive - active high */
95
#if defined(PPC_DEBUG_IRQ)
96
            if (loglevel & CPU_LOG_INT) {
97
                fprintf(logfile, "%s: set the SMI IRQ state to %d\n",
98
                        __func__, level);
99
            }
100
#endif
101
            ppc_set_irq(env, PPC_INTERRUPT_SMI, level);
102
            break;
103
        case PPC6xx_INPUT_MCP:
104
            /* Negative edge sensitive */
105
            /* XXX: TODO: actual reaction may depends on HID0 status
106
             *            603/604/740/750: check HID0[EMCP]
107
             */
108
            if (cur_level == 1 && level == 0) {
109
#if defined(PPC_DEBUG_IRQ)
110
                if (loglevel & CPU_LOG_INT) {
111
                    fprintf(logfile, "%s: raise machine check state\n",
112
                            __func__);
113
                }
114
#endif
115
                ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
116
            }
117
            break;
118
        case PPC6xx_INPUT_CKSTP_IN:
119
            /* Level sensitive - active low */
120
            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
121
            /* XXX: Note that the only way to restart the CPU is to reset it */
122
            if (level) {
123
#if defined(PPC_DEBUG_IRQ)
124
                if (loglevel & CPU_LOG_INT) {
125
                    fprintf(logfile, "%s: stop the CPU\n", __func__);
126
                }
127
#endif
128
                env->halted = 1;
129
            }
130
            break;
131
        case PPC6xx_INPUT_HRESET:
132
            /* Level sensitive - active low */
133
            if (level) {
134
#if defined(PPC_DEBUG_IRQ)
135
                if (loglevel & CPU_LOG_INT) {
136
                    fprintf(logfile, "%s: reset the CPU\n", __func__);
137
                }
138
#endif
139
                env->interrupt_request |= CPU_INTERRUPT_EXITTB;
140
                /* XXX: TOFIX */
141
#if 0
142
                cpu_ppc_reset(env);
143
#else
144
                qemu_system_reset_request();
145
#endif
146
            }
147
            break;
148
        case PPC6xx_INPUT_SRESET:
149
#if defined(PPC_DEBUG_IRQ)
150
            if (loglevel & CPU_LOG_INT) {
151
                fprintf(logfile, "%s: set the RESET IRQ state to %d\n",
152
                        __func__, level);
153
            }
154
#endif
155
            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
156
            break;
157
        default:
158
            /* Unknown pin - do nothing */
159
#if defined(PPC_DEBUG_IRQ)
160
            if (loglevel & CPU_LOG_INT) {
161
                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
162
            }
163
#endif
164
            return;
165
        }
166
        if (level)
167
            env->irq_input_state |= 1 << pin;
168
        else
169
            env->irq_input_state &= ~(1 << pin);
170
    }
171
}
172

    
173
void ppc6xx_irq_init (CPUState *env)
174
{
175
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env,
176
                                                  PPC6xx_INPUT_NB);
177
}
178

    
179
#if defined(TARGET_PPC64)
180
/* PowerPC 970 internal IRQ controller */
181
static void ppc970_set_irq (void *opaque, int pin, int level)
182
{
183
    CPUState *env = opaque;
184
    int cur_level;
185

    
186
#if defined(PPC_DEBUG_IRQ)
187
    if (loglevel & CPU_LOG_INT) {
188
        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
189
                env, pin, level);
190
    }
191
#endif
192
    cur_level = (env->irq_input_state >> pin) & 1;
193
    /* Don't generate spurious events */
194
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
195
        switch (pin) {
196
        case PPC970_INPUT_INT:
197
            /* Level sensitive - active high */
198
#if defined(PPC_DEBUG_IRQ)
199
            if (loglevel & CPU_LOG_INT) {
200
                fprintf(logfile, "%s: set the external IRQ state to %d\n",
201
                        __func__, level);
202
            }
203
#endif
204
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
205
            break;
206
        case PPC970_INPUT_THINT:
207
            /* Level sensitive - active high */
208
#if defined(PPC_DEBUG_IRQ)
209
            if (loglevel & CPU_LOG_INT) {
210
                fprintf(logfile, "%s: set the SMI IRQ state to %d\n", __func__,
211
                        level);
212
            }
213
#endif
214
            ppc_set_irq(env, PPC_INTERRUPT_THERM, level);
215
            break;
216
        case PPC970_INPUT_MCP:
217
            /* Negative edge sensitive */
218
            /* XXX: TODO: actual reaction may depends on HID0 status
219
             *            603/604/740/750: check HID0[EMCP]
220
             */
221
            if (cur_level == 1 && level == 0) {
222
#if defined(PPC_DEBUG_IRQ)
223
                if (loglevel & CPU_LOG_INT) {
224
                    fprintf(logfile, "%s: raise machine check state\n",
225
                            __func__);
226
                }
227
#endif
228
                ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
229
            }
230
            break;
231
        case PPC970_INPUT_CKSTP:
232
            /* Level sensitive - active low */
233
            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
234
            if (level) {
235
#if defined(PPC_DEBUG_IRQ)
236
                if (loglevel & CPU_LOG_INT) {
237
                    fprintf(logfile, "%s: stop the CPU\n", __func__);
238
                }
239
#endif
240
                env->halted = 1;
241
            } else {
242
#if defined(PPC_DEBUG_IRQ)
243
                if (loglevel & CPU_LOG_INT) {
244
                    fprintf(logfile, "%s: restart the CPU\n", __func__);
245
                }
246
#endif
247
                env->halted = 0;
248
            }
249
            break;
250
        case PPC970_INPUT_HRESET:
251
            /* Level sensitive - active low */
252
            if (level) {
253
#if 0 // XXX: TOFIX
254
#if defined(PPC_DEBUG_IRQ)
255
                if (loglevel & CPU_LOG_INT) {
256
                    fprintf(logfile, "%s: reset the CPU\n", __func__);
257
                }
258
#endif
259
                cpu_reset(env);
260
#endif
261
            }
262
            break;
263
        case PPC970_INPUT_SRESET:
264
#if defined(PPC_DEBUG_IRQ)
265
            if (loglevel & CPU_LOG_INT) {
266
                fprintf(logfile, "%s: set the RESET IRQ state to %d\n",
267
                        __func__, level);
268
            }
269
#endif
270
            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
271
            break;
272
        case PPC970_INPUT_TBEN:
273
#if defined(PPC_DEBUG_IRQ)
274
            if (loglevel & CPU_LOG_INT) {
275
                fprintf(logfile, "%s: set the TBEN state to %d\n", __func__,
276
                        level);
277
            }
278
#endif
279
            /* XXX: TODO */
280
            break;
281
        default:
282
            /* Unknown pin - do nothing */
283
#if defined(PPC_DEBUG_IRQ)
284
            if (loglevel & CPU_LOG_INT) {
285
                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
286
            }
287
#endif
288
            return;
289
        }
290
        if (level)
291
            env->irq_input_state |= 1 << pin;
292
        else
293
            env->irq_input_state &= ~(1 << pin);
294
    }
295
}
296

    
297
void ppc970_irq_init (CPUState *env)
298
{
299
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env,
300
                                                  PPC970_INPUT_NB);
301
}
302
#endif /* defined(TARGET_PPC64) */
303

    
304
/* PowerPC 40x internal IRQ controller */
305
static void ppc40x_set_irq (void *opaque, int pin, int level)
306
{
307
    CPUState *env = opaque;
308
    int cur_level;
309

    
310
#if defined(PPC_DEBUG_IRQ)
311
    if (loglevel & CPU_LOG_INT) {
312
        fprintf(logfile, "%s: env %p pin %d level %d\n", __func__,
313
                env, pin, level);
314
    }
315
#endif
316
    cur_level = (env->irq_input_state >> pin) & 1;
317
    /* Don't generate spurious events */
318
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
319
        switch (pin) {
320
        case PPC40x_INPUT_RESET_SYS:
321
            if (level) {
322
#if defined(PPC_DEBUG_IRQ)
323
                if (loglevel & CPU_LOG_INT) {
324
                    fprintf(logfile, "%s: reset the PowerPC system\n",
325
                            __func__);
326
                }
327
#endif
328
                ppc40x_system_reset(env);
329
            }
330
            break;
331
        case PPC40x_INPUT_RESET_CHIP:
332
            if (level) {
333
#if defined(PPC_DEBUG_IRQ)
334
                if (loglevel & CPU_LOG_INT) {
335
                    fprintf(logfile, "%s: reset the PowerPC chip\n", __func__);
336
                }
337
#endif
338
                ppc40x_chip_reset(env);
339
            }
340
            break;
341
        case PPC40x_INPUT_RESET_CORE:
342
            /* XXX: TODO: update DBSR[MRR] */
343
            if (level) {
344
#if defined(PPC_DEBUG_IRQ)
345
                if (loglevel & CPU_LOG_INT) {
346
                    fprintf(logfile, "%s: reset the PowerPC core\n", __func__);
347
                }
348
#endif
349
                ppc40x_core_reset(env);
350
            }
351
            break;
352
        case PPC40x_INPUT_CINT:
353
            /* Level sensitive - active high */
354
#if defined(PPC_DEBUG_IRQ)
355
            if (loglevel & CPU_LOG_INT) {
356
                fprintf(logfile, "%s: set the critical IRQ state to %d\n",
357
                        __func__, level);
358
            }
359
#endif
360
            ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
361
            break;
362
        case PPC40x_INPUT_INT:
363
            /* Level sensitive - active high */
364
#if defined(PPC_DEBUG_IRQ)
365
            if (loglevel & CPU_LOG_INT) {
366
                fprintf(logfile, "%s: set the external IRQ state to %d\n",
367
                        __func__, level);
368
            }
369
#endif
370
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
371
            break;
372
        case PPC40x_INPUT_HALT:
373
            /* Level sensitive - active low */
374
            if (level) {
375
#if defined(PPC_DEBUG_IRQ)
376
                if (loglevel & CPU_LOG_INT) {
377
                    fprintf(logfile, "%s: stop the CPU\n", __func__);
378
                }
379
#endif
380
                env->halted = 1;
381
            } else {
382
#if defined(PPC_DEBUG_IRQ)
383
                if (loglevel & CPU_LOG_INT) {
384
                    fprintf(logfile, "%s: restart the CPU\n", __func__);
385
                }
386
#endif
387
                env->halted = 0;
388
            }
389
            break;
390
        case PPC40x_INPUT_DEBUG:
391
            /* Level sensitive - active high */
392
#if defined(PPC_DEBUG_IRQ)
393
            if (loglevel & CPU_LOG_INT) {
394
                fprintf(logfile, "%s: set the debug pin state to %d\n",
395
                        __func__, level);
396
            }
397
#endif
398
            ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
399
            break;
400
        default:
401
            /* Unknown pin - do nothing */
402
#if defined(PPC_DEBUG_IRQ)
403
            if (loglevel & CPU_LOG_INT) {
404
                fprintf(logfile, "%s: unknown IRQ pin %d\n", __func__, pin);
405
            }
406
#endif
407
            return;
408
        }
409
        if (level)
410
            env->irq_input_state |= 1 << pin;
411
        else
412
            env->irq_input_state &= ~(1 << pin);
413
    }
414
}
415

    
416
void ppc40x_irq_init (CPUState *env)
417
{
418
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
419
                                                  env, PPC40x_INPUT_NB);
420
}
421

    
422
/*****************************************************************************/
423
/* PowerPC time base and decrementer emulation */
424
struct ppc_tb_t {
425
    /* Time base management */
426
    int64_t  tb_offset;    /* Compensation                    */
427
    int64_t  atb_offset;   /* Compensation                    */
428
    uint32_t tb_freq;      /* TB frequency                    */
429
    /* Decrementer management */
430
    uint64_t decr_next;    /* Tick for next decr interrupt    */
431
    uint32_t decr_freq;    /* decrementer frequency           */
432
    struct QEMUTimer *decr_timer;
433
    /* Hypervisor decrementer management */
434
    uint64_t hdecr_next;    /* Tick for next hdecr interrupt  */
435
    struct QEMUTimer *hdecr_timer;
436
    uint64_t purr_load;
437
    uint64_t purr_start;
438
    void *opaque;
439
};
440

    
441
static always_inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env, uint64_t vmclk,
442
                                              int64_t tb_offset)
443
{
444
    /* TB time in tb periods */
445
    return muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec) + tb_offset;
446
}
447

    
448
uint32_t cpu_ppc_load_tbl (CPUState *env)
449
{
450
    ppc_tb_t *tb_env = env->tb_env;
451
    uint64_t tb;
452

    
453
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
454
#if defined(PPC_DEBUG_TB)
455
    if (loglevel != 0) {
456
        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
457
    }
458
#endif
459

    
460
    return tb & 0xFFFFFFFF;
461
}
462

    
463
static always_inline uint32_t _cpu_ppc_load_tbu (CPUState *env)
464
{
465
    ppc_tb_t *tb_env = env->tb_env;
466
    uint64_t tb;
467

    
468
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
469
#if defined(PPC_DEBUG_TB)
470
    if (loglevel != 0) {
471
        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
472
    }
473
#endif
474

    
475
    return tb >> 32;
476
}
477

    
478
uint32_t cpu_ppc_load_tbu (CPUState *env)
479
{
480
    return _cpu_ppc_load_tbu(env);
481
}
482

    
483
static always_inline void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t vmclk,
484
                                            int64_t *tb_offsetp,
485
                                            uint64_t value)
486
{
487
    *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, ticks_per_sec);
488
#ifdef PPC_DEBUG_TB
489
    if (loglevel != 0) {
490
        fprintf(logfile, "%s: tb=0x%016lx offset=%08lx\n", __func__, value,
491
                *tb_offsetp);
492
    }
493
#endif
494
}
495

    
496
void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
497
{
498
    ppc_tb_t *tb_env = env->tb_env;
499
    uint64_t tb;
500

    
501
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
502
    tb &= 0xFFFFFFFF00000000ULL;
503
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
504
                     &tb_env->tb_offset, tb | (uint64_t)value);
505
}
506

    
507
static always_inline void _cpu_ppc_store_tbu (CPUState *env, uint32_t value)
508
{
509
    ppc_tb_t *tb_env = env->tb_env;
510
    uint64_t tb;
511

    
512
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->tb_offset);
513
    tb &= 0x00000000FFFFFFFFULL;
514
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
515
                     &tb_env->tb_offset, ((uint64_t)value << 32) | tb);
516
}
517

    
518
void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
519
{
520
    _cpu_ppc_store_tbu(env, value);
521
}
522

    
523
uint32_t cpu_ppc_load_atbl (CPUState *env)
524
{
525
    ppc_tb_t *tb_env = env->tb_env;
526
    uint64_t tb;
527

    
528
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
529
#if defined(PPC_DEBUG_TB)
530
    if (loglevel != 0) {
531
        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
532
    }
533
#endif
534

    
535
    return tb & 0xFFFFFFFF;
536
}
537

    
538
uint32_t cpu_ppc_load_atbu (CPUState *env)
539
{
540
    ppc_tb_t *tb_env = env->tb_env;
541
    uint64_t tb;
542

    
543
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
544
#if defined(PPC_DEBUG_TB)
545
    if (loglevel != 0) {
546
        fprintf(logfile, "%s: tb=0x%016lx\n", __func__, tb);
547
    }
548
#endif
549

    
550
    return tb >> 32;
551
}
552

    
553
void cpu_ppc_store_atbl (CPUState *env, uint32_t value)
554
{
555
    ppc_tb_t *tb_env = env->tb_env;
556
    uint64_t tb;
557

    
558
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
559
    tb &= 0xFFFFFFFF00000000ULL;
560
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
561
                     &tb_env->atb_offset, tb | (uint64_t)value);
562
}
563

    
564
void cpu_ppc_store_atbu (CPUState *env, uint32_t value)
565
{
566
    ppc_tb_t *tb_env = env->tb_env;
567
    uint64_t tb;
568

    
569
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock(vm_clock), tb_env->atb_offset);
570
    tb &= 0x00000000FFFFFFFFULL;
571
    cpu_ppc_store_tb(tb_env, qemu_get_clock(vm_clock),
572
                     &tb_env->atb_offset, ((uint64_t)value << 32) | tb);
573
}
574

    
575
static void cpu_ppc_tb_stop (CPUState *env)
576
{
577
    ppc_tb_t *tb_env = env->tb_env;
578
    uint64_t tb, atb, vmclk;
579

    
580
    /* If the time base is already frozen, do nothing */
581
    if (tb_env->tb_freq != 0) {
582
        vmclk = qemu_get_clock(vm_clock);
583
        /* Get the time base */
584
        tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset);
585
        /* Get the alternate time base */
586
        atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset);
587
        /* Store the time base value (ie compute the current offset) */
588
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
589
        /* Store the alternate time base value (compute the current offset) */
590
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
591
        /* Set the time base frequency to zero */
592
        tb_env->tb_freq = 0;
593
        /* Now, the time bases are frozen to tb_offset / atb_offset value */
594
    }
595
}
596

    
597
static void cpu_ppc_tb_start (CPUState *env)
598
{
599
    ppc_tb_t *tb_env = env->tb_env;
600
    uint64_t tb, atb, vmclk;
601
    
602
    /* If the time base is not frozen, do nothing */
603
    if (tb_env->tb_freq == 0) {
604
        vmclk = qemu_get_clock(vm_clock);
605
        /* Get the time base from tb_offset */
606
        tb = tb_env->tb_offset;
607
        /* Get the alternate time base from atb_offset */
608
        atb = tb_env->atb_offset;
609
        /* Restore the tb frequency from the decrementer frequency */
610
        tb_env->tb_freq = tb_env->decr_freq;
611
        /* Store the time base value */
612
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
613
        /* Store the alternate time base value */
614
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
615
    }
616
}
617

    
618
static always_inline uint32_t _cpu_ppc_load_decr (CPUState *env,
619
                                                  uint64_t *next)
620
{
621
    ppc_tb_t *tb_env = env->tb_env;
622
    uint32_t decr;
623
    int64_t diff;
624

    
625
    diff = tb_env->decr_next - qemu_get_clock(vm_clock);
626
    if (diff >= 0)
627
        decr = muldiv64(diff, tb_env->decr_freq, ticks_per_sec);
628
    else
629
        decr = -muldiv64(-diff, tb_env->decr_freq, ticks_per_sec);
630
#if defined(PPC_DEBUG_TB)
631
    if (loglevel != 0) {
632
        fprintf(logfile, "%s: 0x%08x\n", __func__, decr);
633
    }
634
#endif
635

    
636
    return decr;
637
}
638

    
639
uint32_t cpu_ppc_load_decr (CPUState *env)
640
{
641
    ppc_tb_t *tb_env = env->tb_env;
642

    
643
    return _cpu_ppc_load_decr(env, &tb_env->decr_next);
644
}
645

    
646
uint32_t cpu_ppc_load_hdecr (CPUState *env)
647
{
648
    ppc_tb_t *tb_env = env->tb_env;
649

    
650
    return _cpu_ppc_load_decr(env, &tb_env->hdecr_next);
651
}
652

    
653
uint64_t cpu_ppc_load_purr (CPUState *env)
654
{
655
    ppc_tb_t *tb_env = env->tb_env;
656
    uint64_t diff;
657

    
658
    diff = qemu_get_clock(vm_clock) - tb_env->purr_start;
659

    
660
    return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, ticks_per_sec);
661
}
662

    
663
/* When decrementer expires,
664
 * all we need to do is generate or queue a CPU exception
665
 */
666
static always_inline void cpu_ppc_decr_excp (CPUState *env)
667
{
668
    /* Raise it */
669
#ifdef PPC_DEBUG_TB
670
    if (loglevel != 0) {
671
        fprintf(logfile, "raise decrementer exception\n");
672
    }
673
#endif
674
    ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
675
}
676

    
677
static always_inline void cpu_ppc_hdecr_excp (CPUState *env)
678
{
679
    /* Raise it */
680
#ifdef PPC_DEBUG_TB
681
    if (loglevel != 0) {
682
        fprintf(logfile, "raise decrementer exception\n");
683
    }
684
#endif
685
    ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1);
686
}
687

    
688
static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
689
                                  struct QEMUTimer *timer,
690
                                  void (*raise_excp)(CPUState *),
691
                                  uint32_t decr, uint32_t value,
692
                                  int is_excp)
693
{
694
    ppc_tb_t *tb_env = env->tb_env;
695
    uint64_t now, next;
696

    
697
#ifdef PPC_DEBUG_TB
698
    if (loglevel != 0) {
699
        fprintf(logfile, "%s: 0x%08x => 0x%08x\n", __func__, decr, value);
700
    }
701
#endif
702
    now = qemu_get_clock(vm_clock);
703
    next = now + muldiv64(value, ticks_per_sec, tb_env->decr_freq);
704
    if (is_excp)
705
        next += *nextp - now;
706
    if (next == now)
707
        next++;
708
    *nextp = next;
709
    /* Adjust timer */
710
    qemu_mod_timer(timer, next);
711
    /* If we set a negative value and the decrementer was positive,
712
     * raise an exception.
713
     */
714
    if ((value & 0x80000000) && !(decr & 0x80000000))
715
        (*raise_excp)(env);
716
}
717

    
718
static always_inline void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
719
                                               uint32_t value, int is_excp)
720
{
721
    ppc_tb_t *tb_env = env->tb_env;
722

    
723
    __cpu_ppc_store_decr(env, &tb_env->decr_next, tb_env->decr_timer,
724
                         &cpu_ppc_decr_excp, decr, value, is_excp);
725
}
726

    
727
void cpu_ppc_store_decr (CPUState *env, uint32_t value)
728
{
729
    _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
730
}
731

    
732
static void cpu_ppc_decr_cb (void *opaque)
733
{
734
    _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
735
}
736

    
737
static always_inline void _cpu_ppc_store_hdecr (CPUState *env, uint32_t hdecr,
738
                                                uint32_t value, int is_excp)
739
{
740
    ppc_tb_t *tb_env = env->tb_env;
741

    
742
    if (tb_env->hdecr_timer != NULL) {
743
        __cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer,
744
                             &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
745
    }
746
}
747

    
748
void cpu_ppc_store_hdecr (CPUState *env, uint32_t value)
749
{
750
    _cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0);
751
}
752

    
753
static void cpu_ppc_hdecr_cb (void *opaque)
754
{
755
    _cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1);
756
}
757

    
758
void cpu_ppc_store_purr (CPUState *env, uint64_t value)
759
{
760
    ppc_tb_t *tb_env = env->tb_env;
761

    
762
    tb_env->purr_load = value;
763
    tb_env->purr_start = qemu_get_clock(vm_clock);
764
}
765

    
766
static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
767
{
768
    CPUState *env = opaque;
769
    ppc_tb_t *tb_env = env->tb_env;
770

    
771
    tb_env->tb_freq = freq;
772
    tb_env->decr_freq = freq;
773
    /* There is a bug in Linux 2.4 kernels:
774
     * if a decrementer exception is pending when it enables msr_ee at startup,
775
     * it's not ready to handle it...
776
     */
777
    _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
778
    _cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
779
    cpu_ppc_store_purr(env, 0x0000000000000000ULL);
780
}
781

    
782
/* Set up (once) timebase frequency (in Hz) */
783
clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
784
{
785
    ppc_tb_t *tb_env;
786

    
787
    tb_env = qemu_mallocz(sizeof(ppc_tb_t));
788
    if (tb_env == NULL)
789
        return NULL;
790
    env->tb_env = tb_env;
791
    /* Create new timer */
792
    tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
793
    if (0) {
794
        /* XXX: find a suitable condition to enable the hypervisor decrementer
795
         */
796
        tb_env->hdecr_timer = qemu_new_timer(vm_clock, &cpu_ppc_hdecr_cb, env);
797
    } else {
798
        tb_env->hdecr_timer = NULL;
799
    }
800
    cpu_ppc_set_tb_clk(env, freq);
801

    
802
    return &cpu_ppc_set_tb_clk;
803
}
804

    
805
/* Specific helpers for POWER & PowerPC 601 RTC */
806
clk_setup_cb cpu_ppc601_rtc_init (CPUState *env)
807
{
808
    return cpu_ppc_tb_init(env, 7812500);
809
}
810

    
811
void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
812
{
813
    _cpu_ppc_store_tbu(env, value);
814
}
815

    
816
uint32_t cpu_ppc601_load_rtcu (CPUState *env)
817
{
818
    return _cpu_ppc_load_tbu(env);
819
}
820

    
821
void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
822
{
823
    cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
824
}
825

    
826
uint32_t cpu_ppc601_load_rtcl (CPUState *env)
827
{
828
    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
829
}
830

    
831
/*****************************************************************************/
832
/* Embedded PowerPC timers */
833

    
834
/* PIT, FIT & WDT */
835
typedef struct ppcemb_timer_t ppcemb_timer_t;
836
struct ppcemb_timer_t {
837
    uint64_t pit_reload;  /* PIT auto-reload value        */
838
    uint64_t fit_next;    /* Tick for next FIT interrupt  */
839
    struct QEMUTimer *fit_timer;
840
    uint64_t wdt_next;    /* Tick for next WDT interrupt  */
841
    struct QEMUTimer *wdt_timer;
842
};
843

    
844
/* Fixed interval timer */
845
static void cpu_4xx_fit_cb (void *opaque)
846
{
847
    CPUState *env;
848
    ppc_tb_t *tb_env;
849
    ppcemb_timer_t *ppcemb_timer;
850
    uint64_t now, next;
851

    
852
    env = opaque;
853
    tb_env = env->tb_env;
854
    ppcemb_timer = tb_env->opaque;
855
    now = qemu_get_clock(vm_clock);
856
    switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
857
    case 0:
858
        next = 1 << 9;
859
        break;
860
    case 1:
861
        next = 1 << 13;
862
        break;
863
    case 2:
864
        next = 1 << 17;
865
        break;
866
    case 3:
867
        next = 1 << 21;
868
        break;
869
    default:
870
        /* Cannot occur, but makes gcc happy */
871
        return;
872
    }
873
    next = now + muldiv64(next, ticks_per_sec, tb_env->tb_freq);
874
    if (next == now)
875
        next++;
876
    qemu_mod_timer(ppcemb_timer->fit_timer, next);
877
    env->spr[SPR_40x_TSR] |= 1 << 26;
878
    if ((env->spr[SPR_40x_TCR] >> 23) & 0x1)
879
        ppc_set_irq(env, PPC_INTERRUPT_FIT, 1);
880
#ifdef PPC_DEBUG_TB
881
    if (loglevel != 0) {
882
        fprintf(logfile, "%s: ir %d TCR " ADDRX " TSR " ADDRX "\n", __func__,
883
                (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
884
                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
885
    }
886
#endif
887
}
888

    
889
/* Programmable interval timer */
890
static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp)
891
{
892
    ppcemb_timer_t *ppcemb_timer;
893
    uint64_t now, next;
894

    
895
    ppcemb_timer = tb_env->opaque;
896
    if (ppcemb_timer->pit_reload <= 1 ||
897
        !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
898
        (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
899
        /* Stop PIT */
900
#ifdef PPC_DEBUG_TB
901
        if (loglevel != 0) {
902
            fprintf(logfile, "%s: stop PIT\n", __func__);
903
        }
904
#endif
905
        qemu_del_timer(tb_env->decr_timer);
906
    } else {
907
#ifdef PPC_DEBUG_TB
908
        if (loglevel != 0) {
909
            fprintf(logfile, "%s: start PIT 0x" REGX "\n",
910
                    __func__, ppcemb_timer->pit_reload);
911
        }
912
#endif
913
        now = qemu_get_clock(vm_clock);
914
        next = now + muldiv64(ppcemb_timer->pit_reload,
915
                              ticks_per_sec, tb_env->decr_freq);
916
        if (is_excp)
917
            next += tb_env->decr_next - now;
918
        if (next == now)
919
            next++;
920
        qemu_mod_timer(tb_env->decr_timer, next);
921
        tb_env->decr_next = next;
922
    }
923
}
924

    
925
static void cpu_4xx_pit_cb (void *opaque)
926
{
927
    CPUState *env;
928
    ppc_tb_t *tb_env;
929
    ppcemb_timer_t *ppcemb_timer;
930

    
931
    env = opaque;
932
    tb_env = env->tb_env;
933
    ppcemb_timer = tb_env->opaque;
934
    env->spr[SPR_40x_TSR] |= 1 << 27;
935
    if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
936
        ppc_set_irq(env, PPC_INTERRUPT_PIT, 1);
937
    start_stop_pit(env, tb_env, 1);
938
#ifdef PPC_DEBUG_TB
939
    if (loglevel != 0) {
940
        fprintf(logfile, "%s: ar %d ir %d TCR " ADDRX " TSR " ADDRX " "
941
                "%016" PRIx64 "\n", __func__,
942
                (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
943
                (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
944
                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
945
                ppcemb_timer->pit_reload);
946
    }
947
#endif
948
}
949

    
950
/* Watchdog timer */
951
static void cpu_4xx_wdt_cb (void *opaque)
952
{
953
    CPUState *env;
954
    ppc_tb_t *tb_env;
955
    ppcemb_timer_t *ppcemb_timer;
956
    uint64_t now, next;
957

    
958
    env = opaque;
959
    tb_env = env->tb_env;
960
    ppcemb_timer = tb_env->opaque;
961
    now = qemu_get_clock(vm_clock);
962
    switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
963
    case 0:
964
        next = 1 << 17;
965
        break;
966
    case 1:
967
        next = 1 << 21;
968
        break;
969
    case 2:
970
        next = 1 << 25;
971
        break;
972
    case 3:
973
        next = 1 << 29;
974
        break;
975
    default:
976
        /* Cannot occur, but makes gcc happy */
977
        return;
978
    }
979
    next = now + muldiv64(next, ticks_per_sec, tb_env->decr_freq);
980
    if (next == now)
981
        next++;
982
#ifdef PPC_DEBUG_TB
983
    if (loglevel != 0) {
984
        fprintf(logfile, "%s: TCR " ADDRX " TSR " ADDRX "\n", __func__,
985
                env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
986
    }
987
#endif
988
    switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
989
    case 0x0:
990
    case 0x1:
991
        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
992
        ppcemb_timer->wdt_next = next;
993
        env->spr[SPR_40x_TSR] |= 1 << 31;
994
        break;
995
    case 0x2:
996
        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
997
        ppcemb_timer->wdt_next = next;
998
        env->spr[SPR_40x_TSR] |= 1 << 30;
999
        if ((env->spr[SPR_40x_TCR] >> 27) & 0x1)
1000
            ppc_set_irq(env, PPC_INTERRUPT_WDT, 1);
1001
        break;
1002
    case 0x3:
1003
        env->spr[SPR_40x_TSR] &= ~0x30000000;
1004
        env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
1005
        switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
1006
        case 0x0:
1007
            /* No reset */
1008
            break;
1009
        case 0x1: /* Core reset */
1010
            ppc40x_core_reset(env);
1011
            break;
1012
        case 0x2: /* Chip reset */
1013
            ppc40x_chip_reset(env);
1014
            break;
1015
        case 0x3: /* System reset */
1016
            ppc40x_system_reset(env);
1017
            break;
1018
        }
1019
    }
1020
}
1021

    
1022
void store_40x_pit (CPUState *env, target_ulong val)
1023
{
1024
    ppc_tb_t *tb_env;
1025
    ppcemb_timer_t *ppcemb_timer;
1026

    
1027
    tb_env = env->tb_env;
1028
    ppcemb_timer = tb_env->opaque;
1029
#ifdef PPC_DEBUG_TB
1030
    if (loglevel != 0) {
1031
        fprintf(logfile, "%s %p %p\n", __func__, tb_env, ppcemb_timer);
1032
    }
1033
#endif
1034
    ppcemb_timer->pit_reload = val;
1035
    start_stop_pit(env, tb_env, 0);
1036
}
1037

    
1038
target_ulong load_40x_pit (CPUState *env)
1039
{
1040
    return cpu_ppc_load_decr(env);
1041
}
1042

    
1043
void store_booke_tsr (CPUState *env, target_ulong val)
1044
{
1045
#ifdef PPC_DEBUG_TB
1046
    if (loglevel != 0) {
1047
        fprintf(logfile, "%s: val=" ADDRX "\n", __func__, val);
1048
    }
1049
#endif
1050
    env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
1051
    if (val & 0x80000000)
1052
        ppc_set_irq(env, PPC_INTERRUPT_PIT, 0);
1053
}
1054

    
1055
void store_booke_tcr (CPUState *env, target_ulong val)
1056
{
1057
    ppc_tb_t *tb_env;
1058

    
1059
    tb_env = env->tb_env;
1060
#ifdef PPC_DEBUG_TB
1061
    if (loglevel != 0) {
1062
        fprintf(logfile, "%s: val=" ADDRX "\n", __func__, val);
1063
    }
1064
#endif
1065
    env->spr[SPR_40x_TCR] = val & 0xFFC00000;
1066
    start_stop_pit(env, tb_env, 1);
1067
    cpu_4xx_wdt_cb(env);
1068
}
1069

    
1070
static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
1071
{
1072
    CPUState *env = opaque;
1073
    ppc_tb_t *tb_env = env->tb_env;
1074

    
1075
#ifdef PPC_DEBUG_TB
1076
    if (loglevel != 0) {
1077
        fprintf(logfile, "%s set new frequency to %u\n", __func__, freq);
1078
    }
1079
#endif
1080
    tb_env->tb_freq = freq;
1081
    tb_env->decr_freq = freq;
1082
    /* XXX: we should also update all timers */
1083
}
1084

    
1085
clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq)
1086
{
1087
    ppc_tb_t *tb_env;
1088
    ppcemb_timer_t *ppcemb_timer;
1089

    
1090
    tb_env = qemu_mallocz(sizeof(ppc_tb_t));
1091
    if (tb_env == NULL) {
1092
        return NULL;
1093
    }
1094
    env->tb_env = tb_env;
1095
    ppcemb_timer = qemu_mallocz(sizeof(ppcemb_timer_t));
1096
    tb_env->tb_freq = freq;
1097
    tb_env->decr_freq = freq;
1098
    tb_env->opaque = ppcemb_timer;
1099
#ifdef PPC_DEBUG_TB
1100
    if (loglevel != 0) {
1101
        fprintf(logfile, "%s %p %p %p\n", __func__, tb_env, ppcemb_timer,
1102
                &ppc_emb_set_tb_clk);
1103
    }
1104
#endif
1105
    if (ppcemb_timer != NULL) {
1106
        /* We use decr timer for PIT */
1107
        tb_env->decr_timer = qemu_new_timer(vm_clock, &cpu_4xx_pit_cb, env);
1108
        ppcemb_timer->fit_timer =
1109
            qemu_new_timer(vm_clock, &cpu_4xx_fit_cb, env);
1110
        ppcemb_timer->wdt_timer =
1111
            qemu_new_timer(vm_clock, &cpu_4xx_wdt_cb, env);
1112
    }
1113

    
1114
    return &ppc_emb_set_tb_clk;
1115
}
1116

    
1117
/*****************************************************************************/
1118
/* Embedded PowerPC Device Control Registers */
1119
typedef struct ppc_dcrn_t ppc_dcrn_t;
1120
struct ppc_dcrn_t {
1121
    dcr_read_cb dcr_read;
1122
    dcr_write_cb dcr_write;
1123
    void *opaque;
1124
};
1125

    
1126
/* XXX: on 460, DCR addresses are 32 bits wide,
1127
 *      using DCRIPR to get the 22 upper bits of the DCR address
1128
 */
1129
#define DCRN_NB 1024
1130
struct ppc_dcr_t {
1131
    ppc_dcrn_t dcrn[DCRN_NB];
1132
    int (*read_error)(int dcrn);
1133
    int (*write_error)(int dcrn);
1134
};
1135

    
1136
int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
1137
{
1138
    ppc_dcrn_t *dcr;
1139

    
1140
    if (dcrn < 0 || dcrn >= DCRN_NB)
1141
        goto error;
1142
    dcr = &dcr_env->dcrn[dcrn];
1143
    if (dcr->dcr_read == NULL)
1144
        goto error;
1145
    *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
1146

    
1147
    return 0;
1148

    
1149
 error:
1150
    if (dcr_env->read_error != NULL)
1151
        return (*dcr_env->read_error)(dcrn);
1152

    
1153
    return -1;
1154
}
1155

    
1156
int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
1157
{
1158
    ppc_dcrn_t *dcr;
1159

    
1160
    if (dcrn < 0 || dcrn >= DCRN_NB)
1161
        goto error;
1162
    dcr = &dcr_env->dcrn[dcrn];
1163
    if (dcr->dcr_write == NULL)
1164
        goto error;
1165
    (*dcr->dcr_write)(dcr->opaque, dcrn, val);
1166

    
1167
    return 0;
1168

    
1169
 error:
1170
    if (dcr_env->write_error != NULL)
1171
        return (*dcr_env->write_error)(dcrn);
1172

    
1173
    return -1;
1174
}
1175

    
1176
int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
1177
                      dcr_read_cb dcr_read, dcr_write_cb dcr_write)
1178
{
1179
    ppc_dcr_t *dcr_env;
1180
    ppc_dcrn_t *dcr;
1181

    
1182
    dcr_env = env->dcr_env;
1183
    if (dcr_env == NULL)
1184
        return -1;
1185
    if (dcrn < 0 || dcrn >= DCRN_NB)
1186
        return -1;
1187
    dcr = &dcr_env->dcrn[dcrn];
1188
    if (dcr->opaque != NULL ||
1189
        dcr->dcr_read != NULL ||
1190
        dcr->dcr_write != NULL)
1191
        return -1;
1192
    dcr->opaque = opaque;
1193
    dcr->dcr_read = dcr_read;
1194
    dcr->dcr_write = dcr_write;
1195

    
1196
    return 0;
1197
}
1198

    
1199
int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn),
1200
                  int (*write_error)(int dcrn))
1201
{
1202
    ppc_dcr_t *dcr_env;
1203

    
1204
    dcr_env = qemu_mallocz(sizeof(ppc_dcr_t));
1205
    if (dcr_env == NULL)
1206
        return -1;
1207
    dcr_env->read_error = read_error;
1208
    dcr_env->write_error = write_error;
1209
    env->dcr_env = dcr_env;
1210

    
1211
    return 0;
1212
}
1213

    
1214
#if 0
1215
/*****************************************************************************/
1216
/* Handle system reset (for now, just stop emulation) */
1217
void cpu_ppc_reset (CPUState *env)
1218
{
1219
    printf("Reset asked... Stop emulation\n");
1220
    abort();
1221
}
1222
#endif
1223

    
1224
/*****************************************************************************/
1225
/* Debug port */
1226
void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
1227
{
1228
    addr &= 0xF;
1229
    switch (addr) {
1230
    case 0:
1231
        printf("%c", val);
1232
        break;
1233
    case 1:
1234
        printf("\n");
1235
        fflush(stdout);
1236
        break;
1237
    case 2:
1238
        printf("Set loglevel to %04x\n", val);
1239
        cpu_set_log(val | 0x100);
1240
        break;
1241
    }
1242
}
1243

    
1244
/*****************************************************************************/
1245
/* NVRAM helpers */
1246
static inline uint32_t nvram_read (nvram_t *nvram, uint32_t addr)
1247
{
1248
    return (*nvram->read_fn)(nvram->opaque, addr);;
1249
}
1250

    
1251
static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
1252
{
1253
    (*nvram->write_fn)(nvram->opaque, addr, val);
1254
}
1255

    
1256
void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value)
1257
{
1258
    nvram_write(nvram, addr, value);
1259
}
1260

    
1261
uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr)
1262
{
1263
    return nvram_read(nvram, addr);
1264
}
1265

    
1266
void NVRAM_set_word (nvram_t *nvram, uint32_t addr, uint16_t value)
1267
{
1268
    nvram_write(nvram, addr, value >> 8);
1269
    nvram_write(nvram, addr + 1, value & 0xFF);
1270
}
1271

    
1272
uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr)
1273
{
1274
    uint16_t tmp;
1275

    
1276
    tmp = nvram_read(nvram, addr) << 8;
1277
    tmp |= nvram_read(nvram, addr + 1);
1278

    
1279
    return tmp;
1280
}
1281

    
1282
void NVRAM_set_lword (nvram_t *nvram, uint32_t addr, uint32_t value)
1283
{
1284
    nvram_write(nvram, addr, value >> 24);
1285
    nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
1286
    nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
1287
    nvram_write(nvram, addr + 3, value & 0xFF);
1288
}
1289

    
1290
uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
1291
{
1292
    uint32_t tmp;
1293

    
1294
    tmp = nvram_read(nvram, addr) << 24;
1295
    tmp |= nvram_read(nvram, addr + 1) << 16;
1296
    tmp |= nvram_read(nvram, addr + 2) << 8;
1297
    tmp |= nvram_read(nvram, addr + 3);
1298

    
1299
    return tmp;
1300
}
1301

    
1302
void NVRAM_set_string (nvram_t *nvram, uint32_t addr,
1303
                       const unsigned char *str, uint32_t max)
1304
{
1305
    int i;
1306

    
1307
    for (i = 0; i < max && str[i] != '\0'; i++) {
1308
        nvram_write(nvram, addr + i, str[i]);
1309
    }
1310
    nvram_write(nvram, addr + i, str[i]);
1311
    nvram_write(nvram, addr + max - 1, '\0');
1312
}
1313

    
1314
int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max)
1315
{
1316
    int i;
1317

    
1318
    memset(dst, 0, max);
1319
    for (i = 0; i < max; i++) {
1320
        dst[i] = NVRAM_get_byte(nvram, addr + i);
1321
        if (dst[i] == '\0')
1322
            break;
1323
    }
1324

    
1325
    return i;
1326
}
1327

    
1328
static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
1329
{
1330
    uint16_t tmp;
1331
    uint16_t pd, pd1, pd2;
1332

    
1333
    tmp = prev >> 8;
1334
    pd = prev ^ value;
1335
    pd1 = pd & 0x000F;
1336
    pd2 = ((pd >> 4) & 0x000F) ^ pd1;
1337
    tmp ^= (pd1 << 3) | (pd1 << 8);
1338
    tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
1339

    
1340
    return tmp;
1341
}
1342

    
1343
uint16_t NVRAM_compute_crc (nvram_t *nvram, uint32_t start, uint32_t count)
1344
{
1345
    uint32_t i;
1346
    uint16_t crc = 0xFFFF;
1347
    int odd;
1348

    
1349
    odd = count & 1;
1350
    count &= ~1;
1351
    for (i = 0; i != count; i++) {
1352
        crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
1353
    }
1354
    if (odd) {
1355
        crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
1356
    }
1357

    
1358
    return crc;
1359
}
1360

    
1361
#define CMDLINE_ADDR 0x017ff000
1362

    
1363
int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
1364
                          const unsigned char *arch,
1365
                          uint32_t RAM_size, int boot_device,
1366
                          uint32_t kernel_image, uint32_t kernel_size,
1367
                          const char *cmdline,
1368
                          uint32_t initrd_image, uint32_t initrd_size,
1369
                          uint32_t NVRAM_image,
1370
                          int width, int height, int depth)
1371
{
1372
    uint16_t crc;
1373

    
1374
    /* Set parameters for Open Hack'Ware BIOS */
1375
    NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
1376
    NVRAM_set_lword(nvram,  0x10, 0x00000002); /* structure v2 */
1377
    NVRAM_set_word(nvram,   0x14, NVRAM_size);
1378
    NVRAM_set_string(nvram, 0x20, arch, 16);
1379
    NVRAM_set_lword(nvram,  0x30, RAM_size);
1380
    NVRAM_set_byte(nvram,   0x34, boot_device);
1381
    NVRAM_set_lword(nvram,  0x38, kernel_image);
1382
    NVRAM_set_lword(nvram,  0x3C, kernel_size);
1383
    if (cmdline) {
1384
        /* XXX: put the cmdline in NVRAM too ? */
1385
        strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
1386
        NVRAM_set_lword(nvram,  0x40, CMDLINE_ADDR);
1387
        NVRAM_set_lword(nvram,  0x44, strlen(cmdline));
1388
    } else {
1389
        NVRAM_set_lword(nvram,  0x40, 0);
1390
        NVRAM_set_lword(nvram,  0x44, 0);
1391
    }
1392
    NVRAM_set_lword(nvram,  0x48, initrd_image);
1393
    NVRAM_set_lword(nvram,  0x4C, initrd_size);
1394
    NVRAM_set_lword(nvram,  0x50, NVRAM_image);
1395

    
1396
    NVRAM_set_word(nvram,   0x54, width);
1397
    NVRAM_set_word(nvram,   0x56, height);
1398
    NVRAM_set_word(nvram,   0x58, depth);
1399
    crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
1400
    NVRAM_set_word(nvram,   0xFC, crc);
1401

    
1402
    return 0;
1403
}