~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to hw/sparc64/sun4u.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
#include "hw/boards.h"
39
39
#include "hw/nvram/sun_nvram.h"
40
40
#include "hw/nvram/chrp_nvram.h"
 
41
#include "hw/sparc/sparc64.h"
41
42
#include "hw/nvram/fw_cfg.h"
42
43
#include "hw/sysbus.h"
43
44
#include "hw/ide.h"
44
45
#include "hw/loader.h"
45
46
#include "elf.h"
46
 
#include "sysemu/block-backend.h"
47
 
#include "exec/address-spaces.h"
48
47
#include "qemu/cutils.h"
49
48
 
50
 
//#define DEBUG_IRQ
51
49
//#define DEBUG_EBUS
52
 
//#define DEBUG_TIMER
53
 
 
54
 
#ifdef DEBUG_IRQ
55
 
#define CPUIRQ_DPRINTF(fmt, ...)                                \
56
 
    do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0)
57
 
#else
58
 
#define CPUIRQ_DPRINTF(fmt, ...)
59
 
#endif
60
50
 
61
51
#ifdef DEBUG_EBUS
62
52
#define EBUS_DPRINTF(fmt, ...)                                  \
65
55
#define EBUS_DPRINTF(fmt, ...)
66
56
#endif
67
57
 
68
 
#ifdef DEBUG_TIMER
69
 
#define TIMER_DPRINTF(fmt, ...)                                  \
70
 
    do { printf("TIMER: " fmt , ## __VA_ARGS__); } while (0)
71
 
#else
72
 
#define TIMER_DPRINTF(fmt, ...)
73
 
#endif
74
 
 
75
58
#define KERNEL_LOAD_ADDR     0x00404000
76
59
#define CMDLINE_ADDR         0x003ff000
77
60
#define PROM_SIZE_MAX        (4 * 1024 * 1024)
89
72
 
90
73
#define IVEC_MAX             0x40
91
74
 
92
 
#define TICK_MAX             0x7fffffffffffffffULL
93
 
 
94
75
struct hwdef {
95
76
    const char * const default_cpu_model;
96
77
    uint16_t machine_id;
216
197
    return kernel_size;
217
198
}
218
199
 
219
 
void cpu_check_irqs(CPUSPARCState *env)
220
 
{
221
 
    CPUState *cs;
222
 
    uint32_t pil = env->pil_in |
223
 
                  (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER));
224
 
 
225
 
    /* TT_IVEC has a higher priority (16) than TT_EXTINT (31..17) */
226
 
    if (env->ivec_status & 0x20) {
227
 
        return;
228
 
    }
229
 
    cs = CPU(sparc_env_get_cpu(env));
230
 
    /* check if TM or SM in SOFTINT are set
231
 
       setting these also causes interrupt 14 */
232
 
    if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) {
233
 
        pil |= 1 << 14;
234
 
    }
235
 
 
236
 
    /* The bit corresponding to psrpil is (1<< psrpil), the next bit
237
 
       is (2 << psrpil). */
238
 
    if (pil < (2 << env->psrpil)){
239
 
        if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
240
 
            CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n",
241
 
                           env->interrupt_index);
242
 
            env->interrupt_index = 0;
243
 
            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
244
 
        }
245
 
        return;
246
 
    }
247
 
 
248
 
    if (cpu_interrupts_enabled(env)) {
249
 
 
250
 
        unsigned int i;
251
 
 
252
 
        for (i = 15; i > env->psrpil; i--) {
253
 
            if (pil & (1 << i)) {
254
 
                int old_interrupt = env->interrupt_index;
255
 
                int new_interrupt = TT_EXTINT | i;
256
 
 
257
 
                if (unlikely(env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt
258
 
                  && ((cpu_tsptr(env)->tt & 0x1f0) == TT_EXTINT))) {
259
 
                    CPUIRQ_DPRINTF("Not setting CPU IRQ: TL=%d "
260
 
                                   "current %x >= pending %x\n",
261
 
                                   env->tl, cpu_tsptr(env)->tt, new_interrupt);
262
 
                } else if (old_interrupt != new_interrupt) {
263
 
                    env->interrupt_index = new_interrupt;
264
 
                    CPUIRQ_DPRINTF("Set CPU IRQ %d old=%x new=%x\n", i,
265
 
                                   old_interrupt, new_interrupt);
266
 
                    cpu_interrupt(cs, CPU_INTERRUPT_HARD);
267
 
                }
268
 
                break;
269
 
            }
270
 
        }
271
 
    } else if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
