Exemplo n.º 1
0
static void mpc8544ds_init(ram_addr_t ram_size,
                         const char *boot_device,
                         const char *kernel_filename,
                         const char *kernel_cmdline,
                         const char *initrd_filename,
                         const char *cpu_model)
{
    MemoryRegion *address_space_mem = get_system_memory();
    MemoryRegion *ram = g_new(MemoryRegion, 1);
    PCIBus *pci_bus;
    CPUPPCState *env = NULL;
    uint64_t elf_entry;
    uint64_t elf_lowaddr;
    target_phys_addr_t entry=0;
    target_phys_addr_t loadaddr=UIMAGE_LOAD_BASE;
    target_long kernel_size=0;
    target_ulong dt_base = 0;
    target_ulong initrd_base = 0;
    target_long initrd_size=0;
    int i=0;
    unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
    qemu_irq **irqs, *mpic;
    DeviceState *dev;
    CPUPPCState *firstenv = NULL;

    /* Setup CPUs */
    if (cpu_model == NULL) {
        cpu_model = "e500v2_v30";
    }

    irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
    irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
    for (i = 0; i < smp_cpus; i++) {
        PowerPCCPU *cpu;
        qemu_irq *input;

        cpu = cpu_ppc_init(cpu_model);
        if (cpu == NULL) {
            fprintf(stderr, "Unable to initialize CPU!\n");
            exit(1);
        }
        env = &cpu->env;

        if (!firstenv) {
            firstenv = env;
        }

        irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB);
        input = (qemu_irq *)env->irq_inputs;
        irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
        irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
        env->spr[SPR_BOOKE_PIR] = env->cpu_index = i;

        ppc_booke_timers_init(env, 400000000, PPC_TIMER_E500);

        /* Register reset handler */
        if (!i) {
            /* Primary CPU */
            struct boot_info *boot_info;
            boot_info = g_malloc0(sizeof(struct boot_info));
            qemu_register_reset(mpc8544ds_cpu_reset, cpu);
            env->load_info = boot_info;
        } else {
            /* Secondary CPUs */
            qemu_register_reset(mpc8544ds_cpu_reset_sec, cpu);
        }
    }

    env = firstenv;

    /* Fixup Memory size on a alignment boundary */
    ram_size &= ~(RAM_SIZES_ALIGN - 1);

    /* Register Memory */
    memory_region_init_ram(ram, "mpc8544ds.ram", ram_size);
    vmstate_register_ram_global(ram);
    memory_region_add_subregion(address_space_mem, 0, ram);

    /* MPIC */
    mpic = mpic_init(address_space_mem, MPC8544_MPIC_REGS_BASE,
                     smp_cpus, irqs, NULL);

    if (!mpic) {
        cpu_abort(env, "MPIC failed to initialize\n");
    }

    /* Serial */
    if (serial_hds[0]) {
        serial_mm_init(address_space_mem, MPC8544_SERIAL0_REGS_BASE,
                       0, mpic[12+26], 399193,
                       serial_hds[0], DEVICE_BIG_ENDIAN);
    }

    if (serial_hds[1]) {
        serial_mm_init(address_space_mem, MPC8544_SERIAL1_REGS_BASE,
                       0, mpic[12+26], 399193,
                       serial_hds[0], DEVICE_BIG_ENDIAN);
    }

    /* General Utility device */
    sysbus_create_simple("mpc8544-guts", MPC8544_UTIL_BASE, NULL);

    /* PCI */
    dev = sysbus_create_varargs("e500-pcihost", MPC8544_PCI_REGS_BASE,
                                mpic[pci_irq_nrs[0]], mpic[pci_irq_nrs[1]],
                                mpic[pci_irq_nrs[2]], mpic[pci_irq_nrs[3]],
                                NULL);
    pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
    if (!pci_bus)
        printf("couldn't create PCI controller!\n");

    isa_mmio_init(MPC8544_PCI_IO, MPC8544_PCI_IOLEN);

    if (pci_bus) {
        /* Register network interfaces. */
        for (i = 0; i < nb_nics; i++) {
            pci_nic_init_nofail(&nd_table[i], "virtio", NULL);
        }
    }

    /* Register spinning region */
    sysbus_create_simple("e500-spin", MPC8544_SPIN_BASE, NULL);

    /* Load kernel. */
    if (kernel_filename) {
        kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
        if (kernel_size < 0) {
            kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
                                   &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
            entry = elf_entry;
            loadaddr = elf_lowaddr;
        }
        /* XXX try again as binary */
        if (kernel_size < 0) {
            fprintf(stderr, "qemu: could not load kernel '%s'\n",
                    kernel_filename);
            exit(1);
        }
    }

    /* Load initrd. */
    if (initrd_filename) {
        initrd_base = (kernel_size + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK;
        initrd_size = load_image_targphys(initrd_filename, initrd_base,
                                          ram_size - initrd_base);

        if (initrd_size < 0) {
            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
                    initrd_filename);
            exit(1);
        }
    }

    /* If we're loading a kernel directly, we must load the device tree too. */
    if (kernel_filename) {
        struct boot_info *boot_info;

#ifndef CONFIG_FDT
        cpu_abort(env, "Compiled without FDT support - can't load kernel\n");
#endif
        dt_base = (kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
        if (mpc8544_load_device_tree(env, dt_base, ram_size,
                    initrd_base, initrd_size, kernel_cmdline) < 0) {
            fprintf(stderr, "couldn't load device tree\n");
            exit(1);
        }

        boot_info = env->load_info;
        boot_info->entry = entry;
        boot_info->dt_base = dt_base;
    }

    if (kvm_enabled()) {
        kvmppc_init();
    }
}
Exemplo n.º 2
0
static void mpc8544ds_init(ram_addr_t ram_size,
                         const char *boot_device,
                         const char *kernel_filename,
                         const char *kernel_cmdline,
                         const char *initrd_filename,
                         const char *cpu_model)
{
    PCIBus *pci_bus;
    CPUState *env;
    uint64_t elf_entry;
    uint64_t elf_lowaddr;
    target_phys_addr_t entry=0;
    target_phys_addr_t loadaddr=UIMAGE_LOAD_BASE;
    target_long kernel_size=0;
    target_ulong dt_base = 0;
    target_ulong initrd_base = 0;
    target_long initrd_size=0;
    int i=0;
    unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
    qemu_irq *irqs, *mpic, *pci_irqs;
    SerialState * serial[2];

    /* Setup CPU */
    env = cpu_ppc_init("e500v2_v30");
    if (!env) {
        fprintf(stderr, "Unable to initialize CPU!\n");
        exit(1);
    }

    /* Fixup Memory size on a alignment boundary */
    ram_size &= ~(RAM_SIZES_ALIGN - 1);

    /* Register Memory */
    cpu_register_physical_memory(0, ram_size, qemu_ram_alloc(NULL,
                                 "mpc8544ds.ram", ram_size));

    /* MPIC */
    irqs = qemu_mallocz(sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
    irqs[OPENPIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPCE500_INPUT_INT];
    irqs[OPENPIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPCE500_INPUT_CINT];
    mpic = mpic_init(MPC8544_MPIC_REGS_BASE, 1, &irqs, NULL);

    /* Serial */
    if (serial_hds[0]) {
        serial[0] = serial_mm_init(MPC8544_SERIAL0_REGS_BASE,
                                   0, mpic[12+26], 399193,
                                   serial_hds[0], 1, 1);
    }

    if (serial_hds[1]) {
        serial[0] = serial_mm_init(MPC8544_SERIAL1_REGS_BASE,
                                   0, mpic[12+26], 399193,
                                   serial_hds[0], 1, 1);
    }

    /* PCI */
    pci_irqs = qemu_malloc(sizeof(qemu_irq) * 4);
    pci_irqs[0] = mpic[pci_irq_nrs[0]];
    pci_irqs[1] = mpic[pci_irq_nrs[1]];
    pci_irqs[2] = mpic[pci_irq_nrs[2]];
    pci_irqs[3] = mpic[pci_irq_nrs[3]];
    pci_bus = ppce500_pci_init(pci_irqs, MPC8544_PCI_REGS_BASE);
    if (!pci_bus)
        printf("couldn't create PCI controller!\n");

    isa_mmio_init(MPC8544_PCI_IO, MPC8544_PCI_IOLEN, 1);

    if (pci_bus) {
        /* Register network interfaces. */
        for (i = 0; i < nb_nics; i++) {
            pci_nic_init_nofail(&nd_table[i], "virtio", NULL);
        }
    }

    /* Load kernel. */
    if (kernel_filename) {
        kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
        if (kernel_size < 0) {
            kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
                                   &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
            entry = elf_entry;
            loadaddr = elf_lowaddr;
        }
        /* XXX try again as binary */
        if (kernel_size < 0) {
            fprintf(stderr, "qemu: could not load kernel '%s'\n",
                    kernel_filename);
            exit(1);
        }
    }

    /* Load initrd. */
    if (initrd_filename) {
        initrd_base = (kernel_size + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK;
        initrd_size = load_image_targphys(initrd_filename, initrd_base,
                                          ram_size - initrd_base);

        if (initrd_size < 0) {
            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
                    initrd_filename);
            exit(1);
        }
    }

    /* If we're loading a kernel directly, we must load the device tree too. */
    if (kernel_filename) {
        dt_base = (kernel_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
        if (mpc8544_load_device_tree(dt_base, ram_size,
                    initrd_base, initrd_size, kernel_cmdline) < 0) {
            fprintf(stderr, "couldn't load device tree\n");
            exit(1);
        }

        cpu_synchronize_state(env);

        /* Set initial guest state. */
        env->gpr[1] = (16<<20) - 8;
        env->gpr[3] = dt_base;
        env->nip = entry;
        /* XXX we currently depend on KVM to create some initial TLB entries. */
    }

    if (kvm_enabled())
        kvmppc_init();

    return;
}