status_t arch_int_init_io(kernel_args* args) { msi_init(args); ioapic_init(args); return B_OK; }
void arch_init() { pci_init(); #ifdef __CONFIG_ENABLE_MPTABLES__ mptables_parse(); ioapic_init(); // MUST BE AFTER PCI/ISA INIT! // TODO: move these back to regular init. requires fixing the // __CONFIG_NETWORKING__ inits to not need multiple cores running. #endif // this returns when all other cores are done and ready to receive IPIs #ifdef __CONFIG_SINGLE_CORE__ smp_percpu_init(); #else smp_boot(); #endif proc_init(); /* EXPERIMENTAL NETWORK FUNCTIONALITY * To enable, define __CONFIG_NETWORKING__ in your Makelocal * If enabled, will load the rl8168 driver (if device exists) * and will a boot into userland matrix, so remote syscalls can be performed. * If in simulation, will do some debugging information with the ne2k device * * Note: If you use this, you should also define the mac address of the * teathered machine via USER_MAC_ADDRESS in Makelocal. * * Additionally, you should have a look at the syscall server in the tools directory */ #ifdef __CONFIG_NETWORKING__ #ifdef __CONFIG_SINGLE_CORE__ warn("You currently can't have networking if you boot into single core mode!!\n"); #else rl8168_init(); ne2k_init(); e1000_init(); #endif // __CONFIG_SINGLE_CORE__ #endif // __CONFIG_NETWORKING__ perfmon_init(); #ifdef __CONFIG_MONITOR_ON_INT__ /* Handler to read a char from the interrupt source and call the monitor. * Need to read the character so the device will send another interrupt. * Note this will read from both the serial and the keyboard, and throw away * the result. We condition, since we don't want to trigger on a keyboard * up interrupt */ void mon_int(struct trapframe *tf, void *data) { // Enable interrupts here so that we can receive // other interrupts (e.g. from the NIC) enable_irq(); if (cons_getc()) monitor(0); }
void kernel_entry (multiboot_info* bootinfo) { clear_screen(); puts("Kernel loaded.\n"); gdt_install(); puts("GDT initialised.\n"); idt_install(); puts("IDT initialised.\n"); memman_init(bootinfo); kheap_init(); fat32_init(); // TODO: figure out how to do it safely //acpi_init(); apic_init(); ioapic_init(); // keyboard only for now register_handler(0x21, keyboard_handler); register_handler(0xD, gpf_handler); syscalls_init(); // maybe syscalls_init() like acpi_init, apic_init, etc... there should be common naming timer_init(0x20, 0x002fffff, 0xB, 1); // vector, counter, divider, periodic -- check manual before using // sets up kernel task and registers handler for timer scheduler_init(); // registers locking sys monitor_init(); keyboard_init(); // testing scheduler if (fork_kernel() == 0) { if (!exec("SHELL")) { // something horrible happend // exit() } exit(); } else { for(;;) { asm volatile("hlt"); } } asm ("sti"); // release monsters, it can be set earlier, but fails horribly if set before acpi_init for(;;); }
void inmate_main(void) { printk_uart_base = UART_BASE; int_init(); int_set_handler(IRQ_VECTOR, irq_handler); ioapic_init(); ioapic_pin_set_vector(ACPI_GSI, TRIGGER_LEVEL_ACTIVE_HIGH, IRQ_VECTOR); printk("Press power button to trigger an IRQ\n" "Note: ACPI IRQs are broken for Linux now.\n"); asm volatile("sti"); while (1) asm volatile("hlt"); }
void inmate_main(void) { printk_uart_base = UART_BASE; int_init(); int_set_handler(IRQ_VECTOR, irq_handler); ioapic_init(); ioapic_pin_set_vector(ACPI_GSI, TRIGGER_LEVEL_ACTIVE_HIGH, IRQ_VECTOR); pm_base = comm_region->pm_timer_address - 8; outw(inw(pm_base + PM1_ENABLE) | PM1_TMR_EN, pm_base + PM1_ENABLE); printk("Note: ACPI IRQs are broken for Linux now.\n"); asm volatile("sti"); while (1) asm volatile("hlt"); }
static void vm_reset_vdevs(struct vmctx *ctx) { /* * The current virtual devices doesn't define virtual * device reset function. So we call vdev deinit/init * pairing to emulate the device reset operation. * * pci/ioapic deinit/init is needed because of dependency * of pci irq allocation/free. * * acpi build is necessary because irq for each vdev * could be assigned with different number after reset. */ atkbdc_deinit(ctx); if (debugexit_enabled) deinit_debugexit(); vhpet_deinit(ctx); vpit_deinit(ctx); vrtc_deinit(ctx); deinit_pci(ctx); pci_irq_deinit(ctx); ioapic_deinit(); pci_irq_init(ctx); atkbdc_init(ctx); vrtc_init(ctx); vpit_init(ctx); vhpet_init(ctx); if (debugexit_enabled) init_debugexit(); ioapic_init(ctx); init_pci(ctx); if (acpi) { acpi_build(ctx, guest_ncpus); } }
bool apic_init(){ char apic[4] = {'A', 'P', 'I', 'C'}; MADT_t *madt = (MADT_t *)acpi_table(apic); if (madt != null){ // Gather Local and IO APIC(s) _lapic_addr = (uint64)madt->lapic_addr; // Enumerate APICs uint64 length = (madt->h.length - sizeof(MADT_t) + 4); APICHeader_t *ah = (APICHeader_t *)(&madt->ptr); while (length > 0){ #if DEBUG == 1 //debug_print(DC_WGR, "APIC type: %d", ah->type); #endif switch (ah->type){ case APIC_TYPE_LAPIC: // Test if it's enabled - if not - don't touch it if ((((LocalAPIC_t *)ah)->flags & 1) != 0){ _lapic[_lapic_count] = (LocalAPIC_t *)ah; _lapic_count ++; } break; case APIC_TYPE_IOAPIC: _ioapic[_ioapic_count] = (IOAPIC_t *)ah; _ioapic_count ++; break; } length -= ah->length; ah = (APICHeader_t *)(((uint64)ah) + ah->length); } #if DEBUG == 1 debug_print(DC_WB, "CPU count:%d", _lapic_count); #endif // Initialize Local APIC lapic_init(); // Initialize IO APIC ioapic_init(); } }
/** * Bootstrap processor starts running C code here. */ int main(void) { /** * ld会生成如下几个变量用来标识程序的段 * * _etext(etext) 正文段结束后第一个地址 * _edata(edata) 数据段结束后第一个地址 * _end(end) bss段结束后第一个地址 */ extern char edata[], end[]; // clear BSS memset(edata, 0, end - edata); // collect info about this machine mp_init(); lapic_init(mp_bcpu()); cprintf("\ncpu%d: starting myos\n\n", cpu()); cprintf("Welcome to myos !\n"); pinit(); // process table binit(); // buffer cache pic_init(); // interrupt controller ioapic_init(); // another interrupt controller kinit(); // physical memory allocator tvinit(); // trap vectors fileinit(); // file table iinit(); // inode cache console_init(); // I/O devices & their interrupts ide_init(); // disk if(!ismp) timer_init(); // uniprocessor timer userinit(); // first user process bootothers(); // start other processors // Finish setting up this processor in mpmain. mpmain(); }
/* 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); } }
static BOOT_CODE bool_t try_boot_sys( unsigned long multiboot_magic, multiboot_info_t* mbi ) { /* ==== following code corresponds to the "select" in abstract specification ==== */ acpi_rsdt_t* acpi_rsdt; /* physical address of ACPI root */ paddr_t mods_end_paddr; /* physical address where boot modules end */ paddr_t load_paddr; word_t i; p_region_t ui_p_regs; multiboot_module_t *modules = (multiboot_module_t*)(word_t)mbi->mod_list; if (multiboot_magic != MULTIBOOT_MAGIC) { printf("Boot loader not multiboot compliant\n"); return false; } cmdline_parse((const char *)(word_t)mbi->cmdline, &cmdline_opt); if ((mbi->flags & MULTIBOOT_INFO_MEM_FLAG) == 0) { printf("Boot loader did not provide information about physical memory size\n"); return false; } if (!x86_cpuid_initialize()) { printf("Warning: Your x86 CPU has an unsupported vendor, '%s'.\n" "\tYour setup may not be able to competently run seL4 as " "intended.\n" "\tCurrently supported x86 vendors are AMD and Intel.\n", x86_cpuid_get_identity()->vendor_string); } if (!is_compiled_for_microarchitecture()) { printf("Warning: Your kernel was not compiled for the current microarchitecture.\n"); } #if CONFIG_MAX_NUM_NODES > 1 /* copy boot code for APs to lower memory to run in real mode */ if (!copy_boot_code_aps(mbi->mem_lower)) { return false; } /* Initialize any kernel TLS */ mode_init_tls(0); #endif /* initialize the memory. We track two kinds of memory regions. Physical memory * that we will use for the kernel, and physical memory regions that we must * not give to the user. Memory regions that must not be given to the user * include all the physical memory in the kernel window, but also includes any * important or kernel devices. */ boot_state.mem_p_regs.count = 0; init_allocated_p_regions(); if (mbi->flags & MULTIBOOT_INFO_MMAP_FLAG) { if (!parse_mem_map(mbi->mmap_length, mbi->mmap_addr)) { return false; } } else { /* calculate memory the old way */ p_region_t avail; avail.start = HIGHMEM_PADDR; avail.end = ROUND_DOWN(avail.start + (mbi->mem_upper << 10), PAGE_BITS); if (!add_mem_p_regs(avail)) { return false; } } boot_state.ki_p_reg.start = PADDR_LOAD; boot_state.ki_p_reg.end = kpptr_to_paddr(ki_end); /* copy VESA information from multiboot header */ if ((mbi->flags & MULTIBOOT_INFO_GRAPHICS_FLAG) == 0) { boot_state.vbe_info.vbeMode = -1; printf("Multiboot gave us no video information\n"); } else { boot_state.vbe_info.vbeInfoBlock = *(seL4_VBEInfoBlock_t*)(seL4_Word)mbi->vbe_control_info; boot_state.vbe_info.vbeModeInfoBlock = *(seL4_VBEModeInfoBlock_t*)(seL4_Word)mbi->vbe_mode_info; boot_state.vbe_info.vbeMode = mbi->vbe_mode; printf("Got VBE info in multiboot. Current video mode is %d\n", mbi->vbe_mode); boot_state.vbe_info.vbeInterfaceSeg = mbi->vbe_interface_seg; boot_state.vbe_info.vbeInterfaceOff = mbi->vbe_interface_off; boot_state.vbe_info.vbeInterfaceLen = mbi->vbe_interface_len; } printf("Kernel loaded to: start=0x%lx end=0x%lx size=0x%lx entry=0x%lx\n", boot_state.ki_p_reg.start, boot_state.ki_p_reg.end, boot_state.ki_p_reg.end - boot_state.ki_p_reg.start, (paddr_t)_start ); /* remapping legacy IRQs to their correct vectors */ pic_remap_irqs(IRQ_INT_OFFSET); if (config_set(CONFIG_IRQ_IOAPIC)) { /* Disable the PIC so that it does not generate any interrupts. We need to * do this *before* we initialize the apic */ pic_disable(); } /* get ACPI root table */ acpi_rsdt = acpi_init(); if (!acpi_rsdt) { return false; } /* check if kernel configuration matches platform requirments */ if (!acpi_fadt_scan(acpi_rsdt)) { return false; } if (!config_set(CONFIG_IOMMU) || cmdline_opt.disable_iommu) { boot_state.num_drhu = 0; } else { /* query available IOMMUs from ACPI */ acpi_dmar_scan( acpi_rsdt, boot_state.drhu_list, &boot_state.num_drhu, MAX_NUM_DRHU, &boot_state.rmrr_list ); } /* query available CPUs from ACPI */ boot_state.num_cpus = acpi_madt_scan(acpi_rsdt, boot_state.cpus, &boot_state.num_ioapic, boot_state.ioapic_paddr); if (boot_state.num_cpus == 0) { printf("No CPUs detected\n"); return false; } if (config_set(CONFIG_IRQ_IOAPIC)) { if (boot_state.num_ioapic == 0) { printf("No IOAPICs detected\n"); return false; } } else { if (boot_state.num_ioapic > 0) { printf("Detected %d IOAPICs, but configured to use PIC instead\n", boot_state.num_ioapic); } } if (!(mbi->flags & MULTIBOOT_INFO_MODS_FLAG)) { printf("Boot loader did not provide information about boot modules\n"); return false; } printf("Detected %d boot module(s):\n", mbi->mod_count); if (mbi->mod_count < 1) { printf("Expect at least one boot module (containing a userland image)\n"); return false; } mods_end_paddr = 0; for (i = 0; i < mbi->mod_count; i++) { printf( " module #%ld: start=0x%x end=0x%x size=0x%x name='%s'\n", i, modules[i].start, modules[i].end, modules[i].end - modules[i].start, (char *) (long)modules[i].name ); if ((sword_t)(modules[i].end - modules[i].start) <= 0) { printf("Invalid boot module size! Possible cause: boot module file not found by QEMU\n"); return false; } if (mods_end_paddr < modules[i].end) { mods_end_paddr = modules[i].end; } } mods_end_paddr = ROUND_UP(mods_end_paddr, PAGE_BITS); assert(mods_end_paddr > boot_state.ki_p_reg.end); printf("ELF-loading userland images from boot modules:\n"); load_paddr = mods_end_paddr; load_paddr = load_boot_module(modules, load_paddr); if (!load_paddr) { return false; } /* calculate final location of userland images */ ui_p_regs.start = boot_state.ki_p_reg.end; ui_p_regs.end = ui_p_regs.start + load_paddr - mods_end_paddr; printf( "Moving loaded userland images to final location: from=0x%lx to=0x%lx size=0x%lx\n", mods_end_paddr, ui_p_regs.start, ui_p_regs.end - ui_p_regs.start ); memcpy((void*)ui_p_regs.start, (void*)mods_end_paddr, ui_p_regs.end - ui_p_regs.start); /* adjust p_reg and pv_offset to final load address */ boot_state.ui_info.p_reg.start -= mods_end_paddr - ui_p_regs.start; boot_state.ui_info.p_reg.end -= mods_end_paddr - ui_p_regs.start; boot_state.ui_info.pv_offset -= mods_end_paddr - ui_p_regs.start; /* ==== following code corresponds to abstract specification after "select" ==== */ if (!platAddDevices()) { return false; } /* Total number of cores we intend to boot */ ksNumCPUs = boot_state.num_cpus; printf("Starting node #0 with APIC ID %lu\n", boot_state.cpus[0]); if (!try_boot_sys_node(boot_state.cpus[0])) { return false; } if (config_set(CONFIG_IRQ_IOAPIC)) { ioapic_init(1, boot_state.cpus, boot_state.num_ioapic); } /* initialize BKL before booting up APs */ SMP_COND_STATEMENT(clh_lock_init()); SMP_COND_STATEMENT(start_boot_aps()); /* grab BKL before leaving the kernel */ NODE_LOCK_SYS; printf("Booting all finished, dropped to user space\n"); return true; }
// Called first from entry.S on the bootstrap processor, // and later from boot/bootother.S on all other processors. // As a rule, "init" functions in PIOS are called once on EACH processor. void init(void) { extern char start[], edata[], end[]; // Before anything else, complete the ELF loading process. // Clear all uninitialized global data (BSS) in our program, // ensuring that all static/global variables start out zero. if (cpu_onboot()) memset(edata, 0, end - edata); // Initialize the console. // Can't call cprintf until after we do this! cons_init(); extern uint8_t _binary_obj_boot_bootother_start[], _binary_obj_boot_bootother_size[]; uint8_t *code = (uint8_t*)lowmem_bootother_vec; memmove(code, _binary_obj_boot_bootother_start, (uint32_t) _binary_obj_boot_bootother_size); // Lab 1: test cprintf and debug_trace cprintf("1234 decimal is %o octal!\n", 1234); debug_check(); // Initialize and load the bootstrap CPU's GDT, TSS, and IDT. cpu_init(); trap_init(); // Physical memory detection/initialization. // Can't call mem_alloc until after we do this! mem_init(); // Lab 2: check spinlock implementation if (cpu_onboot()) spinlock_check(); // Initialize the paged virtual memory system. pmap_init(); // Find and start other processors in a multiprocessor system mp_init(); // Find info about processors in system pic_init(); // setup the legacy PIC (mainly to disable it) ioapic_init(); // prepare to handle external device interrupts lapic_init(); // setup this CPU's local APIC cpu_bootothers(); // Get other processors started // cprintf("CPU %d (%s) has booted\n", cpu_cur()->id, // cpu_onboot() ? "BP" : "AP"); file_init(); // Create root directory and console I/O files // Lab 4: uncomment this when you can handle IRQ_SERIAL and IRQ_KBD. //cons_intenable(); // Let the console start producing interrupts // Initialize the process management code. proc_init(); // Initialize the process management code. proc_init(); if(!cpu_onboot()) proc_sched(); proc *root = proc_root = proc_alloc(NULL,0); elfhdr *ehs = (elfhdr *)ROOTEXE_START; assert(ehs->e_magic == ELF_MAGIC); proghdr *phs = (proghdr *) ((void *) ehs + ehs->e_phoff); proghdr *ep = phs + ehs->e_phnum; for (; phs < ep; phs++) { if (phs->p_type != ELF_PROG_LOAD) continue; void *fa = (void *) ehs + ROUNDDOWN(phs->p_offset, PAGESIZE); uint32_t va = ROUNDDOWN(phs->p_va, PAGESIZE); uint32_t zva = phs->p_va + phs->p_filesz; uint32_t eva = ROUNDUP(phs->p_va + phs->p_memsz, PAGESIZE); uint32_t perm = SYS_READ | PTE_P | PTE_U; if(phs->p_flags & ELF_PROG_FLAG_WRITE) perm |= SYS_WRITE | PTE_W; for (; va < eva; va += PAGESIZE, fa += PAGESIZE) { pageinfo *pi = mem_alloc(); assert(pi != NULL); if(va < ROUNDDOWN(zva, PAGESIZE)) memmove(mem_pi2ptr(pi), fa, PAGESIZE); else if (va < zva && phs->p_filesz) { memset(mem_pi2ptr(pi),0, PAGESIZE); memmove(mem_pi2ptr(pi), fa, zva-va); } else memset(mem_pi2ptr(pi), 0, PAGESIZE); pte_t *pte = pmap_insert(root->pdir, pi, va, perm); assert(pte != NULL); } } root->sv.tf.eip = ehs->e_entry; root->sv.tf.eflags |= FL_IF; pageinfo *pi = mem_alloc(); assert(pi != NULL); pte_t *pte = pmap_insert(root->pdir, pi, VM_STACKHI-PAGESIZE, SYS_READ | SYS_WRITE | PTE_P | PTE_U | PTE_W); assert(pte != NULL); root->sv.tf.esp = VM_STACKHI; proc_ready(root); proc_sched(); // Initialize the I/O system. // Lab 1: change this so it enters user() in user mode, // running on the user_stack declared above, // instead of just calling user() directly. user(); // FIXME: Maybe get rid of this }
/* 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); } }
int main(int argc, char *argv[]) { int c, error, gdb_port, err, bvmcons; int max_vcpus, mptgen, memflags; int rtc_localtime; struct vmctx *ctx; uint64_t rip; size_t memsize; char *optstr; bvmcons = 0; progname = basename(argv[0]); gdb_port = 0; guest_ncpus = 1; memsize = 256 * MB; mptgen = 1; rtc_localtime = 1; memflags = 0; optstr = "abehuwxACHIPSWYp:g:c:s:m:l:U:"; while ((c = getopt(argc, argv, optstr)) != -1) { switch (c) { case 'a': x2apic_mode = 0; break; case 'A': acpi = 1; break; case 'b': bvmcons = 1; break; case 'p': if (pincpu_parse(optarg) != 0) { errx(EX_USAGE, "invalid vcpu pinning " "configuration '%s'", optarg); } break; case 'c': guest_ncpus = atoi(optarg); break; case 'C': memflags |= VM_MEM_F_INCORE; break; case 'g': gdb_port = atoi(optarg); break; case 'l': if (lpc_device_parse(optarg) != 0) { errx(EX_USAGE, "invalid lpc device " "configuration '%s'", optarg); } break; case 's': if (pci_parse_slot(optarg) != 0) exit(1); else break; case 'S': memflags |= VM_MEM_F_WIRED; break; case 'm': error = vm_parse_memsize(optarg, &memsize); if (error) errx(EX_USAGE, "invalid memsize '%s'", optarg); break; case 'H': guest_vmexit_on_hlt = 1; break; case 'I': /* * The "-I" option was used to add an ioapic to the * virtual machine. * * An ioapic is now provided unconditionally for each * virtual machine and this option is now deprecated. */ break; case 'P': guest_vmexit_on_pause = 1; break; case 'e': strictio = 1; break; case 'u': rtc_localtime = 0; break; case 'U': guest_uuid_str = optarg; break; case 'w': strictmsr = 0; break; case 'W': virtio_msix = 0; break; case 'x': x2apic_mode = 1; break; case 'Y': mptgen = 0; break; case 'h': usage(0); default: usage(1); } } argc -= optind; argv += optind; if (argc != 1) usage(1); vmname = argv[0]; ctx = do_open(vmname); if (guest_ncpus < 1) { fprintf(stderr, "Invalid guest vCPUs (%d)\n", guest_ncpus); exit(1); } max_vcpus = num_vcpus_allowed(ctx); if (guest_ncpus > max_vcpus) { fprintf(stderr, "%d vCPUs requested but only %d available\n", guest_ncpus, max_vcpus); exit(1); } fbsdrun_set_capabilities(ctx, BSP); vm_set_memflags(ctx, memflags); err = vm_setup_memory(ctx, memsize, VM_MMAP_ALL); if (err) { fprintf(stderr, "Unable to setup memory (%d)\n", errno); exit(1); } error = init_msr(); if (error) { fprintf(stderr, "init_msr error %d", error); exit(1); } init_mem(); init_inout(); pci_irq_init(ctx); ioapic_init(ctx); rtc_init(ctx, rtc_localtime); sci_init(ctx); /* * Exit if a device emulation finds an error in it's initilization */ if (init_pci(ctx) != 0) exit(1); if (gdb_port != 0) init_dbgport(gdb_port); if (bvmcons) init_bvmcons(); if (lpc_bootrom()) { if (vm_set_capability(ctx, BSP, VM_CAP_UNRESTRICTED_GUEST, 1)) { fprintf(stderr, "ROM boot failed: unrestricted guest " "capability not available\n"); exit(1); } error = vcpu_reset(ctx, BSP); assert(error == 0); } error = vm_get_register(ctx, BSP, VM_REG_GUEST_RIP, &rip); assert(error == 0); /* * build the guest tables, MP etc. */ if (mptgen) { error = mptable_build(ctx, guest_ncpus); if (error) exit(1); } error = smbios_build(ctx); assert(error == 0); if (acpi) { error = acpi_build(ctx, guest_ncpus); assert(error == 0); } if (lpc_bootrom()) fwctl_init(); /* * Change the proc title to include the VM name. */ setproctitle("%s", vmname); /* * Add CPU 0 */ fbsdrun_addcpu(ctx, BSP, BSP, rip); /* * Head off to the main event dispatch loop */ mevent_dispatch(); exit(1); }
/* * Bootstrap-CPU start; we came from head.S */ void __no_return kernel_start(void) { /* Before anything else, zero the bss section. As said by C99: * “All objects with static storage duration shall be inited * before program startup”, and that the implicit init is done * with zero. Kernel assembly code also assumes a zeroed BSS * space */ clear_bss(); /* * Very-early setup: Do not call any code that will use * printk(), `current', per-CPU vars, or a spin lock. */ setup_idt(); schedulify_this_code_path(BOOTSTRAP); /* * Memory Management init */ print_info(); /* First, don't override the ramdisk area (if any) */ ramdisk_init(); /* Then discover our physical memory map .. */ e820_init(); /* and tokenize the available memory into allocatable pages */ pagealloc_init(); /* With the page allocator in place, git rid of our temporary * early-boot page tables and setup dynamic permanent ones */ vm_init(); /* MM basics done, enable dynamic heap memory to kernel code * early on .. */ kmalloc_init(); /* * Secondary-CPUs startup */ /* Discover our secondary-CPUs and system IRQs layout before * initializing the local APICs */ mptables_init(); /* Remap and mask the PIC; it's just a disturbance */ serial_init(); pic_init(); /* Initialize the APICs (and map their MMIO regs) before enabling * IRQs, and before firing other cores using Inter-CPU Interrupts */ apic_init(); ioapic_init(); /* SMP infrastructure ready, fire the CPUs! */ smpboot_init(); keyboard_init(); /* Startup finished, roll-in the scheduler! */ sched_init(); local_irq_enable(); /* * Second part of kernel initialization (Scheduler is now on!) */ ext2_init(); // Signal the secondary cores to run their own test-cases code. // They've been waiting for us (thread 0) till all of kernel // subsystems has been properly initialized. Wait No More! smpboot_trigger_secondary_cores_testcases(); run_test_cases(); halt(); }
int main(int argc, char *argv[]) { int c, error, gdb_port, err, bvmcons; int max_vcpus; struct vmctx *ctx; uint64_t rip; size_t memsize; bvmcons = 0; progname = basename(argv[0]); gdb_port = 0; guest_ncpus = 1; memsize = 256 * MB; while ((c = getopt(argc, argv, "abehwxAHIPWp:g:c:s:m:l:U:")) != -1) { switch (c) { case 'a': x2apic_mode = 0; break; case 'A': acpi = 1; break; case 'b': bvmcons = 1; break; case 'p': pincpu = atoi(optarg); break; case 'c': guest_ncpus = atoi(optarg); break; case 'g': gdb_port = atoi(optarg); break; case 'l': if (lpc_device_parse(optarg) != 0) { errx(EX_USAGE, "invalid lpc device " "configuration '%s'", optarg); } break; case 's': if (pci_parse_slot(optarg) != 0) exit(1); else break; case 'm': error = vm_parse_memsize(optarg, &memsize); if (error) errx(EX_USAGE, "invalid memsize '%s'", optarg); break; case 'H': guest_vmexit_on_hlt = 1; break; case 'I': /* * The "-I" option was used to add an ioapic to the * virtual machine. * * An ioapic is now provided unconditionally for each * virtual machine and this option is now deprecated. */ break; case 'P': guest_vmexit_on_pause = 1; break; case 'e': strictio = 1; break; case 'U': guest_uuid_str = optarg; break; case 'w': strictmsr = 0; break; case 'W': virtio_msix = 0; break; case 'x': x2apic_mode = 1; break; case 'h': usage(0); default: usage(1); } } argc -= optind; argv += optind; if (argc != 1) usage(1); vmname = argv[0]; ctx = vm_open(vmname); if (ctx == NULL) { perror("vm_open"); exit(1); } max_vcpus = num_vcpus_allowed(ctx); if (guest_ncpus > max_vcpus) { fprintf(stderr, "%d vCPUs requested but only %d available\n", guest_ncpus, max_vcpus); exit(1); } fbsdrun_set_capabilities(ctx, BSP); err = vm_setup_memory(ctx, memsize, VM_MMAP_ALL); if (err) { fprintf(stderr, "Unable to setup memory (%d)\n", err); exit(1); } init_mem(); init_inout(); ioapic_init(ctx); rtc_init(ctx); /* * Exit if a device emulation finds an error in it's initilization */ if (init_pci(ctx) != 0) exit(1); if (gdb_port != 0) init_dbgport(gdb_port); if (bvmcons) init_bvmcons(); error = vm_get_register(ctx, BSP, VM_REG_GUEST_RIP, &rip); assert(error == 0); /* * build the guest tables, MP etc. */ mptable_build(ctx, guest_ncpus); error = smbios_build(ctx); assert(error == 0); if (acpi) { error = acpi_build(ctx, guest_ncpus); assert(error == 0); } /* * Change the proc title to include the VM name. */ setproctitle("%s", vmname); /* * Add CPU 0 */ fbsdrun_addcpu(ctx, BSP, BSP, rip); /* * Head off to the main event dispatch loop */ mevent_dispatch(); exit(1); }
int kern_init(uint64_t mbmagic, uint64_t mbmem) { extern char edata[], end[]; memset(edata, 0, end - edata); /* percpu variable for CPU0 is preallocated */ percpu_offsets[0] = __percpu_start; cons_init(); // init the console const char *message = "(THU.CST) os is loading ..."; kprintf("%s\n\n", message); if(mbmagic == MULTIBOOT_BOOTLOADER_MAGIC){ kprintf("Multiboot dectected: param %p\n", (void*)mbmem); mbmem2e820((Mbdata*)VADDR_DIRECT(mbmem)); parse_initrd((Mbdata*)VADDR_DIRECT(mbmem)); } print_kerninfo(); /* get_cpu_var not available before tls_init() */ hz_init(); gdt_init(per_cpu_ptr(cpus, 0)); tls_init(per_cpu_ptr(cpus, 0)); acpitables_init(); lapic_init(); numa_init(); pmm_init_numa(); // init physical memory management, numa awared /* map the lapic */ lapic_init_late(); //init the acpi stuff idt_init(); // init interrupt descriptor table pic_init(); // init interrupt controller // acpi_conf_init(); percpu_init(); cpus_init(); #ifdef UCONFIG_ENABLE_IPI ipi_init(); #endif refcache_init(); vmm_init(); // init virtual memory management sched_init(); // init scheduler proc_init(); // init process table sync_init(); // init sync struct /* ext int */ ioapic_init(); acpi_init(); ide_init(); // init ide devices #ifdef UCONFIG_SWAP swap_init(); // init swap #endif fs_init(); // init fs clock_init(); // init clock interrupt mod_init(); trap_init(); //XXX put here? bootaps(); intr_enable(); // enable irq interrupt #ifdef UCONFIG_HAVE_LINUX_DDE36_BASE dde_kit_init(); #endif /* do nothing */ cpu_idle(); // run idle process }
static int vm_init_vdevs(struct vmctx *ctx) { int ret; init_mem(); init_inout(); pci_irq_init(ctx); atkbdc_init(ctx); ioapic_init(ctx); /* * We don't care ioc_init return value so far. * Will add return value check once ioc is full function. */ ret = ioc_init(ctx); ret = vrtc_init(ctx); if (ret < 0) goto vrtc_fail; ret = vpit_init(ctx); if (ret < 0) goto vpit_fail; ret = vhpet_init(ctx); if (ret < 0) goto vhpet_fail; sci_init(ctx); if (debugexit_enabled) init_debugexit(); ret = monitor_init(ctx); if (ret < 0) goto monitor_fail; ret = init_pci(ctx); if (ret < 0) goto pci_fail; init_vtpm2(ctx); return 0; pci_fail: monitor_close(); monitor_fail: if (debugexit_enabled) deinit_debugexit(); vhpet_deinit(ctx); vhpet_fail: vpit_deinit(ctx); vpit_fail: vrtc_deinit(ctx); vrtc_fail: ioc_deinit(ctx); atkbdc_deinit(ctx); pci_irq_deinit(ctx); ioapic_deinit(); return -1; }
/* 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; void *fw_cfg = NULL; 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()) { fw_cfg = 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_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_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]); pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL); if (xen_enabled()) { pci_create_simple(pci_bus, -1, "xen-platform"); } if (pci_enabled && vmsocket_enabled) pci_vmsocket_init(pci_bus); /* 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"); } 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) { 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); } }
/* 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); } }