Пример #1
0
PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
                     qemu_irq *p_rtc_irq,
                     AlphaCPU *cpus[4], pci_map_irq_fn sys_map_irq)
{
    const uint64_t MB = 1024 * 1024;
    const uint64_t GB = 1024 * MB;
    MemoryRegion *addr_space = get_system_memory();
    DeviceState *dev;
    TyphoonState *s;
    PCIHostState *phb;
    PCIBus *b;
    int i;

    dev = qdev_create(NULL, TYPE_TYPHOON_PCI_HOST_BRIDGE);
    qdev_init_nofail(dev);

    s = TYPHOON_PCI_HOST_BRIDGE(dev);
    phb = PCI_HOST_BRIDGE(dev);

    /* Remember the CPUs so that we can deliver interrupts to them.  */
    for (i = 0; i < 4; i++) {
        AlphaCPU *cpu = cpus[i];
        s->cchip.cpu[i] = cpu;
        if (cpu != NULL) {
            cpu->alarm_timer = qemu_new_timer_ns(vm_clock,
                                                 typhoon_alarm_timer,
                                                 (void *)((uintptr_t)s + i));
        }
    }

    *p_rtc_irq = *qemu_allocate_irqs(typhoon_set_timer_irq, s, 1);

    /* Main memory region, 0x00.0000.0000.  Real hardware supports 32GB,
       but the address space hole reserved at this point is 8TB.  */
    memory_region_init_ram(&s->ram_region, OBJECT(s), "ram", ram_size);
    vmstate_register_ram_global(&s->ram_region);
    memory_region_add_subregion(addr_space, 0, &s->ram_region);

    /* TIGbus, 0x801.0000.0000, 1GB.  */
    /* ??? The TIGbus is used for delivering interrupts, and access to
       the flash ROM.  I'm not sure that we need to implement it at all.  */

    /* Pchip0 CSRs, 0x801.8000.0000, 256MB.  */
    memory_region_init_io(&s->pchip.region, OBJECT(s), &pchip_ops, s, "pchip0",
                          256*MB);
    memory_region_add_subregion(addr_space, 0x80180000000ULL,
                                &s->pchip.region);

    /* Cchip CSRs, 0x801.A000.0000, 256MB.  */
    memory_region_init_io(&s->cchip.region, OBJECT(s), &cchip_ops, s, "cchip0",
                          256*MB);
    memory_region_add_subregion(addr_space, 0x801a0000000ULL,
                                &s->cchip.region);

    /* Dchip CSRs, 0x801.B000.0000, 256MB.  */
    memory_region_init_io(&s->dchip_region, OBJECT(s), &dchip_ops, s, "dchip0",
                          256*MB);
    memory_region_add_subregion(addr_space, 0x801b0000000ULL,
                                &s->dchip_region);

    /* Pchip0 PCI memory, 0x800.0000.0000, 4GB.  */
    memory_region_init(&s->pchip.reg_mem, OBJECT(s), "pci0-mem", 4*GB);
    memory_region_add_subregion(addr_space, 0x80000000000ULL,
                                &s->pchip.reg_mem);

    /* Pchip0 PCI I/O, 0x801.FC00.0000, 32MB.  */
    memory_region_init_io(&s->pchip.reg_io, OBJECT(s), &alpha_pci_ignore_ops,
                          NULL, "pci0-io", 32*MB);
    memory_region_add_subregion(addr_space, 0x801fc000000ULL,
                                &s->pchip.reg_io);

    b = pci_register_bus(dev, "pci",
                         typhoon_set_irq, sys_map_irq, s,
                         &s->pchip.reg_mem, &s->pchip.reg_io,
                         0, 64, TYPE_PCI_BUS);
    phb->bus = b;

    /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB.  */
    memory_region_init_io(&s->pchip.reg_iack, OBJECT(s), &alpha_pci_iack_ops,
                          b, "pci0-iack", 64*MB);
    memory_region_add_subregion(addr_space, 0x801f8000000ULL,
                                &s->pchip.reg_iack);

    /* Pchip0 PCI configuration, 0x801.FE00.0000, 16MB.  */
    memory_region_init_io(&s->pchip.reg_conf, OBJECT(s), &alpha_pci_conf1_ops,
                          b, "pci0-conf", 16*MB);
    memory_region_add_subregion(addr_space, 0x801fe000000ULL,
                                &s->pchip.reg_conf);

    /* For the record, these are the mappings for the second PCI bus.
       We can get away with not implementing them because we indicate
       via the Cchip.CSC<PIP> bit that Pchip1 is not present.  */
    /* Pchip1 PCI memory, 0x802.0000.0000, 4GB.  */
    /* Pchip1 CSRs, 0x802.8000.0000, 256MB.  */
    /* Pchip1 PCI special/interrupt acknowledge, 0x802.F800.0000, 64MB.  */
    /* Pchip1 PCI I/O, 0x802.FC00.0000, 32MB.  */
    /* Pchip1 PCI configuration, 0x802.FE00.0000, 16MB.  */

    /* Init the ISA bus.  */
    /* ??? Technically there should be a cy82c693ub pci-isa bridge.  */
    {
        qemu_irq isa_pci_irq, *isa_irqs;

        *isa_bus = isa_bus_new(NULL, &s->pchip.reg_io);
        isa_pci_irq = *qemu_allocate_irqs(typhoon_set_isa_irq, s, 1);
        isa_irqs = i8259_init(*isa_bus, isa_pci_irq);
        isa_bus_irqs(*isa_bus, isa_irqs);
    }

    return b;
}
Пример #2
0
/* PowerPC Mac99 hardware initialisation */
static void ppc_core99_init (ram_addr_t ram_size, int vga_ram_size,
                             const char *boot_device, DisplayState *ds,
                             const char *kernel_filename,
                             const char *kernel_cmdline,
                             const char *initrd_filename,
                             const char *cpu_model)
{
    CPUState *env = NULL, *envs[MAX_CPUS];
    char buf[1024];
    qemu_irq *pic, **openpic_irqs;
    int unin_memory;
    int linux_boot, i;
    unsigned long bios_offset, vga_bios_offset;
    uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
    PCIBus *pci_bus;
    nvram_t nvram;
#if 0
    MacIONVRAMState *nvr;
    int nvram_mem_index;
#endif
    m48t59_t *m48t59;
    int vga_bios_size, bios_size;
    qemu_irq *dummy_irq;
    int pic_mem_index, dbdma_mem_index, cuda_mem_index;
    int ide_mem_index[2];
    int ppc_boot_device;
    int index;
    BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];

    linux_boot = (kernel_filename != NULL);

    /* init CPUs */
    if (cpu_model == NULL)
        cpu_model = "default";
    for (i = 0; i < smp_cpus; i++) {
        env = cpu_init(cpu_model);
        if (!env) {
            fprintf(stderr, "Unable to find PowerPC CPU definition\n");
            exit(1);
        }
        /* Set time-base frequency to 100 Mhz */
        cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
#if 0
        env->osi_call = vga_osi_call;
#endif
        qemu_register_reset(&cpu_ppc_reset, env);
        register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
        envs[i] = env;
    }
    if (env->nip < 0xFFF80000) {
        /* Special test for PowerPC 601:
         * the boot vector is at 0xFFF00100, then we need a 1MB BIOS.
         * But the NVRAM is located at 0xFFF04000...
         */
        cpu_abort(env, "Mac99 hardware can not handle 1 MB BIOS\n");
    }

    /* allocate RAM */
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);

    /* allocate and load BIOS */
    bios_offset = ram_size + vga_ram_size;
    if (bios_name == NULL)
        bios_name = BIOS_FILENAME;
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
    bios_size = load_image(buf, phys_ram_base + bios_offset);
    if (bios_size < 0 || bios_size > BIOS_SIZE) {
        cpu_abort(env, "qemu: could not load PowerPC bios '%s'\n", buf);
        exit(1);
    }
    bios_size = (bios_size + 0xfff) & ~0xfff;
    if (bios_size > 0x00080000) {
        /* As the NVRAM is located at 0xFFF04000, we cannot use 1 MB BIOSes */
        cpu_abort(env, "Mac99 hardware can not handle 1 MB BIOS\n");
    }
    cpu_register_physical_memory((uint32_t)(-bios_size),
                                 bios_size, bios_offset | IO_MEM_ROM);

    /* allocate and load VGA BIOS */
    vga_bios_offset = bios_offset + bios_size;
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
    vga_bios_size = load_image(buf, phys_ram_base + vga_bios_offset + 8);
    if (vga_bios_size < 0) {
        /* if no bios is present, we can still work */
        fprintf(stderr, "qemu: warning: could not load VGA bios '%s'\n", buf);
        vga_bios_size = 0;
    } else {
        /* set a specific header (XXX: find real Apple format for NDRV
           drivers) */
        phys_ram_base[vga_bios_offset] = 'N';
        phys_ram_base[vga_bios_offset + 1] = 'D';
        phys_ram_base[vga_bios_offset + 2] = 'R';
        phys_ram_base[vga_bios_offset + 3] = 'V';
        cpu_to_be32w((uint32_t *)(phys_ram_base + vga_bios_offset + 4),
                     vga_bios_size);
        vga_bios_size += 8;
    }
    vga_bios_size = (vga_bios_size + 0xfff) & ~0xfff;

    if (linux_boot) {
        kernel_base = KERNEL_LOAD_ADDR;
        /* now we can load the kernel */
        kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
        if (kernel_size < 0) {
            cpu_abort(env, "qemu: could not load kernel '%s'\n",
                      kernel_filename);
            exit(1);
        }
        /* load initrd */
        if (initrd_filename) {
            initrd_base = INITRD_LOAD_ADDR;
            initrd_size = load_image(initrd_filename,
                                     phys_ram_base + initrd_base);
            if (initrd_size < 0) {
                cpu_abort(env, "qemu: could not load initial ram disk '%s'\n",
                          initrd_filename);
                exit(1);
            }
        } else {
            initrd_base = 0;
            initrd_size = 0;
        }
        ppc_boot_device = 'm';
    } else {
        kernel_base = 0;
        kernel_size = 0;
        initrd_base = 0;
        initrd_size = 0;
        ppc_boot_device = '\0';
        /* We consider that NewWorld PowerMac never have any floppy drive
         * For now, OHW cannot boot from the network.
         */
        for (i = 0; boot_device[i] != '\0'; i++) {
            if (boot_device[i] >= 'c' && boot_device[i] <= 'f') {
                ppc_boot_device = boot_device[i];
                break;
            }
        }
        if (ppc_boot_device == '\0') {
            fprintf(stderr, "No valid boot device for Mac99 machine\n");
            exit(1);
        }
    }

    isa_mem_base = 0x80000000;

    /* Register 8 MB of ISA IO space */
    isa_mmio_init(0xf2000000, 0x00800000);

    /* UniN init */
    unin_memory = cpu_register_io_memory(0, unin_read, unin_write, NULL);
    cpu_register_physical_memory(0xf8000000, 0x00001000, unin_memory);

    openpic_irqs = qemu_mallocz(smp_cpus * sizeof(qemu_irq *));
    openpic_irqs[0] =
        qemu_mallocz(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
    for (i = 0; i < smp_cpus; i++) {
        /* Mac99 IRQ connection between OpenPIC outputs pins
         * and PowerPC input pins
         */
        switch (PPC_INPUT(env)) {
        case PPC_FLAGS_INPUT_6xx:
            openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
            openpic_irqs[i][OPENPIC_OUTPUT_INT] =
                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
            openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT];
            openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_MCP];
            /* Not connected ? */
            openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
            /* Check this */
            openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
                ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_HRESET];
            break;
#if defined(TARGET_PPC64)
        case PPC_FLAGS_INPUT_970:
            openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB);
            openpic_irqs[i][OPENPIC_OUTPUT_INT] =
                ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
            openpic_irqs[i][OPENPIC_OUTPUT_CINT] =
                ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT];
            openpic_irqs[i][OPENPIC_OUTPUT_MCK] =
                ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_MCP];
            /* Not connected ? */
            openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL;
            /* Check this */
            openpic_irqs[i][OPENPIC_OUTPUT_RESET] =
                ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_HRESET];
            break;
#endif /* defined(TARGET_PPC64) */
        default:
            cpu_abort(env, "Bus model not supported on mac99 machine\n");
            exit(1);
        }
    }
    pic = openpic_init(NULL, &pic_mem_index, smp_cpus, openpic_irqs, NULL);
    pci_bus = pci_pmac_init(pic);
    /* init basic PC hardware */
    pci_vga_init(pci_bus, ds, phys_ram_base + ram_size,
                 ram_size, vga_ram_size,
                 vga_bios_offset, vga_bios_size);

    /* XXX: suppress that */
    dummy_irq = i8259_init(NULL);

    /* XXX: use Mac Serial port */
    serial_init(0x3f8, dummy_irq[4], 115200, serial_hds[0]);
    for(i = 0; i < nb_nics; i++) {
        if (!nd_table[i].model)
            nd_table[i].model = "ne2k_pci";
        pci_nic_init(pci_bus, &nd_table[i], -1);
    }
    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
        fprintf(stderr, "qemu: too many IDE bus\n");
        exit(1);
    }
    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
        index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
        if (index != -1)
            hd[i] = drives_table[index].bdrv;
        else
            hd[i] = NULL;
    }
#if 1
    ide_mem_index[0] = pmac_ide_init(&hd[0], pic[0x13]);
    ide_mem_index[1] = pmac_ide_init(&hd[2], pic[0x14]);
#else
    pci_cmd646_ide_init(pci_bus, &hd[0], 0);
#endif
    /* cuda also initialize ADB */
    cuda_init(&cuda_mem_index, pic[0x19]);

    adb_kbd_init(&adb_bus);
    adb_mouse_init(&adb_bus);

    dbdma_init(&dbdma_mem_index);

    macio_init(pci_bus, 0x0022, 0, pic_mem_index, dbdma_mem_index,
               cuda_mem_index, NULL, 2, ide_mem_index);

    if (usb_enabled) {
        usb_ohci_init_pci(pci_bus, 3, -1);
    }

    if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
        graphic_depth = 15;
#if 0 /* XXX: this is ugly but needed for now, or OHW won't boot */
    /* The NewWorld NVRAM is not located in the MacIO device */
    nvr = macio_nvram_init(&nvram_mem_index, 0x2000);
    pmac_format_nvram_partition(nvr, 0x2000);
    macio_nvram_map(nvr, 0xFFF04000);
    nvram.opaque = nvr;
    nvram.read_fn = &macio_nvram_read;
    nvram.write_fn = &macio_nvram_write;
#else
    m48t59 = m48t59_init(dummy_irq[8], 0xFFF04000, 0x0074, NVRAM_SIZE, 59);
    nvram.opaque = m48t59;
    nvram.read_fn = &m48t59_read;
    nvram.write_fn = &m48t59_write;
#endif
    PPC_NVRAM_set_params(&nvram, NVRAM_SIZE, "MAC99", ram_size,
                         ppc_boot_device, kernel_base, kernel_size,
                         kernel_cmdline,
                         initrd_base, initrd_size,
                         /* XXX: need an option to load a NVRAM image */
                         0,
                         graphic_width, graphic_height, graphic_depth);
    /* No PCI init: the BIOS will do it */

    /* Special port to get debug messages from Open-Firmware */
    register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
}
Пример #3
0
/* PC hardware initialisation */
static void pc_init1(MachineState *machine,
                     int pci_enabled,
                     int kvmclock_enabled)
{
    PCMachineState *pc_machine = PC_MACHINE(machine);
    MemoryRegion *system_memory = get_system_memory();
    MemoryRegion *system_io = get_system_io();
    int i;
    ram_addr_t below_4g_mem_size, above_4g_mem_size;
    PCIBus *pci_bus;
    ISABus *isa_bus;
    PCII440FXState *i440fx_state;
    int piix3_devfn = -1;
    qemu_irq *cpu_irq;
    qemu_irq *gsi;
    qemu_irq *i8259;
    qemu_irq *smi_irq;
    GSIState *gsi_state;
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
    BusState *idebus[MAX_IDE_BUS];
    ISADevice *rtc_state;
    ISADevice *floppy;
    MemoryRegion *ram_memory;
    MemoryRegion *pci_memory;
    MemoryRegion *rom_memory;
    DeviceState *icc_bridge;
    FWCfgState *fw_cfg = NULL;
    PcGuestInfo *guest_info;
    ram_addr_t lowmem;

    /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory).
     * If it doesn't, we need to split it in chunks below and above 4G.
     * In any case, try to make sure that guest addresses aligned at
     * 1G boundaries get mapped to host addresses aligned at 1G boundaries.
     * For old machine types, use whatever split we used historically to avoid
     * breaking migration.
     */
    if (machine->ram_size >= 0xe0000000) {
        lowmem = gigabyte_align ? 0xc0000000 : 0xe0000000;
    } else {
        lowmem = 0xe0000000;
    }

    /* Handle the machine opt max-ram-below-4g.  It is basically doing
     * min(qemu limit, user limit).
     */
    if (lowmem > pc_machine->max_ram_below_4g) {
        lowmem = pc_machine->max_ram_below_4g;
        if (machine->ram_size - lowmem > lowmem &&
            lowmem & ((1ULL << 30) - 1)) {
            error_report("Warning: Large machine and max_ram_below_4g(%"PRIu64
                         ") not a multiple of 1G; possible bad performance.",
                         pc_machine->max_ram_below_4g);
        }
    }

    if (machine->ram_size >= lowmem) {
        above_4g_mem_size = machine->ram_size - lowmem;
        below_4g_mem_size = lowmem;
    } else {
        above_4g_mem_size = 0;
        below_4g_mem_size = machine->ram_size;
    }

    if (xen_enabled() && xen_hvm_init(&below_4g_mem_size, &above_4g_mem_size,
                                      &ram_memory) != 0) {
        fprintf(stderr, "xen hardware virtual machine initialisation failed\n");
        exit(1);
    }

    icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
    object_property_add_child(qdev_get_machine(), "icc-bridge",
                              OBJECT(icc_bridge), NULL);

    pc_cpus_init(machine->cpu_model, icc_bridge);

    if (kvm_enabled() && kvmclock_enabled) {
        kvmclock_create();
    }

    if (pci_enabled) {
        pci_memory = g_new(MemoryRegion, 1);
        memory_region_init(pci_memory, NULL, "pci", UINT64_MAX);
        rom_memory = pci_memory;
    } else {
        pci_memory = NULL;
        rom_memory = system_memory;
    }

    guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);

    guest_info->has_acpi_build = has_acpi_build;
    guest_info->legacy_acpi_table_size = legacy_acpi_table_size;

    guest_info->isapc_ram_fw = !pci_enabled;
    guest_info->has_reserved_memory = has_reserved_memory;

    if (smbios_defaults) {
        MachineClass *mc = MACHINE_GET_CLASS(machine);
        /* These values are guest ABI, do not change */
        smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)",
                            mc->name, smbios_legacy_mode);
    }

    /* allocate ram and load rom/bios */
    if (!xen_enabled()) {
        fw_cfg = pc_memory_init(machine, system_memory,
                                below_4g_mem_size, above_4g_mem_size,
                                rom_memory, &ram_memory, guest_info);
    } else if (machine->kernel_filename != NULL) {
        /* For xen HVM direct kernel boot, load linux here */
        fw_cfg = xen_load_linux(machine->kernel_filename,
                                machine->kernel_cmdline,
                                machine->initrd_filename,
                                below_4g_mem_size,
                                guest_info);
    }

    gsi_state = g_malloc0(sizeof(*gsi_state));
    if (kvm_irqchip_in_kernel()) {
        kvm_pc_setup_irq_routing(pci_enabled);
        gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
                                 GSI_NUM_PINS);
    } else {
        gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
    }

    if (pci_enabled) {
        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
                              system_memory, system_io, machine->ram_size,
                              below_4g_mem_size,
                              above_4g_mem_size,
                              pci_memory, ram_memory);
    } else {
        pci_bus = NULL;
        i440fx_state = NULL;
        isa_bus = isa_bus_new(NULL, system_io);
        no_hpet = 1;
    }
    isa_bus_irqs(isa_bus, gsi);

    if (kvm_irqchip_in_kernel()) {
        i8259 = kvm_i8259_init(isa_bus);
    } else if (xen_enabled()) {
        i8259 = xen_interrupt_controller_init();
    } else {
        cpu_irq = pc_allocate_cpu_irq();
        i8259 = i8259_init(isa_bus, cpu_irq[0]);
    }

    for (i = 0; i < ISA_NUM_IRQS; i++) {
        gsi_state->i8259_irq[i] = i8259[i];
    }
    if (pci_enabled) {
        ioapic_init_gsi(gsi_state, "i440fx");
    }
    qdev_init_nofail(icc_bridge);

    pc_register_ferr_irq(gsi[13]);

    pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);

    /* init basic PC hardware */
    pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled(),
        0x4);

    pc_nic_init(isa_bus, pci_bus);

    ide_drive_get(hd, ARRAY_SIZE(hd));
    if (pci_enabled) {
        PCIDevice *dev;
        if (xen_enabled()) {
            dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1);
        } else {
            dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
        }
        idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
        idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
    } else {
        for(i = 0; i < MAX_IDE_BUS; i++) {
            ISADevice *dev;
            char busname[] = "ide.0";
            dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
                               ide_irq[i],
                               hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
            /*
             * The ide bus name is ide.0 for the first bus and ide.1 for the
             * second one.
             */
            busname[4] = '0' + i;
            idebus[i] = qdev_get_child_bus(DEVICE(dev), busname);
        }
    }

    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, machine->boot_order,
                 floppy, idebus[0], idebus[1], rtc_state);

    if (pci_enabled && usb_enabled(false)) {
        pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci");
    }

    if (pci_enabled && acpi_enabled) {
        DeviceState *piix4_pm;
        I2CBus *smbus;

        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
        /* TODO: Populate SPD eeprom data.  */
        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
                              gsi[9], *smi_irq,
                              kvm_enabled(), fw_cfg, &piix4_pm);
        smbus_eeprom_init(smbus, 8, NULL, 0);

        object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
                                 TYPE_HOTPLUG_HANDLER,
                                 (Object **)&pc_machine->acpi_dev,
                                 object_property_allow_set_link,
                                 OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort);
        object_property_set_link(OBJECT(machine), OBJECT(piix4_pm),
                                 PC_MACHINE_ACPI_DEVICE_PROP, &error_abort);
    }

    if (pci_enabled) {
        pc_pci_device_init(pci_bus);
    }
}
Пример #4
0
/* PC hardware initialisation */
static void pc_q35_init(MachineState *machine)
{
    PCMachineState *pcms = PC_MACHINE(machine);
    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
    Q35PCIHost *q35_host;
    PCIHostState *phb;
    PCIBus *host_bus;
    PCIDevice *lpc;
    DeviceState *lpc_dev;
    BusState *idebus[MAX_SATA_PORTS];
    ISADevice *rtc_state;
    MemoryRegion *system_io = get_system_io();
    MemoryRegion *pci_memory;
    MemoryRegion *rom_memory;
    MemoryRegion *ram_memory;
    GSIState *gsi_state;
    ISABus *isa_bus;
    qemu_irq *i8259;
    int i;
    ICH9LPCState *ich9_lpc;
    PCIDevice *ahci;
    ram_addr_t lowmem;
    DriveInfo *hd[MAX_SATA_PORTS];
    MachineClass *mc = MACHINE_GET_CLASS(machine);

    /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory
     * and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping
     * also known as MMCFG).
     * If it doesn't, we need to split it in chunks below and above 4G.
     * In any case, try to make sure that guest addresses aligned at
     * 1G boundaries get mapped to host addresses aligned at 1G boundaries.
     */
    if (machine->ram_size >= 0xb0000000) {
        lowmem = 0x80000000;
    } else {
        lowmem = 0xb0000000;
    }

    /* Handle the machine opt max-ram-below-4g.  It is basically doing
     * min(qemu limit, user limit).
     */
    if (!pcms->max_ram_below_4g) {
        pcms->max_ram_below_4g = 1ULL << 32; /* default: 4G */;
    }
    if (lowmem > pcms->max_ram_below_4g) {
        lowmem = pcms->max_ram_below_4g;
        if (machine->ram_size - lowmem > lowmem &&
            lowmem & ((1ULL << 30) - 1)) {
            error_report("Warning: Large machine and max_ram_below_4g(%"PRIu64
                         ") not a multiple of 1G; possible bad performance.",
                         pcms->max_ram_below_4g);
        }
    }

    if (machine->ram_size >= lowmem) {
        pcms->above_4g_mem_size = machine->ram_size - lowmem;
        pcms->below_4g_mem_size = lowmem;
    } else {
        pcms->above_4g_mem_size = 0;
        pcms->below_4g_mem_size = machine->ram_size;
    }

    if (xen_enabled()) {
        xen_hvm_init(pcms, &ram_memory);
    }

    pc_cpus_init(pcms);

    kvmclock_create();

    /* pci enabled */
    if (pcmc->pci_enabled) {
        pci_memory = g_new(MemoryRegion, 1);
        memory_region_init(pci_memory, NULL, "pci", UINT64_MAX);
        rom_memory = pci_memory;
    } else {
        pci_memory = NULL;
        rom_memory = get_system_memory();
    }

    pc_guest_info_init(pcms);

    if (pcmc->smbios_defaults) {
        /* These values are guest ABI, do not change */
        smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
                            mc->name, pcmc->smbios_legacy_mode,
                            pcmc->smbios_uuid_encoded,
                            SMBIOS_ENTRY_POINT_21);
    }

    /* allocate ram and load rom/bios */
    if (!xen_enabled()) {
        pc_memory_init(pcms, get_system_memory(),
                       rom_memory, &ram_memory);
    }

    /* irq lines */
    gsi_state = g_malloc0(sizeof(*gsi_state));
    if (kvm_ioapic_in_kernel()) {
        kvm_pc_setup_irq_routing(pcmc->pci_enabled);
        pcms->gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
                                       GSI_NUM_PINS);
    } else {
        pcms->gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
    }

    /* create pci host bus */
    q35_host = Q35_HOST_DEVICE(qdev_create(NULL, TYPE_Q35_HOST_DEVICE));

    object_property_add_child(qdev_get_machine(), "q35", OBJECT(q35_host), NULL);
    object_property_set_link(OBJECT(q35_host), OBJECT(ram_memory),
                             MCH_HOST_PROP_RAM_MEM, NULL);
    object_property_set_link(OBJECT(q35_host), OBJECT(pci_memory),
                             MCH_HOST_PROP_PCI_MEM, NULL);
    object_property_set_link(OBJECT(q35_host), OBJECT(get_system_memory()),
                             MCH_HOST_PROP_SYSTEM_MEM, NULL);
    object_property_set_link(OBJECT(q35_host), OBJECT(system_io),
                             MCH_HOST_PROP_IO_MEM, NULL);
    object_property_set_int(OBJECT(q35_host), pcms->below_4g_mem_size,
                            PCI_HOST_BELOW_4G_MEM_SIZE, NULL);
    object_property_set_int(OBJECT(q35_host), pcms->above_4g_mem_size,
                            PCI_HOST_ABOVE_4G_MEM_SIZE, NULL);
    /* pci */
    qdev_init_nofail(DEVICE(q35_host));
    phb = PCI_HOST_BRIDGE(q35_host);
    host_bus = phb->bus;
    /* create ISA bus */
    lpc = pci_create_simple_multifunction(host_bus, PCI_DEVFN(ICH9_LPC_DEV,
                                          ICH9_LPC_FUNC), true,
                                          TYPE_ICH9_LPC_DEVICE);

    object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
                             TYPE_HOTPLUG_HANDLER,
                             (Object **)&pcms->acpi_dev,
                             object_property_allow_set_link,
                             OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort);
    object_property_set_link(OBJECT(machine), OBJECT(lpc),
                             PC_MACHINE_ACPI_DEVICE_PROP, &error_abort);

    ich9_lpc = ICH9_LPC_DEVICE(lpc);
    lpc_dev = DEVICE(lpc);
    for (i = 0; i < GSI_NUM_PINS; i++) {
        qdev_connect_gpio_out_named(lpc_dev, ICH9_GPIO_GSI, i, pcms->gsi[i]);
    }
    pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc,
                 ICH9_LPC_NB_PIRQS);
    pci_bus_set_route_irq_fn(host_bus, ich9_route_intx_pin_to_irq);
    isa_bus = ich9_lpc->isa_bus;

    if (kvm_pic_in_kernel()) {
        i8259 = kvm_i8259_init(isa_bus);
    } else if (xen_enabled()) {
        i8259 = xen_interrupt_controller_init();
    } else {
        i8259 = i8259_init(isa_bus, pc_allocate_cpu_irq());
    }

    for (i = 0; i < ISA_NUM_IRQS; i++) {
        gsi_state->i8259_irq[i] = i8259[i];
    }
    g_free(i8259);

    if (pcmc->pci_enabled) {
        ioapic_init_gsi(gsi_state, "q35");
    }

    pc_register_ferr_irq(pcms->gsi[13]);

    assert(pcms->vmport != ON_OFF_AUTO__MAX);
    if (pcms->vmport == ON_OFF_AUTO_AUTO) {
        pcms->vmport = ON_OFF_AUTO_OFF;
    }

    /* init basic PC hardware */
    pc_basic_device_init(isa_bus, pcms->gsi, &rtc_state, !mc->no_floppy,
                         (pcms->vmport != ON_OFF_AUTO_ON), 0xff0104);

    /* connect pm stuff to lpc */
    ich9_lpc_pm_init(lpc, pc_machine_is_smm_enabled(pcms));

    /* ahci and SATA device, for q35 1 ahci controller is built-in */
    ahci = pci_create_simple_multifunction(host_bus,
                                           PCI_DEVFN(ICH9_SATA1_DEV,
                                                     ICH9_SATA1_FUNC),
                                           true, "ich9-ahci");
    idebus[0] = qdev_get_child_bus(&ahci->qdev, "ide.0");
    idebus[1] = qdev_get_child_bus(&ahci->qdev, "ide.1");
    g_assert(MAX_SATA_PORTS == ICH_AHCI(ahci)->ahci.ports);
    ide_drive_get(hd, ICH_AHCI(ahci)->ahci.ports);
    ahci_ide_create_devs(ahci, hd);

    if (machine_usb(machine)) {
        /* Should we create 6 UHCI according to ich9 spec? */
        ehci_create_ich9_with_companions(host_bus, 0x1d);
    }

    /* TODO: Populate SPD eeprom data.  */
    smbus_eeprom_init(ich9_smb_init(host_bus,
                                    PCI_DEVFN(ICH9_SMB_DEV, ICH9_SMB_FUNC),
                                    0xb100),
                      8, NULL, 0);

    pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state);

    /* the rest devices to which pci devfn is automatically assigned */
    pc_vga_init(isa_bus, host_bus);
    pc_nic_init(isa_bus, host_bus);
    if (pcmc->pci_enabled) {
        pc_pci_device_init(host_bus);
    }

    if (pcms->acpi_nvdimm_state.is_enabled) {
        nvdimm_init_acpi_state(&pcms->acpi_nvdimm_state, system_io,
                               pcms->fw_cfg, OBJECT(pcms));
    }
}
Пример #5
0
/* Check if MAGIC is valid and print the Multiboot information structure
   pointed by ADDR. */
void
entry (unsigned long magic, unsigned long addr)
{
	multiboot_info_t *mbi;

	/* Clear the screen. */
	clear();

	paging_init();

	/* Am I booted by a Multiboot-compliant boot loader? */
	if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
	{
		printf ("Invalid magic number: 0x%#x\n", (unsigned) magic);
		return;
	}

	/* Set MBI to the address of the Multiboot information structure. */
	mbi = (multiboot_info_t *) addr;

	/* Print out the flags. */
	printf ("flags = 0x%#x\n", (unsigned) mbi->flags);

	/* Are mem_* valid? */
	if (CHECK_FLAG (mbi->flags, 0))
		printf ("mem_lower = %uKB, mem_upper = %uKB\n",
				(unsigned) mbi->mem_lower, (unsigned) mbi->mem_upper);

	/* Is boot_device valid? */
	if (CHECK_FLAG (mbi->flags, 1))
		printf ("boot_device = 0x%#x\n", (unsigned) mbi->boot_device);

	/* Is the command line passed? */
	if (CHECK_FLAG (mbi->flags, 2))
		printf ("cmdline = %s\n", (char *) mbi->cmdline);

	if (CHECK_FLAG (mbi->flags, 3)) {
		int mod_count = 0;
		int i;
		module_t* mod = (module_t*)mbi->mods_addr;
		while(mod_count < mbi->mods_count) {
			printf("Module %d loaded at address: 0x%#x\n", mod_count, (unsigned int)mod->mod_start);
			printf("Module %d ends at address: 0x%#x\n", mod_count, (unsigned int)mod->mod_end);
			printf("First few bytes of module:\n");
			for(i = 0; i<16; i++) {
				printf("0x%x ", *((char*)(mod->mod_start+i)));
			}
			printf("\n");
			mod_count++;
		}
	}
	/* Bits 4 and 5 are mutually exclusive! */
	if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG (mbi->flags, 5))
	{
		printf ("Both bits 4 and 5 are set.\n");
		return;
	}

	/* Is the section header table of ELF valid? */
	if (CHECK_FLAG (mbi->flags, 5))
	{
		elf_section_header_table_t *elf_sec = &(mbi->elf_sec);

		printf ("elf_sec: num = %u, size = 0x%#x,"
				" addr = 0x%#x, shndx = 0x%#x\n",
				(unsigned) elf_sec->num, (unsigned) elf_sec->size,
				(unsigned) elf_sec->addr, (unsigned) elf_sec->shndx);
	}

	/* Are mmap_* valid? */
	if (CHECK_FLAG (mbi->flags, 6))
	{
		memory_map_t *mmap;

		printf ("mmap_addr = 0x%#x, mmap_length = 0x%x\n",
				(unsigned) mbi->mmap_addr, (unsigned) mbi->mmap_length);
		for (mmap = (memory_map_t *) mbi->mmap_addr;
				(unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length;
				mmap = (memory_map_t *) ((unsigned long) mmap
					+ mmap->size + sizeof (mmap->size)))
			printf (" size = 0x%x,     base_addr = 0x%#x%#x\n"
					"     type = 0x%x,  length    = 0x%#x%#x\n",
					(unsigned) mmap->size,
					(unsigned) mmap->base_addr_high,
					(unsigned) mmap->base_addr_low,
					(unsigned) mmap->type,
					(unsigned) mmap->length_high,
					(unsigned) mmap->length_low);
	}

	/* Construct an LDT entry in the GDT */
	{
		seg_desc_t the_ldt_desc;
		the_ldt_desc.granularity    = 0;
		the_ldt_desc.opsize         = 1;
		the_ldt_desc.reserved       = 0;
		the_ldt_desc.avail          = 0;
		the_ldt_desc.present        = 1;
		the_ldt_desc.dpl            = 0x0;
		the_ldt_desc.sys            = 0;
		the_ldt_desc.type           = 0x2;

		SET_LDT_PARAMS(the_ldt_desc, &ldt, ldt_size);
		ldt_desc_ptr = the_ldt_desc;
		lldt(KERNEL_LDT);
	}

	/* Construct a TSS entry in the GDT */
	{
		seg_desc_t the_tss_desc;
		the_tss_desc.granularity    = 0;
		the_tss_desc.opsize         = 0;
		the_tss_desc.reserved       = 0;
		the_tss_desc.avail          = 0;
		the_tss_desc.seg_lim_19_16  = TSS_SIZE & 0x000F0000;
		the_tss_desc.present        = 1;
		the_tss_desc.dpl            = 0x0;
		the_tss_desc.sys            = 0;
		the_tss_desc.type           = 0x9;
		the_tss_desc.seg_lim_15_00  = TSS_SIZE & 0x0000FFFF;

		SET_TSS_PARAMS(the_tss_desc, &tss, tss_size);

		tss_desc_ptr = the_tss_desc;

		tss.ldt_segment_selector = KERNEL_LDT;
		tss.ss0 = KERNEL_DS;
		tss.esp0 = 0x800000;
		ltr(KERNEL_TSS);
	}


	idt_desc_t interrupt;

	interrupt.seg_selector = KERNEL_CS;
	interrupt.dpl = 0;
	interrupt.size = 1;
	interrupt.reserved0 = 0;
	interrupt.reserved1 = 1;
	interrupt.reserved2 = 1;
	interrupt.reserved3 = 0;
	interrupt.reserved4 = 0;
	interrupt.present = 1;

	idt_desc_t divide_error_desc = interrupt;
	SET_IDT_ENTRY(divide_error_desc, divide_error);
	idt[0] = divide_error_desc;

	idt_desc_t reserved_desc = interrupt;
	SET_IDT_ENTRY(reserved_desc, reserved);
	idt[1] = reserved_desc;

	idt_desc_t nmi_interrupt_desc = interrupt;
	SET_IDT_ENTRY(nmi_interrupt_desc, nmi_interrupt);
	idt[2] = nmi_interrupt_desc;

	idt_desc_t breakpoint_desc = interrupt;
	SET_IDT_ENTRY(breakpoint_desc, breakpoint);
	idt[3] = breakpoint_desc;

	idt_desc_t overflow_desc = interrupt;
	SET_IDT_ENTRY(overflow_desc, overflow);
	idt[4] = overflow_desc;

	idt_desc_t bound_range_exceeded_desc = interrupt;
	SET_IDT_ENTRY(bound_range_exceeded_desc, bound_range_exceeded);
	idt[5] = bound_range_exceeded_desc;

	idt_desc_t invalid_opcode_desc = interrupt;
	SET_IDT_ENTRY(invalid_opcode_desc, invalid_opcode);
	idt[6] = invalid_opcode_desc;

	idt_desc_t device_not_available_desc = interrupt;
	SET_IDT_ENTRY(device_not_available_desc, device_not_available);
	idt[7] = device_not_available_desc;

	idt_desc_t double_fault_desc = interrupt;
	SET_IDT_ENTRY(double_fault_desc, double_fault);
	idt[8] = double_fault_desc;

	idt_desc_t coprocessor_segment_overrun_desc = interrupt;
	SET_IDT_ENTRY(coprocessor_segment_overrun_desc, coprocessor_segment_overrun);
	idt[9] = divide_error_desc;

	idt_desc_t invalid_tss_desc = interrupt;
	SET_IDT_ENTRY(invalid_tss_desc, invalid_tss);
	idt[10] = invalid_tss_desc;

	idt_desc_t segment_not_present_desc = interrupt;
	segment_not_present_desc.present = 0;
	SET_IDT_ENTRY(segment_not_present_desc, segment_not_present);
	idt[11] = segment_not_present_desc;

	idt_desc_t stack_segment_fault_desc = interrupt;
	SET_IDT_ENTRY(stack_segment_fault_desc, stack_segment_fault);
	idt[12] = stack_segment_fault_desc;

	idt_desc_t general_protection_desc = interrupt;
	SET_IDT_ENTRY(general_protection_desc, general_protection);
	idt[13] = general_protection_desc;

	idt_desc_t page_fault_desc = interrupt;
	SET_IDT_ENTRY(page_fault_desc, page_fault);
	idt[14] = page_fault_desc;

	idt_desc_t math_fault_desc = interrupt;
	SET_IDT_ENTRY(math_fault_desc, math_fault);
	idt[16] = math_fault_desc;

	idt_desc_t alignment_check_desc = interrupt;
	SET_IDT_ENTRY(alignment_check_desc, alignment_check);
	idt[17] = alignment_check_desc;

	idt_desc_t machine_check_desc = interrupt;
	SET_IDT_ENTRY(machine_check_desc, machine_check);
	idt[18] = machine_check_desc;

	idt_desc_t simd_desc = interrupt;
	SET_IDT_ENTRY(simd_desc, simd_floating_exception);
	idt[19] = simd_desc;

	idt_desc_t keyboard_desc = interrupt;
	SET_IDT_ENTRY(keyboard_desc, &keyboard_wrapper);
	idt[KEYBOARD_IDT] = keyboard_desc;

	idt_desc_t rtc_desc = interrupt;
	SET_IDT_ENTRY(rtc_desc, &rtc_wrapper);
	idt[RTC_IDT] = rtc_desc;

	idt_desc_t syscall = interrupt;
	syscall.dpl = 3;
	SET_IDT_ENTRY(syscall, &syscall_wrapper);
	idt[SYSCALL_IDT] = syscall;

	// load idt
	lidt(idt_desc_ptr);

	/* Init the PIC */
	i8259_init();

	/* Initialize devices, memory, filesystem, enable device interrupts on the
	 * PIC, any other initialization stuff... */

	// initialize rtc
	rtc_init();

	// enable irq1 for keyboard
	enable_irq(KEYBOARD_IRQ);	

	// initialize rtc, terminal, and file operation tables
	fops_init();


	/* Enable interrupts */
	/* Do not enable the following until after you have set up your
	 * IDT correctly otherwise QEMU will triple fault and simple close
	 * without showing you any output */
	printf("Enabling Interrupts\n");
	sti();

	// int freq = 32;
	// rtc_write(2, (uint8_t *) (&freq), 4);

	// while(1) {
	// 	printf("h");
	// 	rtc_read(2, (uint8_t *) (&freq), 4);
	// }
	
	clear();
	set_new_position(0, 0);

	module_t* mod = (module_t*)mbi->mods_addr;
	setup_fs(mod->mod_start);
	// char * fname = "frame0.txt";
	// uint8_t buf[187];
	// fs_read_name((uint8_t*) fname, buf, 187);

	// int i;

	// for (i = 0; i < 187; i++) {
	// 	printf("%c ", buf[i]);
	// }	

	/*uint32_t a = open_keyboard();
	uint32_t b = close_keyboard();
	printf("Keyboard Open Value: %d\n", a);
	printf("Keyboard Close Value: %d\n", b);

	
	char testbuf1[12] = {'h','e','l','l','o',' ', 'w','o','r','l','d','\n'};
	printf("write_keyboard() output: ");
	uint32_t c = write_keyboard(testbuf1, 128);
	printf("Keyboard Write Value: %d\n", c);*/
	

	// char keybuf[128];
	// read_keyboard(keybuf, 128);
	// sti();

	// int x = 3 / 0;
	// int * x = 0x12345000;
	// int y;
	// y = *x;

	/* Execute the first program (`shell') ... */
	init_terminals();
	system_execute("shell");
		
	/* Spin (nicely, so we don't chew up cycles) */
	asm volatile(".1: hlt; jmp .1;");
}
Пример #6
0
void
xics_init_IRQ( void )
{
	int i;
	unsigned long intr_size = 0;
	struct device_node *np;
	uint *ireg, ilen, indx=0;

	ibm_get_xive = rtas_token("ibm,get-xive");
	ibm_set_xive = rtas_token("ibm,set-xive");
	ibm_int_off = rtas_token("ibm,int-off");

	np = find_type_devices("PowerPC-External-Interrupt-Presentation");
	if (!np) {
		printk(KERN_WARNING "Can't find Interrupt Presentation\n");
		udbg_printf("Can't find Interrupt Presentation\n");
		while (1);
	}
nextnode:
	ireg = (uint *)get_property(np, "ibm,interrupt-server-ranges", 0);
	if (ireg) {
		/*
		 * set node starting index for this node
		 */
		indx = *ireg;
	}

	ireg = (uint *)get_property(np, "reg", &ilen);
	if (!ireg) {
		printk(KERN_WARNING "Can't find Interrupt Reg Property\n");
		udbg_printf("Can't find Interrupt Reg Property\n");
		while (1);
	}
	
	while (ilen) {
		inodes[indx].addr = (unsigned long long)*ireg++ << 32;
		ilen -= sizeof(uint);
		inodes[indx].addr |= *ireg++;
		ilen -= sizeof(uint);
		inodes[indx].size = (unsigned long long)*ireg++ << 32;
		ilen -= sizeof(uint);
		inodes[indx].size |= *ireg++;
		ilen -= sizeof(uint);
		indx++;
		if (indx >= NR_CPUS) break;
	}

	np = np->next;
	if ((indx < NR_CPUS) && np) goto nextnode;

	/* Find the server numbers for the boot cpu. */
	for (np = find_type_devices("cpu"); np; np = np->next) {
		ireg = (uint *)get_property(np, "reg", &ilen);
		if (ireg && ireg[0] == hard_smp_processor_id()) {
			ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
			i = ilen / sizeof(int);
			if (ireg && i > 0) {
				default_server = ireg[0];
				default_distrib_server = ireg[i-1]; /* take last element */
			}
			break;
		}
	}

	intr_base = inodes[0].addr;
	intr_size = (ulong)inodes[0].size;

	np = find_type_devices("interrupt-controller");
	if (!np) {
		printk(KERN_WARNING "xics:  no ISA Interrupt Controller\n");
		xics_irq_8259_cascade = -1;
	} else {
		ireg = (uint *) get_property(np, "interrupts", 0);
		if (!ireg) {
			printk(KERN_WARNING "Can't find ISA Interrupts Property\n");
			udbg_printf("Can't find ISA Interrupts Property\n");
			while (1);
		}
		xics_irq_8259_cascade_real = *ireg;
		xics_irq_8259_cascade = virt_irq_create_mapping(xics_irq_8259_cascade_real);
	}

	if (naca->platform == PLATFORM_PSERIES) {
#ifdef CONFIG_SMP
		for (i = 0; i < naca->processorCount; ++i) {
			xics_info.per_cpu[i] =
			  __ioremap((ulong)inodes[get_hard_smp_processor_id(i)].addr, 
				  (ulong)inodes[get_hard_smp_processor_id(i)].size, _PAGE_NO_CACHE);
		}
#else
		xics_info.per_cpu[0] = __ioremap((ulong)intr_base, intr_size, _PAGE_NO_CACHE);
#endif /* CONFIG_SMP */
#ifdef CONFIG_PPC_PSERIES
	/* actually iSeries does not use any of xics...but it has link dependencies
	 * for now, except this new one...
	 */
	} else if (naca->platform == PLATFORM_PSERIES_LPAR) {
		ops = &pSeriesLP_ops;
#endif
	}

	xics_8259_pic.enable = i8259_pic.enable;
	xics_8259_pic.disable = i8259_pic.disable;
	for (i = 0; i < 16; ++i)
		irq_desc[i].handler = &xics_8259_pic;
	for (; i < NR_IRQS; ++i)
		irq_desc[i].handler = &xics_pic;

	ops->cppr_info(0, 0xff);
	iosync();
	if (xics_irq_8259_cascade != -1) {
		if (request_irq(xics_irq_8259_cascade + XICS_IRQ_OFFSET, no_action,
				0, "8259 cascade", 0))
			printk(KERN_ERR "xics_init_IRQ: couldn't get 8259 cascade\n");
		i8259_init();
	}

#ifdef CONFIG_SMP
	real_irq_to_virt_map[XICS_IPI] = virt_irq_to_real_map[XICS_IPI] = XICS_IPI;
	request_irq(XICS_IPI + XICS_IRQ_OFFSET, xics_ipi_action, 0, "IPI", 0);
	irq_desc[XICS_IPI+XICS_IRQ_OFFSET].status |= IRQ_PER_CPU;
#endif
}
Пример #7
0
static
void mips_r4k_init (ram_addr_t ram_size, int vga_ram_size,
                    const char *boot_device,
                    const char *kernel_filename, const char *kernel_cmdline,
                    const char *initrd_filename, const char *cpu_model)
{
    char buf[1024];
    unsigned long bios_offset;
    int bios_size;
    CPUState *env;
    RTCState *rtc_state;
    int i;
    qemu_irq *i8259;
    int index;
    BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];

    /* init CPUs */
    if (cpu_model == NULL) {
#ifdef TARGET_MIPS64
        cpu_model = "R4000";
#else
        cpu_model = "24Kf";
#endif
    }
    env = cpu_init(cpu_model);
    if (!env) {
        fprintf(stderr, "Unable to find CPU definition\n");
        exit(1);
    }
    qemu_register_reset(main_cpu_reset, env);

    /* allocate RAM */
    if (ram_size > (256 << 20)) {
        fprintf(stderr,
                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
                ((unsigned int)ram_size / (1 << 20)));
        exit(1);
    }
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);

    if (!mips_qemu_iomemtype) {
        mips_qemu_iomemtype = cpu_register_io_memory(0, mips_qemu_read,
                                                     mips_qemu_write, NULL);
    }
    cpu_register_physical_memory(0x1fbf0000, 0x10000, mips_qemu_iomemtype);

    /* Try to load a BIOS image. If this fails, we continue regardless,
       but initialize the hardware ourselves. When a kernel gets
       preloaded we also initialize the hardware, since the BIOS wasn't
       run. */
    bios_offset = ram_size + vga_ram_size;
    if (bios_name == NULL)
        bios_name = BIOS_FILENAME;
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
    bios_size = load_image(buf, phys_ram_base + bios_offset);
    if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
	cpu_register_physical_memory(0x1fc00000,
				     BIOS_SIZE, bios_offset | IO_MEM_ROM);
    } else if ((index = drive_get_index(IF_PFLASH, 0, 0)) > -1) {
        uint32_t mips_rom = 0x00400000;
        cpu_register_physical_memory(0x1fc00000, mips_rom,
	                     qemu_ram_alloc(mips_rom) | IO_MEM_ROM);
        if (!pflash_cfi01_register(0x1fc00000, qemu_ram_alloc(mips_rom),
            drives_table[index].bdrv, sector_len, mips_rom / sector_len,
            4, 0, 0, 0, 0)) {
            fprintf(stderr, "qemu: Error registering flash memory.\n");
	}
    }
    else {
	/* not fatal */
        fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
		buf);
    }

    if (kernel_filename) {
        loaderparams.ram_size = ram_size;
        loaderparams.kernel_filename = kernel_filename;
        loaderparams.kernel_cmdline = kernel_cmdline;
        loaderparams.initrd_filename = initrd_filename;
        load_kernel (env);
    }

    /* Init CPU internal devices */
    cpu_mips_irq_init_cpu(env);
    cpu_mips_clock_init(env);

    /* The PIC is attached to the MIPS CPU INT0 pin */
    i8259 = i8259_init(env->irq[2]);

    rtc_state = rtc_init(0x70, i8259[8], 2000);

    /* Register 64 KB of ISA IO space at 0x14000000 */
    isa_mmio_init(0x14000000, 0x00010000);
    isa_mem_base = 0x10000000;

    pit = pit_init(0x40, i8259[0]);

    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
        if (serial_hds[i]) {
            serial_init(serial_io[i], i8259[serial_irq[i]], 115200,
                        serial_hds[i]);
        }
    }

    isa_vga_init(phys_ram_base + ram_size, ram_size,
                 vga_ram_size);

    if (nd_table[0].vlan)
        isa_ne2000_init(0x300, i8259[9], &nd_table[0]);

    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
        fprintf(stderr, "qemu: too many IDE bus\n");
        exit(1);
    }

    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
        index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
        if (index != -1)
            hd[i] = drives_table[index].bdrv;
        else
            hd[i] = NULL;
    }

    for(i = 0; i < MAX_IDE_BUS; i++)
        isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
                     hd[MAX_IDE_DEVS * i],
		     hd[MAX_IDE_DEVS * i + 1]);

    i8042_init(i8259[1], i8259[12], 0x60);
}
Пример #8
0
void xbox_init_common(MachineState *machine,
                      const uint8_t *eeprom,
                      PCIBus **pci_bus_out,
                      ISABus **isa_bus_out)
{
    PCMachineState *pcms = PC_MACHINE(machine);
    // PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);

    MemoryRegion *system_memory = get_system_memory();
    // MemoryRegion *system_io = get_system_io();

    int i;

    PCIBus *pci_bus;
    ISABus *isa_bus;

    qemu_irq *i8259;
    // qemu_irq smi_irq; // XBOX_TODO: SMM support?

    GSIState *gsi_state;

    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
    BusState *idebus[MAX_IDE_BUS];
    ISADevice *rtc_state;
    // ISADevice *pit;

    MemoryRegion *ram_memory;
    MemoryRegion *pci_memory;
    MemoryRegion *rom_memory;

    I2CBus *smbus;
    PCIBus *agp_bus;

    pc_cpus_init(pcms);

    pci_memory = g_new(MemoryRegion, 1);
    memory_region_init(pci_memory, NULL, "pci", UINT64_MAX);
    rom_memory = pci_memory;

    // pc_guest_info_init(pcms);

    /* allocate ram and load rom/bios */
    xbox_memory_init(pcms, system_memory, rom_memory, &ram_memory);

    gsi_state = g_malloc0(sizeof(*gsi_state));
    pcms->gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);

    xbox_pci_init(pcms->gsi,
                  get_system_memory(), get_system_io(),
                  pci_memory, ram_memory,
                  &pci_bus,
                  &isa_bus,
                  &smbus,
                  &agp_bus);

    pcms->bus = pci_bus;

    isa_bus_irqs(isa_bus, pcms->gsi);

    i8259 = i8259_init(isa_bus, pc_allocate_cpu_irq());

    for (i = 0; i < ISA_NUM_IRQS; i++) {
        gsi_state->i8259_irq[i] = i8259[i];
    }
    g_free(i8259);

    pc_register_ferr_irq(pcms->gsi[13]);

    /* init basic PC hardware */
    pcms->pit = 1; // XBOX_FIXME: What's the right way to do this?
    rtc_state = mc146818_rtc_init(isa_bus, 2000, NULL);

    // qemu_register_boot_set(pc_boot_set, rtc_state);
    ISADevice *pit = i8254_pit_init(isa_bus, 0x40, 0, NULL);

    pcspk_init(isa_bus, pit);

    ide_drive_get(hd, ARRAY_SIZE(hd));
    PCIDevice *ide_dev = pci_piix3_ide_init(pci_bus, hd, PCI_DEVFN(9, 0));
    idebus[0] = qdev_get_child_bus(&ide_dev->qdev, "ide.0");
    idebus[1] = qdev_get_child_bus(&ide_dev->qdev, "ide.1");

    // xbox bios wants this bit pattern set to mark the data as valid
    uint8_t bits = 0x55;
    for (i = 0x10; i < 0x70; i++) {
        rtc_set_memory(rtc_state, i, bits);
        bits = ~bits;
    }
    bits = 0x55;
    for (i = 0x80; i < 0x100; i++) {
        rtc_set_memory(rtc_state, i, bits);
        bits = ~bits;
    }

    /* smbus devices */
    uint8_t *eeprom_buf = g_malloc0(256);
    memcpy(eeprom_buf, eeprom, 256);
    smbus_eeprom_init_one(smbus, 0x54, eeprom_buf);

    smbus_xbox_smc_init(smbus, 0x10);
    smbus_cx25871_init(smbus, 0x45);
    smbus_adm1032_init(smbus, 0x4c);

    /* USB */
    PCIDevice *usb1 = pci_create(pci_bus, PCI_DEVFN(3, 0), "pci-ohci");
    qdev_prop_set_uint32(&usb1->qdev, "num-ports", 4);
    qdev_init_nofail(&usb1->qdev);

    PCIDevice *usb0 = pci_create(pci_bus, PCI_DEVFN(2, 0), "pci-ohci");
    qdev_prop_set_uint32(&usb0->qdev, "num-ports", 4);
    qdev_init_nofail(&usb0->qdev);

    /* Ethernet! */
    PCIDevice *nvnet = pci_create(pci_bus, PCI_DEVFN(4, 0), "nvnet");

    for (i = 0; i < nb_nics; i++) {
        NICInfo *nd = &nd_table[i];
        qemu_check_nic_model(nd, "nvnet");
        qdev_set_nic_properties(&nvnet->qdev, nd);
        qdev_init_nofail(&nvnet->qdev);
    }

    /* APU! */
    mcpx_apu_init(pci_bus, PCI_DEVFN(5, 0), ram_memory);

    /* ACI! */
    pci_create_simple(pci_bus, PCI_DEVFN(6, 0), "mcpx-aci");

    /* GPU! */
    nv2a_init(agp_bus, PCI_DEVFN(0, 0), ram_memory);

    if (pci_bus_out) {
        *pci_bus_out = pci_bus;
    }
    if (isa_bus_out) {
        *isa_bus_out = isa_bus;
    }
}
Пример #9
0
static
void mips_r4k_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)
{
    char *filename;
    ram_addr_t ram_offset;
    ram_addr_t bios_offset;
    int bios_size;
    CPUState *env;
    ResetData *reset_info;
    ISADevice *rtc_state;
    int i;
    qemu_irq *i8259;
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
    DriveInfo *dinfo;
    int be;

    /* init CPUs */
    if (cpu_model == NULL) {
#ifdef TARGET_MIPS64
        cpu_model = "R4000";
#else
        cpu_model = "24Kf";
#endif
    }
    env = cpu_init(cpu_model);
    if (!env) {
        fprintf(stderr, "Unable to find CPU definition\n");
        exit(1);
    }
    reset_info = qemu_mallocz(sizeof(ResetData));
    reset_info->env = env;
    reset_info->vector = env->active_tc.PC;
    qemu_register_reset(main_cpu_reset, reset_info);

    /* allocate RAM */
    if (ram_size > (256 << 20)) {
        fprintf(stderr,
                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
                ((unsigned int)ram_size / (1 << 20)));
        exit(1);
    }
    ram_offset = qemu_ram_alloc(ram_size);

    cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);

    if (!mips_qemu_iomemtype) {
        mips_qemu_iomemtype = cpu_register_io_memory(mips_qemu_read,
                                                     mips_qemu_write, NULL);
    }
    cpu_register_physical_memory(0x1fbf0000, 0x10000, mips_qemu_iomemtype);

    /* Try to load a BIOS image. If this fails, we continue regardless,
       but initialize the hardware ourselves. When a kernel gets
       preloaded we also initialize the hardware, since the BIOS wasn't
       run. */
    if (bios_name == NULL)
        bios_name = BIOS_FILENAME;
    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
    if (filename) {
        bios_size = get_image_size(filename);
    } else {
        bios_size = -1;
    }
#ifdef TARGET_WORDS_BIGENDIAN
    be = 1;
#else
    be = 0;
#endif
    if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
        bios_offset = qemu_ram_alloc(BIOS_SIZE);
	cpu_register_physical_memory(0x1fc00000, BIOS_SIZE,
                                     bios_offset | IO_MEM_ROM);

        load_image_targphys(filename, 0x1fc00000, BIOS_SIZE);
    } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
        uint32_t mips_rom = 0x00400000;
        bios_offset = qemu_ram_alloc(mips_rom);
        if (!pflash_cfi01_register(0x1fc00000, bios_offset,
                                   dinfo->bdrv, sector_len,
                                   mips_rom / sector_len,
                                   4, 0, 0, 0, 0, be)) {
            fprintf(stderr, "qemu: Error registering flash memory.\n");
	}
    }
    else {
	/* not fatal */
        fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
		bios_name);
    }
    if (filename) {
        qemu_free(filename);
    }

    if (kernel_filename) {
        loaderparams.ram_size = ram_size;
        loaderparams.kernel_filename = kernel_filename;
        loaderparams.kernel_cmdline = kernel_cmdline;
        loaderparams.initrd_filename = initrd_filename;
        reset_info->vector = load_kernel();
    }

    /* Init CPU internal devices */
    cpu_mips_irq_init_cpu(env);
    cpu_mips_clock_init(env);

    /* The PIC is attached to the MIPS CPU INT0 pin */
    i8259 = i8259_init(env->irq[2]);
    isa_bus_new(NULL);
    isa_bus_irqs(i8259);

    rtc_state = rtc_init(2000);

    /* Register 64 KB of ISA IO space at 0x14000000 */
#ifdef TARGET_WORDS_BIGENDIAN
    isa_mmio_init(0x14000000, 0x00010000, 1);
#else
    isa_mmio_init(0x14000000, 0x00010000, 0);
#endif
    isa_mem_base = 0x10000000;

    pit = pit_init(0x40, i8259[0]);

    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
        if (serial_hds[i]) {
            serial_isa_init(i, serial_hds[i]);
        }
    }

    isa_vga_init();

    if (nd_table[0].vlan)
        isa_ne2000_init(0x300, 9, &nd_table[0]);

    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
        fprintf(stderr, "qemu: too many IDE bus\n");
        exit(1);
    }

    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
    }

    for(i = 0; i < MAX_IDE_BUS; i++)
        isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
                     hd[MAX_IDE_DEVS * i],
		     hd[MAX_IDE_DEVS * i + 1]);

    isa_create_simple("i8042");
}
Пример #10
0
/* Check if MAGIC is valid and print the Multiboot information structure
   pointed by ADDR. */
void
entry (unsigned long magic, unsigned long addr)
{
	uint32_t file_system_start;
	multiboot_info_t *mbi;

	/* Clear the screen. */
	clear();

	/* Am I booted by a Multiboot-compliant boot loader? */
	if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
	{
		printf ("Invalid magic number: 0x%#x\n", (unsigned) magic);
		return;
	}

	/* Set MBI to the address of the Multiboot information structure. */
	mbi = (multiboot_info_t *) addr;

	/* Print out the flags. */
	printf ("flags = 0x%#x\n", (unsigned) mbi->flags);

	/* Are mem_* valid? */
	if (CHECK_FLAG (mbi->flags, 0))
		printf ("mem_lower = %uKB, mem_upper = %uKB\n",
				(unsigned) mbi->mem_lower, (unsigned) mbi->mem_upper);

	/* Is boot_device valid? */
	if (CHECK_FLAG (mbi->flags, 1))
		printf ("boot_device = 0x%#x\n", (unsigned) mbi->boot_device);

	/* Is the command line passed? */
	if (CHECK_FLAG (mbi->flags, 2))
		printf ("cmdline = %s\n", (char *) mbi->cmdline);

	if (CHECK_FLAG (mbi->flags, 3)) {
		int mod_count = 0;
		int i;
		module_t* mod = (module_t*)mbi->mods_addr;

		file_system_start = mod->mod_start;  // store mod_start as start address of file system
		
		while(mod_count < mbi->mods_count) {
			printf("Module %d loaded at address: 0x%#x\n", mod_count, (unsigned int)mod->mod_start);
			printf("Module %d ends at address: 0x%#x\n", mod_count, (unsigned int)mod->mod_end);
			printf("First few bytes of module:\n");
			for(i = 0; i<16; i++) {
				printf("0x%x ", *((char*)(mod->mod_start+i)));
			}
			printf("\n");
			mod_count++;
			mod++;
		}
	}
	/* Bits 4 and 5 are mutually exclusive! */
	if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG (mbi->flags, 5))
	{
		printf ("Both bits 4 and 5 are set.\n");
		return;
	}

	/* Is the section header table of ELF valid? */
	if (CHECK_FLAG (mbi->flags, 5))
	{
		elf_section_header_table_t *elf_sec = &(mbi->elf_sec);

		printf ("elf_sec: num = %u, size = 0x%#x,"
				" addr = 0x%#x, shndx = 0x%#x\n",
				(unsigned) elf_sec->num, (unsigned) elf_sec->size,
				(unsigned) elf_sec->addr, (unsigned) elf_sec->shndx);
	}

	/* Are mmap_* valid? */
	if (CHECK_FLAG (mbi->flags, 6))
	{
		memory_map_t *mmap;

		printf ("mmap_addr = 0x%#x, mmap_length = 0x%x\n",
				(unsigned) mbi->mmap_addr, (unsigned) mbi->mmap_length);
		for (mmap = (memory_map_t *) mbi->mmap_addr;
				(unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length;
				mmap = (memory_map_t *) ((unsigned long) mmap
					+ mmap->size + sizeof (mmap->size)))
			printf (" size = 0x%x,     base_addr = 0x%#x%#x\n"
					"     type = 0x%x,  length    = 0x%#x%#x\n",
					(unsigned) mmap->size,
					(unsigned) mmap->base_addr_high,
					(unsigned) mmap->base_addr_low,
					(unsigned) mmap->type,
					(unsigned) mmap->length_high,
					(unsigned) mmap->length_low);
	}

	/* Construct an LDT entry in the GDT */
	{
		seg_desc_t the_ldt_desc;
		the_ldt_desc.granularity    = 0;
		the_ldt_desc.opsize         = 1;
		the_ldt_desc.reserved       = 0;
		the_ldt_desc.avail          = 0;
		the_ldt_desc.present        = 1;
		the_ldt_desc.dpl            = 0x0;
		the_ldt_desc.sys            = 0;
		the_ldt_desc.type           = 0x2;

		SET_LDT_PARAMS(the_ldt_desc, &ldt, ldt_size);
		ldt_desc_ptr = the_ldt_desc;
		lldt(KERNEL_LDT);
	}

	/* Construct a TSS entry in the GDT */
	{
		seg_desc_t the_tss_desc;
		the_tss_desc.granularity    = 0;
		the_tss_desc.opsize         = 0;
		the_tss_desc.reserved       = 0;
		the_tss_desc.avail          = 0;
		the_tss_desc.seg_lim_19_16  = TSS_SIZE & 0x000F0000;
		the_tss_desc.present        = 1;
		the_tss_desc.dpl            = 0x0;
		the_tss_desc.sys            = 0;
		the_tss_desc.type           = 0x9;
		the_tss_desc.seg_lim_15_00  = TSS_SIZE & 0x0000FFFF;

		SET_TSS_PARAMS(the_tss_desc, &tss, tss_size);

		tss_desc_ptr = the_tss_desc;

		tss.ldt_segment_selector = KERNEL_LDT;
		tss.ss0 = KERNEL_DS;
		tss.esp0 = 0x800000 - 4;
		ltr(KERNEL_TSS);
	}

///////////////////////////////

	/* Initialize first 20 IDT entries for exceptions */
	/* Initialize interrupt descriptor entries defined in x86_desc.h*/
	int i;
	for (i=0; i<EXCEPTION_NUM; i++)
	{

		idt[i].seg_selector = KERNEL_CS;    // set up elements in the exception entry
		idt[i].reserved4 = 0;			
		idt[i].reserved3 = 0;		
		idt[i].reserved2 = 1;
		idt[i].reserved1 = 1;
		idt[i].size = 1;
		idt[i].reserved0 = 0;
		idt[i].dpl = 0;          
		idt[i].present = 1;

		SET_IDT_ENTRY(idt[i], reserved);
	}

	// /* set 20 idt entries for exceptions */
    init_exception();

	// set idt entry for RTC
	{ 
		idt[RTC_ENTRY].seg_selector = KERNEL_CS;   // set up elements in the RTC entry
		idt[RTC_ENTRY].reserved4 = 0;			
		idt[RTC_ENTRY].reserved3 = 0;		
		idt[RTC_ENTRY].reserved2 = 1;
		idt[RTC_ENTRY].reserved1 = 1;
		idt[RTC_ENTRY].size = 1;
		idt[RTC_ENTRY].reserved0 = 0;
		idt[RTC_ENTRY].dpl = 0;          
		idt[RTC_ENTRY].present = 1;

		SET_IDT_ENTRY(idt[RTC_ENTRY], rtc_wrapper);   // set idt entry for RTC
	}

	// set idt entry for keyboard
	{
		idt[KEYBRD_ENTRY].seg_selector = KERNEL_CS;   // set up elements in the keyboard entry
		idt[KEYBRD_ENTRY].reserved4 = 0;			
		idt[KEYBRD_ENTRY].reserved3 = 0;		
		idt[KEYBRD_ENTRY].reserved2 = 1;
		idt[KEYBRD_ENTRY].reserved1 = 1;
		idt[KEYBRD_ENTRY].size = 1;
		idt[KEYBRD_ENTRY].reserved0 = 0;
		idt[KEYBRD_ENTRY].dpl = 0;          
		idt[KEYBRD_ENTRY].present = 1;

		SET_IDT_ENTRY(idt[KEYBRD_ENTRY], keybrd_wrapper);   // set idt entry for keyboard

	} 

	//set idt entry for system call
	{
		idt[SYSCALL_ENTRY].seg_selector = KERNEL_CS;		
		idt[SYSCALL_ENTRY].reserved4 = 0;
		idt[SYSCALL_ENTRY].reserved3 = 0;
		idt[SYSCALL_ENTRY].reserved2 = 1;		
		idt[SYSCALL_ENTRY].reserved1 = 1;
		idt[SYSCALL_ENTRY].size = 1;
		idt[SYSCALL_ENTRY].reserved0 = 0;
		idt[SYSCALL_ENTRY].dpl = 3;
		idt[SYSCALL_ENTRY].present = 1;
		SET_IDT_ENTRY(idt[SYSCALL_ENTRY], syscall_wrapper);
	}
	
	{
		idt[MOUSE_VECTOR].seg_selector = KERNEL_CS;		
		idt[MOUSE_VECTOR].reserved4 = 0;
		idt[MOUSE_VECTOR].reserved3 = 0;
		idt[MOUSE_VECTOR].reserved2 = 1;		
		idt[MOUSE_VECTOR].reserved1 = 1;
		idt[MOUSE_VECTOR].size = 1;
		idt[MOUSE_VECTOR].reserved0 = 0;
		idt[MOUSE_VECTOR].dpl = 0;
		idt[MOUSE_VECTOR].present = 1;
		SET_IDT_ENTRY(idt[MOUSE_VECTOR], mouse_linkage);      
	}

	// set idt entry for pit
	{
		idt[PIT_ENTRY].seg_selector = KERNEL_CS;		
		idt[PIT_ENTRY].reserved4 = 0;
		idt[PIT_ENTRY].reserved3 = 0;
		idt[PIT_ENTRY].reserved2 = 1;		
		idt[PIT_ENTRY].reserved1 = 1;
		idt[PIT_ENTRY].size = 1;
		idt[PIT_ENTRY].reserved0 = 0;
		idt[PIT_ENTRY].dpl = 3;
		idt[PIT_ENTRY].present = 1;
		SET_IDT_ENTRY(idt[PIT_ENTRY], pit_wrapper);
	}




/////////////////////////////////

	// keyboard_handler(); 

	 //	test divide_error
	
	 // i=1/0;  

	// initialize devices
	// enable associated interrupts on PIC
	
	/* devices initialization ends*/	

	/* Initialize devices, memory, filesystem, enable device interrupts on the
	 * PIC, any other initialization stuff... */

	/* Enable interrupts */
	/* Do not enable the following until after you have set up your
	 * IDT correctly otherwise QEMU will triple fault and simple close
	 * without showing you any output */

	 i8259_init();   /* Init the PIC */ 

     // printf("Enabling Interrupts\n");


	 paging_init();    // set up paging

	 //testing purpose of paging
	 // uint8_t * test_ptr = 0x000B8000;
	 // * test_ptr = 1;
	 // // uint8_t * test_ptr = 0xB6000;
	 // *test_ptr = 1;

	 // printf("paging works!!\n");

	 // clear();   
	 sche_init();
	 pit_init();
	 rtc_init();     // init rtc  
	 keybrd_init();
	 init_mouse();

	 fs_init(file_system_start);   // init file system, test case: test_fs_init() is commented in the fs_init function
	 //sche_init();
	 for(i = 0; i < 30; i++){
		pid_status[i] = 0;
	 }
	 pid = -1;




   // enable interrupts on processor
	 /*****test cases*****/

	 // uint8_t* filename;
	 /*test rtc open*/
	 // rtc_open(filename);

	 /*test rtc write*/
	 // int32_t fd;
	 // uint8_t* buf;
	 // rtc_write(fd, buf, 2);

	 // // /*test rtc read*/ 
	 // while(1){
	 // 	rtc_read(fd, buf, 16);
	 // 	printf("rtc_read\n");
	 // }


	  //test_dir_read();
	  // read_test_text();  // read file depends on the READ_TEXT and READ_TXT flag on the top of file_system_driver.c 
	 //read_test_exe();
	 /*****test cases*****/


	//puts("here",1);
	 enable_irq(8);  //enable rtc interrupt 
	 enable_irq(1);  //enable keyboard interrupt
	 enable_irq(0);
	 sti();

	 //while(1){
		/*
		printf("here\n");
		dentry_t tmp_dentry;
		uint32_t tmp_eip, user_esp;
		uint8_t buf[4];
		read_dentry_by_name((uint8_t*)"testprint", &tmp_dentry);
		read_data(tmp_dentry.inode_num, 0, (uint8_t*)(0x08048000), 0x400000);	
		read_data(tmp_dentry.inode_num, 24, buf, 4);
		printf("here2\n");
		tmp_eip = 0x080481a4;	
		user_esp = 0x8000000 + 0x400000 - 4; //user space stack = 132MB - 4B
		
		tss.esp0 =0x800000-4;	//kernel stack = 128MB - 4B
		tss.ss0 = KERNEL_DS;
		asm volatile ("							\n\
				 cli 						\n\
				 movw %0, %%ax				\n\
				 movw %%ax, %%ds 			\n\
    			 pushl %0 					\n\
    			 pushl %1 					\n\
				 pushfl						\n\
				 popl %%eax 				\n\
    			 orl %2, %%eax 				\n\
    			 pushl %%eax 				\n\
    			 pushl %3 					\n\
    			 pushl %4 					\n\
				 iret 						\n\
    			 "
    			 :
    			 :"i"(USER_DS), "r"(user_esp), "r"(0x200), "i"(USER_CS), "r"(tmp_eip)
    			 :"eax", "memory"
    			 );
		*/
	 //}
	execute((uint8_t *) "shell");
	while(1){
		
	}


	/* Spin (nicely, so we don't chew up cycles) */


	// uint8_t test_read_buffer[TEST_READ_BUFFER_SIZE];										//initialize buffer for testing terminal_read
	// uint8_t test_write_buffer[TEST_WRITE_BUFFER_SIZE] = "teststringforwritefunction\n";     //initialize buffer for testing terminal_write
	// while(1){
	// 	memset(test_read_buffer, 0, TEST_READ_BUFFER_SIZE);
	// 	printf("Number of bytes read: %d\n", terminal_read(0, test_read_buffer, TEST_READ_BUFFER_SIZE-1));		//testing terminal_read
	// 	terminal_write(1, test_read_buffer, TEST_READ_BUFFER_SIZE);										//testing terminal _write
	// 	terminal_write(1, test_write_buffer, TEST_WRITE_BUFFER_SIZE);			
	// }

	asm volatile(".1: hlt; jmp .1;");
}
Пример #11
0
/* PC hardware initialisation */
static void pc_init1(MemoryRegion *system_memory,
                     MemoryRegion *system_io,
                     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,
                     int pci_enabled,
                     int kvmclock_enabled)
{
    int i;
    ram_addr_t below_4g_mem_size, above_4g_mem_size;
    PCIBus *pci_bus;
    PCII440FXState *i440fx_state;
    int piix3_devfn = -1;
    qemu_irq *cpu_irq;
    qemu_irq *gsi;
    qemu_irq *i8259;
    qemu_irq *cmos_s3;
    qemu_irq *smi_irq;
    GSIState *gsi_state;
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
    BusState *idebus[MAX_IDE_BUS];
    ISADevice *rtc_state;
    ISADevice *floppy;
    MemoryRegion *ram_memory;
    MemoryRegion *pci_memory;
    MemoryRegion *rom_memory;

    pc_cpus_init(cpu_model);

    if (kvmclock_enabled) {
        kvmclock_create();
    }

    if (ram_size >= 0xe0000000 ) {
        above_4g_mem_size = ram_size - 0xe0000000;
        below_4g_mem_size = 0xe0000000;
    } else {
        above_4g_mem_size = 0;
        below_4g_mem_size = ram_size;
    }

    if (pci_enabled) {
        pci_memory = g_new(MemoryRegion, 1);
        memory_region_init(pci_memory, "pci", INT64_MAX);
        rom_memory = pci_memory;
    } else {
        pci_memory = NULL;
        rom_memory = system_memory;
    }

    /* allocate ram and load rom/bios */
    if (!xen_enabled()) {
        pc_memory_init(system_memory,
                       kernel_filename, kernel_cmdline, initrd_filename,
                       below_4g_mem_size, above_4g_mem_size,
                       pci_enabled ? rom_memory : system_memory, &ram_memory);
    }

    gsi_state = g_malloc0(sizeof(*gsi_state));
    gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);

    if (pci_enabled) {
        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, gsi,
                              system_memory, system_io, ram_size,
                              below_4g_mem_size,
                              0x100000000ULL - below_4g_mem_size,
                              0x100000000ULL + above_4g_mem_size,
                              (sizeof(target_phys_addr_t) == 4
                               ? 0
                               : ((uint64_t)1 << 62)),
                              pci_memory, ram_memory);
    } else {
        pci_bus = NULL;
        i440fx_state = NULL;
        isa_bus_new(NULL, system_io);
        no_hpet = 1;
    }
    isa_bus_irqs(gsi);

    if (!xen_enabled()) {
        cpu_irq = pc_allocate_cpu_irq();
        i8259 = i8259_init(cpu_irq[0]);
    } else {
        i8259 = xen_interrupt_controller_init();
    }

    for (i = 0; i < ISA_NUM_IRQS; i++) {
        gsi_state->i8259_irq[i] = i8259[i];
    }
    if (pci_enabled) {
        ioapic_init(gsi_state);
    }

    pc_register_ferr_irq(gsi[13]);

    pc_vga_init(pci_enabled? pci_bus: NULL);

    if (xen_enabled()) {
        pci_create_simple(pci_bus, -1, "xen-platform");
    }

    /* init basic PC hardware */
    pc_basic_device_init(gsi, &rtc_state, &floppy, xen_enabled());

    for(i = 0; i < nb_nics; i++) {
        NICInfo *nd = &nd_table[i];

        if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
            pc_init_ne2k_isa(nd);
        else
            pci_nic_init_nofail(nd, "e1000", NULL);
    }

    ide_drive_get(hd, MAX_IDE_BUS);
    if (pci_enabled) {
        PCIDevice *dev;
        if (xen_enabled()) {
            dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1);
        } else {
            dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
        }
        idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
        idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
    } else {
        for(i = 0; i < MAX_IDE_BUS; i++) {
            ISADevice *dev;
            dev = isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
                               hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
            idebus[i] = qdev_get_child_bus(&dev->qdev, "ide.0");
        }
    }

    audio_init(gsi, pci_enabled ? pci_bus : NULL);

    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
                 floppy, idebus[0], idebus[1], rtc_state);

    if (pci_enabled && usb_enabled) {
        usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
    }

    if (pci_enabled && acpi_enabled) {
        i2c_bus *smbus;

        if (!xen_enabled()) {
            cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1);
        } else {
            cmos_s3 = qemu_allocate_irqs(xen_cmos_set_s3_resume, rtc_state, 1);
        }
        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
        /* TODO: Populate SPD eeprom data.  */
        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
                              gsi[9], *cmos_s3, *smi_irq,
                              kvm_enabled());
        smbus_eeprom_init(smbus, 8, NULL, 0);
    }

    if (pci_enabled) {
        pc_pci_device_init(pci_bus);
    }
}
Пример #12
0
void pic_init() {
    i8259_init();
}
Пример #13
0
/* Check if MAGIC is valid and print the Multiboot information structure
   pointed by ADDR. */
void
entry (unsigned long magic, unsigned long addr)
{
	multiboot_info_t *mbi;

	/* Clear the screen. */
	clear();

	/* Am I booted by a Multiboot-compliant boot loader? */
	if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
	{
		printf ("Invalid magic number: 0x%#x\n", (unsigned) magic);
		return;
	}

	/* Set MBI to the address of the Multiboot information structure. */
	mbi = (multiboot_info_t *) addr;

	/* Print out the flags. */
	printf ("flags = 0x%#x\n", (unsigned) mbi->flags);

	/* Are mem_* valid? */
	if (CHECK_FLAG (mbi->flags, 0))
		printf ("mem_lower = %uKB, mem_upper = %uKB\n",
				(unsigned) mbi->mem_lower, (unsigned) mbi->mem_upper);

	/* Is boot_device valid? */
	if (CHECK_FLAG (mbi->flags, 1))
		printf ("boot_device = 0x%#x\n", (unsigned) mbi->boot_device);

	/* Is the command line passed? */
	if (CHECK_FLAG (mbi->flags, 2))
		printf ("cmdline = %s\n", (char *) mbi->cmdline);

	if (CHECK_FLAG (mbi->flags, 3)) {
		int mod_count = 0;
		int i;
		module_t* mod = (module_t*)mbi->mods_addr;
		while(mod_count < mbi->mods_count) {
			printf("Module %d loaded at address: 0x%#x\n", mod_count, (unsigned int)mod->mod_start);
			printf("Module %d ends at address: 0x%#x\n", mod_count, (unsigned int)mod->mod_end);
			printf("First few bytes of module:\n");
			for(i = 0; i<16; i++) {
				printf("0x%x ", *((char*)(mod->mod_start+i)));
			}
			printf("\n");
			mod_count++;
			mod++;
		}
	}
	/* Bits 4 and 5 are mutually exclusive! */
	if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG (mbi->flags, 5))
	{
		printf ("Both bits 4 and 5 are set.\n");
		return;
	}

	/* Is the section header table of ELF valid? */
	if (CHECK_FLAG (mbi->flags, 5))
	{
		elf_section_header_table_t *elf_sec = &(mbi->elf_sec);

		printf ("elf_sec: num = %u, size = 0x%#x,"
				" addr = 0x%#x, shndx = 0x%#x\n",
				(unsigned) elf_sec->num, (unsigned) elf_sec->size,
				(unsigned) elf_sec->addr, (unsigned) elf_sec->shndx);
	}

	/* Are mmap_* valid? */
	if (CHECK_FLAG (mbi->flags, 6))
	{
		memory_map_t *mmap;

		printf ("mmap_addr = 0x%#x, mmap_length = 0x%x\n",
				(unsigned) mbi->mmap_addr, (unsigned) mbi->mmap_length);
		for (mmap = (memory_map_t *) mbi->mmap_addr;
				(unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length;
				mmap = (memory_map_t *) ((unsigned long) mmap
					+ mmap->size + sizeof (mmap->size)))
			printf (" size = 0x%x,     base_addr = 0x%#x%#x\n"
					"     type = 0x%x,  length    = 0x%#x%#x\n",
					(unsigned) mmap->size,
					(unsigned) mmap->base_addr_high,
					(unsigned) mmap->base_addr_low,
					(unsigned) mmap->type,
					(unsigned) mmap->length_high,
					(unsigned) mmap->length_low);
	}

	/* Construct an LDT entry in the GDT */
	{
		seg_desc_t the_ldt_desc;
		the_ldt_desc.granularity    = 0;
		the_ldt_desc.opsize         = 1;
		the_ldt_desc.reserved       = 0;
		the_ldt_desc.avail          = 0;
		the_ldt_desc.present        = 1;
		the_ldt_desc.dpl            = 0x0;
		the_ldt_desc.sys            = 0;
		the_ldt_desc.type           = 0x2;

		SET_LDT_PARAMS(the_ldt_desc, &ldt, ldt_size);
		ldt_desc_ptr = the_ldt_desc;
		lldt(KERNEL_LDT);
	}

	/* Construct a TSS entry in the GDT */
	{
		seg_desc_t the_tss_desc;
		the_tss_desc.granularity    = 0;
		the_tss_desc.opsize         = 0;
		the_tss_desc.reserved       = 0;
		the_tss_desc.avail          = 0;
		the_tss_desc.seg_lim_19_16  = TSS_SIZE & 0x000F0000;
		the_tss_desc.present        = 1;
		the_tss_desc.dpl            = 0x0;
		the_tss_desc.sys            = 0;
		the_tss_desc.type           = 0x9;
		the_tss_desc.seg_lim_15_00  = TSS_SIZE & 0x0000FFFF;

		SET_TSS_PARAMS(the_tss_desc, &tss, tss_size);

		tss_desc_ptr = the_tss_desc;

		tss.ldt_segment_selector = KERNEL_LDT;
		tss.ss0 = KERNEL_DS;
		tss.esp0 = 0x800000;
		ltr(KERNEL_TSS);
	}

	fill_idt();
	lidt(idt_desc_ptr);	// Load IDT Pointer
	//Init the PIC
	i8259_init();
	pit_init();
	init_keyboard();
	rtc_init();
	terminal_open((uint8_t*)1);
	init_paging();


	/* initializing file systems */
	module_t * boot_fs = (module_t*)mbi->mods_addr;
	init_fs(boot_fs->mod_start);
	/* Done initializing fs */


	/* Initialize devices, memory, filesystem, enable device interrupts on the
	 * PIC, any other initialization stuff... */

	/* Enable interrupts */
	// printf("Enabling Interrupts\n");
	sti();

	// uint32_t bmap_val = 10;
	// char bitmap_temp[6];
    // itoa(bmap_val , bitmap_temp, 2);
    // // printf("BMAP VALUE - %d\n", bmap_val);
	// printf("%s\n", bitmap_temp);
    // char bitmap[6];
    // uint32_t l = strlen((uint8_t*)bitmap_temp);
    // uint32_t temp_idx;
    // for (temp_idx=0; temp_idx<5; temp_idx++){
    //     if (temp_idx<(5-l))
    //         bitmap[temp_idx] = '0';
    //     else
    //         bitmap[temp_idx] = bitmap_temp[temp_idx+l-5];
    // }
    // bitmap[5] = '\0';
    // printf("%s\n", bitmap);

	// Initialization for the process
	init_terminals();
	execute_func((uint8_t *)"shell");


	// Spin (nicely, so we don't chew up cycles)
	asm volatile(".1: hlt; jmp .1;");
}
Пример #14
0
static
void mips_pica61_init (int ram_size, int vga_ram_size, int boot_device,
                    DisplayState *ds, const char **fd_filename, int snapshot,
                    const char *kernel_filename, const char *kernel_cmdline,
                    const char *initrd_filename, const char *cpu_model)
{
    char buf[1024];
    unsigned long bios_offset;
    int bios_size;
    CPUState *env;
    int i;
    mips_def_t *def;
    int available_ram;
    qemu_irq *i8259;

    /* init CPUs */
    if (cpu_model == NULL) {
#ifdef TARGET_MIPS64
        cpu_model = "R4000";
#else
        /* FIXME: All wrong, this maybe should be R3000 for the older PICAs. */
        cpu_model = "24Kf";
#endif
    }
    if (mips_find_by_name(cpu_model, &def) != 0)
        def = NULL;
    env = cpu_init();
    cpu_mips_register(env, def);
    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
    qemu_register_reset(main_cpu_reset, env);

    /* allocate RAM (limited to 256 MB) */
    if (ram_size < 256 * 1024 * 1024)
        available_ram = ram_size;
    else
        available_ram = 256 * 1024 * 1024;
    cpu_register_physical_memory(0, available_ram, IO_MEM_RAM);

    /* load a BIOS image */
    bios_offset = ram_size + vga_ram_size;
    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
    bios_size = load_image(buf, phys_ram_base + bios_offset);
    if ((bios_size <= 0) || (bios_size > BIOS_SIZE)) {
        /* fatal */
        fprintf(stderr, "qemu: Error, could not load MIPS bios '%s'\n",
                buf);
        exit(1);
    }
    cpu_register_physical_memory(0x1fc00000,
                                     BIOS_SIZE, bios_offset | IO_MEM_ROM);

    /* Device map
     *
     * addr 0xe0004000: mc146818
     * addr 0xe0005000 intr 6: ps2 keyboard
     * addr 0xe0005000 intr 7: ps2 mouse
     * addr 0xe0006000 intr 8: ns16550a,
     * addr 0xe0007000 intr 9: ns16550a
     * isa_io_base 0xe2000000 isa_mem_base 0xe3000000
     */

    /* Init CPU internal devices */
    cpu_mips_irq_init_cpu(env);
    cpu_mips_clock_init(env);
    cpu_mips_irqctrl_init();

    /* Register 64 KB of ISA IO space at 0x10000000 */
    isa_mmio_init(0x10000000, 0x00010000);
    isa_mem_base = 0x11000000;

    /* PC style IRQ (i8259/i8254) and DMA (i8257) */
    /* The PIC is attached to the MIPS CPU INT0 pin */
    i8259 = i8259_init(env->irq[2]);
    rtc_mm_init(0x80004070, 1, i8259[14]);
    pit_init(0x40, 0);

    /* Keyboard (i8042) */
    i8042_mm_init(i8259[6], i8259[7], 0x80005060, 0);

    /* IDE controller */
    for(i = 0; i < 2; i++)
        isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
                     bs_table[2 * i], bs_table[2 * i + 1]);

    /* Network controller */
    /* FIXME: missing NS SONIC DP83932 */

    /* SCSI adapter */
    /* FIXME: missing NCR 53C94 */

    /* ISA devices (floppy, serial, parallel) */
    fdctrl_init(i8259[1], 1, 1, 0x80003000, fd_table);
    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
        if (serial_hds[i]) {
            serial_mm_init(serial_base[i], 0, i8259[serial_irq[i]], serial_hds[i], 1);
        }
    }
    /* Parallel port */
    if (parallel_hds[0]) parallel_mm_init(0x80008000, 0, i8259[1], parallel_hds[0]);

    /* Sound card */
    /* FIXME: missing Jazz sound, IRQ 18 */

    /* LED indicator */
    /* FIXME: missing LED indicator */

    /* NVRAM */
    ds1225y_init(0x80009000, "nvram");

    /* Video card */
    /* FIXME: This card is not the real one which was in the original PICA,
     * but let's do with what Qemu currenly emulates... */
    isa_vga_mm_init(ds, phys_ram_base + ram_size, ram_size, vga_ram_size,
                    0x40000000, 0x60000000, 0);
}
Пример #15
0
PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
                     qemu_irq *p_rtc_irq,
                     CPUState *cpus[4], pci_map_irq_fn sys_map_irq)
{
    const uint64_t MB = 1024 * 1024;
    const uint64_t GB = 1024 * MB;
    MemoryRegion *addr_space = get_system_memory();
    MemoryRegion *addr_space_io = get_system_io();
    DeviceState *dev;
    PCIHostState *p;
    TyphoonState *s;
    PCIBus *b;
    int i;

    dev = qdev_create(NULL, "typhoon-pcihost");
    qdev_init_nofail(dev);

    p = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
    s = container_of(p, TyphoonState, host);

    /* Remember the CPUs so that we can deliver interrupts to them.  */
    for (i = 0; i < 4; i++) {
        CPUState *env = cpus[i];
        s->cchip.cpu[i] = env;
        if (env) {
            env->alarm_timer = qemu_new_timer_ns(rtc_clock,
                                                 typhoon_alarm_timer,
                                                 (void *)((uintptr_t)s + i));
        }
    }

    *p_rtc_irq = *qemu_allocate_irqs(typhoon_set_timer_irq, s, 1);

    /* Main memory region, 0x00.0000.0000.  Real hardware supports 32GB,
       but the address space hole reserved at this point is 8TB.  */
    memory_region_init_ram(&s->ram_region, "ram", ram_size);
    vmstate_register_ram_global(&s->ram_region);
    memory_region_add_subregion(addr_space, 0, &s->ram_region);

    /* TIGbus, 0x801.0000.0000, 1GB.  */
    /* ??? The TIGbus is used for delivering interrupts, and access to
       the flash ROM.  I'm not sure that we need to implement it at all.  */

    /* Pchip0 CSRs, 0x801.8000.0000, 256MB.  */
    memory_region_init_io(&s->pchip.region, &pchip_ops, s, "pchip0", 256*MB);
    memory_region_add_subregion(addr_space, 0x80180000000ULL,
                                &s->pchip.region);

    /* Cchip CSRs, 0x801.A000.0000, 256MB.  */
    memory_region_init_io(&s->cchip.region, &cchip_ops, s, "cchip0", 256*MB);
    memory_region_add_subregion(addr_space, 0x801a0000000ULL,
                                &s->cchip.region);

    /* Dchip CSRs, 0x801.B000.0000, 256MB.  */
    memory_region_init_io(&s->dchip_region, &dchip_ops, s, "dchip0", 256*MB);
    memory_region_add_subregion(addr_space, 0x801b0000000ULL,
                                &s->dchip_region);

    /* Pchip0 PCI memory, 0x800.0000.0000, 4GB.  */
    memory_region_init(&s->pchip.reg_mem, "pci0-mem", 4*GB);
    memory_region_add_subregion(addr_space, 0x80000000000ULL,
                                &s->pchip.reg_mem);

    /* Pchip0 PCI I/O, 0x801.FC00.0000, 32MB.  */
    /* ??? Ideally we drop the "system" i/o space on the floor and give the
       PCI subsystem the full address space reserved by the chipset.
       We can't do that until the MEM and IO paths in memory.c are unified.  */
    memory_region_init_io(&s->pchip.reg_io, &alpha_pci_bw_io_ops, NULL,
                          "pci0-io", 32*MB);
    memory_region_add_subregion(addr_space, 0x801fc000000ULL,
                                &s->pchip.reg_io);

    b = pci_register_bus(&s->host.busdev.qdev, "pci",
                         typhoon_set_irq, sys_map_irq, s,
                         &s->pchip.reg_mem, addr_space_io, 0, 64);
    s->host.bus = b;

    /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB.  */
    memory_region_init_io(&s->pchip.reg_iack, &alpha_pci_iack_ops, b,
                          "pci0-iack", 64*MB);
    memory_region_add_subregion(addr_space, 0x801f8000000ULL,
                                &s->pchip.reg_iack);

    /* Pchip0 PCI configuration, 0x801.FE00.0000, 16MB.  */
    memory_region_init_io(&s->pchip.reg_conf, &alpha_pci_conf1_ops, b,
                          "pci0-conf", 16*MB);
    memory_region_add_subregion(addr_space, 0x801fe000000ULL,
                                &s->pchip.reg_conf);

    /* For the record, these are the mappings for the second PCI bus.
       We can get away with not implementing them because we indicate
       via the Cchip.CSC<PIP> bit that Pchip1 is not present.  */
    /* Pchip1 PCI memory, 0x802.0000.0000, 4GB.  */
    /* Pchip1 CSRs, 0x802.8000.0000, 256MB.  */
    /* Pchip1 PCI special/interrupt acknowledge, 0x802.F800.0000, 64MB.  */
    /* Pchip1 PCI I/O, 0x802.FC00.0000, 32MB.  */
    /* Pchip1 PCI configuration, 0x802.FE00.0000, 16MB.  */

    /* Init the ISA bus.  */
    /* ??? Technically there should be a cy82c693ub pci-isa bridge.  */
    {
        qemu_irq isa_pci_irq, *isa_irqs;

        *isa_bus = isa_bus_new(NULL, addr_space_io);
        isa_pci_irq = *qemu_allocate_irqs(typhoon_set_isa_irq, s, 1);
        isa_irqs = i8259_init(*isa_bus, isa_pci_irq);
        isa_bus_irqs(*isa_bus, isa_irqs);
    }

    return b;
}
Пример #16
0
static void mips_jazz_init(MachineState *machine,
                           enum jazz_model_e jazz_model)
{
    MemoryRegion *address_space = get_system_memory();
    char *filename;
    int bios_size, n;
    MIPSCPU *cpu;
    CPUClass *cc;
    CPUMIPSState *env;
    qemu_irq *i8259;
    rc4030_dma *dmas;
    IOMMUMemoryRegion *rc4030_dma_mr;
    MemoryRegion *isa_mem = g_new(MemoryRegion, 1);
    MemoryRegion *isa_io = g_new(MemoryRegion, 1);
    MemoryRegion *rtc = g_new(MemoryRegion, 1);
    MemoryRegion *i8042 = g_new(MemoryRegion, 1);
    MemoryRegion *dma_dummy = g_new(MemoryRegion, 1);
    NICInfo *nd;
    DeviceState *dev, *rc4030;
    SysBusDevice *sysbus;
    ISABus *isa_bus;
    ISADevice *pit;
    DriveInfo *fds[MAX_FD];
    qemu_irq esp_reset, dma_enable;
    MemoryRegion *ram = g_new(MemoryRegion, 1);
    MemoryRegion *bios = g_new(MemoryRegion, 1);
    MemoryRegion *bios2 = g_new(MemoryRegion, 1);

    /* init CPUs */
    cpu = MIPS_CPU(cpu_create(machine->cpu_type));
    env = &cpu->env;
    qemu_register_reset(main_cpu_reset, cpu);

    /* Chipset returns 0 in invalid reads and do not raise data exceptions.
     * However, we can't simply add a global memory region to catch
     * everything, as memory core directly call unassigned_mem_read/write
     * on some invalid accesses, which call do_unassigned_access on the
     * CPU, which raise an exception.
     * Handle that case by hijacking the do_unassigned_access method on
     * the CPU, and do not raise exceptions for data access. */
    cc = CPU_GET_CLASS(cpu);
    real_do_unassigned_access = cc->do_unassigned_access;
    cc->do_unassigned_access = mips_jazz_do_unassigned_access;

    /* allocate RAM */
    memory_region_allocate_system_memory(ram, NULL, "mips_jazz.ram",
                                         machine->ram_size);
    memory_region_add_subregion(address_space, 0, ram);

    memory_region_init_ram(bios, NULL, "mips_jazz.bios", MAGNUM_BIOS_SIZE,
                           &error_fatal);
    memory_region_set_readonly(bios, true);
    memory_region_init_alias(bios2, NULL, "mips_jazz.bios", bios,
                             0, MAGNUM_BIOS_SIZE);
    memory_region_add_subregion(address_space, 0x1fc00000LL, bios);
    memory_region_add_subregion(address_space, 0xfff00000LL, bios2);

    /* load the BIOS image. */
    if (bios_name == NULL)
        bios_name = BIOS_FILENAME;
    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
    if (filename) {
        bios_size = load_image_targphys(filename, 0xfff00000LL,
                                        MAGNUM_BIOS_SIZE);
        g_free(filename);
    } else {
        bios_size = -1;
    }
    if ((bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) && !qtest_enabled()) {
        error_report("Could not load MIPS bios '%s'", bios_name);
        exit(1);
    }

    /* Init CPU internal devices */
    cpu_mips_irq_init_cpu(cpu);
    cpu_mips_clock_init(cpu);

    /* Chipset */
    rc4030 = rc4030_init(&dmas, &rc4030_dma_mr);
    sysbus = SYS_BUS_DEVICE(rc4030);
    sysbus_connect_irq(sysbus, 0, env->irq[6]);
    sysbus_connect_irq(sysbus, 1, env->irq[3]);
    memory_region_add_subregion(address_space, 0x80000000,
                                sysbus_mmio_get_region(sysbus, 0));
    memory_region_add_subregion(address_space, 0xf0000000,
                                sysbus_mmio_get_region(sysbus, 1));
    memory_region_init_io(dma_dummy, NULL, &dma_dummy_ops, NULL, "dummy_dma", 0x1000);
    memory_region_add_subregion(address_space, 0x8000d000, dma_dummy);

    /* ISA bus: IO space at 0x90000000, mem space at 0x91000000 */
    memory_region_init(isa_io, NULL, "isa-io", 0x00010000);
    memory_region_init(isa_mem, NULL, "isa-mem", 0x01000000);
    memory_region_add_subregion(address_space, 0x90000000, isa_io);
    memory_region_add_subregion(address_space, 0x91000000, isa_mem);
    isa_bus = isa_bus_new(NULL, isa_mem, isa_io, &error_abort);

    /* ISA devices */
    i8259 = i8259_init(isa_bus, env->irq[4]);
    isa_bus_irqs(isa_bus, i8259);
    DMA_init(isa_bus, 0);
    pit = pit_init(isa_bus, 0x40, 0, NULL);
    pcspk_init(isa_bus, pit);

    /* Video card */
    switch (jazz_model) {
    case JAZZ_MAGNUM:
        dev = qdev_create(NULL, "sysbus-g364");
        qdev_init_nofail(dev);
        sysbus = SYS_BUS_DEVICE(dev);
        sysbus_mmio_map(sysbus, 0, 0x60080000);
        sysbus_mmio_map(sysbus, 1, 0x40000000);
        sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(rc4030, 3));
        {
            /* Simple ROM, so user doesn't have to provide one */
            MemoryRegion *rom_mr = g_new(MemoryRegion, 1);
            memory_region_init_ram(rom_mr, NULL, "g364fb.rom", 0x80000,
                                   &error_fatal);
            memory_region_set_readonly(rom_mr, true);
            uint8_t *rom = memory_region_get_ram_ptr(rom_mr);
            memory_region_add_subregion(address_space, 0x60000000, rom_mr);
            rom[0] = 0x10; /* Mips G364 */
        }
        break;
    case JAZZ_PICA61:
        isa_vga_mm_init(0x40000000, 0x60000000, 0, get_system_memory());
        break;
    default:
        break;
    }

    /* Network controller */
    for (n = 0; n < nb_nics; n++) {
        nd = &nd_table[n];
        if (!nd->model)
            nd->model = g_strdup("dp83932");
        if (strcmp(nd->model, "dp83932") == 0) {
            qemu_check_nic_model(nd, "dp83932");

            dev = qdev_create(NULL, "dp8393x");
            qdev_set_nic_properties(dev, nd);
            qdev_prop_set_uint8(dev, "it_shift", 2);
            qdev_prop_set_ptr(dev, "dma_mr", rc4030_dma_mr);
            qdev_init_nofail(dev);
            sysbus = SYS_BUS_DEVICE(dev);
            sysbus_mmio_map(sysbus, 0, 0x80001000);
            sysbus_mmio_map(sysbus, 1, 0x8000b000);
            sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(rc4030, 4));
            break;
        } else if (is_help_option(nd->model)) {
            fprintf(stderr, "qemu: Supported NICs: dp83932\n");
            exit(1);
        } else {
            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
            exit(1);
        }
    }

    /* SCSI adapter */
    esp_init(0x80002000, 0,
             rc4030_dma_read, rc4030_dma_write, dmas[0],
             qdev_get_gpio_in(rc4030, 5), &esp_reset, &dma_enable);

    /* Floppy */
    for (n = 0; n < MAX_FD; n++) {
        fds[n] = drive_get(IF_FLOPPY, 0, n);
    }
    /* FIXME: we should enable DMA with a custom IsaDma device */
    fdctrl_init_sysbus(qdev_get_gpio_in(rc4030, 1), -1, 0x80003000, fds);

    /* Real time clock */
    rtc_init(isa_bus, 1980, NULL);
    memory_region_init_io(rtc, NULL, &rtc_ops, NULL, "rtc", 0x1000);
    memory_region_add_subregion(address_space, 0x80004000, rtc);

    /* Keyboard (i8042) */
    i8042_mm_init(qdev_get_gpio_in(rc4030, 6), qdev_get_gpio_in(rc4030, 7),
                  i8042, 0x1000, 0x1);
    memory_region_add_subregion(address_space, 0x80005000, i8042);

    /* Serial ports */
    if (serial_hds[0]) {
        serial_mm_init(address_space, 0x80006000, 0,
                       qdev_get_gpio_in(rc4030, 8), 8000000/16,
                       serial_hds[0], DEVICE_NATIVE_ENDIAN);
    }
    if (serial_hds[1]) {
        serial_mm_init(address_space, 0x80007000, 0,
                       qdev_get_gpio_in(rc4030, 9), 8000000/16,
                       serial_hds[1], DEVICE_NATIVE_ENDIAN);
    }

    /* Parallel port */
    if (parallel_hds[0])
        parallel_mm_init(address_space, 0x80008000, 0,
                         qdev_get_gpio_in(rc4030, 0), parallel_hds[0]);

    /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */

    /* NVRAM */
    dev = qdev_create(NULL, "ds1225y");
    qdev_init_nofail(dev);
    sysbus = SYS_BUS_DEVICE(dev);
    sysbus_mmio_map(sysbus, 0, 0x80009000);

    /* LED indicator */
    sysbus_create_simple("jazz-led", 0x8000f000, NULL);
}
Пример #17
0
/* PC hardware initialisation */
static void pc_init1(MemoryRegion *system_memory,
                     MemoryRegion *system_io,
                     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,
                     int pci_enabled,
                     int kvmclock_enabled)
{
    int i;
    ram_addr_t below_4g_mem_size, above_4g_mem_size;
    PCIBus *pci_bus;
    ISABus *isa_bus;
    PCII440FXState *i440fx_state;
    int piix3_devfn = -1;
    qemu_irq *cpu_irq;
    qemu_irq *gsi;
    qemu_irq *i8259;
    qemu_irq *cmos_s3;
    qemu_irq *smi_irq;
    GSIState *gsi_state;
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
    BusState *idebus[MAX_IDE_BUS];
    ISADevice *rtc_state;
    ISADevice *floppy;
    MemoryRegion *ram_memory;
    MemoryRegion *pci_memory;
    MemoryRegion *rom_memory;
    DeviceState *dev;

    pc_cpus_init(cpu_model);

    if (kvmclock_enabled) {
        kvmclock_create();
    }

    if (ram_size >= 0xe0000000 ) {
        above_4g_mem_size = ram_size - 0xe0000000;
        below_4g_mem_size = 0xe0000000;
    } else {
        above_4g_mem_size = 0;
        below_4g_mem_size = ram_size;
    }

    if (pci_enabled) {
        pci_memory = g_new(MemoryRegion, 1);
        memory_region_init(pci_memory, "pci", INT64_MAX);
        rom_memory = pci_memory;
    } else {
        pci_memory = NULL;
        rom_memory = system_memory;
    }

    /* allocate ram and load rom/bios */
    if (!xen_enabled()) {
        pc_memory_init(system_memory,
                       kernel_filename, kernel_cmdline, initrd_filename,
                       below_4g_mem_size, above_4g_mem_size,
                       pci_enabled ? rom_memory : system_memory, &ram_memory);
    }

    gsi_state = g_malloc0(sizeof(*gsi_state));
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
        kvm_piix3_setup_irq_routing(pci_enabled);
        gsi = qemu_allocate_irqs(kvm_piix3_gsi_handler, gsi_state,
                                 GSI_NUM_PINS);
    } else {
        gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
    }

    if (pci_enabled) {
        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
                              system_memory, system_io, ram_size,
                              below_4g_mem_size,
                              0x100000000ULL - below_4g_mem_size,
                              0x100000000ULL + above_4g_mem_size,
                              (sizeof(target_phys_addr_t) == 4
                               ? 0
                               : ((uint64_t)1 << 62)),
                              pci_memory, ram_memory);
    } else {
        pci_bus = NULL;
        i440fx_state = NULL;
        isa_bus = isa_bus_new(NULL, system_io);
        no_hpet = 1;
    }
    isa_bus_irqs(isa_bus, gsi);

    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
        i8259 = kvm_i8259_init(isa_bus);
    } else if (xen_enabled()) {
        i8259 = xen_interrupt_controller_init();
    } else {
        cpu_irq = pc_allocate_cpu_irq();
        i8259 = i8259_init(isa_bus, cpu_irq[0]);
    }

    for (i = 0; i < ISA_NUM_IRQS; i++) {
        gsi_state->i8259_irq[i] = i8259[i];
    }
    if (pci_enabled) {
        ioapic_init(gsi_state);
    }

    pc_register_ferr_irq(gsi[13]);

    dev = pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
    if (dev) {
        qdev_property_add_child(qdev_get_root(), "vga", dev, NULL);
    }

    if (xen_enabled()) {
        pci_create_simple(pci_bus, -1, "xen-platform");
    }

    /* init basic PC hardware */
    pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled());

    for(i = 0; i < nb_nics; i++) {
        NICInfo *nd = &nd_table[i];

        if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
            pc_init_ne2k_isa(isa_bus, nd);
        else
            pci_nic_init_nofail(nd, "e1000", NULL);
    }

    ide_drive_get(hd, MAX_IDE_BUS);
    if (pci_enabled) {
        PCIDevice *dev;
        if (xen_enabled()) {
            dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1);
        } else {
            dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
        }
        idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
        idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");

        /* FIXME there's some major spaghetti here.  Somehow we create the
         * devices on the PIIX before we actually create it.  We create the
         * PIIX3 deep in the recess of the i440fx creation too and then lose
         * the DeviceState.
         *
         * For now, let's "fix" this by making judicious use of paths.  This
         * is not generally the right way to do this.
         */
        qdev_property_add_child(qdev_resolve_path("/i440fx/piix3", NULL),
                                "rtc", (DeviceState *)rtc_state, NULL);
    } else {
        for(i = 0; i < MAX_IDE_BUS; i++) {
            ISADevice *dev;
            dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
                               ide_irq[i],
                               hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
            idebus[i] = qdev_get_child_bus(&dev->qdev, "ide.0");
        }
    }

    audio_init(isa_bus, pci_enabled ? pci_bus : NULL);

    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
                 floppy, idebus[0], idebus[1], rtc_state);

    if (pci_enabled && usb_enabled) {
        usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
    }

    if (pci_enabled && acpi_enabled) {
        i2c_bus *smbus;

        if (!xen_enabled()) {
            cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1);
        } else {
            cmos_s3 = qemu_allocate_irqs(xen_cmos_set_s3_resume, rtc_state, 1);
        }
        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
        /* TODO: Populate SPD eeprom data.  */
        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
                              gsi[9], *cmos_s3, *smi_irq,
                              kvm_enabled());
        smbus_eeprom_init(smbus, 8, NULL, 0);
    }

    if (pci_enabled) {
        pc_pci_device_init(pci_bus);
    }
}
Пример #18
0
/* PC hardware initialisation */
static void pc_init1(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,
                     int pci_enabled)
{
    int i;
    ram_addr_t below_4g_mem_size, above_4g_mem_size;
    PCIBus *pci_bus;
    PCII440FXState *i440fx_state;
    int piix3_devfn = -1;
    qemu_irq *cpu_irq;
    qemu_irq *isa_irq;
    qemu_irq *i8259;
    qemu_irq *cmos_s3;
    qemu_irq *smi_irq;
    IsaIrqState *isa_irq_state;
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
    FDCtrl *floppy_controller;
    BusState *idebus[MAX_IDE_BUS];
    ISADevice *rtc_state;

    pc_cpus_init(cpu_model);

    vmport_init();

    /* allocate ram and load rom/bios */
    pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename,
                   &below_4g_mem_size, &above_4g_mem_size);

    cpu_irq = pc_allocate_cpu_irq();
    i8259 = i8259_init(cpu_irq[0]);
    isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
    isa_irq_state->i8259 = i8259;
    if (pci_enabled) {
        ioapic_init(isa_irq_state);
    }
    isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);

    if (pci_enabled) {
        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
    } else {
        pci_bus = NULL;
        i440fx_state = NULL;
        isa_bus_new(NULL);
    }
    isa_bus_irqs(isa_irq);

    pc_register_ferr_irq(isa_reserve_irq(13));

    pc_vga_init(pci_enabled? pci_bus: NULL);

    /* init basic PC hardware */
    pc_basic_device_init(isa_irq, &floppy_controller, &rtc_state);

    for(i = 0; i < nb_nics; i++) {
        NICInfo *nd = &nd_table[i];

        if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
            pc_init_ne2k_isa(nd);
        else
            pci_nic_init_nofail(nd, "e1000", NULL);
    }

    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
        fprintf(stderr, "qemu: too many IDE bus\n");
        exit(1);
    }

    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
        hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
    }

    if (pci_enabled) {
        PCIDevice *dev;
        dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
        idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
        idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
    } else {
        for(i = 0; i < MAX_IDE_BUS; i++) {
            ISADevice *dev;
            dev = isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
                               hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
            idebus[i] = qdev_get_child_bus(&dev->qdev, "ide.0");
        }
    }

    audio_init(isa_irq, pci_enabled ? pci_bus : NULL);

    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
                 idebus[0], idebus[1], floppy_controller, rtc_state);

    if (pci_enabled && usb_enabled) {
        usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
    }

    if (pci_enabled && acpi_enabled) {
        uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
        i2c_bus *smbus;

        cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1);
        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
        /* TODO: Populate SPD eeprom data.  */
        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
                              isa_reserve_irq(9), *cmos_s3, *smi_irq,
                              kvm_enabled());
        for (i = 0; i < 8; i++) {
            DeviceState *eeprom;
            eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
            qdev_prop_set_uint8(eeprom, "address", 0x50 + i);
            qdev_prop_set_ptr(eeprom, "data", eeprom_buf + (i * 256));
            qdev_init_nofail(eeprom);
        }
    }

    if (i440fx_state) {
        i440fx_init_memory_mappings(i440fx_state);
    }

    if (pci_enabled) {
        pc_pci_device_init(pci_bus);
    }
}
Пример #19
0
/* PC hardware initialisation */
static void pc_q35_init(MachineState *machine)
{
    PCMachineState *pcms = PC_MACHINE(machine);
    Q35PCIHost *q35_host;
    PCIHostState *phb;
    PCIBus *host_bus;
    PCIDevice *lpc;
    BusState *idebus[MAX_SATA_PORTS];
    ISADevice *rtc_state;
    MemoryRegion *pci_memory;
    MemoryRegion *rom_memory;
    MemoryRegion *ram_memory;
    GSIState *gsi_state;
    ISABus *isa_bus;
    int pci_enabled = 1;
    qemu_irq *gsi;
    qemu_irq *i8259;
    int i;
    ICH9LPCState *ich9_lpc;
    PCIDevice *ahci;
    DeviceState *icc_bridge;
    PcGuestInfo *guest_info;
    ram_addr_t lowmem;
    DriveInfo *hd[MAX_SATA_PORTS];
    MachineClass *mc = MACHINE_GET_CLASS(machine);

    /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory
     * and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping
     * also known as MMCFG).
     * If it doesn't, we need to split it in chunks below and above 4G.
     * In any case, try to make sure that guest addresses aligned at
     * 1G boundaries get mapped to host addresses aligned at 1G boundaries.
     * For old machine types, use whatever split we used historically to avoid
     * breaking migration.
     */
    if (machine->ram_size >= 0xb0000000) {
        lowmem = gigabyte_align ? 0x80000000 : 0xb0000000;
    } else {
        lowmem = 0xb0000000;
    }

    /* Handle the machine opt max-ram-below-4g.  It is basically doing
     * min(qemu limit, user limit).
     */
    if (lowmem > pcms->max_ram_below_4g) {
        lowmem = pcms->max_ram_below_4g;
        if (machine->ram_size - lowmem > lowmem &&
            lowmem & ((1ULL << 30) - 1)) {
            error_report("Warning: Large machine and max_ram_below_4g(%"PRIu64
                         ") not a multiple of 1G; possible bad performance.",
                         pcms->max_ram_below_4g);
        }
    }

    if (machine->ram_size >= lowmem) {
        pcms->above_4g_mem_size = machine->ram_size - lowmem;
        pcms->below_4g_mem_size = lowmem;
    } else {
        pcms->above_4g_mem_size = 0;
        pcms->below_4g_mem_size = machine->ram_size;
    }

    if (xen_enabled() && xen_hvm_init(pcms, &ram_memory) != 0) {
        fprintf(stderr, "xen hardware virtual machine initialisation failed\n");
        exit(1);
    }

    icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
    object_property_add_child(qdev_get_machine(), "icc-bridge",
                              OBJECT(icc_bridge), NULL);

    pc_cpus_init(machine->cpu_model, icc_bridge);
    pc_acpi_init("q35-acpi-dsdt.aml");

    kvmclock_create();

    /* pci enabled */
    if (pci_enabled) {
        pci_memory = g_new(MemoryRegion, 1);
        memory_region_init(pci_memory, NULL, "pci", UINT64_MAX);
        rom_memory = pci_memory;
    } else {
        pci_memory = NULL;
        rom_memory = get_system_memory();
    }

    guest_info = pc_guest_info_init(pcms);
    guest_info->isapc_ram_fw = false;
    guest_info->has_acpi_build = has_acpi_build;
    guest_info->has_reserved_memory = has_reserved_memory;
    guest_info->rsdp_in_ram = rsdp_in_ram;

    /* Migration was not supported in 2.0 for Q35, so do not bother
     * with this hack (see hw/i386/acpi-build.c).
     */
    guest_info->legacy_acpi_table_size = 0;

    if (smbios_defaults) {
        /* These values are guest ABI, do not change */
        smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
                            mc->name, smbios_legacy_mode, smbios_uuid_encoded,
                            SMBIOS_ENTRY_POINT_21);
    }

    /* allocate ram and load rom/bios */
    if (!xen_enabled()) {
        pc_memory_init(pcms, get_system_memory(),
                       rom_memory, &ram_memory, guest_info);
    }

    /* irq lines */
    gsi_state = g_malloc0(sizeof(*gsi_state));
    if (kvm_irqchip_in_kernel()) {
        kvm_pc_setup_irq_routing(pci_enabled);
        gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
                                 GSI_NUM_PINS);
    } else {
        gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
    }

    /* create pci host bus */
    q35_host = Q35_HOST_DEVICE(qdev_create(NULL, TYPE_Q35_HOST_DEVICE));

    object_property_add_child(qdev_get_machine(), "q35", OBJECT(q35_host), NULL);
    q35_host->mch.ram_memory = ram_memory;
    q35_host->mch.pci_address_space = pci_memory;
    q35_host->mch.system_memory = get_system_memory();
    q35_host->mch.address_space_io = get_system_io();
    q35_host->mch.below_4g_mem_size = pcms->below_4g_mem_size;
    q35_host->mch.above_4g_mem_size = pcms->above_4g_mem_size;
    q35_host->mch.guest_info = guest_info;
    /* pci */
    qdev_init_nofail(DEVICE(q35_host));
    phb = PCI_HOST_BRIDGE(q35_host);
    host_bus = phb->bus;
    /* create ISA bus */
    lpc = pci_create_simple_multifunction(host_bus, PCI_DEVFN(ICH9_LPC_DEV,
                                          ICH9_LPC_FUNC), true,
                                          TYPE_ICH9_LPC_DEVICE);

    object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
                             TYPE_HOTPLUG_HANDLER,
                             (Object **)&pcms->acpi_dev,
                             object_property_allow_set_link,
                             OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort);
    object_property_set_link(OBJECT(machine), OBJECT(lpc),
                             PC_MACHINE_ACPI_DEVICE_PROP, &error_abort);

    ich9_lpc = ICH9_LPC_DEVICE(lpc);
    ich9_lpc->pic = gsi;
    ich9_lpc->ioapic = gsi_state->ioapic_irq;
    pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc,
                 ICH9_LPC_NB_PIRQS);
    pci_bus_set_route_irq_fn(host_bus, ich9_route_intx_pin_to_irq);
    isa_bus = ich9_lpc->isa_bus;

    /*end early*/
    isa_bus_irqs(isa_bus, gsi);

    if (kvm_irqchip_in_kernel()) {
        i8259 = kvm_i8259_init(isa_bus);
    } else if (xen_enabled()) {
        i8259 = xen_interrupt_controller_init();
    } else {
        i8259 = i8259_init(isa_bus, pc_allocate_cpu_irq());
    }

    for (i = 0; i < ISA_NUM_IRQS; i++) {
        gsi_state->i8259_irq[i] = i8259[i];
    }
    if (pci_enabled) {
        ioapic_init_gsi(gsi_state, "q35");
    }
    qdev_init_nofail(icc_bridge);

    pc_register_ferr_irq(gsi[13]);

    assert(pcms->vmport != ON_OFF_AUTO_MAX);
    if (pcms->vmport == ON_OFF_AUTO_AUTO) {
        pcms->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON;
    }

    /* init basic PC hardware */
    pc_basic_device_init(isa_bus, gsi, &rtc_state, !mc->no_floppy,
                         (pcms->vmport != ON_OFF_AUTO_ON), 0xff0104);

    /* connect pm stuff to lpc */
    ich9_lpc_pm_init(lpc, pc_machine_is_smm_enabled(pcms), !mc->no_tco);

    /* ahci and SATA device, for q35 1 ahci controller is built-in */
    ahci = pci_create_simple_multifunction(host_bus,
                                           PCI_DEVFN(ICH9_SATA1_DEV,
                                                     ICH9_SATA1_FUNC),
                                           true, "ich9-ahci");
    idebus[0] = qdev_get_child_bus(&ahci->qdev, "ide.0");
    idebus[1] = qdev_get_child_bus(&ahci->qdev, "ide.1");
    g_assert(MAX_SATA_PORTS == ICH_AHCI(ahci)->ahci.ports);
    ide_drive_get(hd, ICH_AHCI(ahci)->ahci.ports);
    ahci_ide_create_devs(ahci, hd);

    if (usb_enabled()) {
        /* Should we create 6 UHCI according to ich9 spec? */
        ehci_create_ich9_with_companions(host_bus, 0x1d);
    }

    /* TODO: Populate SPD eeprom data.  */
    smbus_eeprom_init(ich9_smb_init(host_bus,
                                    PCI_DEVFN(ICH9_SMB_DEV, ICH9_SMB_FUNC),
                                    0xb100),
                      8, NULL, 0);

    pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state);

    /* the rest devices to which pci devfn is automatically assigned */
    pc_vga_init(isa_bus, host_bus);
    pc_nic_init(isa_bus, host_bus);
    if (pci_enabled) {
        pc_pci_device_init(host_bus);
    }
}
/* PC hardware initialisation */
static void pc_q35_init(QEMUMachineInitArgs *args)
{
    ram_addr_t below_4g_mem_size, above_4g_mem_size;
    Q35PCIHost *q35_host;
    PCIHostState *phb;
    PCIBus *host_bus;
    PCIDevice *lpc;
    BusState *idebus[MAX_SATA_PORTS];
    ISADevice *rtc_state;
    ISADevice *floppy;
    MemoryRegion *pci_memory;
    MemoryRegion *rom_memory;
    MemoryRegion *ram_memory;
    GSIState *gsi_state;
    ISABus *isa_bus;
    int pci_enabled = 1;
    qemu_irq *cpu_irq;
    qemu_irq *gsi;
    qemu_irq *i8259;
    int i;
    ICH9LPCState *ich9_lpc;
    PCIDevice *ahci;
    DeviceState *icc_bridge;
    PcGuestInfo *guest_info;

    if (xen_enabled() && xen_hvm_init(&ram_memory) != 0) {
        fprintf(stderr, "xen hardware virtual machine initialisation failed\n");
        exit(1);
    }

    icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
    object_property_add_child(qdev_get_machine(), "icc-bridge",
                              OBJECT(icc_bridge), NULL);

    pc_cpus_init(args->cpu_model, icc_bridge);
    pc_acpi_init("q35-acpi-dsdt.aml");

    kvmclock_create();

    /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory
     * and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping
     * also known as MMCFG).
     * If it doesn't, we need to split it in chunks below and above 4G.
     * In any case, try to make sure that guest addresses aligned at
     * 1G boundaries get mapped to host addresses aligned at 1G boundaries.
     * For old machine types, use whatever split we used historically to avoid
     * breaking migration.
     */
    if (args->ram_size >= 0xb0000000) {
        ram_addr_t lowmem = gigabyte_align ? 0x80000000 : 0xb0000000;
        above_4g_mem_size = args->ram_size - lowmem;
        below_4g_mem_size = lowmem;
    } else {
        above_4g_mem_size = 0;
        below_4g_mem_size = args->ram_size;
    }

    /* pci enabled */
    if (pci_enabled) {
        pci_memory = g_new(MemoryRegion, 1);
        memory_region_init(pci_memory, NULL, "pci", UINT64_MAX);
        rom_memory = pci_memory;
    } else {
        pci_memory = NULL;
        rom_memory = get_system_memory();
    }

    guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
    guest_info->has_pci_info = has_pci_info;
    guest_info->isapc_ram_fw = false;
    guest_info->has_acpi_build = has_acpi_build;

    if (smbios_type1_defaults) {
        /* These values are guest ABI, do not change */
        smbios_set_type1_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)",
                                  args->machine->name);
    }

    /* allocate ram and load rom/bios */
    if (!xen_enabled()) {
        pc_memory_init(get_system_memory(),
                       args->kernel_filename, args->kernel_cmdline,
                       args->initrd_filename,
                       below_4g_mem_size, above_4g_mem_size,
                       rom_memory, &ram_memory, guest_info);
    }

    /* irq lines */
    gsi_state = g_malloc0(sizeof(*gsi_state));
    if (kvm_irqchip_in_kernel()) {
        kvm_pc_setup_irq_routing(pci_enabled);
        gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
                                 GSI_NUM_PINS);
    } else {
        gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
    }

    /* create pci host bus */
    q35_host = Q35_HOST_DEVICE(qdev_create(NULL, TYPE_Q35_HOST_DEVICE));

    object_property_add_child(qdev_get_machine(), "q35", OBJECT(q35_host), NULL);
    q35_host->mch.ram_memory = ram_memory;
    q35_host->mch.pci_address_space = pci_memory;
    q35_host->mch.system_memory = get_system_memory();
    q35_host->mch.address_space_io = get_system_io();
    q35_host->mch.below_4g_mem_size = below_4g_mem_size;
    q35_host->mch.above_4g_mem_size = above_4g_mem_size;
    q35_host->mch.guest_info = guest_info;
    /* pci */
    qdev_init_nofail(DEVICE(q35_host));
    phb = PCI_HOST_BRIDGE(q35_host);
    host_bus = phb->bus;
    /* create ISA bus */
    lpc = pci_create_simple_multifunction(host_bus, PCI_DEVFN(ICH9_LPC_DEV,
                                          ICH9_LPC_FUNC), true,
                                          TYPE_ICH9_LPC_DEVICE);
    ich9_lpc = ICH9_LPC_DEVICE(lpc);
    ich9_lpc->pic = gsi;
    ich9_lpc->ioapic = gsi_state->ioapic_irq;
    pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc,
                 ICH9_LPC_NB_PIRQS);
    pci_bus_set_route_irq_fn(host_bus, ich9_route_intx_pin_to_irq);
    isa_bus = ich9_lpc->isa_bus;

    /*end early*/
    isa_bus_irqs(isa_bus, gsi);

    if (kvm_irqchip_in_kernel()) {
        i8259 = kvm_i8259_init(isa_bus);
    } else if (xen_enabled()) {
        i8259 = xen_interrupt_controller_init();
    } else {
        cpu_irq = pc_allocate_cpu_irq();
        i8259 = i8259_init(isa_bus, cpu_irq[0]);
    }

    for (i = 0; i < ISA_NUM_IRQS; i++) {
        gsi_state->i8259_irq[i] = i8259[i];
    }
    if (pci_enabled) {
        ioapic_init_gsi(gsi_state, NULL);
    }
    qdev_init_nofail(icc_bridge);

    pc_register_ferr_irq(gsi[13]);

    /* init basic PC hardware */
    pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, false, 0xff0104);

    /* connect pm stuff to lpc */
    ich9_lpc_pm_init(lpc);

    /* ahci and SATA device, for q35 1 ahci controller is built-in */
    ahci = pci_create_simple_multifunction(host_bus,
                                           PCI_DEVFN(ICH9_SATA1_DEV,
                                                     ICH9_SATA1_FUNC),
                                           true, "ich9-ahci");
    idebus[0] = qdev_get_child_bus(&ahci->qdev, "ide.0");
    idebus[1] = qdev_get_child_bus(&ahci->qdev, "ide.1");

    if (usb_enabled(false)) {
        /* Should we create 6 UHCI according to ich9 spec? */
        ehci_create_ich9_with_companions(host_bus, 0x1d);
    }

    /* TODO: Populate SPD eeprom data.  */
    smbus_eeprom_init(ich9_smb_init(host_bus,
                                    PCI_DEVFN(ICH9_SMB_DEV, ICH9_SMB_FUNC),
                                    0xb100),
                      8, NULL, 0);

    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, args->boot_order,
                 floppy, idebus[0], idebus[1], rtc_state);

    /* the rest devices to which pci devfn is automatically assigned */
    pc_vga_init(isa_bus, host_bus);
    pc_nic_init(isa_bus, host_bus);
    if (pci_enabled) {
        pc_pci_device_init(host_bus);
    }
}
Пример #21
0
static void __init pseries_mpic_init_IRQ(void)
{
	struct device_node *np, *old, *cascade = NULL;
        const unsigned int *addrp;
	unsigned long intack = 0;
	const unsigned int *opprop;
	unsigned long openpic_addr = 0;
	unsigned int cascade_irq;
	int naddr, n, i, opplen;
	struct mpic *mpic;

	np = of_find_node_by_path("/");
	naddr = prom_n_addr_cells(np);
	opprop = get_property(np, "platform-open-pic", &opplen);
	if (opprop != 0) {
		openpic_addr = of_read_number(opprop, naddr);
		printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic_addr);
	}
	of_node_put(np);

	BUG_ON(openpic_addr == 0);

	/* Setup the openpic driver */
	mpic = mpic_alloc(pSeries_mpic_node, openpic_addr,
			  MPIC_PRIMARY,
			  16, 250, /* isu size, irq count */
			  " MPIC     ");
	BUG_ON(mpic == NULL);

	/* Add ISUs */
	opplen /= sizeof(u32);
	for (n = 0, i = naddr; i < opplen; i += naddr, n++) {
		unsigned long isuaddr = of_read_number(opprop + i, naddr);
		mpic_assign_isu(mpic, n, isuaddr);
	}

	/* All ISUs are setup, complete initialization */
	mpic_init(mpic);

	/* Look for cascade */
	for_each_node_by_type(np, "interrupt-controller")
		if (device_is_compatible(np, "chrp,iic")) {
			cascade = np;
			break;
		}
	if (cascade == NULL)
		return;

	cascade_irq = irq_of_parse_and_map(cascade, 0);
	if (cascade == NO_IRQ) {
		printk(KERN_ERR "mpic: failed to map cascade interrupt");
		return;
	}

	/* Check ACK type */
	for (old = of_node_get(cascade); old != NULL ; old = np) {
		np = of_get_parent(old);
		of_node_put(old);
		if (np == NULL)
			break;
		if (strcmp(np->name, "pci") != 0)
			continue;
		addrp = get_property(np, "8259-interrupt-acknowledge",
					    NULL);
		if (addrp == NULL)
			continue;
		naddr = prom_n_addr_cells(np);
		intack = addrp[naddr-1];
		if (naddr > 1)
			intack |= ((unsigned long)addrp[naddr-2]) << 32;
	}
	if (intack)
		printk(KERN_DEBUG "mpic: PCI 8259 intack at 0x%016lx\n",
		       intack);
	i8259_init(cascade, intack);
	of_node_put(cascade);
	set_irq_chained_handler(cascade_irq, pseries_8259_cascade);
}
Пример #22
0
static
void mips_jazz_init (ram_addr_t ram_size,
                     const char *cpu_model,
                     enum jazz_model_e jazz_model)
{
    char *filename;
    int bios_size, n;
    CPUState *env;
    qemu_irq *rc4030, *i8259;
    rc4030_dma *dmas;
    void* rc4030_opaque;
    int s_rtc, s_dma_dummy;
    NICInfo *nd;
    PITState *pit;
    DriveInfo *fds[MAX_FD];
    qemu_irq esp_reset;
    ram_addr_t ram_offset;
    ram_addr_t bios_offset;

    /* init CPUs */
    if (cpu_model == NULL) {
#ifdef TARGET_MIPS64
        cpu_model = "R4000";
#else
        /* FIXME: All wrong, this maybe should be R3000 for the older JAZZs. */
        cpu_model = "24Kf";
#endif
    }
    env = cpu_init(cpu_model);
    if (!env) {
        fprintf(stderr, "Unable to find CPU definition\n");
        exit(1);
    }
    qemu_register_reset(main_cpu_reset, env);

    /* allocate RAM */
    ram_offset = qemu_ram_alloc(ram_size);
    cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);

    bios_offset = qemu_ram_alloc(MAGNUM_BIOS_SIZE);
    cpu_register_physical_memory(0x1fc00000LL,
                                 MAGNUM_BIOS_SIZE, bios_offset | IO_MEM_ROM);
    cpu_register_physical_memory(0xfff00000LL,
                                 MAGNUM_BIOS_SIZE, bios_offset | IO_MEM_ROM);

    /* load the BIOS image. */
    if (bios_name == NULL)
        bios_name = BIOS_FILENAME;
    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
    if (filename) {
        bios_size = load_image_targphys(filename, 0xfff00000LL,
                                        MAGNUM_BIOS_SIZE);
        qemu_free(filename);
    } else {
        bios_size = -1;
    }
    if (bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) {
        fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n",
                bios_name);
        exit(1);
    }

    /* Init CPU internal devices */
    cpu_mips_irq_init_cpu(env);
    cpu_mips_clock_init(env);

    /* Chipset */
    rc4030_opaque = rc4030_init(env->irq[6], env->irq[3], &rc4030, &dmas);
    s_dma_dummy = cpu_register_io_memory(dma_dummy_read, dma_dummy_write, NULL);
    cpu_register_physical_memory(0x8000d000, 0x00001000, s_dma_dummy);

    /* ISA devices */
    i8259 = i8259_init(env->irq[4]);
    isa_bus_new(NULL);
    isa_bus_irqs(i8259);
    DMA_init(0);
    pit = pit_init(0x40, i8259[0]);
    pcspk_init(pit);

    /* ISA IO space at 0x90000000 */
    isa_mmio_init(0x90000000, 0x01000000);
    isa_mem_base = 0x11000000;

    /* Video card */
    switch (jazz_model) {
    case JAZZ_MAGNUM:
        g364fb_mm_init(0x40000000, 0x60000000, 0, rc4030[3]);
        break;
    case JAZZ_PICA61:
        isa_vga_mm_init(0x40000000, 0x60000000, 0);
        break;
    default:
        break;
    }

    /* Network controller */
    for (n = 0; n < nb_nics; n++) {
        nd = &nd_table[n];
        if (!nd->model)
            nd->model = qemu_strdup("dp83932");
        if (strcmp(nd->model, "dp83932") == 0) {
            dp83932_init(nd, 0x80001000, 2, rc4030[4],
                         rc4030_opaque, rc4030_dma_memory_rw);
            break;
        } else if (strcmp(nd->model, "?") == 0) {
            fprintf(stderr, "qemu: Supported NICs: dp83932\n");
            exit(1);
        } else {
            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
            exit(1);
        }
    }

    /* SCSI adapter */
    esp_init(0x80002000, 0,
             rc4030_dma_read, rc4030_dma_write, dmas[0],
             rc4030[5], &esp_reset);

    /* Floppy */
    if (drive_get_max_bus(IF_FLOPPY) >= MAX_FD) {
        fprintf(stderr, "qemu: too many floppy drives\n");
        exit(1);
    }
    for (n = 0; n < MAX_FD; n++) {
        fds[n] = drive_get(IF_FLOPPY, 0, n);
    }
    fdctrl_init_sysbus(rc4030[1], 0, 0x80003000, fds);

    /* Real time clock */
    rtc_init(1980);
    s_rtc = cpu_register_io_memory(rtc_read, rtc_write, NULL);
    cpu_register_physical_memory(0x80004000, 0x00001000, s_rtc);

    /* Keyboard (i8042) */
    i8042_mm_init(rc4030[6], rc4030[7], 0x80005000, 0x1000, 0x1);

    /* Serial ports */
    if (serial_hds[0])
        serial_mm_init(0x80006000, 0, rc4030[8], 8000000/16, serial_hds[0], 1);
    if (serial_hds[1])
        serial_mm_init(0x80007000, 0, rc4030[9], 8000000/16, serial_hds[1], 1);

    /* Parallel port */
    if (parallel_hds[0])
        parallel_mm_init(0x80008000, 0, rc4030[0], parallel_hds[0]);

    /* Sound card */
    /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */
#ifdef HAS_AUDIO
    audio_init(i8259);
#endif

    /* NVRAM: Unprotected at 0x9000, Protected at 0xa000, Read only at 0xb000 */
    ds1225y_init(0x80009000, "nvram");

    /* LED indicator */
    jazz_led_init(0x8000f000);
}
Пример #23
0
/* Check if MAGIC is valid and print the Multiboot information structure
   pointed by ADDR. */
void
entry(unsigned long magic, unsigned long addr)
{
	multiboot_info_t *mbi;
	uint32_t filesys_start_addr;

	/* Clear the screen. */
	vga_text_clear();

	/* Am I booted by a Multiboot-compliant boot loader? */
	if(magic != MULTIBOOT_BOOTLOADER_MAGIC) {
		printf("Invalid magic number: 0x%#x\n", (unsigned)magic);
		return;
	}

	/* Set MBI to the address of the Multiboot information structure. */
	mbi = (multiboot_info_t *)addr;

	/* Print out the flags. */
	printf("flags = 0x%#x\n", (unsigned)mbi->flags);

	/* Are mem_* valid? */
	if(CHECK_FLAG(mbi->flags, 0))
		printf("mem_lower = %uKB, mem_upper = %uKB\n", (unsigned)mbi->mem_lower, (unsigned)mbi->mem_upper);

	/* Is boot_device valid? */
	if(CHECK_FLAG(mbi->flags, 1))
		printf("boot_device = 0x%#x\n", (unsigned)mbi->boot_device);

	/* Is the command line passed? */
	if(CHECK_FLAG(mbi->flags, 2))
		printf("cmdline = %s\n", (char *)mbi->cmdline);

	if(CHECK_FLAG(mbi->flags, 3)) {
		int mod_count = 0;
		int i;
		module_t* mod = (module_t*)mbi->mods_addr;
		filesys_start_addr = (uint32_t)mod->mod_start;
		while(mod_count < mbi->mods_count) {
			printf("Module %d loaded at address: 0x%#x\n", mod_count, (unsigned int)mod->mod_start);
			printf("Module %d ends at address: 0x%#x\n", mod_count, (unsigned int)mod->mod_end);
			printf("First few bytes of module:\n");
			for(i = 0; i < 16; i++) {
				printf("0x%x ", *((char*)(mod->mod_start+i)));
			}
			printf("\n");
			mod_count++;
		}
	}

	/* Bits 4 and 5 are mutually exclusive! */
	if(CHECK_FLAG(mbi->flags, 4) && CHECK_FLAG(mbi->flags, 5)) {
		printf("Both bits 4 and 5 are set.\n");
		return;
	}

	/* Is the section header table of ELF valid? */
	if(CHECK_FLAG(mbi->flags, 5)) {
		elf_section_header_table_t *elf_sec = &(mbi->elf_sec);

		printf("elf_sec: num = %u, size = 0x%#x,"
			   " addr = 0x%#x, shndx = 0x%#x\n",
			   (unsigned)elf_sec->num, (unsigned)elf_sec->size,
			   (unsigned)elf_sec->addr, (unsigned)elf_sec->shndx);
	}

	/* Are mmap_* valid? */
	if(CHECK_FLAG(mbi->flags, 6)) {
		memory_map_t *mmap;

		printf("mmap_addr = 0x%#x, mmap_length = 0x%x\n",
			   (unsigned)mbi->mmap_addr,
			   (unsigned)mbi->mmap_length);
		for(mmap = (memory_map_t *)mbi->mmap_addr; 
			(unsigned long)mmap < mbi->mmap_addr + mbi->mmap_length;
			mmap = (memory_map_t *)((unsigned long)mmap + mmap->size + sizeof(mmap->size)))
			printf(" size = 0x%x,    base_addr = 0x%#x%#x\n"
				   " type = 0x%x,    length    = 0x%#x%#x\n",
				   (unsigned)mmap->size,
				   (unsigned)mmap->base_addr_high,
				   (unsigned)mmap->base_addr_low,
				   (unsigned)mmap->type,
				   (unsigned)mmap->length_high,
				   (unsigned)mmap->length_low);
	}

	/* Construct an LDT entry in the GDT */
	{
		seg_desc_t the_ldt_desc;
		the_ldt_desc.granularity	= 0;
		the_ldt_desc.opsize			= 1;
		the_ldt_desc.reserved		= 0;
		the_ldt_desc.avail			= 0;
		the_ldt_desc.present		= 1;
		the_ldt_desc.dpl			= 0x0;
		the_ldt_desc.sys			= 0;
		the_ldt_desc.type			= 0x2;

		SET_LDT_PARAMS(the_ldt_desc, &ldt, ldt_size);
		ldt_desc_ptr = the_ldt_desc;
		lldt(KERNEL_LDT);
	}

	/* Construct a TSS entry in the GDT */
	{
		seg_desc_t the_tss_desc;
		the_tss_desc.granularity	= 0;
		the_tss_desc.opsize			= 0;
		the_tss_desc.reserved		= 0;
		the_tss_desc.avail			= 0;
		the_tss_desc.seg_lim_19_16	= TSS_SIZE & 0x000F0000;
		the_tss_desc.present		= 1;
		the_tss_desc.dpl			= 0x0;
		the_tss_desc.sys			= 0;
		the_tss_desc.type			= 0x9;
		the_tss_desc.seg_lim_15_00	= TSS_SIZE & 0x0000FFFF;

		SET_TSS_PARAMS(the_tss_desc, &tss, tss_size);

		tss_desc_ptr = the_tss_desc;

		tss.ldt_segment_selector = KERNEL_LDT;
		tss.ss0 = KERNEL_DS;
		tss.esp0 = 0x800000;
		ltr(KERNEL_TSS);
	}
	
	/* If kernel got to here, that means everything should be fine with the boot.
	 * Now we should initialize IDT, PIC, Syscall, paging, devices, filesystem,
	 * and any other initialization stuff... terminal_init() should be called at
	 * the very end of the initializations (after sti). */
	
	/* But first, let's clear the screen */
	vga_text_clear();
	
	/* Init the IDT */
	idt_init();

	/* Init the PIC */
	i8259_init();
	
	/* Init Syscall */
	syscall_init();
	
	/* Init Paging */
	paging_init();
	
	/* Init file system */
	filesys_init(filesys_start_addr);
	
	/* Init the Keyboard */
	keyboard_init();
	
	/* Init the RTC */
	rtc_init();

	/* Enable interrupts */
	sti();
	
	/* booting screen in mode X */
	start_up = 3;
	set_mode_x();
	load_bmp((uint8_t*)"boot", LOAD_FLAG_BOOT);
	while(start_up == 3);
	set_text_mode();
	
	/* Init the good looking terminal */
	terminal_init();
	
	/* wait for a key press to clear the start up screen */
	while(start_up == 2);

	vga_text_clear();
	welcome_and_credit();
	while(start_up == 1);
	
	/* Init the status bar for that terminal */
	terminal_stat_bar_init();
	terminal_clear();

	/* Init the PIT */
	pit_init();
	
	/* Execute the first program "shell" */
	pid_now = 1;
	pid_running[0] = 1;
	root_shell_flag = 1;
	execute((uint8_t*)"shell");

	/* Spin (nicely, so we don't chew up cycles) */
	asm volatile(".1: hlt; jmp .1;");
}
Пример #24
0
/* PC hardware initialisation */
static void pc_init1(MemoryRegion *system_memory,
                     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,
                     int pci_enabled,
                     int kvmclock_enabled)
{
    int i;
    ram_addr_t below_4g_mem_size, above_4g_mem_size;
    PCIBus *pci_bus;
    PCII440FXState *i440fx_state;
    int piix3_devfn = -1;
    qemu_irq *cpu_irq;
    qemu_irq *isa_irq;
    qemu_irq *i8259;
    qemu_irq *cmos_s3;
    qemu_irq *smi_irq;
    IsaIrqState *isa_irq_state;
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
    BusState *idebus[MAX_IDE_BUS];
    ISADevice *rtc_state;

    pc_cpus_init(cpu_model);

    if (kvmclock_enabled) {
        kvmclock_create();
    }

    if (ram_size >= 0xe0000000 ) {
        above_4g_mem_size = ram_size - 0xe0000000;
        below_4g_mem_size = 0xe0000000;
    } else {
        above_4g_mem_size = 0;
        below_4g_mem_size = ram_size;
    }

    /* allocate ram and load rom/bios */
    if (!xen_enabled()) {
        pc_memory_init(system_memory,
                       kernel_filename, kernel_cmdline, initrd_filename,
                       below_4g_mem_size, above_4g_mem_size);
    }

    if (!xen_enabled()) {
        cpu_irq = pc_allocate_cpu_irq();
        i8259 = i8259_init(cpu_irq[0]);
    } else {
        i8259 = xen_interrupt_controller_init();
    }
    isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
    isa_irq_state->i8259 = i8259;
    if (pci_enabled) {
        ioapic_init(isa_irq_state);
    }
    isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);

    if (pci_enabled) {
        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq,
                              system_memory, ram_size);
    } else {
        pci_bus = NULL;
        i440fx_state = NULL;
        isa_bus_new(NULL);
    }
    isa_bus_irqs(isa_irq);

    pc_register_ferr_irq(isa_get_irq(13));

    pc_vga_init(pci_enabled? pci_bus: NULL);

    if (xen_enabled()) {
        pci_create_simple(pci_bus, -1, "xen-platform");
    }

    /* init basic PC hardware */
    pc_basic_device_init(isa_irq, &rtc_state, xen_enabled());

    for(i = 0; i < nb_nics; i++) {
        NICInfo *nd = &nd_table[i];

        if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
            pc_init_ne2k_isa(nd);
        else
            pci_nic_init_nofail(nd, "e1000", NULL);
    }

    ide_drive_get(hd, MAX_IDE_BUS);
    if (pci_enabled) {
        PCIDevice *dev;
        if (xen_enabled()) {
            dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1);
        } else {
            dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
        }
        idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
        idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
    } else {
        for(i = 0; i < MAX_IDE_BUS; i++) {
            ISADevice *dev;
            dev = isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
                               hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
            idebus[i] = qdev_get_child_bus(&dev->qdev, "ide.0");
        }
    }

    audio_init(isa_irq, pci_enabled ? pci_bus : NULL);

    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
                 idebus[0], idebus[1], rtc_state);

    if (pci_enabled && usb_enabled) {
        usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
    }

    if (pci_enabled && acpi_enabled) {
        i2c_bus *smbus;

        if (!xen_enabled()) {
            cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1);
        } else {
            cmos_s3 = qemu_allocate_irqs(xen_cmos_set_s3_resume, rtc_state, 1);
        }
        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
        /* TODO: Populate SPD eeprom data.  */
        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
                              isa_get_irq(9), *cmos_s3, *smi_irq,
                              kvm_enabled());
        smbus_eeprom_init(smbus, 8, NULL, 0);
    }

    if (i440fx_state) {
        i440fx_init_memory_mappings(i440fx_state);
    }

    if (pci_enabled) {
        pc_pci_device_init(pci_bus);
    }
}
Пример #25
0
/* Check if MAGIC is valid and print the Multiboot information structure
   pointed by ADDR. */
void
entry (unsigned long magic, unsigned long addr)
{
	uint32_t fileptr;// start of file system
	multiboot_info_t *mbi;

	/* Initialize the screen. */
	terminal_open();

	/* Am I booted by a Multiboot-compliant boot loader? */
	if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
	{
		printf ("Invalid magic number: 0x%#x\n", (unsigned) magic);
		return;
	}

	/* Set MBI to the address of the Multiboot information structure. */
	mbi = (multiboot_info_t *) addr;

	/* Print out the flags. */
	printf ("flags = 0x%#x\n", (unsigned) mbi->flags);

	/* Are mem_* valid? */
	if (CHECK_FLAG (mbi->flags, 0))
		printf ("mem_lower = %uKB, mem_upper = %uKB\n",
				(unsigned) mbi->mem_lower, (unsigned) mbi->mem_upper);

	/* Is boot_device valid? */
	if (CHECK_FLAG (mbi->flags, 1))
		printf ("boot_device = 0x%#x\n", (unsigned) mbi->boot_device);

	/* Is the command line passed? */
	if (CHECK_FLAG (mbi->flags, 2))
		printf ("cmdline = %s\n", (char *) mbi->cmdline);

	if (CHECK_FLAG (mbi->flags, 3)) {
		int mod_count = 0;
		int i;
		module_t* mod = (module_t*)mbi->mods_addr;
		fileptr = mod->mod_start;
		while(mod_count < mbi->mods_count) {
			printf("Module %d loaded at address: 0x%#x\n", mod_count, (unsigned int)mod->mod_start);
			printf("Module %d ends at address: 0x%#x\n", mod_count, (unsigned int)mod->mod_end);
			printf("First few bytes of module:\n");
			for(i = 0; i<16; i++) {
				printf("0x%x ", *((char*)(mod->mod_start+i)));
			}
			printf("\n");
			mod_count++;
		}
	}
	/* Bits 4 and 5 are mutually exclusive! */
	if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG (mbi->flags, 5))
	{
		printf ("Both bits 4 and 5 are set.\n");
		return;
	}

	/* Is the section header table of ELF valid? */
	if (CHECK_FLAG (mbi->flags, 5))
	{
		elf_section_header_table_t *elf_sec = &(mbi->elf_sec);

		printf ("elf_sec: num = %u, size = 0x%#x,"
				" addr = 0x%#x, shndx = 0x%#x\n",
				(unsigned) elf_sec->num, (unsigned) elf_sec->size,
				(unsigned) elf_sec->addr, (unsigned) elf_sec->shndx);
	}

	/* Are mmap_* valid? */
	if (CHECK_FLAG (mbi->flags, 6))
	{
		memory_map_t *mmap;

		printf ("mmap_addr = 0x%#x, mmap_length = 0x%x\n",
				(unsigned) mbi->mmap_addr, (unsigned) mbi->mmap_length);
		for (mmap = (memory_map_t *) mbi->mmap_addr;
				(unsigned long) mmap < mbi->mmap_addr + mbi->mmap_length;
				mmap = (memory_map_t *) ((unsigned long) mmap
					+ mmap->size + sizeof (mmap->size)))
			printf (" size = 0x%x,     base_addr = 0x%#x%#x\n"
					"     type = 0x%x,  length    = 0x%#x%#x\n",
					(unsigned) mmap->size,
					(unsigned) mmap->base_addr_high,
					(unsigned) mmap->base_addr_low,
					(unsigned) mmap->type,
					(unsigned) mmap->length_high,
					(unsigned) mmap->length_low);
	}

	/* Construct an LDT entry in the GDT */
	{
		seg_desc_t the_ldt_desc;
		the_ldt_desc.granularity    = 0;
		the_ldt_desc.opsize         = 1;
		the_ldt_desc.reserved       = 0;
		the_ldt_desc.avail          = 0;
		the_ldt_desc.present        = 1;
		the_ldt_desc.dpl            = 0x0;
		the_ldt_desc.sys            = 0;
		the_ldt_desc.type           = 0x2;

		SET_LDT_PARAMS(the_ldt_desc, &ldt, ldt_size);
		ldt_desc_ptr = the_ldt_desc;
		lldt(KERNEL_LDT);
	}

	/* Construct a TSS entry in the GDT */
	{
		seg_desc_t the_tss_desc;
		the_tss_desc.granularity    = 0;
		the_tss_desc.opsize         = 0;
		the_tss_desc.reserved       = 0;
		the_tss_desc.avail          = 0;
		the_tss_desc.seg_lim_19_16  = TSS_SIZE & 0x000F0000;
		the_tss_desc.present        = 1;
		the_tss_desc.dpl            = 0x0;
		the_tss_desc.sys            = 0;
		the_tss_desc.type           = 0x9;
		the_tss_desc.seg_lim_15_00  = TSS_SIZE & 0x0000FFFF;

		SET_TSS_PARAMS(the_tss_desc, &tss, tss_size);

		tss_desc_ptr = the_tss_desc;

		tss.ldt_segment_selector = KERNEL_LDT;
		tss.ss0 = KERNEL_DS;
		tss.esp0 = 0x800000;
		ltr(KERNEL_TSS);
	}
	/* Mask all IRQs again*/
	int j;
	for(j=0;j<16;j++)
	{
		disable_irq(j);
	}
	/* Init the PIC */
	i8259_init();
	
	/* Init IDT vector 0-20*/
	{
		int i;
		for(i=0;i<20;i++)
		{	
			if(i!=15)
			{
				//Define an idt_desc_t structure
				idt_desc_t idt_desc;
				//populate w/ correct values
				idt_desc.seg_selector=0x0010;
				idt_desc.present=1;
				idt_desc.size=1;
				idt_desc.dpl=0x0;
				idt_desc.reserved1=1;
				idt_desc.reserved2=1;
				idt_desc.reserved3=1;
				SET_IDT_ENTRY(idt_desc, ehandlers[i]);
				//Set new entry in table
				idt[i]=idt_desc;
			}
		}
	}
	/* Init IRQ Interrupts*/
	//Timer Chip
	{
		//Define an idt_desc_t structure
		idt_desc_t idt_desc;
		//populate w/ correct values
		idt_desc.seg_selector=0x0010;
		idt_desc.present=1;
		idt_desc.size=1;
		idt_desc.dpl=0x0;
		idt_desc.reserved1=1;
		idt_desc.reserved2=1;
		SET_IDT_ENTRY(idt_desc, irqhandlers[0]);
		//Set new entry in table
		idt[32]=idt_desc;
		//Disable IRQ masking
		//enable_irq(0);
	}
	//Keyboard
	{
		//Define an idt_desc_t structure
		idt_desc_t idt_desc;
		//populate w/ correct values
		idt_desc.seg_selector=0x0010;
		idt_desc.present=1;
		idt_desc.size=1;
		idt_desc.dpl=0x0;
		idt_desc.reserved1=1;
		idt_desc.reserved2=1;
		SET_IDT_ENTRY(idt_desc, irqhandlers[1]);
		//Set new entry in table
		idt[33]=idt_desc;
		//Disable IRQ masking
		//enable_irq(1);
	}
	//Real Time Clock
	{
		//Define an idt_desc_t structure
		idt_desc_t idt_desc;
		//populate w/ correct values
		idt_desc.seg_selector=0x0010;
		idt_desc.present=1;
		idt_desc.size=1;
		idt_desc.dpl=0x0;
		idt_desc.reserved1=1;
		idt_desc.reserved2=1;
		SET_IDT_ENTRY(idt_desc, irqhandlers[2]);
		//Set new entry in table
		idt[40]=idt_desc;
	//Disable IRQ masking
		//enable_irq(8);
	}
	/* Init System Call 0x80 */
	//Define an idt_desc_t structure
	idt_desc_t idt_desc;
	//populate w/ correct values
	idt_desc.seg_selector=0x0010;
	idt_desc.present=1;
	idt_desc.size=1;
	idt_desc.dpl=0x0;
	idt_desc.reserved1=1;
	idt_desc.reserved2=1;
	SET_IDT_ENTRY(idt_desc, systemcall);
	//Set new entry in table
	idt[128]=idt_desc;
			
	//Load new IDT
	lidt(idt_desc_ptr);

	/* Initialize devices, memory, filesystem, enable device interrupts on the
	 * PIC, any other initialization stuff... */
	paging_init();
	
	//Enable IRQ interrupts. 
	enable_irq(8);
	enable_irq(2);
	enable_irq(1);
	
	/* Enable interrupts */
	/* Do not enable the following until after you have set up your
	 * IDT correctly otherwise QEMU will triple fault and simple close
	 * without showing you any output */
	printf("Enabling Interrupts\n");
	sti();
	/* This will be replaced by a system call after CP3 */
	rtc_open();
	filesys_init(fileptr); // start of filesystem
	
	while(1)
	{
		
		printf("Reading-> ");
		uint8_t buf[1024];
		int cnt = terminal_read(buf, 1024);
		buf[cnt] = '\0';
		puts ((int8_t*)"Typed:    ");
		puts ((int8_t*)buf);
		putc('\n');
		
	}
	/* Execute the first program (`shell') ... */
	/* Spin (nicely, so we don't chew up cycles) */
	asm volatile(".1: hlt; jmp .1;");
}
Пример #26
0
void
atpic_startup(void)
{
	struct atpic_intsrc *ai;
	int i;

	/* Start off with all interrupts disabled. */
	imen = 0xffff;
	i8259_init(&atpics[MASTER], 0);
	i8259_init(&atpics[SLAVE], 1);
	atpic_enable_source((struct intsrc *)&atintrs[ICU_SLAVEID]);

	/* Install low-level interrupt handlers for all of our IRQs. */
	for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) {
		if (i == ICU_SLAVEID)
			continue;
		ai->at_intsrc.is_count = &ai->at_count;
		ai->at_intsrc.is_straycount = &ai->at_straycount;
		setidt(((struct atpic *)ai->at_intsrc.is_pic)->at_intbase +
		    ai->at_irq, ai->at_intr, SDT_ATPIC, SEL_KPL, GSEL_ATPIC);
	}

#ifdef DEV_MCA
	/* For MCA systems, all interrupts are level triggered. */
	if (MCA_system)
		for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
			ai->at_trigger = INTR_TRIGGER_LEVEL;
	else
#endif

#ifdef PC98
	for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
		switch (i) {
		case 0:
		case 1:
		case 7:
		case 8:
			ai->at_trigger = INTR_TRIGGER_EDGE;
			break;
		default:
			ai->at_trigger = INTR_TRIGGER_LEVEL;
			break;
		}
#else
	/*
	 * Look for an ELCR.  If we find one, update the trigger modes.
	 * If we don't find one, assume that IRQs 0, 1, 2, and 13 are
	 * edge triggered and that everything else is level triggered.
	 * We only use the trigger information to reprogram the ELCR if
	 * we have one and as an optimization to avoid masking edge
	 * triggered interrupts.  For the case that we don't have an ELCR,
	 * it doesn't hurt to mask an edge triggered interrupt, so we
	 * assume level trigger for any interrupt that we aren't sure is
	 * edge triggered.
	 */
	if (elcr_found) {
		for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
			ai->at_trigger = elcr_read_trigger(i);
	} else {
		for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
			switch (i) {
			case 0:
			case 1:
			case 2:
			case 8:
			case 13:
				ai->at_trigger = INTR_TRIGGER_EDGE;
				break;
			default:
				ai->at_trigger = INTR_TRIGGER_LEVEL;
				break;
			}
	}
#endif /* PC98 */
}
Пример #27
0
/* PC hardware initialisation */
static void pc_init1(MemoryRegion *system_memory,
                     MemoryRegion *system_io,
                     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,
                     int pci_enabled,
                     int kvmclock_enabled)
{
    int i;
    ram_addr_t below_4g_mem_size, above_4g_mem_size;
    PCIBus *pci_bus;
    ISABus *isa_bus;
    PCII440FXState *i440fx_state;
    int piix3_devfn = -1;
    qemu_irq *cpu_irq;
    qemu_irq *gsi;
    qemu_irq *i8259;
    qemu_irq *smi_irq;
    GSIState *gsi_state;
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
    BusState *idebus[MAX_IDE_BUS];
    ISADevice *rtc_state;
    ISADevice *floppy;
    MemoryRegion *ram_memory;
    MemoryRegion *pci_memory;
    MemoryRegion *rom_memory;
    DeviceState *icc_bridge;
    FWCfgState *fw_cfg = NULL;
    PcGuestInfo *guest_info;

    if (xen_enabled() && xen_hvm_init() != 0) {
        fprintf(stderr, "xen hardware virtual machine initialisation failed\n");
        exit(1);
    }

    icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
    object_property_add_child(qdev_get_machine(), "icc-bridge",
                              OBJECT(icc_bridge), NULL);

    pc_cpus_init(cpu_model, icc_bridge);
    pc_acpi_init("acpi-dsdt.aml");

    if (kvm_enabled() && kvmclock_enabled) {
        kvmclock_create();
    }

    if (ram_size >= 0xe0000000 ) {
        above_4g_mem_size = ram_size - 0xe0000000;
        below_4g_mem_size = 0xe0000000;
    } else {
        above_4g_mem_size = 0;
        below_4g_mem_size = ram_size;
    }

    if (pci_enabled) {
        pci_memory = g_new(MemoryRegion, 1);
        memory_region_init(pci_memory, NULL, "pci", INT64_MAX);
        rom_memory = pci_memory;
    } else {
        pci_memory = NULL;
        rom_memory = system_memory;
    }

    guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
    guest_info->has_pci_info = has_pci_info;

    /* Set PCI window size the way seabios has always done it. */
    /* Power of 2 so bios can cover it with a single MTRR */
    if (ram_size <= 0x80000000)
        guest_info->pci_info.w32.begin = 0x80000000;
    else if (ram_size <= 0xc0000000)
        guest_info->pci_info.w32.begin = 0xc0000000;
    else
        guest_info->pci_info.w32.begin = 0xe0000000;

    /* allocate ram and load rom/bios */
    if (!xen_enabled()) {
        fw_cfg = pc_memory_init(system_memory,
                       kernel_filename, kernel_cmdline, initrd_filename,
                       below_4g_mem_size, above_4g_mem_size,
                       rom_memory, &ram_memory, guest_info);
    }

    gsi_state = g_malloc0(sizeof(*gsi_state));
    if (kvm_irqchip_in_kernel()) {
        kvm_pc_setup_irq_routing(pci_enabled);
        gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
                                 GSI_NUM_PINS);
    } else {
        gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
    }

    if (pci_enabled) {
        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
                              system_memory, system_io, ram_size,
                              below_4g_mem_size,
                              0x100000000ULL - below_4g_mem_size,
                              0x100000000ULL + above_4g_mem_size,
                              (sizeof(hwaddr) == 4
                               ? 0
                               : ((uint64_t)1 << 62)),
                              pci_memory, ram_memory);
    } else {
        pci_bus = NULL;
        i440fx_state = NULL;
        isa_bus = isa_bus_new(NULL, system_io);
        no_hpet = 1;
    }
    isa_bus_irqs(isa_bus, gsi);

    if (kvm_irqchip_in_kernel()) {
        i8259 = kvm_i8259_init(isa_bus);
    } else if (xen_enabled()) {
        i8259 = xen_interrupt_controller_init();
    } else {
        cpu_irq = pc_allocate_cpu_irq();
        i8259 = i8259_init(isa_bus, cpu_irq[0]);
    }

    for (i = 0; i < ISA_NUM_IRQS; i++) {
        gsi_state->i8259_irq[i] = i8259[i];
    }
    if (pci_enabled) {
        ioapic_init_gsi(gsi_state, "i440fx");
    }
    qdev_init_nofail(icc_bridge);

    pc_register_ferr_irq(gsi[13]);

    pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);

    /* init basic PC hardware */
    pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled());

    pc_nic_init(isa_bus, pci_bus);

    ide_drive_get(hd, MAX_IDE_BUS);
    if (pci_enabled) {
        PCIDevice *dev;
        if (xen_enabled()) {
            dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1);
        } else {
            dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
        }
        idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
        idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
    } else {
        for(i = 0; i < MAX_IDE_BUS; i++) {
            ISADevice *dev;
            dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
                               ide_irq[i],
                               hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
            idebus[i] = qdev_get_child_bus(DEVICE(dev), "ide.0");
        }
    }

    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
                 floppy, idebus[0], idebus[1], rtc_state);

    if (pci_enabled && usb_enabled(false)) {
        pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci");
    }

    if (pci_enabled && acpi_enabled) {
        i2c_bus *smbus;

        smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1);
        /* TODO: Populate SPD eeprom data.  */
        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
                              gsi[9], *smi_irq,
                              kvm_enabled(), fw_cfg);
        smbus_eeprom_init(smbus, 8, NULL, 0);
    }

    if (pci_enabled) {
        pc_pci_device_init(pci_bus);
    }

    if (has_pvpanic) {
        pvpanic_init(isa_bus);
    }
}
Пример #28
0
static
void mips_r4k_init(MachineState *machine)
{
    ram_addr_t ram_size = machine->ram_size;
    const char *cpu_model = machine->cpu_model;
    const char *kernel_filename = machine->kernel_filename;
    const char *kernel_cmdline = machine->kernel_cmdline;
    const char *initrd_filename = machine->initrd_filename;
    char *filename;
    MemoryRegion *address_space_mem = get_system_memory();
    MemoryRegion *ram = g_new(MemoryRegion, 1);
    MemoryRegion *bios;
    MemoryRegion *iomem = g_new(MemoryRegion, 1);
    MemoryRegion *isa_io = g_new(MemoryRegion, 1);
    MemoryRegion *isa_mem = g_new(MemoryRegion, 1);
    int bios_size;
    MIPSCPU *cpu;
    CPUMIPSState *env;
    ResetData *reset_info;
    int i;
    qemu_irq *i8259;
    ISABus *isa_bus;
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
    DriveInfo *dinfo;
    int be;

    /* init CPUs */
    if (cpu_model == NULL) {
#ifdef TARGET_MIPS64
        cpu_model = "R4000";
#else
        cpu_model = "24Kf";
#endif
    }
    cpu = cpu_mips_init(cpu_model);
    if (cpu == NULL) {
        fprintf(stderr, "Unable to find CPU definition\n");
        exit(1);
    }
    env = &cpu->env;

    reset_info = g_malloc0(sizeof(ResetData));
    reset_info->cpu = cpu;
    reset_info->vector = env->active_tc.PC;
    qemu_register_reset(main_cpu_reset, reset_info);

    /* allocate RAM */
    if (ram_size > (256 << 20)) {
        fprintf(stderr,
                "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
                ((unsigned int)ram_size / (1 << 20)));
        exit(1);
    }
    memory_region_allocate_system_memory(ram, NULL, "mips_r4k.ram", ram_size);

    memory_region_add_subregion(address_space_mem, 0, ram);

    memory_region_init_io(iomem, NULL, &mips_qemu_ops, NULL, "mips-qemu", 0x10000);
    memory_region_add_subregion(address_space_mem, 0x1fbf0000, iomem);

    /* Try to load a BIOS image. If this fails, we continue regardless,
       but initialize the hardware ourselves. When a kernel gets
       preloaded we also initialize the hardware, since the BIOS wasn't
       run. */
    if (bios_name == NULL)
        bios_name = BIOS_FILENAME;
    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
    if (filename) {
        bios_size = get_image_size(filename);
    } else {
        bios_size = -1;
    }
#ifdef TARGET_WORDS_BIGENDIAN
    be = 1;
#else
    be = 0;
#endif
    if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) {
        bios = g_new(MemoryRegion, 1);
        memory_region_init_ram(bios, NULL, "mips_r4k.bios", BIOS_SIZE,
                               &error_fatal);
        vmstate_register_ram_global(bios);
        memory_region_set_readonly(bios, true);
        memory_region_add_subregion(get_system_memory(), 0x1fc00000, bios);

        load_image_targphys(filename, 0x1fc00000, BIOS_SIZE);
    } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
        uint32_t mips_rom = 0x00400000;
        if (!pflash_cfi01_register(0x1fc00000, NULL, "mips_r4k.bios", mips_rom,
                                   blk_by_legacy_dinfo(dinfo),
                                   sector_len, mips_rom / sector_len,
                                   4, 0, 0, 0, 0, be)) {
            fprintf(stderr, "qemu: Error registering flash memory.\n");
	}
    } else if (!qtest_enabled()) {
	/* not fatal */
        fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
		bios_name);
    }
    g_free(filename);

    if (kernel_filename) {
        loaderparams.ram_size = ram_size;
        loaderparams.kernel_filename = kernel_filename;
        loaderparams.kernel_cmdline = kernel_cmdline;
        loaderparams.initrd_filename = initrd_filename;
        reset_info->vector = load_kernel();
    }

    /* Init CPU internal devices */
    cpu_mips_irq_init_cpu(env);
    cpu_mips_clock_init(env);

    /* ISA bus: IO space at 0x14000000, mem space at 0x10000000 */
    memory_region_init_alias(isa_io, NULL, "isa-io",
                             get_system_io(), 0, 0x00010000);
    memory_region_init(isa_mem, NULL, "isa-mem", 0x01000000);
    memory_region_add_subregion(get_system_memory(), 0x14000000, isa_io);
    memory_region_add_subregion(get_system_memory(), 0x10000000, isa_mem);
    isa_bus = isa_bus_new(NULL, isa_mem, get_system_io(), &error_abort);

    /* The PIC is attached to the MIPS CPU INT0 pin */
    i8259 = i8259_init(isa_bus, env->irq[2]);
    isa_bus_irqs(isa_bus, i8259);

    rtc_init(isa_bus, 2000, NULL);

    pit = pit_init(isa_bus, 0x40, 0, NULL);

    serial_hds_isa_init(isa_bus, MAX_SERIAL_PORTS);

    isa_vga_init(isa_bus);

    if (nd_table[0].used)
        isa_ne2000_init(isa_bus, 0x300, 9, &nd_table[0]);

    ide_drive_get(hd, ARRAY_SIZE(hd));
    for(i = 0; i < MAX_IDE_BUS; i++)
        isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], ide_irq[i],
                     hd[MAX_IDE_DEVS * i],
		     hd[MAX_IDE_DEVS * i + 1]);

    isa_create_simple(isa_bus, "i8042");
}
Пример #29
0
/* PC hardware initialisation */
static void pc_q35_init(QEMUMachineInitArgs *args)
{
    ram_addr_t below_4g_mem_size, above_4g_mem_size;
    Q35PCIHost *q35_host;
    PCIHostState *phb;
    PCIBus *host_bus;
    PCIDevice *lpc;
    BusState *idebus[MAX_SATA_PORTS];
    ISADevice *rtc_state;
    ISADevice *floppy;
    MemoryRegion *pci_memory;
    MemoryRegion *rom_memory;
    MemoryRegion *ram_memory;
    GSIState *gsi_state;
    ISABus *isa_bus;
    int pci_enabled = 1;
    qemu_irq *cpu_irq;
    qemu_irq *gsi;
    qemu_irq *i8259;
    int i;
    ICH9LPCState *ich9_lpc;
    PCIDevice *ahci;
    DeviceState *icc_bridge;
    PcGuestInfo *guest_info;

    if (xen_enabled() && xen_hvm_init(&ram_memory) != 0) {
        fprintf(stderr, "xen hardware virtual machine initialisation failed\n");
        exit(1);
    }

    icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE);
    object_property_add_child(qdev_get_machine(), "icc-bridge",
                              OBJECT(icc_bridge), NULL);

    pc_cpus_init(args->cpu_model, icc_bridge);
    pc_acpi_init("q35-acpi-dsdt.aml");

    kvmclock_create();

    if (args->ram_size >= 0xb0000000) {
        above_4g_mem_size = args->ram_size - 0xb0000000;
        below_4g_mem_size = 0xb0000000;
    } else {
        above_4g_mem_size = 0;
        below_4g_mem_size = args->ram_size;
    }

    /* pci enabled */
    if (pci_enabled) {
        pci_memory = g_new(MemoryRegion, 1);
        memory_region_init(pci_memory, NULL, "pci", INT64_MAX);
        rom_memory = pci_memory;
    } else {
        pci_memory = NULL;
        rom_memory = get_system_memory();
    }

    guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
    guest_info->has_pci_info = has_pci_info;
    guest_info->isapc_ram_fw = false;

    /* allocate ram and load rom/bios */
    if (!xen_enabled()) {
        pc_memory_init(get_system_memory(),
                       args->kernel_filename, args->kernel_cmdline,
                       args->initrd_filename,
                       below_4g_mem_size, above_4g_mem_size,
                       rom_memory, &ram_memory, guest_info);
    }

    /* irq lines */
    gsi_state = g_malloc0(sizeof(*gsi_state));
    if (kvm_irqchip_in_kernel()) {
        kvm_pc_setup_irq_routing(pci_enabled);
        gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
                                 GSI_NUM_PINS);
    } else {
        gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
    }

    /* create pci host bus */
    q35_host = Q35_HOST_DEVICE(qdev_create(NULL, TYPE_Q35_HOST_DEVICE));

    object_property_add_child(qdev_get_machine(), "q35", OBJECT(q35_host), NULL);
    q35_host->mch.ram_memory = ram_memory;
    q35_host->mch.pci_address_space = pci_memory;
    q35_host->mch.system_memory = get_system_memory();
    q35_host->mch.address_space_io = get_system_io();
    q35_host->mch.below_4g_mem_size = below_4g_mem_size;
    q35_host->mch.above_4g_mem_size = above_4g_mem_size;
    q35_host->mch.guest_info = guest_info;
    /* pci */
    qdev_init_nofail(DEVICE(q35_host));
    phb = PCI_HOST_BRIDGE(q35_host);
    host_bus = phb->bus;
    /* create ISA bus */
    lpc = pci_create_simple_multifunction(host_bus, PCI_DEVFN(ICH9_LPC_DEV,
                                          ICH9_LPC_FUNC), true,
                                          TYPE_ICH9_LPC_DEVICE);
    ich9_lpc = ICH9_LPC_DEVICE(lpc);
    ich9_lpc->pic = gsi;
    ich9_lpc->ioapic = gsi_state->ioapic_irq;
    pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc,
                 ICH9_LPC_NB_PIRQS);
    pci_bus_set_route_irq_fn(host_bus, ich9_route_intx_pin_to_irq);
    isa_bus = ich9_lpc->isa_bus;

    /*end early*/
    isa_bus_irqs(isa_bus, gsi);

    if (kvm_irqchip_in_kernel()) {
        i8259 = kvm_i8259_init(isa_bus);
    } else if (xen_enabled()) {
        i8259 = xen_interrupt_controller_init();
    } else {
        cpu_irq = pc_allocate_cpu_irq();
        i8259 = i8259_init(isa_bus, cpu_irq[0]);
    }

    for (i = 0; i < ISA_NUM_IRQS; i++) {
        gsi_state->i8259_irq[i] = i8259[i];
    }
    if (pci_enabled) {
        ioapic_init_gsi(gsi_state, NULL);
    }
    qdev_init_nofail(icc_bridge);

    pc_register_ferr_irq(gsi[13]);

    /* init basic PC hardware */
    pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, false);

    /* connect pm stuff to lpc */
    ich9_lpc_pm_init(lpc);

    /* ahci and SATA device, for q35 1 ahci controller is built-in */
    ahci = pci_create_simple_multifunction(host_bus,
                                           PCI_DEVFN(ICH9_SATA1_DEV,
                                                     ICH9_SATA1_FUNC),
                                           true, "ich9-ahci");
    idebus[0] = qdev_get_child_bus(&ahci->qdev, "ide.0");
    idebus[1] = qdev_get_child_bus(&ahci->qdev, "ide.1");

    if (usb_enabled(false)) {
        /* Should we create 6 UHCI according to ich9 spec? */
        ehci_create_ich9_with_companions(host_bus, 0x1d);
    }

    /* TODO: Populate SPD eeprom data.  */
    smbus_eeprom_init(ich9_smb_init(host_bus,
                                    PCI_DEVFN(ICH9_SMB_DEV, ICH9_SMB_FUNC),
                                    0xb100),
                      8, NULL, 0);

    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, args->boot_order,
                 floppy, idebus[0], idebus[1], rtc_state);

    /* the rest devices to which pci devfn is automatically assigned */
    pc_vga_init(isa_bus, host_bus);
    pc_nic_init(isa_bus, host_bus);
    if (pci_enabled) {
        pc_pci_device_init(host_bus);
    }

    if (has_pvpanic) {
        pvpanic_init(isa_bus);
    }
}
Пример #30
0
/* PC hardware initialisation */
static void pc_init1(MachineState *machine,
                     const char *host_type, const char *pci_type)
{
    PCMachineState *pcms = PC_MACHINE(machine);
    PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
    MemoryRegion *system_memory = get_system_memory();
    MemoryRegion *system_io = get_system_io();
    int i;
    PCIBus *pci_bus;
    ISABus *isa_bus;
    PCII440FXState *i440fx_state;
    int piix3_devfn = -1;
    qemu_irq *gsi;
    qemu_irq *i8259;
    qemu_irq smi_irq;
    GSIState *gsi_state;
    DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
    BusState *idebus[MAX_IDE_BUS];
    ISADevice *rtc_state;
    MemoryRegion *ram_memory;
    MemoryRegion *pci_memory;
    MemoryRegion *rom_memory;
    ram_addr_t lowmem;

    /*
     * Calculate ram split, for memory below and above 4G.  It's a bit
     * complicated for backward compatibility reasons ...
     *
     *  - Traditional split is 3.5G (lowmem = 0xe0000000).  This is the
     *    default value for max_ram_below_4g now.
     *
     *  - Then, to gigabyte align the memory, we move the split to 3G
     *    (lowmem = 0xc0000000).  But only in case we have to split in
     *    the first place, i.e. ram_size is larger than (traditional)
     *    lowmem.  And for new machine types (gigabyte_align = true)
     *    only, for live migration compatibility reasons.
     *
     *  - Next the max-ram-below-4g option was added, which allowed to
     *    reduce lowmem to a smaller value, to allow a larger PCI I/O
     *    window below 4G.  qemu doesn't enforce gigabyte alignment here,
     *    but prints a warning.
     *
     *  - Finally max-ram-below-4g got updated to also allow raising lowmem,
     *    so legacy non-PAE guests can get as much memory as possible in
     *    the 32bit address space below 4G.
     *
     *  - Note that Xen has its own ram setp code in xen_ram_init(),
     *    called via xen_hvm_init().
     *
     * Examples:
     *    qemu -M pc-1.7 -m 4G    (old default)    -> 3584M low,  512M high
     *    qemu -M pc -m 4G        (new default)    -> 3072M low, 1024M high
     *    qemu -M pc,max-ram-below-4g=2G -m 4G     -> 2048M low, 2048M high
     *    qemu -M pc,max-ram-below-4g=4G -m 3968M  -> 3968M low (=4G-128M)
     */
    if (xen_enabled()) {
        xen_hvm_init(pcms, &ram_memory);
    } else {
        if (!pcms->max_ram_below_4g) {
            pcms->max_ram_below_4g = 0xe0000000; /* default: 3.5G */
        }
        lowmem = pcms->max_ram_below_4g;
        if (machine->ram_size >= pcms->max_ram_below_4g) {
            if (pcmc->gigabyte_align) {
                if (lowmem > 0xc0000000) {
                    lowmem = 0xc0000000;
                }
                if (lowmem & ((1ULL << 30) - 1)) {
                    error_report("Warning: Large machine and max_ram_below_4g "
                                 "(%" PRIu64 ") not a multiple of 1G; "
                                 "possible bad performance.",
                                 pcms->max_ram_below_4g);
                }
            }
        }

        if (machine->ram_size >= lowmem) {
            pcms->above_4g_mem_size = machine->ram_size - lowmem;
            pcms->below_4g_mem_size = lowmem;
        } else {
            pcms->above_4g_mem_size = 0;
            pcms->below_4g_mem_size = machine->ram_size;
        }
    }

    pc_cpus_init(pcms);

    if (kvm_enabled() && pcmc->kvmclock_enabled) {
        kvmclock_create();
    }

    if (pcmc->pci_enabled) {
        pci_memory = g_new(MemoryRegion, 1);
        memory_region_init(pci_memory, NULL, "pci", UINT64_MAX);
        rom_memory = pci_memory;
    } else {
        pci_memory = NULL;
        rom_memory = system_memory;
    }

    pc_guest_info_init(pcms);

    if (pcmc->smbios_defaults) {
        MachineClass *mc = MACHINE_GET_CLASS(machine);
        /* These values are guest ABI, do not change */
        smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)",
                            mc->name, pcmc->smbios_legacy_mode,
                            pcmc->smbios_uuid_encoded,
                            SMBIOS_ENTRY_POINT_21);
    }

    /* allocate ram and load rom/bios */
    if (!xen_enabled()) {
        pc_memory_init(pcms, system_memory,
                       rom_memory, &ram_memory);
    } else if (machine->kernel_filename != NULL) {
        /* For xen HVM direct kernel boot, load linux here */
        xen_load_linux(pcms);
    }

    gsi_state = g_malloc0(sizeof(*gsi_state));
    if (kvm_ioapic_in_kernel()) {
        kvm_pc_setup_irq_routing(pcmc->pci_enabled);
        gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
                                 GSI_NUM_PINS);
    } else {
        gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
    }

    if (pcmc->pci_enabled) {
        pci_bus = i440fx_init(host_type,
                              pci_type,
                              &i440fx_state, &piix3_devfn, &isa_bus, gsi,
                              system_memory, system_io, machine->ram_size,
                              pcms->below_4g_mem_size,
                              pcms->above_4g_mem_size,
                              pci_memory, ram_memory);
        pcms->bus = pci_bus;
    } else {
        pci_bus = NULL;
        i440fx_state = NULL;
        isa_bus = isa_bus_new(NULL, get_system_memory(), system_io,
                              &error_abort);
        no_hpet = 1;
    }
    isa_bus_irqs(isa_bus, gsi);

    if (kvm_pic_in_kernel()) {
        i8259 = kvm_i8259_init(isa_bus);
    } else if (xen_enabled()) {
        i8259 = xen_interrupt_controller_init();
    } else {
        i8259 = i8259_init(isa_bus, pc_allocate_cpu_irq());
    }

    for (i = 0; i < ISA_NUM_IRQS; i++) {
        gsi_state->i8259_irq[i] = i8259[i];
    }
    g_free(i8259);
    if (pcmc->pci_enabled) {
        ioapic_init_gsi(gsi_state, "i440fx");
    }

    pc_register_ferr_irq(gsi[13]);

    pc_vga_init(isa_bus, pcmc->pci_enabled ? pci_bus : NULL);

    assert(pcms->vmport != ON_OFF_AUTO__MAX);
    if (pcms->vmport == ON_OFF_AUTO_AUTO) {
        pcms->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON;
    }

    /* init basic PC hardware */
    pc_basic_device_init(isa_bus, gsi, &rtc_state, true,
                         (pcms->vmport != ON_OFF_AUTO_ON), 0x4);

    pc_nic_init(isa_bus, pci_bus);

    ide_drive_get(hd, ARRAY_SIZE(hd));
    if (pcmc->pci_enabled) {
        PCIDevice *dev;
        if (xen_enabled()) {
            dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1);
        } else {
            dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
        }
        idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
        idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
    } else {
        for(i = 0; i < MAX_IDE_BUS; i++) {
            ISADevice *dev;
            char busname[] = "ide.0";
            dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i],
                               ide_irq[i],
                               hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
            /*
             * The ide bus name is ide.0 for the first bus and ide.1 for the
             * second one.
             */
            busname[4] = '0' + i;
            idebus[i] = qdev_get_child_bus(DEVICE(dev), busname);
        }
    }

    pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state);

    if (pcmc->pci_enabled && machine_usb(machine)) {
        pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci");
    }

    if (pcmc->pci_enabled && acpi_enabled) {
        DeviceState *piix4_pm;
        I2CBus *smbus;

        smi_irq = qemu_allocate_irq(pc_acpi_smi_interrupt, first_cpu, 0);
        /* TODO: Populate SPD eeprom data.  */
        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
                              gsi[9], smi_irq,
                              pc_machine_is_smm_enabled(pcms),
                              &piix4_pm);
        smbus_eeprom_init(smbus, 8, NULL, 0);

        object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
                                 TYPE_HOTPLUG_HANDLER,
                                 (Object **)&pcms->acpi_dev,
                                 object_property_allow_set_link,
                                 OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort);
        object_property_set_link(OBJECT(machine), OBJECT(piix4_pm),
                                 PC_MACHINE_ACPI_DEVICE_PROP, &error_abort);
    }

    if (pcmc->pci_enabled) {
        pc_pci_device_init(pci_bus);
    }

    if (pcms->acpi_nvdimm_state.is_enabled) {
        nvdimm_init_acpi_state(&pcms->acpi_nvdimm_state, system_io,
                               pcms->fw_cfg, OBJECT(pcms));
    }
}