⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mips_malta.c

📁 qemu性能直逼VMware的仿真器QEMU 的模擬速度約為實機的 25%;約為 Bochs 的 60 倍。Plex86、User-Mode-Linux、VMware 和 Virtual PC 則比
💻 C
📖 第 1 页 / 共 2 页
字号:
    qemu_chr_printf(s->display, "+--------+\r\n");    qemu_chr_printf(s->display, "\n");    qemu_chr_printf(s->display, "Malta ASCII\r\n");    qemu_chr_printf(s->display, "+--------+\r\n");    qemu_chr_printf(s->display, "+        +\r\n");    qemu_chr_printf(s->display, "+--------+\r\n");    malta_fpga_reset(s);    qemu_register_reset(malta_fpga_reset, s);    return s;}/* Audio support */#ifdef HAS_AUDIOstatic void audio_init (PCIBus *pci_bus){    struct soundhw *c;    int audio_enabled = 0;    for (c = soundhw; !audio_enabled && c->name; ++c) {        audio_enabled = c->enabled;    }    if (audio_enabled) {        AudioState *s;        s = AUD_init ();        if (s) {            for (c = soundhw; c->name; ++c) {                if (c->enabled) {                    if (c->isa) {                        fprintf(stderr, "qemu: Unsupported Sound Card: %s\n", c->name);                        exit(1);                    }                    else {                        if (pci_bus) {                            c->init.init_pci (pci_bus, s);                        }                    }                }            }        }    }}#endif/* Network support */static void network_init (PCIBus *pci_bus){    int i;    NICInfo *nd;    for(i = 0; i < nb_nics; i++) {        nd = &nd_table[i];        if (!nd->model) {            nd->model = "pcnet";        }        if (i == 0  && strcmp(nd->model, "pcnet") == 0) {            /* The malta board has a PCNet card using PCI SLOT 11 */            pci_nic_init(pci_bus, nd, 88);        } else {            pci_nic_init(pci_bus, nd, -1);        }    }}/* ROM and pseudo bootloader   The following code implements a very very simple bootloader. It first   loads the registers a0 to a3 to the values expected by the OS, and   then jump at the kernel address.   The bootloader should pass the locations of the kernel arguments and   environment variables tables. Those tables contain the 32-bit address   of NULL terminated strings. The environment variables table should be   terminated by a NULL address.   For a simpler implementation, the number of kernel arguments is fixed   to two (the name of the kernel and the command line), and the two   tables are actually the same one.   The registers a0 to a3 should contain the following values:     a0 - number of kernel arguments     a1 - 32-bit address of the kernel arguments table     a2 - 32-bit address of the environment variables table     a3 - RAM size in bytes*/static void write_bootloader (CPUState *env, unsigned long bios_offset, int64_t kernel_addr){    uint32_t *p;    /* Small bootloader */    p = (uint32_t *) (phys_ram_base + bios_offset);    stl_raw(p++, 0x0bf00010);                                      /* j 0x1fc00040 */    stl_raw(p++, 0x00000000);                                      /* nop */    /* Second part of the bootloader */    p = (uint32_t *) (phys_ram_base + bios_offset + 0x040);    stl_raw(p++, 0x3c040000);                                      /* lui a0, 0 */    stl_raw(p++, 0x34840002);                                      /* ori a0, a0, 2 */    stl_raw(p++, 0x3c050000 | ((ENVP_ADDR >> 16) & 0xffff));       /* lui a1, high(ENVP_ADDR) */    stl_raw(p++, 0x34a50000 | (ENVP_ADDR & 0xffff));               /* ori a1, a0, low(ENVP_ADDR) */    stl_raw(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */    stl_raw(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff));         /* ori a2, a2, low(ENVP_ADDR + 8) */    stl_raw(p++, 0x3c070000 | (env->ram_size >> 16));              /* lui a3, high(env->ram_size) */    stl_raw(p++, 0x34e70000 | (env->ram_size & 0xffff));           /* ori a3, a3, low(env->ram_size) */    stl_raw(p++, 0x3c1f0000 | ((kernel_addr >> 16) & 0xffff));     /* lui ra, high(kernel_addr) */;    stl_raw(p++, 0x37ff0000 | (kernel_addr & 0xffff));             /* ori ra, ra, low(kernel_addr) */    stl_raw(p++, 0x03e00008);                                      /* jr ra */    stl_raw(p++, 0x00000000);                                      /* nop */}static void prom_set(int index, const char *string, ...){    va_list ap;    int32_t *p;    int32_t table_addr;    char *s;    if (index >= ENVP_NB_ENTRIES)        return;    p = (int32_t *) (phys_ram_base + ENVP_ADDR + VIRT_TO_PHYS_ADDEND);    p += index;    if (string == NULL) {        stl_raw(p, 0);        return;    }    table_addr = ENVP_ADDR + sizeof(int32_t) * ENVP_NB_ENTRIES + index * ENVP_ENTRY_SIZE;    s = (char *) (phys_ram_base + VIRT_TO_PHYS_ADDEND + table_addr);    stl_raw(p, table_addr);    va_start(ap, string);    vsnprintf (s, ENVP_ENTRY_SIZE, string, ap);    va_end(ap);}/* Kernel */static int64_t load_kernel (CPUState *env){    int64_t kernel_addr = 0;    int index = 0;    long initrd_size;    if (load_elf(env->kernel_filename, VIRT_TO_PHYS_ADDEND, &kernel_addr) < 0) {        fprintf(stderr, "qemu: could not load kernel '%s'\n",                env->kernel_filename);      exit(1);    }    /* load initrd */    initrd_size = 0;    if (env->initrd_filename) {        initrd_size = load_image(env->initrd_filename,                                 phys_ram_base + INITRD_LOAD_ADDR + VIRT_TO_PHYS_ADDEND);        if (initrd_size == (target_ulong) -1) {            fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",                    env->initrd_filename);            exit(1);        }    }    /* Store command line.  */    prom_set(index++, env->kernel_filename);    if (initrd_size > 0)        prom_set(index++, "rd_start=0x" TLSZ " rd_size=%li %s", INITRD_LOAD_ADDR, initrd_size, env->kernel_cmdline);    else        prom_set(index++, env->kernel_cmdline);    /* Setup minimum environment variables */    prom_set(index++, "memsize");    prom_set(index++, "%i", env->ram_size);    prom_set(index++, "modetty0");    prom_set(index++, "38400n8r");    prom_set(index++, NULL);    return kernel_addr;}static void main_cpu_reset(void *opaque){    CPUState *env = opaque;    cpu_reset(env);    /* The bootload does not need to be rewritten as it is located in a       read only location. The kernel location and the arguments table       location does not change. */    if (env->kernel_filename)        load_kernel (env);}void mips_malta_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){    char buf[1024];    unsigned long bios_offset;    int64_t kernel_addr;    PCIBus *pci_bus;    CPUState *env;    RTCState *rtc_state;    /* fdctrl_t *floppy_controller; */    MaltaFPGAState *malta_fpga;    int ret;    env = cpu_init();    register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);    qemu_register_reset(main_cpu_reset, env);    /* allocate RAM */    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);    /* Map the bios at two physical locations, as on the real board */    bios_offset = ram_size + vga_ram_size;    cpu_register_physical_memory(0x1e000000LL,                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);    cpu_register_physical_memory(0x1fc00000LL,                                 BIOS_SIZE, bios_offset | IO_MEM_ROM);    /* Load a BIOS image except if a kernel image has been specified. In       the later case, just write a small bootloader to the flash       location. */    if (kernel_filename) {        env->ram_size = ram_size;        env->kernel_filename = kernel_filename;        env->kernel_cmdline = kernel_cmdline;        env->initrd_filename = initrd_filename;        kernel_addr = load_kernel(env);        write_bootloader(env, bios_offset, kernel_addr);    } else {        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);        ret = load_image(buf, phys_ram_base + bios_offset);        if (ret != BIOS_SIZE) {            fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",                    buf);            exit(1);        }    }    /* Board ID = 0x420 (Malta Board with CoreLV)       XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should       map to the board ID. */    stl_raw(phys_ram_base + bios_offset + 0x10, 0x00000420);    /* Init internal devices */    cpu_mips_clock_init(env);    cpu_mips_irqctrl_init();    /* FPGA */    malta_fpga = malta_fpga_init(0x1f000000LL);    /* Interrupt controller */    isa_pic = pic_init(pic_irq_request, env);    /* Northbridge */    pci_bus = pci_gt64120_init(isa_pic);    /* Southbridge */    piix4_init(pci_bus, 80);    pci_piix3_ide_init(pci_bus, bs_table, 81);    usb_uhci_init(pci_bus, 82);    piix4_pm_init(pci_bus, 83);    pit = pit_init(0x40, 0);    DMA_init(0);    /* Super I/O */    kbd_init();    rtc_state = rtc_init(0x70, 8);    serial_init(&pic_set_irq_new, isa_pic, 0x3f8, 4, serial_hds[0]);    parallel_init(0x378, 7, parallel_hds[0]);    /* XXX: The floppy controller does not work correctly, something is       probably wrong.    floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table); */    /* Sound card */#ifdef HAS_AUDIO    audio_init(pci_bus);#endif    /* Network card */    network_init(pci_bus);}QEMUMachine mips_malta_machine = {    "malta",    "MIPS Malta Core LV",    mips_malta_init,};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -