#include "elf.h"
#include "multiboot.h"
#include "mc146818rtc.h"
+#include "i8254.h"
+#include "pcspk.h"
#include "msi.h"
#include "sysbus.h"
#include "sysemu.h"
#include "kvm.h"
+#include "xen.h"
#include "blockdev.h"
#include "ui/qemu-spice.h"
#include "memory.h"
#define DPRINTF(fmt, ...)
#endif
-#define BIOS_FILENAME "bios.bin"
-
-#define PC_MAX_BIOS_SIZE (4 * 1024 * 1024)
-
/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables. */
#define ACPI_DATA_SIZE 0x10000
#define BIOS_CFG_IOPORT 0x510
smm_arg = arg;
}
-void cpu_smm_update(CPUState *env)
+void cpu_smm_update(CPUX86State *env)
{
if (smm_set && smm_arg && env == first_cpu)
smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg);
/* IRQ handling */
-int cpu_get_pic_interrupt(CPUState *env)
+int cpu_get_pic_interrupt(CPUX86State *env)
{
int intno;
static void pic_irq_request(void *opaque, int irq, int level)
{
- CPUState *env = first_cpu;
+ CPUX86State *env = first_cpu;
DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq);
if (env->apic_state) {
{
int val, nb, nb_heads, max_track, last_sect, i;
FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
+ FDriveRate rate;
BlockDriverState *fd[MAX_FD];
static pc_cmos_init_late_arg arg;
if (fd[i] && bdrv_is_inserted(fd[i])) {
bdrv_get_floppy_geometry_hint(fd[i], &nb_heads, &max_track,
&last_sect, FDRIVE_DRV_NONE,
- &fd_type[i]);
+ &fd_type[i], &rate);
}
}
}
.class_init = port92_class_initfn,
};
-static void port92_register(void)
+static void port92_register_types(void)
{
type_register_static(&port92_info);
}
-device_init(port92_register)
+
+type_init(port92_register_types)
static void handle_a20_line_change(void *opaque, int irq, int level)
{
- CPUState *cpu = opaque;
+ CPUX86State *cpu = opaque;
/* XXX: send to all CPUs ? */
/* XXX: add logic to handle multiple A20 line sources */
}
/* loader type */
- /* High nybble = B reserved for Qemu; low nybble is revision number.
+ /* High nybble = B reserved for QEMU; low nybble is revision number.
If this code is substantially changed, you may want to consider
incrementing the revision. */
if (protocol >= 0x200)
nb_ne2k++;
}
-int cpu_is_bsp(CPUState *env)
+int cpu_is_bsp(CPUX86State *env)
{
/* We hard-wire the BSP to the first CPU. */
return env->cpu_index == 0;
DeviceState *dev;
static int apic_mapped;
- if (kvm_enabled() && kvm_irqchip_in_kernel()) {
+ if (kvm_irqchip_in_kernel()) {
dev = qdev_create(NULL, "kvm-apic");
+ } else if (xen_enabled()) {
+ dev = qdev_create(NULL, "xen-apic");
} else {
dev = qdev_create(NULL, "apic");
}
+
qdev_prop_set_uint8(dev, "id", apic_id);
qdev_prop_set_ptr(dev, "cpu_env", env);
qdev_init_nofail(dev);
}
/* KVM does not support MSI yet. */
- if (!kvm_enabled() || !kvm_irqchip_in_kernel()) {
+ if (!kvm_irqchip_in_kernel()) {
msi_supported = true;
}
- return dev;
-}
-
-/* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
- BIOS will read it and start S3 resume at POST Entry */
-void pc_cmos_set_s3_resume(void *opaque, int irq, int level)
-{
- ISADevice *s = opaque;
-
- if (level) {
- rtc_set_memory(s, 0xF, 0xFE);
+ if (xen_msi_support()) {
+ msi_supported = true;
}
+
+ return dev;
}
void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
{
- CPUState *s = opaque;
+ CPUX86State *s = opaque;
if (level) {
cpu_interrupt(s, CPU_INTERRUPT_SMI);
static void pc_cpu_reset(void *opaque)
{
- CPUState *env = opaque;
+ CPUX86State *env = opaque;
- cpu_reset(env);
+ cpu_state_reset(env);
env->halted = !cpu_is_bsp(env);
}
-static CPUState *pc_new_cpu(const char *cpu_model)
+static CPUX86State *pc_new_cpu(const char *cpu_model)
{
- CPUState *env;
+ CPUX86State *env;
env = cpu_init(cpu_model);
if (!env) {
MemoryRegion *rom_memory,
MemoryRegion **ram_memory)
{
- char *filename;
- int ret, linux_boot, i;
- MemoryRegion *ram, *bios, *isa_bios, *option_rom_mr;
+ int linux_boot, i;
+ MemoryRegion *ram, *option_rom_mr;
MemoryRegion *ram_below_4g, *ram_above_4g;
- int bios_size, isa_bios_size;
void *fw_cfg;
linux_boot = (kernel_filename != NULL);
ram_above_4g);
}
- /* BIOS load */
- 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;
- }
- if (bios_size <= 0 ||
- (bios_size % 65536) != 0) {
- goto bios_error;
- }
- bios = g_malloc(sizeof(*bios));
- memory_region_init_ram(bios, "pc.bios", bios_size);
- vmstate_register_ram_global(bios);
- memory_region_set_readonly(bios, true);
- ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
- if (ret != 0) {
- bios_error:
- fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name);
- exit(1);
- }
- if (filename) {
- g_free(filename);
- }
- /* map the last 128KB of the BIOS in ISA space */
- isa_bios_size = bios_size;
- if (isa_bios_size > (128 * 1024))
- isa_bios_size = 128 * 1024;
- isa_bios = g_malloc(sizeof(*isa_bios));
- memory_region_init_alias(isa_bios, "isa-bios", bios,
- bios_size - isa_bios_size, isa_bios_size);
- memory_region_add_subregion_overlap(rom_memory,
- 0x100000 - isa_bios_size,
- isa_bios,
- 1);
- memory_region_set_readonly(isa_bios, true);
+
+ /* Initialize PC system firmware */
+ pc_system_firmware_init(rom_memory);
option_rom_mr = g_malloc(sizeof(*option_rom_mr));
memory_region_init_ram(option_rom_mr, "pc.rom", PC_ROM_SIZE);
option_rom_mr,
1);
- /* map all the bios at the top of memory */
- memory_region_add_subregion(rom_memory,
- (uint32_t)(-bios_size),
- bios);
-
fw_cfg = bochs_bios_init();
rom_set_fw(fw_cfg);
static void cpu_request_exit(void *opaque, int irq, int level)
{
- CPUState *env = cpu_single_env;
+ CPUX86State *env = cpu_single_env;
if (env && level) {
cpu_exit(env);
{
int i;
DriveInfo *fd[MAX_FD];
+ DeviceState *hpet = NULL;
+ int pit_isa_irq = 0;
+ qemu_irq pit_alt_irq = NULL;
qemu_irq rtc_irq = NULL;
qemu_irq *a20_line;
ISADevice *i8042, *port92, *vmmouse, *pit;
register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
- if (!no_hpet) {
- DeviceState *hpet = sysbus_try_create_simple("hpet", HPET_BASE, NULL);
+ /*
+ * Check if an HPET shall be created.
+ *
+ * Without KVM_CAP_PIT_STATE2, we cannot switch off the in-kernel PIT
+ * when the HPET wants to take over. Thus we have to disable the latter.
+ */
+ if (!no_hpet && (!kvm_irqchip_in_kernel() || kvm_has_pit_state2())) {
+ hpet = sysbus_try_create_simple("hpet", HPET_BASE, NULL);
if (hpet) {
for (i = 0; i < GSI_NUM_PINS; i++) {
sysbus_connect_irq(sysbus_from_qdev(hpet), i, gsi[i]);
}
- rtc_irq = qdev_get_gpio_in(hpet, 0);
+ pit_isa_irq = -1;
+ pit_alt_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_PIT_INT);
+ rtc_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_RTC_INT);
}
}
*rtc_state = rtc_init(isa_bus, 2000, rtc_irq);
qemu_register_boot_set(pc_boot_set, *rtc_state);
- pit = pit_init(isa_bus, 0x40, 0);
- pcspk_init(pit);
+ if (kvm_irqchip_in_kernel()) {
+ pit = kvm_pit_init(isa_bus, 0x40);
+ } else {
+ pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq);
+ }
+ if (hpet) {
+ /* connect PIT to output control line of the HPET */
+ qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0));
+ }
+ pcspk_init(isa_bus, pit);
for(i = 0; i < MAX_SERIAL_PORTS; i++) {
if (serial_hds[i]) {