Statistics
| Branch: | Revision:

root / hw / ppc.c @ 7267c094

History | View | Annotate | Download (39.3 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 "hw.h"
25
#include "ppc.h"
26
#include "qemu-timer.h"
27
#include "sysemu.h"
28
#include "nvram.h"
29
#include "qemu-log.h"
30
#include "loader.h"
31
#include "kvm.h"
32
#include "kvm_ppc.h"
33

    
34
//#define PPC_DEBUG_IRQ
35
//#define PPC_DEBUG_TB
36

    
37
#ifdef PPC_DEBUG_IRQ
38
#  define LOG_IRQ(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
39
#else
40
#  define LOG_IRQ(...) do { } while (0)
41
#endif
42

    
43

    
44
#ifdef PPC_DEBUG_TB
45
#  define LOG_TB(...) qemu_log(__VA_ARGS__)
46
#else
47
#  define LOG_TB(...) do { } while (0)
48
#endif
49

    
50
static void cpu_ppc_tb_stop (CPUState *env);
51
static void cpu_ppc_tb_start (CPUState *env);
52

    
53
static void ppc_set_irq (CPUState *env, int n_IRQ, int level)
54
{
55
    unsigned int old_pending = env->pending_interrupts;
56

    
57
    if (level) {
58
        env->pending_interrupts |= 1 << n_IRQ;
59
        cpu_interrupt(env, CPU_INTERRUPT_HARD);
60
    } else {
61
        env->pending_interrupts &= ~(1 << n_IRQ);
62
        if (env->pending_interrupts == 0)
63
            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
64
    }
65

    
66
    if (old_pending != env->pending_interrupts) {
67
#ifdef CONFIG_KVM
68
        kvmppc_set_interrupt(env, n_IRQ, level);
69
#endif
70
    }
71

    
72
    LOG_IRQ("%s: %p n_IRQ %d level %d => pending %08" PRIx32
73
                "req %08x\n", __func__, env, n_IRQ, level,
74
                env->pending_interrupts, env->interrupt_request);
75
}
76

    
77
/* PowerPC 6xx / 7xx internal IRQ controller */
78
static void ppc6xx_set_irq (void *opaque, int pin, int level)
79
{
80
    CPUState *env = opaque;
81
    int cur_level;
82

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

    
160
void ppc6xx_irq_init (CPUState *env)
161
{
162
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc6xx_set_irq, env,
163
                                                  PPC6xx_INPUT_NB);
164
}
165

    
166
#if defined(TARGET_PPC64)
167
/* PowerPC 970 internal IRQ controller */
168
static void ppc970_set_irq (void *opaque, int pin, int level)
169
{
170
    CPUState *env = opaque;
171
    int cur_level;
172

    
173
    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
174
                env, pin, level);
175
    cur_level = (env->irq_input_state >> pin) & 1;
176
    /* Don't generate spurious events */
177
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
178
        switch (pin) {
179
        case PPC970_INPUT_INT:
180
            /* Level sensitive - active high */
181
            LOG_IRQ("%s: set the external IRQ state to %d\n",
182
                        __func__, level);
183
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
184
            break;
185
        case PPC970_INPUT_THINT:
186
            /* Level sensitive - active high */
187
            LOG_IRQ("%s: set the SMI IRQ state to %d\n", __func__,
188
                        level);
189
            ppc_set_irq(env, PPC_INTERRUPT_THERM, level);
190
            break;
191
        case PPC970_INPUT_MCP:
192
            /* Negative edge sensitive */
193
            /* XXX: TODO: actual reaction may depends on HID0 status
194
             *            603/604/740/750: check HID0[EMCP]
195
             */
196
            if (cur_level == 1 && level == 0) {
197
                LOG_IRQ("%s: raise machine check state\n",
198
                            __func__);
199
                ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
200
            }
201
            break;
202
        case PPC970_INPUT_CKSTP:
203
            /* Level sensitive - active low */
204
            /* XXX: TODO: relay the signal to CKSTP_OUT pin */
205
            if (level) {
206
                LOG_IRQ("%s: stop the CPU\n", __func__);
207
                env->halted = 1;
208
            } else {
209
                LOG_IRQ("%s: restart the CPU\n", __func__);
210
                env->halted = 0;
211
                qemu_cpu_kick(env);
212
            }
213
            break;
214
        case PPC970_INPUT_HRESET:
215
            /* Level sensitive - active low */
216
            if (level) {
217
#if 0 // XXX: TOFIX
218
                LOG_IRQ("%s: reset the CPU\n", __func__);
219
                cpu_reset(env);
220
#endif
221
            }
222
            break;
223
        case PPC970_INPUT_SRESET:
224
            LOG_IRQ("%s: set the RESET IRQ state to %d\n",
225
                        __func__, level);
226
            ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
227
            break;
228
        case PPC970_INPUT_TBEN:
229
            LOG_IRQ("%s: set the TBEN state to %d\n", __func__,
230
                        level);
231
            /* XXX: TODO */
232
            break;
233
        default:
234
            /* Unknown pin - do nothing */
235
            LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
236
            return;
237
        }
238
        if (level)
239
            env->irq_input_state |= 1 << pin;
240
        else
241
            env->irq_input_state &= ~(1 << pin);
242
    }
243
}
244

    
245
void ppc970_irq_init (CPUState *env)
246
{
247
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc970_set_irq, env,
248
                                                  PPC970_INPUT_NB);
249
}
250

    
251
/* POWER7 internal IRQ controller */
252
static void power7_set_irq (void *opaque, int pin, int level)
253
{
254
    CPUState *env = opaque;
255

    
256
    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
257
                env, pin, level);
