~jderose/ubuntu/raring/qemu/vde-again

« back to all changes in this revision

Viewing changes to hw/ppc.c

  • Committer: Bazaar Package Importer
  • Author(s): Aurelien Jarno, Aurelien Jarno
  • Date: 2008-08-25 04:38:35 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20080825043835-8e3tftavy8bujdch
Tags: 0.9.1-6
[ Aurelien Jarno ]
* debian/control: 
  - Update list of supported targets (Closes: bug#488339).
* debian/qemu-make-debian-root:
  - Use mktemp instead of $$ to create temporary directories (Closes: 
    bug#496394).
* debian/links:
  - Add missing links to manpages.

Show diffs side-by-side

added added

removed removed

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