272
 
        CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x "
273
 
                       "current interrupt %x\n",
274
 
                       pil, env->pil_in, env->softint, env->interrupt_index);
275
 
        env->interrupt_index = 0;
276
 
        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
277
 
    }
278
 
}
279
 
 
280
 
static void cpu_kick_irq(SPARCCPU *cpu)
281
 
{
282
 
    CPUState *cs = CPU(cpu);
283
 
    CPUSPARCState *env = &cpu->env;
284
 
 
285
 
    cs->halted = 0;
286
 
    cpu_check_irqs(env);
287
 
    qemu_cpu_kick(cs);
288
 
}
289
 
 
290
 
static void cpu_set_ivec_irq(void *opaque, int irq, int level)
291
 
{
292
 
    SPARCCPU *cpu = opaque;
293
 
    CPUSPARCState *env = &cpu->env;
294
 
    CPUState *cs;
295
 
 
296
 
    if (level) {
297
 
        if (!(env->ivec_status & 0x20)) {
298
 
            CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq);
299
 
            cs = CPU(cpu);
300
 
            cs->halted = 0;
301
 
            env->interrupt_index = TT_IVEC;
302
 
            env->ivec_status |= 0x20;
303
 
            env->ivec_data[0] = (0x1f << 6) | irq;
304
 
            env->ivec_data[1] = 0;
305
 
            env->ivec_data[2] = 0;
306
 
            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
307
 
        }
308
 
    } else {
309
 
        if (env->ivec_status & 0x20) {
310
 
            CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq);
311
 
            cs = CPU(cpu);
312
 
            env->ivec_status &= ~0x20;
313
 
            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
314
 
        }
315
 
    }
316
 
}
317
 
 
318
200
typedef struct ResetData {
319
201
    SPARCCPU *cpu;
320
202
    uint64_t prom_addr;
321
203
} ResetData;
322
204
 
323
 
static CPUTimer *cpu_timer_create(const char *name, SPARCCPU *cpu,
324
 
                                  QEMUBHFunc *cb, uint32_t frequency,
325
 
                                  uint64_t disabled_mask, uint64_t npt_mask)
326
 
{
327
 
    CPUTimer *timer = g_malloc0(sizeof (CPUTimer));
328
 
 
329
 
    timer->name = name;
330
 
    timer->frequency = frequency;
331
 
    timer->disabled_mask = disabled_mask;
332
 
    timer->npt_mask = npt_mask;
333
 
 
334
 
    timer->disabled = 1;
335
 
    timer->npt = 1;
336
 
    timer->clock_offset = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
337
 
 
338
 
    timer->qtimer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cb, cpu);
339
 
 
340
 
    return timer;
341
 
}
342
 
 
343
 
static void cpu_timer_reset(CPUTimer *timer)
344
 
{
345
 
    timer->disabled = 1;
346
 
    timer->clock_offset = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
347
 
 
348
 
    timer_del(timer->qtimer);
349
 
}
350
 
 
351
 
static void main_cpu_reset(void *opaque)
352
 
{
353
 
    ResetData *s = (ResetData *)opaque;
354
 
    CPUSPARCState *env = &s->cpu->env;
355
 
    static unsigned int nr_resets;
356
 
 
357
 
    cpu_reset(CPU(s->cpu));
358
 
 
359
 
    cpu_timer_reset(env->tick);
360
 
    cpu_timer_reset(env->stick);
361
 
    cpu_timer_reset(env->hstick);
362
 
 
363
 
    env->gregs[1] = 0; // Memory start
364
 
    env->gregs[2] = ram_size; // Memory size
365
 
    env->gregs[3] = 0; // Machine description XXX
366
 
    if (nr_resets++ == 0) {
367
 
        /* Power on reset */
368
 
        env->pc = s->prom_addr + 0x20ULL;
369
 
    } else {
370
 
        env->pc = s->prom_addr + 0x40ULL;
371
 
    }
372
 
    env->npc = env->pc + 4;
373
 
}
374
 
 
375
 
