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

📄 pc.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
        isa_bios_size = 128 * 1024;    cpu_register_physical_memory(0xd0000, (192 * 1024) - isa_bios_size,                                 IO_MEM_UNASSIGNED);    cpu_register_physical_memory(0x100000 - isa_bios_size,                                 isa_bios_size,                                 (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);    {        ram_addr_t option_rom_offset;        int size, offset;        offset = 0;        for (i = 0; i < nb_option_roms; i++) {            size = get_image_size(option_rom[i]);            if (size < 0) {                fprintf(stderr, "Could not load option rom '%s'\n",                        option_rom[i]);                exit(1);            }            if (size > (0x10000 - offset))                goto option_rom_error;            option_rom_offset = qemu_ram_alloc(size);            ret = load_image_targphys(option_rom[i], option_rom_offset, size);            if (ret != size) {            option_rom_error:                fprintf(stderr, "Too many option ROMS\n");                exit(1);            }            size = (size + 4095) & ~4095;            cpu_register_physical_memory(0xd0000 + offset,                                         size, option_rom_offset | IO_MEM_ROM);            offset += size;        }    }    /* map all the bios at the top of memory */    cpu_register_physical_memory((uint32_t)(-bios_size),                                 bios_size, bios_offset | IO_MEM_ROM);#else    vga_ram_addr = 0; /* this is not supposed to be used */#endif /* !CONFIG_DM */    bochs_bios_init();    if (linux_boot)	load_linux(kernel_filename, initrd_filename, kernel_cmdline);    cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1);    i8259 = i8259_init(cpu_irq[0]);    ferr_irq = i8259[13];    if (pci_enabled) {        pci_bus = i440fx_init(&i440fx_state, i8259);        piix3_devfn = piix3_init(pci_bus, -1);    } else {        pci_bus = NULL;    }    /* init basic PC hardware */    register_ioport_write(0x80, 1, 1, ioport80_write, NULL);    register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);    if (cirrus_vga_enabled) {        if (pci_enabled) {            pci_cirrus_vga_init(pci_bus,                                ds, phys_ram_base + vga_ram_addr,                                vga_ram_addr, vga_ram_size);        } else {            isa_cirrus_vga_init(ds, phys_ram_base + vga_ram_addr,                                vga_ram_addr, vga_ram_size);        }    } else if (vmsvga_enabled) {        if (pci_enabled)            pci_vmsvga_init(pci_bus, ds, phys_ram_base + vga_ram_addr,                            vga_ram_addr, vga_ram_size);        else            fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);    } else {        if (pci_enabled) {            pci_vga_init(pci_bus, ds, phys_ram_base + vga_ram_addr,                         vga_ram_addr, vga_ram_size, 0, 0);        } else {            isa_vga_init(ds, phys_ram_base + vga_ram_addr,                         vga_ram_addr, vga_ram_size);        }    }#ifdef CONFIG_PASSTHROUGH    /* Pass-through Initialization     * init libpci even direct_pci is null, as can hotplug a dev runtime     */    if ( pci_enabled )    {        rc = pt_init(pci_bus, direct_pci);         if ( rc < 0 )        {            fprintf(logfile, "Error: Initialization failed for pass-through devices\n");            exit(1);        }    }#endif    rtc_state = rtc_init(0x70, i8259[8]);    register_ioport_read(0x92, 1, 1, ioport92_read, NULL);    register_ioport_write(0x92, 1, 1, ioport92_write, NULL);#ifndef CONFIG_DM    if (pci_enabled) {        ioapic = ioapic_init();    }    pit = pit_init(0x40, i8259[0]);    pcspk_init(pit);    if (pci_enabled) {        pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic);    }#endif /* !CONFIG_DM */    if (pci_enabled)        pci_xen_platform_init(pci_bus);    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]);        }    }    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {        if (parallel_hds[i]) {            parallel_init(parallel_io[i], i8259[parallel_irq[i]],                          parallel_hds[i]);        }    }    for(i = 0; i < nb_nics; i++) {        nd = &nd_table[i];        if (!nd->model) {            if (pci_enabled) {                nd->model = "ne2k_pci";            } else {                nd->model = "ne2k_isa";            }        }        if (strcmp(nd->model, "ne2k_isa") == 0) {            pc_init_ne2k_isa(nd, i8259);        } else if (pci_enabled) {            if (strcmp(nd->model, "?") == 0)                fprintf(stderr, "qemu: Supported ISA NICs: ne2k_isa\n");            pci_nic_init(pci_bus, nd, -1);        } else if (strcmp(nd->model, "?") == 0) {            fprintf(stderr, "qemu: Supported ISA NICs: ne2k_isa\n");            exit(1);        } else {            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);            exit(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 (pci_enabled) {        pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1, i8259);    } else {        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]);        }    }#ifdef HAS_TPM    if (has_tpm_device())        tpm_tis_init(&i8259[11]);#endif    i8042_init(i8259[1], i8259[12], 0x60);    DMA_init(0);#ifdef HAS_AUDIO    audio_init(pci_enabled ? pci_bus : NULL, i8259);#endif    for(i = 0; i < MAX_FD; i++) {        index = drive_get_index(IF_FLOPPY, 0, i);	if (index != -1)	    fd[i] = drives_table[index].bdrv;	else	    fd[i] = NULL;    }    floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);    cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd);    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;        /* TODO: Populate SPD eeprom data.  */        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, i8259[9]);	if (smbus) {	    for (i = 0; i < 8; i++) {		smbus_eeprom_device_init(smbus, 0x50 + i, eeprom_buf + (i * 256));	    }        }    }    if (i440fx_state) {        i440fx_init_memory_mappings(i440fx_state);    }    if (pci_enabled) {	int max_bus;        int bus, unit;        void *scsi;        max_bus = drive_get_max_bus(IF_SCSI);	for (bus = 0; bus <= max_bus; bus++) {            scsi = lsi_scsi_init(pci_bus, -1);            for (unit = 0; unit < LSI_MAX_DEVS; unit++) {	        index = drive_get_index(IF_SCSI, bus, unit);		if (index == -1)		    continue;		lsi_scsi_attach(scsi, drives_table[index].bdrv, unit);	    }        }    }    if (pci_enabled) {        PCI_EMULATION_INFO *p;        for (p = PciEmulationInfoHead; p != NULL; p = p->next) {            pci_emulation_init(pci_bus, p);        }    }}static void pc_init_pci(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,                        const char *direct_pci){    pc_init1(ram_size, vga_ram_size, boot_device, ds,             kernel_filename, kernel_cmdline,             initrd_filename, 1, cpu_model,             direct_pci);}static void pc_init_isa(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,                        const char *direct_pci){    pc_init1(ram_size, vga_ram_size, boot_device, ds,             kernel_filename, kernel_cmdline,             initrd_filename, 0, cpu_model,             direct_pci);}/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)   BIOS will read it and start S3 resume at POST Entry*/void cmos_set_s3_resume(void){    if (rtc_state)        rtc_set_memory(rtc_state, 0xF, 0xFE);}QEMUMachine pc_machine = {    "pc",    "Standard PC",    pc_init_pci,    VGA_RAM_SIZE + PC_MAX_BIOS_SIZE,};QEMUMachine isapc_machine = {    "isapc",    "ISA-only PC",    pc_init_isa,    VGA_RAM_SIZE + PC_MAX_BIOS_SIZE,};/* * Evil helper for non-relocatable kernels * * So it works out like this: * *  0x100000  - Xen HVM firmware lives here. Kernel wants to boot here * * You can't both live there and HVM firmware is needed first, thus * our plan is * *  0x200000              - kernel is loaded here by QEMU *  0x200000+kernel_size  - helper code is put here by QEMU * * code32_switch in kernel header is set to point at out helper * code at 0x200000+kernel_size * * Our helper basically does memmove(0x100000,0x200000,kernel_size) * and then jmps to  0x1000000. * * So we've overwritten the HVM firmware (which was no longer * needed) and the non-relocatable kernel can happily boot * at its usual address. * * Simple, eh ? * * Well the assembler needed to do this is fairly short: * *  # Load segments *    cld                          *    cli                          *    movl $0x18,%eax *    mov %ax,%ds                  *    mov %ax,%es                  *    mov %ax,%fs                  *    mov %ax,%gs                  *    mov %ax,%ss                  * *  # Move the kernel into position *    xor    %edx,%edx             *_doloop:                         *    movzbl 0x600000(%edx),%eax   *    mov    %al,0x100000(%edx)    *    add    $0x1,%edx             *    cmp    $0x500000,%edx        *    jne    _doloop               * *  # start kernel *    xorl %ebx,%ebx               *    mov    $0x100000,%ecx        *    jmp    *%ecx                 * */static void setup_relocator(target_phys_addr_t addr, target_phys_addr_t src, target_phys_addr_t dst, size_t len){  /* Now this assembler corresponds to follow machine code, with our args from QEMU spliced in :-) */  unsigned char buf[] = {    /* Load segments */    0xfc,                         /* cld               */    0xfa,                         /* cli               */     0xb8, 0x18, 0x00, 0x00, 0x00, /* mov    $0x18,%eax */    0x8e, 0xd8,                   /* mov    %eax,%ds   */    0x8e, 0xc0,                   /* mov    %eax,%es   */    0x8e, 0xe0,                   /* mov    %eax,%fs   */    0x8e, 0xe8,                   /* mov    %eax,%gs   */    0x8e, 0xd0,                   /* mov    %eax,%ss   */    0x31, 0xd2,                   /* xor    %edx,%edx  */      /* Move the kernel into position */    0x0f, 0xb6, 0x82, (src&0xff), ((src>>8)&0xff), ((src>>16)&0xff), ((src>>24)&0xff), /*   movzbl $src(%edx),%eax */    0x88, 0x82, (dst&0xff), ((dst>>8)&0xff), ((dst>>16)&0xff), ((dst>>24)&0xff),       /*   mov    %al,$dst(%edx)  */    0x83, 0xc2, 0x01,                                                                  /*   add    $0x1,%edx       */    0x81, 0xfa, (len&0xff), ((len>>8)&0xff), ((len>>16)&0xff), ((len>>24)&0xff),       /*   cmp    $len,%edx       */    0x75, 0xe8,                                                                        /*   jne    13 <_doloop>    */    /* Start kernel */    0x31, 0xdb,                                                                        /*   xor    %ebx,%ebx       */    0xb9, (dst&0xff), ((dst>>8)&0xff), ((dst>>16)&0xff), ((dst>>24)&0xff),             /*   mov    $dst,%ecx  */    0xff, 0xe1,                                                                        /*   jmp    *%ecx           */  };  cpu_physical_memory_rw(addr, buf, sizeof(buf), 1);  fprintf(stderr, "qemu: helper at 0x%x of size %d bytes, to move kernel of %d bytes from 0x%x to 0x%x\n",	  (int)addr, (int)sizeof(buf), (int)len, (int)src, (int)dst);}static void xen_relocator_hook(target_phys_addr_t *prot_addr_upd,                               uint16_t protocol,			       const uint8_t header[], int kernel_size,			       target_phys_addr_t real_addr, int real_size){    target_phys_addr_t prot_addr = *prot_addr_upd;    /* Urgh, Xen's HVM firmware lives at 0x100000, but that's also the     * address Linux wants to start life at prior to relocatable support     */    fprintf(stderr, "checking need for relocation, header protocol: %x\n",	    protocol);    if (prot_addr != 0x10000) { /* old low kernels are OK */	target_phys_addr_t reloc_prot_addr = 0x200000;	        if (protocol >= 0x205 && (header[0x234] & 1)) {	    /* Relocatable automatically */	    stl_phys(real_addr+0x214, reloc_prot_addr);	    fprintf(stderr, "qemu: kernel is relocatable\n");	} else {	    /* Setup a helper which moves  kernel back to	     * its expected addr after firmware has got out	     * of the way. We put a helper at  reloc_prot_addr+kernel_size.	     * It moves kernel from reloc_prot_addr to prot_addr and	     * then jumps to prot_addr. Yes this is sick.	     */	    fprintf(stderr, "qemu: kernel is NOT relocatable\n");	    stl_phys(real_addr+0x214, reloc_prot_addr + kernel_size);	    setup_relocator(reloc_prot_addr + kernel_size, reloc_prot_addr, prot_addr, kernel_size);	}	fprintf(stderr, "qemu: loading kernel protected mode (%x bytes) at %#zx\n",		kernel_size, (size_t)reloc_prot_addr);	fprintf(stderr, "qemu: loading kernel real mode (%x bytes) at %#zx\n",		real_size, (size_t)real_addr);        *prot_addr_upd = reloc_prot_addr;    }}#ifdef CONFIG_DMvoid vmport_init(void) { }int apic_init(CPUX86State *env) { return 0; }#endif /* CONFIG_DM */

⌨️ 快捷键说明

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