258

    
259
    switch (pin) {
260
    case POWER7_INPUT_INT:
261
        /* Level sensitive - active high */
262
        LOG_IRQ("%s: set the external IRQ state to %d\n",
263
                __func__, level);
264
        ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
265
        break;
266
    default:
267
        /* Unknown pin - do nothing */
268
        LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
269
        return;
270
    }
271
    if (level) {
272
        env->irq_input_state |= 1 << pin;
273
    } else {
274
        env->irq_input_state &= ~(1 << pin);
275
    }
276
}
277

    
278
void ppcPOWER7_irq_init (CPUState *env)
279
{
280
    env->irq_inputs = (void **)qemu_allocate_irqs(&power7_set_irq, env,
281
                                                  POWER7_INPUT_NB);
282
}
283
#endif /* defined(TARGET_PPC64) */
284

    
285
/* PowerPC 40x internal IRQ controller */
286
static void ppc40x_set_irq (void *opaque, int pin, int level)
287
{
288
    CPUState *env = opaque;
289
    int cur_level;
290

    
291
    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
292
                env, pin, level);
293
    cur_level = (env->irq_input_state >> pin) & 1;
294
    /* Don't generate spurious events */
295
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
296
        switch (pin) {
297
        case PPC40x_INPUT_RESET_SYS:
298
            if (level) {
299
                LOG_IRQ("%s: reset the PowerPC system\n",
300
                            __func__);
301
                ppc40x_system_reset(env);
302
            }
303
            break;
304
        case PPC40x_INPUT_RESET_CHIP:
305
            if (level) {
306
                LOG_IRQ("%s: reset the PowerPC chip\n", __func__);
307
                ppc40x_chip_reset(env);
308
            }
309
            break;
310
        case PPC40x_INPUT_RESET_CORE:
311
            /* XXX: TODO: update DBSR[MRR] */
312
            if (level) {
313
                LOG_IRQ("%s: reset the PowerPC core\n", __func__);
314
                ppc40x_core_reset(env);
315
            }
316
            break;
317
        case PPC40x_INPUT_CINT:
318
            /* Level sensitive - active high */
319
            LOG_IRQ("%s: set the critical IRQ state to %d\n",
320
                        __func__, level);
321
            ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
322
            break;
323
        case PPC40x_INPUT_INT:
324
            /* Level sensitive - active high */
325
            LOG_IRQ("%s: set the external IRQ state to %d\n",
326
                        __func__, level);
327
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
328
            break;
329
        case PPC40x_INPUT_HALT:
330
            /* Level sensitive - active low */
331
            if (level) {
332
                LOG_IRQ("%s: stop the CPU\n", __func__);
333
                env->halted = 1;
334
            } else {
335
                LOG_IRQ("%s: restart the CPU\n", __func__);
336
                env->halted = 0;
337
                qemu_cpu_kick(env);
338
            }
339
            break;
340
        case PPC40x_INPUT_DEBUG:
341
            /* Level sensitive - active high */
342
            LOG_IRQ("%s: set the debug pin state to %d\n",
343
                        __func__, level);
344
            ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
345
            break;
346
        default:
347
            /* Unknown pin - do nothing */
348
            LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
349
            return;
350
        }
351
        if (level)
352
            env->irq_input_state |= 1 << pin;
353
        else
354
            env->irq_input_state &= ~(1 << pin);
355
    }
356
}
357

    
358
void ppc40x_irq_init (CPUState *env)
359
{
360
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppc40x_set_irq,
361
                                                  env, PPC40x_INPUT_NB);
362
}
363

    
364
/* PowerPC E500 internal IRQ controller */
365
static void ppce500_set_irq (void *opaque, int pin, int level)
366
{
367
    CPUState *env = opaque;
368
    int cur_level;
369

    
370
    LOG_IRQ("%s: env %p pin %d level %d\n", __func__,
371
                env, pin, level);
372
    cur_level = (env->irq_input_state >> pin) & 1;
373
    /* Don't generate spurious events */
374
    if ((cur_level == 1 && level == 0) || (cur_level == 0 && level != 0)) {
375
        switch (pin) {
376
        case PPCE500_INPUT_MCK:
377
            if (level) {
378
                LOG_IRQ("%s: reset the PowerPC system\n",
379
                            __func__);
380
                qemu_system_reset_request();
381
            }
382
            break;
383
        case PPCE500_INPUT_RESET_CORE:
384
            if (level) {
385
                LOG_IRQ("%s: reset the PowerPC core\n", __func__);
386
                ppc_set_irq(env, PPC_INTERRUPT_MCK, level);
387
            }
388
            break;
389
        case PPCE500_INPUT_CINT:
390
            /* Level sensitive - active high */
391
            LOG_IRQ("%s: set the critical IRQ state to %d\n",
392
                        __func__, level);
393
            ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
394
            break;
395
        case PPCE500_INPUT_INT:
396
            /* Level sensitive - active high */
397
            LOG_IRQ("%s: set the core IRQ state to %d\n",
398
                        __func__, level);
399
            ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
400
            break;
401
        case PPCE500_INPUT_DEBUG:
402
            /* Level sensitive - active high */
403
            LOG_IRQ("%s: set the debug pin state to %d\n",
404
                        __func__, level);
405
            ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
406
            break;
407
        default:
408
            /* Unknown pin - do nothing */
409
            LOG_IRQ("%s: unknown IRQ pin %d\n", __func__, pin);
410
            return;
411
        }
412
        if (level)
413
            env->irq_input_state |= 1 << pin;
414
        else
415
            env->irq_input_state &= ~(1 << pin);
416
    }
417
}
418

    
419
void ppce500_irq_init (CPUState *env)
420
{
421
    env->irq_inputs = (void **)qemu_allocate_irqs(&ppce500_set_irq,
422
                                        env, PPCE500_INPUT_NB);
423
}
424
/*****************************************************************************/
425
/* PowerPC time base and decrementer emulation */
426
struct ppc_tb_t {
427
    /* Time base management */
428
    int64_t  tb_offset;    /* Compensation                    */
429
    int64_t  atb_offset;   /* Compensation                    */
430
    uint32_t tb_freq;      /* TB frequency                    */
431
    /* Decrementer management */
432
    uint64_t decr_next;    /* Tick for next decr interrupt    */
433
    uint32_t decr_freq;    /* decrementer frequency           */
434
    struct QEMUTimer *decr_timer;
435
    /* Hypervisor decrementer management */
436
    uint64_t hdecr_next;    /* Tick for next hdecr interrupt  */
437
    struct QEMUTimer *hdecr_timer;
438
    uint64_t purr_load;
439
    uint64_t purr_start;
440
    void *opaque;
441
};
442

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

    
450
uint64_t cpu_ppc_load_tbl (CPUState *env)
451
{
452
    ppc_tb_t *tb_env = env->tb_env;
453
    uint64_t tb;
454

    
455
    if (kvm_enabled()) {
456
        return env->spr[SPR_TBL];
457
    }
458

    
459
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
460
    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
461

    
462
    return tb;
463
}
464

    
465
static inline uint32_t _cpu_ppc_load_tbu(CPUState *env)
466
{
467
    ppc_tb_t *tb_env = env->tb_env;
468
    uint64_t tb;
469

    
470
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->tb_offset);
471
    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