static void tick_irq(void *opaque)
376
 
{
377
 
    SPARCCPU *cpu = opaque;
378
 
    CPUSPARCState *env = &cpu->env;
379
 
 
380
 
    CPUTimer* timer = env->tick;
381
 
 
382
 
    if (timer->disabled) {
383
 
        CPUIRQ_DPRINTF("tick_irq: softint disabled\n");
384
 
        return;
385
 
    } else {
386
 
        CPUIRQ_DPRINTF("tick: fire\n");
387
 
    }
388
 
 
389
 
    env->softint |= SOFTINT_TIMER;
390
 
    cpu_kick_irq(cpu);
391
 
}
392
 
 
393
 
static void stick_irq(void *opaque)
394
 
{
395
 
    SPARCCPU *cpu = opaque;
396
 
    CPUSPARCState *env = &cpu->env;
397
 
 
398
 
    CPUTimer* timer = env->stick;
399
 
 
400
 
    if (timer->disabled) {
401
 
        CPUIRQ_DPRINTF("stick_irq: softint disabled\n");
402
 
        return;
403
 
    } else {
404
 
        CPUIRQ_DPRINTF("stick: fire\n");
405
 
    }
406
 
 
407
 
    env->softint |= SOFTINT_STIMER;
408
 
    cpu_kick_irq(cpu);
409
 
}
410
 
 
411
 
static void hstick_irq(void *opaque)
412
 
{
413
 
    SPARCCPU *cpu = opaque;
414
 
    CPUSPARCState *env = &cpu->env;
415
 
 
416
 
    CPUTimer* timer = env->hstick;
417
 
 
418
 
    if (timer->disabled) {
419
 
        CPUIRQ_DPRINTF("hstick_irq: softint disabled\n");
420
 
        return;
421
 
    } else {
422
 
        CPUIRQ_DPRINTF("hstick: fire\n");
423
 
    }
424
 
 
425
 
    env->softint |= SOFTINT_STIMER;
426
 
    cpu_kick_irq(cpu);
427
 
}
428
 
 
429
 
static int64_t cpu_to_timer_ticks(int64_t cpu_ticks, uint32_t frequency)
430
 
{
431
 
    return muldiv64(cpu_ticks, NANOSECONDS_PER_SECOND, frequency);
432
 
}
433
 
 
434
 
static uint64_t timer_to_cpu_ticks(int64_t timer_ticks, uint32_t frequency)
435
 
{
436
 
    return muldiv64(timer_ticks, frequency, NANOSECONDS_PER_SECOND);
437
 
}
438
 
 
439
 
void cpu_tick_set_count(CPUTimer *timer, uint64_t count)
440
 
{
441
 
    uint64_t real_count = count & ~timer->npt_mask;
442
 
    uint64_t npt_bit = count & timer->npt_mask;
443
 
 
444
 
    int64_t vm_clock_offset = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
445
 
                    cpu_to_timer_ticks(real_count, timer->frequency);
446
 
 
447
 
    TIMER_DPRINTF("%s set_count count=0x%016lx (npt %s) p=%p\n",
448
 
                  timer->name, real_count,
449
 
                  timer->npt ? "disabled" : "enabled", timer);
450
 
 
451
 
    timer->npt = npt_bit ? 1 : 0;
452
 
    timer->clock_offset = vm_clock_offset;
453
 
}
454
 
 
455
 
uint64_t cpu_tick_get_count(CPUTimer *timer)
456
 
