Statistics
| Branch: | Revision:

root / hw / ppc.c @ b172c56a

History | View | Annotate | Download (39.9 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, 6);
176
}
177

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

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

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

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

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

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

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

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

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

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

    
458
    return tb & 0xFFFFFFFF;
459
}
460

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

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

    
473
    return tb >> 32;
474
}
475

    
476
uint32_t cpu_ppc_load_tbu (CPUState *env)
477
{
478
    return _cpu_ppc_load_tbu(env);
479
}
480

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

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

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

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

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

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

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

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

    
533
    return tb & 0xFFFFFFFF;
534
}
535

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

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

    
548
    return tb >> 32;
549
}
550

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

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

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

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

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

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

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

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

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

    
634
    return decr;
635
}
636

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

    
641
    return _cpu_ppc_load_decr(env, &tb_env->decr_next);
642
}
643

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

    
648
    return _cpu_ppc_load_decr(env, &tb_env->hdecr_next);
649
}
650

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

    
656
    diff = qemu_get_clock(vm_clock) - tb_env->purr_start;
657

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
760
    tb_env->purr_load = value;
761
    tb_env->purr_start = qemu_get_clock(vm_clock);
762
}
763

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

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

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

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

    
800
    return &cpu_ppc_set_tb_clk;
801
}
802

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

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

    
814
uint32_t cpu_ppc601_load_rtcu (CPUState *env)
815
{
816
    return _cpu_ppc_load_tbu(env);
817
}
818

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

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

    
829
/*****************************************************************************/
830
/* Embedded PowerPC timers */
831

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

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

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

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

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

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

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

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

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

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

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

    
1036
target_ulong load_40x_pit (CPUState *env)
1037
{
1038
    return cpu_ppc_load_decr(env);
1039
}
1040

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

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

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

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

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

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

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

    
1112
    return &ppc_emb_set_tb_clk;
1113
}
1114

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

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

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

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

    
1145
    return 0;
1146

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

    
1151
    return -1;
1152
}
1153

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

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

    
1165
    return 0;
1166

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

    
1171
    return -1;
1172
}
1173

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

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

    
1194
    return 0;
1195
}
1196

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

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

    
1209
    return 0;
1210
}
1211

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

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

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

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

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

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

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

    
1270
uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr)
1271
{
1272
    uint16_t tmp;
1273

    
1274
    tmp = nvram_read(nvram, addr) << 8;
1275
    tmp |= nvram_read(nvram, addr + 1);
1276

    
1277
    return tmp;
1278
}
1279

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

    
1288
uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
1289
{
1290
    uint32_t tmp;
1291

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

    
1297
    return tmp;
1298
}
1299

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

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

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

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

    
1323
    return i;
1324
}
1325

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

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

    
1338
    return tmp;
1339
}
1340

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

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

    
1356
    return crc;
1357
}
1358

    
1359
#define CMDLINE_ADDR 0x017ff000
1360

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

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

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

    
1400
    return 0;
1401
}