472

    
473
    return tb >> 32;
474
}
475

    
476
uint32_t cpu_ppc_load_tbu (CPUState *env)
477
{
478
    if (kvm_enabled()) {
479
        return env->spr[SPR_TBU];
480
    }
481

    
482
    return _cpu_ppc_load_tbu(env);
483
}
484

    
485
static inline void cpu_ppc_store_tb(ppc_tb_t *tb_env, uint64_t vmclk,
486
                                    int64_t *tb_offsetp, uint64_t value)
487
{
488
    *tb_offsetp = value - muldiv64(vmclk, tb_env->tb_freq, get_ticks_per_sec());
489
    LOG_TB("%s: tb %016" PRIx64 " offset %08" PRIx64 "\n",
490
                __func__, value, *tb_offsetp);
491
}
492

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

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

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

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

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

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

    
525
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
526
    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
527

    
528
    return tb;
529
}
530

    
531
uint32_t cpu_ppc_load_atbu (CPUState *env)
532
{
533
    ppc_tb_t *tb_env = env->tb_env;
534
    uint64_t tb;
535

    
536
    tb = cpu_ppc_get_tb(tb_env, qemu_get_clock_ns(vm_clock), tb_env->atb_offset);
537
    LOG_TB("%s: tb %016" PRIx64 "\n", __func__, tb);
538

    
539
    return tb >> 32;
540
}
541

    
542
void cpu_ppc_store_atbl (CPUState *env, uint32_t value)
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_ns(vm_clock), tb_env->atb_offset);
548
    tb &= 0xFFFFFFFF00000000ULL;
549
    cpu_ppc_store_tb(tb_env, qemu_get_clock_ns(vm_clock),
550
                     &tb_env->atb_offset, tb | (uint64_t)value);
551
}
552

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

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

    
564
static void cpu_ppc_tb_stop (CPUState *env)
565
{
566
    ppc_tb_t *tb_env = env->tb_env;
567
    uint64_t tb, atb, vmclk;
568

    
569
    /* If the time base is already frozen, do nothing */
570
    if (tb_env->tb_freq != 0) {
571
        vmclk = qemu_get_clock_ns(vm_clock);
572
        /* Get the time base */
573
        tb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->tb_offset);
574
        /* Get the alternate time base */
575
        atb = cpu_ppc_get_tb(tb_env, vmclk, tb_env->atb_offset);
576
        /* Store the time base value (ie compute the current offset) */
577
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
578
        /* Store the alternate time base value (compute the current offset) */
579
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
580
        /* Set the time base frequency to zero */
581
        tb_env->tb_freq = 0;
582
        /* Now, the time bases are frozen to tb_offset / atb_offset value */
583
    }
584
}
585

    
586
static void cpu_ppc_tb_start (CPUState *env)
587
{
588
    ppc_tb_t *tb_env = env->tb_env;
589
    uint64_t tb, atb, vmclk;
590

    
591
    /* If the time base is not frozen, do nothing */
592
    if (tb_env->tb_freq == 0) {
593
        vmclk = qemu_get_clock_ns(vm_clock);
594
        /* Get the time base from tb_offset */
595
        tb = tb_env->tb_offset;
596
        /* Get the alternate time base from atb_offset */
597
        atb = tb_env->atb_offset;
598
        /* Restore the tb frequency from the decrementer frequency */
599
        tb_env->tb_freq = tb_env->decr_freq;
600
        /* Store the time base value */
601
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->tb_offset, tb);
602
        /* Store the alternate time base value */
603
        cpu_ppc_store_tb(tb_env, vmclk, &tb_env->atb_offset, atb);
604
    }