{
457
 
    uint64_t real_count = timer_to_cpu_ticks(
458
 
                    qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - timer->clock_offset,
459
 
                    timer->frequency);
460
 
 
461
 
    TIMER_DPRINTF("%s get_count count=0x%016lx (npt %s) p=%p\n",
462
 
           timer->name, real_count,
463
 
           timer->npt ? "disabled" : "enabled", timer);
464
 
 
465
 
    if (timer->npt) {
466
 
        real_count |= timer->npt_mask;
467
 
    }
468
 
 
469
 
    return real_count;
470
 
}
471
 
 
472
 
void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit)
473
 
{
474
 
    int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
475
 
 
476
 
    uint64_t real_limit = limit & ~timer->disabled_mask;
477
 
    timer->disabled = (limit & timer->disabled_mask) ? 1 : 0;
478
 
 
479
 
    int64_t expires = cpu_to_timer_ticks(real_limit, timer->frequency) +
480
 
                    timer->clock_offset;
481
 
 
482
 
    if (expires < now) {
483
 
        expires = now + 1;
484
 
    }
485
 
 
486
 
    TIMER_DPRINTF("%s set_limit limit=0x%016lx (%s) p=%p "
487
 
                  "called with limit=0x%016lx at 0x%016lx (delta=0x%016lx)\n",
488
 
                  timer->name, real_limit,
489
 
                  timer->disabled?"disabled":"enabled",
490
 
                  timer, limit,
491
 
                  timer_to_cpu_ticks(now - timer->clock_offset,
492
 
                                     timer->frequency),
493
 
                  timer_to_cpu_ticks(expires - now, timer->frequency));
494
 
 
495
 
    if (!real_limit) {
496
 
        TIMER_DPRINTF("%s set_limit limit=ZERO - not starting timer\n",
497
 
                timer->name);
498
 
        timer_del(timer->qtimer);
499
 
    } else if (timer->disabled) {
500
 
        timer_del(timer->qtimer);
501
 
    } else {
502
 
        timer_mod(timer->qtimer, expires);
503
 
    }
504
 
}
505
 
 
506
205
static void isa_irq_handler(void *opaque, int n, int level)
507
206
{
508
207
    static const int isa_irq_to_ivec[16] = {
723
422
    .class_init    = ram_class_init,
724
423
};
725
424
 
726
 
static SPARCCPU *cpu_devinit(const char *cpu_model, const struct hwdef *hwdef)
727
 
{
728
 
    SPARCCPU *cpu;
729
 
    CPUSPARCState *env;
730
 
    ResetData *reset_info;
731
 
 
732
 
    uint32_t   tick_frequency = 100*1000000;
733
 
    uint32_t  stick_frequency = 100*1000000;
734
 
    uint32_t hstick_frequency = 100*1000000;
735
 
 
736
 
    if (cpu_model == NULL) {
737
 
        cpu_model = hwdef->default_cpu_model;
738
 
    }
739
 
    cpu = cpu_sparc_init(cpu_model);
740
 
    if (cpu == NULL) {
741
 
        fprintf(stderr, "Unable to find Sparc CPU definition\n");
742
 
        exit(1);
743
 
    }
744
 
    env = &cpu->env;
745
 
 
746
 
    env->tick = cpu_timer_create("tick", cpu, tick_irq,
747
 
                                  tick_frequency, TICK_INT_DIS,
748
 
                                  TICK_NPT_MASK);
749
 
 
750
 
    env->stick = cpu_timer_create("stick", cpu, stick_irq,
751
 
                                   stick_frequency, TICK_INT_DIS,
752
 
                                   TICK_NPT_MASK);
753
 
 
754
 
    env->hstick = cpu_timer_create("hstick", cpu, hstick_irq,
755
 
                                    hstick_frequency, TICK_INT_DIS,
756
 
                                    TICK_NPT_MASK);
757
 
 
758
 
    reset_info = g_malloc0(sizeof(ResetData));
759
 
    reset_info->cpu = cpu;
760
 
    reset_info->prom_addr = hwdef->prom_addr;
761
 
    qemu_register_reset(main_cpu_reset, reset_info);
762
 
 
763
 
    return cpu;
764
 
}
765
 
 
766
425
static void sun4uv_init(MemoryRegion *address_space_mem,
767
426
                        MachineState *machine,
768
427
                        const struct hwdef *hwdef)
781
440
    FWCfgState *fw_cfg;
782
441
 
783
442
    /* init CPUs */
784
 
    cpu = cpu_devinit(machine->cpu_model, hwdef);
 
443
    cpu = sparc64_cpu_devinit(machine->cpu_model, hwdef->default_cpu_model,
 
444
                              hwdef->prom_addr);
785
445
 
786
446
    /* set up devices */
787
447
    ram_init(0, machine->ram_size);
788
448
 
789
449
    prom_init(hwdef->prom_addr, bios_name);
790
450
 
791
 
    ivec_irqs = qemu_allocate_irqs(cpu_set_ivec_irq, cpu, IVEC_MAX);
 
451
    ivec_irqs = qemu_allocate_irqs(sparc64_cpu_set_ivec_irq, cpu, IVEC_MAX);
792
452
    pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, ivec_irqs, &pci_bus2,
793
453
                           &pci_bus3, &pbm_irqs);