605
}
606

    
607
static inline uint32_t _cpu_ppc_load_decr(CPUState *env, uint64_t next)
608
{
609
    ppc_tb_t *tb_env = env->tb_env;
610
    uint32_t decr;
611
    int64_t diff;
612

    
613
    diff = next - qemu_get_clock_ns(vm_clock);
614
    if (diff >= 0)
615
        decr = muldiv64(diff, tb_env->decr_freq, get_ticks_per_sec());
616
    else
617
        decr = -muldiv64(-diff, tb_env->decr_freq, get_ticks_per_sec());
618
    LOG_TB("%s: %08" PRIx32 "\n", __func__, decr);
619

    
620
    return decr;
621
}
622

    
623
uint32_t cpu_ppc_load_decr (CPUState *env)
624
{
625
    ppc_tb_t *tb_env = env->tb_env;
626

    
627
    if (kvm_enabled()) {
628
        return env->spr[SPR_DECR];
629
    }
630

    
631
    return _cpu_ppc_load_decr(env, tb_env->decr_next);
632
}
633

    
634
uint32_t cpu_ppc_load_hdecr (CPUState *env)
635
{
636
    ppc_tb_t *tb_env = env->tb_env;
637

    
638
    return _cpu_ppc_load_decr(env, tb_env->hdecr_next);
639
}
640

    
641
uint64_t cpu_ppc_load_purr (CPUState *env)
642
{
643
    ppc_tb_t *tb_env = env->tb_env;
644
    uint64_t diff;
645

    
646
    diff = qemu_get_clock_ns(vm_clock) - tb_env->purr_start;
647

    
648
    return tb_env->purr_load + muldiv64(diff, tb_env->tb_freq, get_ticks_per_sec());
649
}
650

    
651
/* When decrementer expires,
652
 * all we need to do is generate or queue a CPU exception
653
 */
654
static inline void cpu_ppc_decr_excp(CPUState *env)
655
{
656
    /* Raise it */
657
    LOG_TB("raise decrementer exception\n");
658
    ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
659
}
660

    
661
static inline void cpu_ppc_hdecr_excp(CPUState *env)
662
{
663
    /* Raise it */
664
    LOG_TB("raise decrementer exception\n");
665
    ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1);
666
}
667

    
668
static void __cpu_ppc_store_decr (CPUState *env, uint64_t *nextp,
669
                                  struct QEMUTimer *timer,
670
                                  void (*raise_excp)(CPUState *),
671
                                  uint32_t decr, uint32_t value,
672
                                  int is_excp)
673
{
674
    ppc_tb_t *tb_env = env->tb_env;
675
    uint64_t now, next;
676

    
677
    LOG_TB("%s: %08" PRIx32 " => %08" PRIx32 "\n", __func__,
678
                decr, value);
679
    now = qemu_get_clock_ns(vm_clock);
680
    next = now + muldiv64(value, get_ticks_per_sec(), tb_env->decr_freq);
681
    if (is_excp)
682
        next += *nextp - now;
683
    if (next == now)
684
        next++;
685
    *nextp = next;
686
    /* Adjust timer */
687
    qemu_mod_timer(timer, next);
688
    /* If we set a negative value and the decrementer was positive,
689
     * raise an exception.
690
     */
691
    if ((value & 0x80000000) && !(decr & 0x80000000))
692
        (*raise_excp)(env);
693
}
694

    
695
static inline void _cpu_ppc_store_decr(CPUState *env, uint32_t decr,
696
                                       uint32_t value, int is_excp)
697
{
698
    ppc_tb_t *tb_env = env->tb_env;
699

    
700
    __cpu_ppc_store_decr(env, &tb_env->decr_next, tb_env->decr_timer,
701
                         &cpu_ppc_decr_excp, decr, value, is_excp);
702
}
703

    
704
void cpu_ppc_store_decr (CPUState *env, uint32_t value)
705
{
706
    _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
707
}
708

    
709
static void cpu_ppc_decr_cb (void *opaque)
710
{
711
    _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
712
}
713

    
714
static inline void _cpu_ppc_store_hdecr(CPUState *env, uint32_t hdecr,
715
                                        uint32_t value, int is_excp)
716
{
717
    ppc_tb_t *tb_env = env->tb_env;
718

    
719
    if (tb_env->hdecr_timer != NULL) {
720
        __cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer,
721
                             &cpu_ppc_hdecr_excp, hdecr, value, is_excp);
722
    }
723
}
724

    
725
void cpu_ppc_store_hdecr (CPUState *env, uint32_t value)
726
{
727
    _cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0);
728
}
729

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

    
735
void cpu_ppc_store_purr (CPUState *env, uint64_t value)
736
{
737
    ppc_tb_t *tb_env = env->tb_env;
738

    
739
    tb_env->purr_load = value;
740
    tb_env->purr_start = qemu_get_clock_ns(vm_clock);
741
}
742

    
743
static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
744
{
745
    CPUState *env = opaque;
746
    ppc_tb_t *tb_env = env->tb_env;
747

    
748
    tb_env->tb_freq = freq;
749
    tb_env->decr_freq = freq;
750
    /* There is a bug in Linux 2.4 kernels:
751
     * if a decrementer exception is pending when it enables msr_ee at startup,
752
     * it's not ready to handle it...
753
     */
754
    _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
755
    _cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
756
    cpu_ppc_store_purr(env, 0x0000000000000000ULL);
757
}
758

    
759
/* Set up (once) timebase frequency (in Hz) */
760
clk_setup_cb cpu_ppc_tb_init (CPUState *env, uint32_t freq)
761
{
762
    ppc_tb_t *tb_env;
763

    
764
    tb_env = g_malloc0(sizeof(ppc_tb_t));
765
    env->tb_env = tb_env;
766
    /* Create new timer */
767
    tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_decr_cb, env);
768
    if (0) {
769
        /* XXX: find a suitable condition to enable the hypervisor decrementer
770
         */
771
        tb_env->hdecr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_hdecr_cb, env);
772
    } else {
773
        tb_env->hdecr_timer = NULL;
774
    }
775
    cpu_ppc_set_tb_clk(env, freq);
776

    
777
    return &cpu_ppc_set_tb_clk;
778
}
779

    
780
/* Specific helpers for POWER & PowerPC 601 RTC */
781
#if 0
782
static clk_setup_cb cpu_ppc601_rtc_init (CPUState *env)
783
{
784
    return cpu_ppc_tb_init(env, 7812500);
785
}
786
#endif
787

    
788
void cpu_ppc601_store_rtcu (CPUState *env, uint32_t value)
789
{
790
    _cpu_ppc_store_tbu(env, value);
791
}
792

    
793
uint32_t cpu_ppc601_load_rtcu (CPUState *env)
794
{
795
    return _cpu_ppc_load_tbu(env);
796
}
797

    
798
void cpu_ppc601_store_rtcl (CPUState *env, uint32_t value)
799
{
800
    cpu_ppc_store_tbl(env, value & 0x3FFFFF80);
801
}
802

    
803
uint32_t cpu_ppc601_load_rtcl (CPUState *env)
804
{
805
    return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
806
}
807

    
808
/*****************************************************************************/
809
/* Embedded PowerPC timers */
810

    
811
/* PIT, FIT & WDT */
812
typedef struct ppcemb_timer_t ppcemb_timer_t;
813
struct ppcemb_timer_t {
814
    uint64_t pit_reload;  /* PIT auto-reload value        */
815
    uint64_t fit_next;    /* Tick for next FIT interrupt  */
816
    struct QEMUTimer *fit_timer;
817
    uint64_t wdt_next;    /* Tick for next WDT interrupt  */
818
    struct QEMUTimer *wdt_timer;
819

    
820
    /* 405 have the PIT, 440 have a DECR.  */
821
    unsigned int decr_excp;
822
};
823

    
824
/* Fixed interval timer */
825
static void cpu_4xx_fit_cb (void *opaque)
826
{
827
    CPUState *env;
828
    ppc_tb_t *tb_env;
829
    ppcemb_timer_t *ppcemb_timer;
830
    uint64_t now, next;
831

    
832
    env = opaque;
833
    tb_env = env->tb_env;
834
    ppcemb_timer = tb_env->opaque;
835
    now = qemu_get_clock_ns(vm_clock);
836
    switch ((env->spr[SPR_40x_TCR] >> 24) & 0x3) {
837
    case 0:
838
        next = 1 << 9;
839
        break;
840
    case 1:
841
        next = 1 << 13;
842
        break;
843
    case 2:
844
        next = 1 << 17;
845
        break;
846
    case 3:
847
        next = 1 << 21;
848
        break;
849
    default:
850
        /* Cannot occur, but makes gcc happy */
851
        return;
852
    }
853
    next = now + muldiv64(next, get_ticks_per_sec(), tb_env->tb_freq);
854
    if (next == now)
855
        next++;
856
    qemu_mod_timer(ppcemb_timer->fit_timer, next);
857
    env->spr[SPR_40x_TSR] |= 1 << 26;
858
    if ((env->spr[SPR_40x_TCR] >> 23) & 0x1)
859
        ppc_set_irq(env, PPC_INTERRUPT_FIT, 1);
860
    LOG_TB("%s: ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
861
           (int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
862
           env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
863
}
864

    
865
/* Programmable interval timer */
866
static void start_stop_pit (CPUState *env, ppc_tb_t *tb_env, int is_excp)
867
{
868
    ppcemb_timer_t *ppcemb_timer;
869
    uint64_t now, next;
870

    
871
    ppcemb_timer = tb_env->opaque;
872
    if (ppcemb_timer->pit_reload <= 1 ||
873
        !((env->spr[SPR_40x_TCR] >> 26) & 0x1) ||
874
        (is_excp && !((env->spr[SPR_40x_TCR] >> 22) & 0x1))) {
875
        /* Stop PIT */
876
        LOG_TB("%s: stop PIT\n", __func__);
877
        qemu_del_timer(tb_env->decr_timer);
878
    } else {
879
        LOG_TB("%s: start PIT %016" PRIx64 "\n",
880
                    __func__, ppcemb_timer->pit_reload);
881
        now = qemu_get_clock_ns(vm_clock);
882
        next = now + muldiv64(ppcemb_timer->pit_reload,
883
                              get_ticks_per_sec(), tb_env->decr_freq);
884
        if (is_excp)
885
            next += tb_env->decr_next - now;
886
        if (next == now)
887
            next++;
888
        qemu_mod_timer(tb_env->decr_timer, next);
889
        tb_env->decr_next = next;
890
    }
891
}
892

    
893
static void cpu_4xx_pit_cb (void *opaque)
894
{
895
    CPUState *env;
896
    ppc_tb_t *tb_env;
897
    ppcemb_timer_t *ppcemb_timer;
898

    
899
    env = opaque;
900
    tb_env = env->tb_env;
901
    ppcemb_timer = tb_env->opaque;
902
    env->spr[SPR_40x_TSR] |= 1 << 27;
903
    if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
904
        ppc_set_irq(env, ppcemb_timer->decr_excp, 1);
905
    start_stop_pit(env, tb_env, 1);
906
    LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " "
907
           "%016" PRIx64 "\n", __func__,
908
           (int)((env->spr[SPR_40x_TCR] >> 22) & 0x1),
909
           (int)((env->spr[SPR_40x_TCR] >> 26) & 0x1),
910
           env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR],
911
           ppcemb_timer->pit_reload);
912
}
913

    
914
/* Watchdog timer */
915
static void cpu_4xx_wdt_cb (void *opaque)
916
{
917
    CPUState *env;
918
    ppc_tb_t *tb_env;
919
    ppcemb_timer_t *ppcemb_timer;
920
    uint64_t now, next;
921

    
922
    env = opaque;
923
    tb_env = env->tb_env;
924
    ppcemb_timer = tb_env->opaque;
925
    now = qemu_get_clock_ns(vm_clock);
926
    switch ((env->spr[SPR_40x_TCR] >> 30) & 0x3) {
927
    case 0:
928
        next = 1 << 17;
929
        break;
930
    case 1:
931
        next = 1 << 21;
932
        break;
933
    case 2:
934
        next = 1 << 25;
935
        break;
936
    case 3:
937
        next = 1 << 29;
938
        break;
939
    default:
940
        /* Cannot occur, but makes gcc happy */
941
        return;
942
    }
943
    next = now + muldiv64(next, get_ticks_per_sec(), tb_env->decr_freq);
944
    if (next == now)
945
        next++;
946
    LOG_TB("%s: TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
947
           env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
948
    switch ((env->spr[SPR_40x_TSR] >> 30) & 0x3) {
949
    case 0x0:
950
    case 0x1:
951
        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
952
        ppcemb_timer->wdt_next = next;
953
        env->spr[SPR_40x_TSR] |= 1 << 31;
954
        break;
955
    case 0x2:
956
        qemu_mod_timer(ppcemb_timer->wdt_timer, next);
957
        ppcemb_timer->wdt_next = next;
958
        env->spr[SPR_40x_TSR] |= 1 << 30;
959
        if ((env->spr[SPR_40x_TCR] >> 27) & 0x1)
960
            ppc_set_irq(env, PPC_INTERRUPT_WDT, 1);
961
        break;
962
    case 0x3:
963
        env->spr[SPR_40x_TSR] &= ~0x30000000;
964
        env->spr[SPR_40x_TSR] |= env->spr[SPR_40x_TCR] & 0x30000000;
965
        switch ((env->spr[SPR_40x_TCR] >> 28) & 0x3) {
966
        case 0x0:
967
            /* No reset */
968
            break;
969
        case 0x1: /* Core reset */
970
            ppc40x_core_reset(env);
971
            break;
972
        case 0x2: /* Chip reset */
973
            ppc40x_chip_reset(env);
974
            break;
975
        case 0x3: /* System reset */
976
            ppc40x_system_reset(env);
977
            break;
978
        }
979
    }
980
}
981

    
982
void store_40x_pit (CPUState *env, target_ulong val)
983
{
984
    ppc_tb_t *tb_env;
985
    ppcemb_timer_t *ppcemb_timer;
986

    
987
    tb_env = env->tb_env;
988
    ppcemb_timer = tb_env->opaque;
989
    LOG_TB("%s val" TARGET_FMT_lx "\n", __func__, val);
990
    ppcemb_timer->pit_reload = val;
991
    start_stop_pit(env, tb_env, 0);
992
}
993

    
994
target_ulong load_40x_pit (CPUState *env)
995
{
996
    return cpu_ppc_load_decr(env);
997
}
998

    
999
void store_booke_tsr (CPUState *env, target_ulong val)
1000
{
1001
    ppc_tb_t *tb_env = env->tb_env;
1002
    ppcemb_timer_t *ppcemb_timer;
1003

    
1004
    ppcemb_timer = tb_env->opaque;
1005

    
1006
    LOG_TB("%s: val " TARGET_FMT_lx "\n", __func__, val);
1007
    env->spr[SPR_40x_TSR] &= ~(val & 0xFC000000);
1008
    if (val & 0x80000000)
1009
        ppc_set_irq(env, ppcemb_timer->decr_excp, 0);
1010
}
1011

    
1012
void store_booke_tcr (CPUState *env, target_ulong val)
1013
{
1014
    ppc_tb_t *tb_env;
1015

    
1016
    tb_env = env->tb_env;
1017
    LOG_TB("%s: val " TARGET_FMT_lx "\n", __func__, val);
1018
    env->spr[SPR_40x_TCR] = val & 0xFFC00000;
1019
    start_stop_pit(env, tb_env, 1);
1020
    cpu_4xx_wdt_cb(env);
1021
}
1022

    
1023
static void ppc_emb_set_tb_clk (void *opaque, uint32_t freq)
1024
{
1025
    CPUState *env = opaque;
1026
    ppc_tb_t *tb_env = env->tb_env;
1027

    
1028
    LOG_TB("%s set new frequency to %" PRIu32 "\n", __func__,
1029
                freq);
1030
    tb_env->tb_freq = freq;
1031
    tb_env->decr_freq = freq;
1032
    /* XXX: we should also update all timers */
1033
}
1034

    
1035
clk_setup_cb ppc_emb_timers_init (CPUState *env, uint32_t freq,
1036
                                  unsigned int decr_excp)
1037
{
1038
    ppc_tb_t *tb_env;
1039
    ppcemb_timer_t *ppcemb_timer;
1040

    
1041
    tb_env = g_malloc0(sizeof(ppc_tb_t));
1042
    env->tb_env = tb_env;
1043
    ppcemb_timer = g_malloc0(sizeof(ppcemb_timer_t));
1044
    tb_env->tb_freq = freq;
1045
    tb_env->decr_freq = freq;
1046
    tb_env->opaque = ppcemb_timer;
1047
    LOG_TB("%s freq %" PRIu32 "\n", __func__, freq);
1048
    if (ppcemb_timer != NULL) {
1049
        /* We use decr timer for PIT */
1050
        tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_4xx_pit_cb, env);
1051
        ppcemb_timer->fit_timer =
1052
            qemu_new_timer_ns(vm_clock, &cpu_4xx_fit_cb, env);
1053
        ppcemb_timer->wdt_timer =
1054
            qemu_new_timer_ns(vm_clock, &cpu_4xx_wdt_cb, env);
1055
        ppcemb_timer->decr_excp = decr_excp;
1056
    }
1057

    
1058
    return &ppc_emb_set_tb_clk;
1059
}
1060

    
1061
/*****************************************************************************/
1062
/* Embedded PowerPC Device Control Registers */
1063
typedef struct ppc_dcrn_t ppc_dcrn_t;
1064
struct ppc_dcrn_t {
1065
    dcr_read_cb dcr_read;
1066
    dcr_write_cb dcr_write;
1067
    void *opaque;
1068
};
1069

    
1070
/* XXX: on 460, DCR addresses are 32 bits wide,
1071
 *      using DCRIPR to get the 22 upper bits of the DCR address
1072
 */