794
454
    pci_vga_init(pci_bus);
882
542
enum {
883
543
    sun4u_id = 0,
884
544
    sun4v_id = 64,
885
 
    niagara_id,
886
545
};
887
546
 
888
547
static const struct hwdef hwdefs[] = {
900
559
        .prom_addr = 0x1fff0000000ULL,
901
560
        .console_serial_base = 0,
902
561
    },
903
 
    /* Sun4v generic Niagara machine */
904
 
    {
905
 
        .default_cpu_model = "Sun UltraSparc T1",
906
 
        .machine_id = niagara_id,
907
 
        .prom_addr = 0xfff0000000ULL,
908
 
        .console_serial_base = 0xfff0c2c000ULL,
909
 
    },
910
562
};
911
563
 
912
564
/* Sun4u hardware initialisation */
921
573
    sun4uv_init(get_system_memory(), machine, &hwdefs[1]);
922
574
}
923
575
 
924
 
/* Niagara hardware initialisation */
925
 
static void niagara_init(MachineState *machine)
926
 
{
927
 
    sun4uv_init(get_system_memory(), machine, &hwdefs[2]);
928
 
}
929
 
 
930
576
static void sun4u_class_init(ObjectClass *oc, void *data)
931
577
{
932
578
    MachineClass *mc = MACHINE_CLASS(oc);
933
579
 
934
580
    mc->desc = "Sun4u platform";
935
581
    mc->init = sun4u_init;
 
582
    mc->block_default_type = IF_IDE;
936
583
    mc->max_cpus = 1; /* XXX for now */
937
584
    mc->is_default = 1;
938
585
    mc->default_boot_order = "c";
950
597
 
951
598
    mc->desc = "Sun4v platform";
952
599
    mc->init = sun4v_init;
 
600
    mc->block_default_type = IF_IDE;
953
601
    mc->max_cpus = 1; /* XXX for now */
954
602
    mc->default_boot_order = "c";
955
603
}
960
608
    .class_init = sun4v_class_init,
961
609
};
962
610
 
963
 
static void niagara_class_init(ObjectClass *oc, void *data)
964
 
{
965
 
    MachineClass *mc = MACHINE_CLASS(oc);
966
 
 
967
 
    mc->desc = "Sun4v platform, Niagara";
968
 
    mc->init = niagara_init;
969
 
    mc->max_cpus = 1; /* XXX for now */
970
 
    mc->default_boot_order = "c";
971
 
}
972
 
 
973
 
static const TypeInfo niagara_type = {
974
 
    .name = MACHINE_TYPE_NAME("Niagara"),
975
 
    .parent = TYPE_MACHINE,
976
 
    .class_init = niagara_class_init,
977
 
};
978
 
 
979
611
static void sun4u_register_types(void)
980
612
{
981
613
    type_register_static(&ebus_info);
984
616
 
985
617
    type_register_static(&sun4u_type);
986
618
    type_register_static(&sun4v_type);
987
 
    type_register_static(&niagara_type);
988
619
}
989
620
 
990
621
type_init(sun4u_register_types)