1073
#define DCRN_NB 1024
1074
struct ppc_dcr_t {
1075
    ppc_dcrn_t dcrn[DCRN_NB];
1076
    int (*read_error)(int dcrn);
1077
    int (*write_error)(int dcrn);
1078
};
1079

    
1080
int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp)
1081
{
1082
    ppc_dcrn_t *dcr;
1083

    
1084
    if (dcrn < 0 || dcrn >= DCRN_NB)
1085
        goto error;
1086
    dcr = &dcr_env->dcrn[dcrn];
1087
    if (dcr->dcr_read == NULL)
1088
        goto error;
1089
    *valp = (*dcr->dcr_read)(dcr->opaque, dcrn);
1090

    
1091
    return 0;
1092

    
1093
 error:
1094
    if (dcr_env->read_error != NULL)
1095
        return (*dcr_env->read_error)(dcrn);
1096

    
1097
    return -1;
1098
}
1099

    
1100
int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val)
1101
{
1102
    ppc_dcrn_t *dcr;
1103

    
1104
    if (dcrn < 0 || dcrn >= DCRN_NB)
1105
        goto error;
1106
    dcr = &dcr_env->dcrn[dcrn];
1107
    if (dcr->dcr_write == NULL)
1108
        goto error;
1109
    (*dcr->dcr_write)(dcr->opaque, dcrn, val);
1110

    
1111
    return 0;
1112

    
1113
 error:
1114
    if (dcr_env->write_error != NULL)
1115
        return (*dcr_env->write_error)(dcrn);
1116

    
1117
    return -1;
1118
}
1119

    
1120
int ppc_dcr_register (CPUState *env, int dcrn, void *opaque,
1121
                      dcr_read_cb dcr_read, dcr_write_cb dcr_write)
1122
{
1123
    ppc_dcr_t *dcr_env;
1124
    ppc_dcrn_t *dcr;
1125

    
1126
    dcr_env = env->dcr_env;
1127
    if (dcr_env == NULL)
1128
        return -1;
1129
    if (dcrn < 0 || dcrn >= DCRN_NB)
1130
        return -1;
1131
    dcr = &dcr_env->dcrn[dcrn];
1132
    if (dcr->opaque != NULL ||
1133
        dcr->dcr_read != NULL ||
1134
        dcr->dcr_write != NULL)
1135
        return -1;
1136
    dcr->opaque = opaque;
1137
    dcr->dcr_read = dcr_read;
1138
    dcr->dcr_write = dcr_write;
1139

    
1140
    return 0;
1141
}
1142

    
1143
int ppc_dcr_init (CPUState *env, int (*read_error)(int dcrn),
1144
                  int (*write_error)(int dcrn))
1145
{
1146
    ppc_dcr_t *dcr_env;
1147

    
1148
    dcr_env = g_malloc0(sizeof(ppc_dcr_t));
1149
    dcr_env->read_error = read_error;
1150
    dcr_env->write_error = write_error;
1151
    env->dcr_env = dcr_env;
1152

    
1153
    return 0;
1154
}
1155

    
1156
/*****************************************************************************/
1157
/* Debug port */
1158
void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
1159
{
1160
    addr &= 0xF;
1161
    switch (addr) {
1162
    case 0:
1163
        printf("%c", val);
1164
        break;
1165
    case 1:
1166
        printf("\n");
1167
        fflush(stdout);
1168
        break;
1169
    case 2:
1170
        printf("Set loglevel to %04" PRIx32 "\n", val);
1171
        cpu_set_log(val | 0x100);
1172
        break;
1173
    }
1174
}
1175

    
1176
/*****************************************************************************/
1177
/* NVRAM helpers */
1178
static inline uint32_t nvram_read (nvram_t *nvram, uint32_t addr)
1179
{
1180
    return (*nvram->read_fn)(nvram->opaque, addr);;
1181
}
1182

    
1183
static inline void nvram_write (nvram_t *nvram, uint32_t addr, uint32_t val)
1184
{
1185
    (*nvram->write_fn)(nvram->opaque, addr, val);
1186
}
1187

    
1188
void NVRAM_set_byte (nvram_t *nvram, uint32_t addr, uint8_t value)
1189
{
1190
    nvram_write(nvram, addr, value);
1191
}
1192

    
1193
uint8_t NVRAM_get_byte (nvram_t *nvram, uint32_t addr)
1194
{
1195
    return nvram_read(nvram, addr);
1196
}
1197

    
1198
void NVRAM_set_word (nvram_t *nvram, uint32_t addr, uint16_t value)
1199
{
1200
    nvram_write(nvram, addr, value >> 8);
1201
    nvram_write(nvram, addr + 1, value & 0xFF);
1202
}
1203

    
1204
uint16_t NVRAM_get_word (nvram_t *nvram, uint32_t addr)
1205
{
1206
    uint16_t tmp;
1207

    
1208
    tmp = nvram_read(nvram, addr) << 8;
1209
    tmp |= nvram_read(nvram, addr + 1);
1210

    
1211
    return tmp;
1212
}
1213

    
1214
void NVRAM_set_lword (nvram_t *nvram, uint32_t addr, uint32_t value)
1215
{
1216
    nvram_write(nvram, addr, value >> 24);
1217
    nvram_write(nvram, addr + 1, (value >> 16) & 0xFF);
1218
    nvram_write(nvram, addr + 2, (value >> 8) & 0xFF);
1219
    nvram_write(nvram, addr + 3, value & 0xFF);
1220
}
1221

    
1222
uint32_t NVRAM_get_lword (nvram_t *nvram, uint32_t addr)
1223
{
1224
    uint32_t tmp;
1225

    
1226
    tmp = nvram_read(nvram, addr) << 24;
1227
    tmp |= nvram_read(nvram, addr + 1) << 16;
1228
    tmp |= nvram_read(nvram, addr + 2) << 8;
1229
    tmp |= nvram_read(nvram, addr + 3);
1230

    
1231
    return tmp;
1232
}
1233

    
1234
void NVRAM_set_string (nvram_t *nvram, uint32_t addr,
1235
                       const char *str, uint32_t max)
1236
{
1237
    int i;
1238

    
1239
    for (i = 0; i < max && str[i] != '\0'; i++) {
1240
        nvram_write(nvram, addr + i, str[i]);
1241
    }
1242
    nvram_write(nvram, addr + i, str[i]);
1243
    nvram_write(nvram, addr + max - 1, '\0');
1244
}
1245

    
1246
int NVRAM_get_string (nvram_t *nvram, uint8_t *dst, uint16_t addr, int max)
1247
{
1248
    int i;
1249

    
1250
    memset(dst, 0, max);
1251
    for (i = 0; i < max; i++) {
1252
        dst[i] = NVRAM_get_byte(nvram, addr + i);
1253
        if (dst[i] == '\0')
1254
            break;
1255
    }
1256

    
1257
    return i;
1258
}
1259

    
1260
static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
1261
{
1262
    uint16_t tmp;
1263
    uint16_t pd, pd1, pd2;
1264

    
1265
    tmp = prev >> 8;
1266
    pd = prev ^ value;
1267
    pd1 = pd & 0x000F;
1268
    pd2 = ((pd >> 4) & 0x000F) ^ pd1;
1269
    tmp ^= (pd1 << 3) | (pd1 << 8);
1270
    tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
1271

    
1272
    return tmp;
1273
}
1274

    
1275
static uint16_t NVRAM_compute_crc (nvram_t *nvram, uint32_t start, uint32_t count)
1276
{
1277
    uint32_t i;
1278
    uint16_t crc = 0xFFFF;
1279
    int odd;
1280

    
1281
    odd = count & 1;
1282
    count &= ~1;
1283
    for (i = 0; i != count; i++) {
1284
        crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
1285
    }
1286
    if (odd) {
1287
        crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
1288
    }
1289

    
1290
    return crc;
1291
}
1292

    
1293
#define CMDLINE_ADDR 0x017ff000
1294

    
1295
int PPC_NVRAM_set_params (nvram_t *nvram, uint16_t NVRAM_size,
1296
                          const char *arch,
1297
                          uint32_t RAM_size, int boot_device,
1298
                          uint32_t kernel_image, uint32_t kernel_size,
1299
                          const char *cmdline,
1300
                          uint32_t initrd_image, uint32_t initrd_size,
1301
                          uint32_t NVRAM_image,
1302
                          int width, int height, int depth)
1303
{
1304
    uint16_t crc;
1305

    
1306
    /* Set parameters for Open Hack'Ware BIOS */
1307
    NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
1308
    NVRAM_set_lword(nvram,  0x10, 0x00000002); /* structure v2 */
1309
    NVRAM_set_word(nvram,   0x14, NVRAM_size);
1310
    NVRAM_set_string(nvram, 0x20, arch, 16);
1311
    NVRAM_set_lword(nvram,  0x30, RAM_size);
1312
    NVRAM_set_byte(nvram,   0x34, boot_device);
1313
    NVRAM_set_lword(nvram,  0x38, kernel_image);
1314
    NVRAM_set_lword(nvram,  0x3C, kernel_size);
1315
    if (cmdline) {
1316
        /* XXX: put the cmdline in NVRAM too ? */
1317
        pstrcpy_targphys("cmdline", CMDLINE_ADDR, RAM_size - CMDLINE_ADDR, cmdline);
1318
        NVRAM_set_lword(nvram,  0x40, CMDLINE_ADDR);
1319
        NVRAM_set_lword(nvram,  0x44, strlen(cmdline));
1320
    } else {
1321
        NVRAM_set_lword(nvram,  0x40, 0);
1322
        NVRAM_set_lword(nvram,  0x44, 0);
1323
    }
1324
    NVRAM_set_lword(nvram,  0x48, initrd_image);
1325
    NVRAM_set_lword(nvram,  0x4C, initrd_size);
1326
    NVRAM_set_lword(nvram,  0x50, NVRAM_image);
1327

    
1328
    NVRAM_set_word(nvram,   0x54, width);
1329
    NVRAM_set_word(nvram,   0x56, height);
1330
    NVRAM_set_word(nvram,   0x58, depth);
1331
    crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
1332
    NVRAM_set_word(nvram,   0xFC, crc);
1333

    
1334
    return 0;
1335
}