pc.c 31.1 KB
Newer Older
B
bellard 已提交
1 2
/*
 * QEMU PC System Emulator
3
 *
B
bellard 已提交
4
 * Copyright (c) 2003-2004 Fabrice Bellard
5
 *
B
bellard 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
P
pbrook 已提交
24 25
#include "hw.h"
#include "pc.h"
G
Gerd Hoffmann 已提交
26
#include "serial.h"
27
#include "apic.h"
P
pbrook 已提交
28
#include "fdc.h"
29
#include "ide.h"
30
#include "pci/pci.h"
31
#include "monitor/monitor.h"
32
#include "fw_cfg.h"
A
aliguori 已提交
33
#include "hpet_emul.h"
34
#include "smbios.h"
B
Blue Swirl 已提交
35 36
#include "loader.h"
#include "elf.h"
37
#include "multiboot.h"
38
#include "mc146818rtc.h"
J
Jan Kiszka 已提交
39
#include "i8254.h"
J
Jan Kiszka 已提交
40
#include "pcspk.h"
41
#include "pci/msi.h"
J
Jan Kiszka 已提交
42
#include "sysbus.h"
43 44
#include "sysemu/sysemu.h"
#include "sysemu/kvm.h"
45
#include "kvm_i386.h"
46
#include "xen.h"
47
#include "sysemu/blockdev.h"
48
#include "hw/block-common.h"
G
Gerd Hoffmann 已提交
49
#include "ui/qemu-spice.h"
50 51
#include "exec/memory.h"
#include "exec/address-spaces.h"
52
#include "sysemu/arch_init.h"
53
#include "qemu/bitmap.h"
B
bellard 已提交
54

B
Blue Swirl 已提交
55 56 57 58 59 60 61 62 63 64
/* debug PC/ISA interrupts */
//#define DEBUG_IRQ

#ifdef DEBUG_IRQ
#define DPRINTF(fmt, ...)                                       \
    do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0)
#else
#define DPRINTF(fmt, ...)
#endif

65 66
/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables.  */
#define ACPI_DATA_SIZE       0x10000
67
#define BIOS_CFG_IOPORT 0x510
68
#define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0)
69
#define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1)
J
Jes Sorensen 已提交
70
#define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2)
J
Jes Sorensen 已提交
71
#define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3)
72
#define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4)
B
bellard 已提交
73

J
Jes Sorensen 已提交
74 75 76 77 78 79
#define E820_NR_ENTRIES		16

struct e820_entry {
    uint64_t address;
    uint64_t length;
    uint32_t type;
80
} QEMU_PACKED __attribute((__aligned__(4)));
J
Jes Sorensen 已提交
81 82 83 84

struct e820_table {
    uint32_t count;
    struct e820_entry entry[E820_NR_ENTRIES];
85
} QEMU_PACKED __attribute((__aligned__(4)));
J
Jes Sorensen 已提交
86 87

static struct e820_table e820_table;
B
Blue Swirl 已提交
88
struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
J
Jes Sorensen 已提交
89

J
Jan Kiszka 已提交
90
void gsi_handler(void *opaque, int n, int level)
91
{
J
Jan Kiszka 已提交
92
    GSIState *s = opaque;
93

J
Jan Kiszka 已提交
94 95 96
    DPRINTF("pc: %s GSI %d\n", level ? "raising" : "lowering", n);
    if (n < ISA_NUM_IRQS) {
        qemu_set_irq(s->i8259_irq[n], level);
A
Avi Kivity 已提交
97
    }
J
Jan Kiszka 已提交
98
    qemu_set_irq(s->ioapic_irq[n], level);
99
}
100

J
Julien Grall 已提交
101 102
static void ioport80_write(void *opaque, hwaddr addr, uint64_t data,
                           unsigned size)
B
bellard 已提交
103 104 105
{
}

106 107 108 109 110
static uint64_t ioport80_read(void *opaque, hwaddr addr, unsigned size)
{
    return 0xffffffffffffffff;
}

111
/* MSDOS compatibility mode FPU exception support */
P
pbrook 已提交
112
static qemu_irq ferr_irq;
113 114 115 116 117 118

void pc_register_ferr_irq(qemu_irq irq)
{
    ferr_irq = irq;
}

119 120 121
/* XXX: add IGNNE support */
void cpu_set_ferr(CPUX86State *s)
{
P
pbrook 已提交
122
    qemu_irq_raise(ferr_irq);
123 124
}

J
Julien Grall 已提交
125 126
static void ioportF0_write(void *opaque, hwaddr addr, uint64_t data,
                           unsigned size)
127
{
P
pbrook 已提交
128
    qemu_irq_lower(ferr_irq);
129 130
}

131 132 133 134 135
static uint64_t ioportF0_read(void *opaque, hwaddr addr, unsigned size)
{
    return 0xffffffffffffffff;
}

B
bellard 已提交
136 137 138
/* TSC handling */
uint64_t cpu_get_tsc(CPUX86State *env)
{
139
    return cpu_get_ticks();
B
bellard 已提交
140 141
}

B
bellard 已提交
142
/* SMM support */
143 144 145 146 147 148 149 150 151 152 153 154

static cpu_set_smm_t smm_set;
static void *smm_arg;

void cpu_smm_register(cpu_set_smm_t callback, void *arg)
{
    assert(smm_set == NULL);
    assert(smm_arg == NULL);
    smm_set = callback;
    smm_arg = arg;
}

A
Andreas Färber 已提交
155
void cpu_smm_update(CPUX86State *env)
B
bellard 已提交
156
{
157 158
    if (smm_set && smm_arg && env == first_cpu)
        smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg);
B
bellard 已提交
159 160 161
}


B
bellard 已提交
162
/* IRQ handling */
A
Andreas Färber 已提交
163
int cpu_get_pic_interrupt(CPUX86State *env)
B
bellard 已提交
164 165 166
{
    int intno;

167
    intno = apic_get_interrupt(env->apic_state);
B
bellard 已提交
168 169 170 171
    if (intno >= 0) {
        return intno;
    }
    /* read the irq from the PIC */
172
    if (!apic_accept_pic_intr(env->apic_state)) {
173
        return -1;
174
    }
175

B
bellard 已提交
176 177 178 179
    intno = pic_read_irq(isa_pic);
    return intno;
}

P
pbrook 已提交
180
static void pic_irq_request(void *opaque, int irq, int level)
B
bellard 已提交
181
{
A
Andreas Färber 已提交
182
    CPUX86State *env = first_cpu;
183

B
Blue Swirl 已提交
184
    DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq);
A
aurel32 已提交
185 186
    if (env->apic_state) {
        while (env) {
187 188 189
            if (apic_accept_pic_intr(env->apic_state)) {
                apic_deliver_pic_intr(env->apic_state, level);
            }
A
aurel32 已提交
190 191 192
            env = env->next_cpu;
        }
    } else {
A
aurel32 已提交
193 194 195 196
        if (level)
            cpu_interrupt(env, CPU_INTERRUPT_HARD);
        else
            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
197
    }
B
bellard 已提交
198 199
}

B
bellard 已提交
200 201
/* PC cmos mappings */

B
bellard 已提交
202 203
#define REG_EQUIPMENT_BYTE          0x14

204
static int cmos_get_fd_drive_type(FDriveType fd0)
205 206 207 208
{
    int val;

    switch (fd0) {
209
    case FDRIVE_DRV_144:
210 211 212
        /* 1.44 Mb 3"5 drive */
        val = 4;
        break;
213
    case FDRIVE_DRV_288:
214 215 216
        /* 2.88 Mb 3"5 drive */
        val = 5;
        break;
217
    case FDRIVE_DRV_120:
218 219 220
        /* 1.2 Mb 5"5 drive */
        val = 2;
        break;
221
    case FDRIVE_DRV_NONE:
222 223 224 225 226 227 228
    default:
        val = 0;
        break;
    }
    return val;
}

229 230
static void cmos_init_hd(ISADevice *s, int type_ofs, int info_ofs,
                         int16_t cylinders, int8_t heads, int8_t sectors)
B
bellard 已提交
231 232 233 234 235 236 237 238 239 240 241 242 243
{
    rtc_set_memory(s, type_ofs, 47);
    rtc_set_memory(s, info_ofs, cylinders);
    rtc_set_memory(s, info_ofs + 1, cylinders >> 8);
    rtc_set_memory(s, info_ofs + 2, heads);
    rtc_set_memory(s, info_ofs + 3, 0xff);
    rtc_set_memory(s, info_ofs + 4, 0xff);
    rtc_set_memory(s, info_ofs + 5, 0xc0 | ((heads > 8) << 3));
    rtc_set_memory(s, info_ofs + 6, cylinders);
    rtc_set_memory(s, info_ofs + 7, cylinders >> 8);
    rtc_set_memory(s, info_ofs + 8, sectors);
}

244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
/* convert boot_device letter to something recognizable by the bios */
static int boot_device2nibble(char boot_device)
{
    switch(boot_device) {
    case 'a':
    case 'b':
        return 0x01; /* floppy boot */
    case 'c':
        return 0x02; /* hard drive boot */
    case 'd':
        return 0x03; /* CD-ROM boot */
    case 'n':
        return 0x04; /* Network boot */
    }
    return 0;
}

261
static int set_boot_dev(ISADevice *s, const char *boot_device, int fd_bootchk)
262 263 264 265 266 267 268
{
#define PC_MAX_BOOT_DEVICES 3
    int nbds, bds[3] = { 0, };
    int i;

    nbds = strlen(boot_device);
    if (nbds > PC_MAX_BOOT_DEVICES) {
269
        error_report("Too many boot devices for PC");
270 271 272 273 274
        return(1);
    }
    for (i = 0; i < nbds; i++) {
        bds[i] = boot_device2nibble(boot_device[i]);
        if (bds[i] == 0) {
275 276
            error_report("Invalid boot device for PC: '%c'",
                         boot_device[i]);
277 278 279 280
            return(1);
        }
    }
    rtc_set_memory(s, 0x3d, (bds[1] << 4) | bds[0]);
281
    rtc_set_memory(s, 0x38, (bds[2] << 4) | (fd_bootchk ? 0x0 : 0x1));
282 283 284
    return(0);
}

285 286 287 288 289
static int pc_boot_set(void *opaque, const char *boot_device)
{
    return set_boot_dev(opaque, boot_device, 0);
}

290 291
typedef struct pc_cmos_init_late_arg {
    ISADevice *rtc_state;
292
    BusState *idebus[2];
293 294 295 296 297 298
} pc_cmos_init_late_arg;

static void pc_cmos_init_late(void *opaque)
{
    pc_cmos_init_late_arg *arg = opaque;
    ISADevice *s = arg->rtc_state;
299 300
    int16_t cylinders;
    int8_t heads, sectors;
301
    int val;
302
    int i, trans;
303

304 305 306 307 308 309 310 311 312 313 314 315
    val = 0;
    if (ide_get_geometry(arg->idebus[0], 0,
                         &cylinders, &heads, &sectors) >= 0) {
        cmos_init_hd(s, 0x19, 0x1b, cylinders, heads, sectors);
        val |= 0xf0;
    }
    if (ide_get_geometry(arg->idebus[0], 1,
                         &cylinders, &heads, &sectors) >= 0) {
        cmos_init_hd(s, 0x1a, 0x24, cylinders, heads, sectors);
        val |= 0x0f;
    }
    rtc_set_memory(s, 0x12, val);
316 317 318

    val = 0;
    for (i = 0; i < 4; i++) {
319 320 321 322 323 324
        /* NOTE: ide_get_geometry() returns the physical
           geometry.  It is always such that: 1 <= sects <= 63, 1
           <= heads <= 16, 1 <= cylinders <= 16383. The BIOS
           geometry can be different if a translation is done. */
        if (ide_get_geometry(arg->idebus[i / 2], i % 2,
                             &cylinders, &heads, &sectors) >= 0) {
325 326 327
            trans = ide_get_bios_chs_trans(arg->idebus[i / 2], i % 2) - 1;
            assert((trans & ~3) == 0);
            val |= trans << (i * 2);
328 329 330 331 332 333 334
        }
    }
    rtc_set_memory(s, 0x39, val);

    qemu_unregister_reset(pc_cmos_init_late, opaque);
}

335
void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
336
                  const char *boot_device,
K
Kevin Wolf 已提交
337
                  ISADevice *floppy, BusState *idebus0, BusState *idebus1,
B
Blue Swirl 已提交
338
                  ISADevice *s)
B
bellard 已提交
339
{
340
    int val, nb, i;
341
    FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
342
    static pc_cmos_init_late_arg arg;
B
bellard 已提交
343 344

    /* various important CMOS locations needed by PC/Bochs bios */
B
bellard 已提交
345 346

    /* memory size */
347 348
    /* base memory (first MiB) */
    val = MIN(ram_size / 1024, 640);
B
bellard 已提交
349 350
    rtc_set_memory(s, 0x15, val);
    rtc_set_memory(s, 0x16, val >> 8);
351 352 353 354 355 356
    /* extended memory (next 64MiB) */
    if (ram_size > 1024 * 1024) {
        val = (ram_size - 1024 * 1024) / 1024;
    } else {
        val = 0;
    }
B
bellard 已提交
357 358
    if (val > 65535)
        val = 65535;
B
bellard 已提交
359 360 361 362
    rtc_set_memory(s, 0x17, val);
    rtc_set_memory(s, 0x18, val >> 8);
    rtc_set_memory(s, 0x30, val);
    rtc_set_memory(s, 0x31, val >> 8);
363 364 365 366
    /* memory between 16MiB and 4GiB */
    if (ram_size > 16 * 1024 * 1024) {
        val = (ram_size - 16 * 1024 * 1024) / 65536;
    } else {
B
bellard 已提交
367
        val = 0;
368
    }
B
bellard 已提交
369 370
    if (val > 65535)
        val = 65535;
B
bellard 已提交
371 372
    rtc_set_memory(s, 0x34, val);
    rtc_set_memory(s, 0x35, val >> 8);
373 374 375 376 377
    /* memory above 4GiB */
    val = above_4g_mem_size / 65536;
    rtc_set_memory(s, 0x5b, val);
    rtc_set_memory(s, 0x5c, val >> 8);
    rtc_set_memory(s, 0x5d, val >> 16);
378

A
aurel32 已提交
379 380 381
    /* set the number of CPU */
    rtc_set_memory(s, 0x5f, smp_cpus - 1);

382
    /* set boot devices, and disable floppy signature check if requested */
383
    if (set_boot_dev(s, boot_device, fd_bootchk)) {
384 385
        exit(1);
    }
B
bellard 已提交
386

B
bellard 已提交
387
    /* floppy type */
K
Kevin Wolf 已提交
388 389
    if (floppy) {
        for (i = 0; i < 2; i++) {
390
            fd_type[i] = isa_fdc_get_drive_type(floppy, i);
B
Blue Swirl 已提交
391 392 393 394
        }
    }
    val = (cmos_get_fd_drive_type(fd_type[0]) << 4) |
        cmos_get_fd_drive_type(fd_type[1]);
B
bellard 已提交
395
    rtc_set_memory(s, 0x10, val);
396

B
bellard 已提交
397
    val = 0;
B
bellard 已提交
398
    nb = 0;
B
Blue Swirl 已提交
399
    if (fd_type[0] < FDRIVE_DRV_NONE) {
B
bellard 已提交
400
        nb++;
401
    }
B
Blue Swirl 已提交
402
    if (fd_type[1] < FDRIVE_DRV_NONE) {
B
bellard 已提交
403
        nb++;
404
    }
B
bellard 已提交
405 406 407 408
    switch (nb) {
    case 0:
        break;
    case 1:
B
bellard 已提交
409
        val |= 0x01; /* 1 drive, ready for boot */
B
bellard 已提交
410 411
        break;
    case 2:
B
bellard 已提交
412
        val |= 0x41; /* 2 drives, ready for boot */
B
bellard 已提交
413 414
        break;
    }
B
bellard 已提交
415 416 417 418
    val |= 0x02; /* FPU is there */
    val |= 0x04; /* PS/2 mouse installed */
    rtc_set_memory(s, REG_EQUIPMENT_BYTE, val);

B
bellard 已提交
419
    /* hard drives */
420
    arg.rtc_state = s;
421 422
    arg.idebus[0] = idebus0;
    arg.idebus[1] = idebus1;
423
    qemu_register_reset(pc_cmos_init_late, &arg);
B
bellard 已提交
424 425
}

426 427 428
/* port 92 stuff: could be split off */
typedef struct Port92State {
    ISADevice dev;
429
    MemoryRegion io;
430 431 432 433
    uint8_t outport;
    qemu_irq *a20_out;
} Port92State;

434 435
static void port92_write(void *opaque, hwaddr addr, uint64_t val,
                         unsigned size)
436 437 438 439 440 441 442 443 444 445 446
{
    Port92State *s = opaque;

    DPRINTF("port92: write 0x%02x\n", val);
    s->outport = val;
    qemu_set_irq(*s->a20_out, (val >> 1) & 1);
    if (val & 1) {
        qemu_system_reset_request();
    }
}

447 448
static uint64_t port92_read(void *opaque, hwaddr addr,
                            unsigned size)
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
{
    Port92State *s = opaque;
    uint32_t ret;

    ret = s->outport;
    DPRINTF("port92: read 0x%02x\n", ret);
    return ret;
}

static void port92_init(ISADevice *dev, qemu_irq *a20_out)
{
    Port92State *s = DO_UPCAST(Port92State, dev, dev);

    s->a20_out = a20_out;
}

static const VMStateDescription vmstate_port92_isa = {
    .name = "port92",
    .version_id = 1,
    .minimum_version_id = 1,
    .minimum_version_id_old = 1,
    .fields      = (VMStateField []) {
        VMSTATE_UINT8(outport, Port92State),
        VMSTATE_END_OF_LIST()
    }
};

static void port92_reset(DeviceState *d)
{
    Port92State *s = container_of(d, Port92State, dev.qdev);

    s->outport &= ~1;
}

483
static const MemoryRegionOps port92_ops = {
484 485 486 487 488 489 490
    .read = port92_read,
    .write = port92_write,
    .impl = {
        .min_access_size = 1,
        .max_access_size = 1,
    },
    .endianness = DEVICE_LITTLE_ENDIAN,
491 492
};

493 494 495 496
static int port92_initfn(ISADevice *dev)
{
    Port92State *s = DO_UPCAST(Port92State, dev, dev);

497 498 499
    memory_region_init_io(&s->io, &port92_ops, s, "port92", 1);
    isa_register_ioport(dev, &s->io, 0x92);

500 501 502 503
    s->outport = 0;
    return 0;
}

504 505
static void port92_class_initfn(ObjectClass *klass, void *data)
{
506
    DeviceClass *dc = DEVICE_CLASS(klass);
507 508
    ISADeviceClass *ic = ISA_DEVICE_CLASS(klass);
    ic->init = port92_initfn;
509 510 511
    dc->no_user = 1;
    dc->reset = port92_reset;
    dc->vmsd = &vmstate_port92_isa;
512 513
}

514
static const TypeInfo port92_info = {
515 516 517 518
    .name          = "port92",
    .parent        = TYPE_ISA_DEVICE,
    .instance_size = sizeof(Port92State),
    .class_init    = port92_class_initfn,
519 520
};

A
Andreas Färber 已提交
521
static void port92_register_types(void)
522
{
523
    type_register_static(&port92_info);
524
}
A
Andreas Färber 已提交
525 526

type_init(port92_register_types)
527

B
Blue Swirl 已提交
528
static void handle_a20_line_change(void *opaque, int irq, int level)
529
{
A
Andreas Färber 已提交
530
    CPUX86State *cpu = opaque;
B
bellard 已提交
531

B
Blue Swirl 已提交
532
    /* XXX: send to all CPUs ? */
533
    /* XXX: add logic to handle multiple A20 line sources */
B
Blue Swirl 已提交
534
    cpu_x86_set_a20(cpu, level);
B
bellard 已提交
535 536
}

J
Jes Sorensen 已提交
537 538
int e820_add_entry(uint64_t address, uint64_t length, uint32_t type)
{
539
    int index = le32_to_cpu(e820_table.count);
J
Jes Sorensen 已提交
540 541 542 543
    struct e820_entry *entry;

    if (index >= E820_NR_ENTRIES)
        return -EBUSY;
544
    entry = &e820_table.entry[index++];
J
Jes Sorensen 已提交
545

546 547 548
    entry->address = cpu_to_le64(address);
    entry->length = cpu_to_le64(length);
    entry->type = cpu_to_le32(type);
J
Jes Sorensen 已提交
549

550 551
    e820_table.count = cpu_to_le32(index);
    return index;
J
Jes Sorensen 已提交
552 553
}

A
Alexander Graf 已提交
554
static void *bochs_bios_init(void)
B
bellard 已提交
555
{
556
    void *fw_cfg;
557 558
    uint8_t *smbios_table;
    size_t smbios_len;
559 560
    uint64_t *numa_fw_cfg;
    int i, j;
561 562

    fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0);
A
Alexander Graf 已提交
563

564
    fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1);
565
    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
566 567
    fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES, (uint8_t *)acpi_tables,
                     acpi_tables_len);
568
    fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override());
569 570 571 572 573

    smbios_table = smbios_get_table(&smbios_len);
    if (smbios_table)
        fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES,
                         smbios_table, smbios_len);
J
Jes Sorensen 已提交
574 575
    fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE, (uint8_t *)&e820_table,
                     sizeof(struct e820_table));
576

577 578
    fw_cfg_add_bytes(fw_cfg, FW_CFG_HPET, (uint8_t *)&hpet_cfg,
                     sizeof(struct hpet_fw_config));
579 580 581 582
    /* allocate memory for the NUMA channel: one (64bit) word for the number
     * of nodes, one word for each VCPU->node and one word for each node to
     * hold the amount of memory.
     */
583
    numa_fw_cfg = g_malloc0((1 + max_cpus + nb_numa_nodes) * 8);
584
    numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes);
585
    for (i = 0; i < max_cpus; i++) {
586
        for (j = 0; j < nb_numa_nodes; j++) {
587
            if (test_bit(i, node_cpumask[j])) {
588 589 590 591 592 593
                numa_fw_cfg[i + 1] = cpu_to_le64(j);
                break;
            }
        }
    }
    for (i = 0; i < nb_numa_nodes; i++) {
594
        numa_fw_cfg[max_cpus + 1 + i] = cpu_to_le64(node_mem[i]);
595 596
    }
    fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, (uint8_t *)numa_fw_cfg,
597
                     (1 + max_cpus + nb_numa_nodes) * 8);
A
Alexander Graf 已提交
598 599

    return fw_cfg;
B
bellard 已提交
600 601
}

T
ths 已提交
602 603 604 605 606 607 608 609 610 611 612 613 614 615
static long get_file_size(FILE *f)
{
    long where, size;

    /* XXX: on Unix systems, using fstat() probably makes more sense */

    where = ftell(f);
    fseek(f, 0, SEEK_END);
    size = ftell(f);
    fseek(f, where, SEEK_SET);

    return size;
}

A
Alexander Graf 已提交
616
static void load_linux(void *fw_cfg,
617
                       const char *kernel_filename,
T
ths 已提交
618
		       const char *initrd_filename,
G
Glauber Costa 已提交
619
		       const char *kernel_cmdline,
A
Avi Kivity 已提交
620
                       hwaddr max_ram_size)
T
ths 已提交
621 622
{
    uint16_t protocol;
P
Paul Brook 已提交
623
    int setup_size, kernel_size, initrd_size = 0, cmdline_size;
T
ths 已提交
624
    uint32_t initrd_max;
625
    uint8_t header[8192], *setup, *kernel, *initrd_data;
A
Avi Kivity 已提交
626
    hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0;
627
    FILE *f;
P
Pascal Terjan 已提交
628
    char *vmode;
T
ths 已提交
629 630 631 632 633 634 635

    /* Align to 16 bytes as a paranoia measure */
    cmdline_size = (strlen(kernel_cmdline)+16) & ~15;

    /* load the kernel header */
    f = fopen(kernel_filename, "rb");
    if (!f || !(kernel_size = get_file_size(f)) ||
A
Alexander Graf 已提交
636 637
	fread(header, 1, MIN(ARRAY_SIZE(header), kernel_size), f) !=
	MIN(ARRAY_SIZE(header), kernel_size)) {
638 639
	fprintf(stderr, "qemu: could not load kernel '%s': %s\n",
		kernel_filename, strerror(errno));
T
ths 已提交
640 641 642 643
	exit(1);
    }

    /* kernel protocol version */
B
bellard 已提交
644
#if 0
T
ths 已提交
645
    fprintf(stderr, "header magic: %#x\n", ldl_p(header+0x202));
B
bellard 已提交
646
#endif
T
ths 已提交
647 648
    if (ldl_p(header+0x202) == 0x53726448)
	protocol = lduw_p(header+0x206);
A
Alexander Graf 已提交
649 650 651
    else {
	/* This looks like a multiboot kernel. If it is, let's stop
	   treating it like a Linux kernel. */
652 653
        if (load_multiboot(fw_cfg, f, kernel_filename, initrd_filename,
                           kernel_cmdline, kernel_size, header))
B
Blue Swirl 已提交
654
            return;
T
ths 已提交
655
	protocol = 0;
A
Alexander Graf 已提交
656
    }
T
ths 已提交
657 658 659

    if (protocol < 0x200 || !(header[0x211] & 0x01)) {
	/* Low kernel */
660 661 662
	real_addr    = 0x90000;
	cmdline_addr = 0x9a000 - cmdline_size;
	prot_addr    = 0x10000;
T
ths 已提交
663 664
    } else if (protocol < 0x202) {
	/* High but ancient kernel */
665 666 667
	real_addr    = 0x90000;
	cmdline_addr = 0x9a000 - cmdline_size;
	prot_addr    = 0x100000;
T
ths 已提交
668 669
    } else {
	/* High and recent kernel */
670 671 672
	real_addr    = 0x10000;
	cmdline_addr = 0x20000;
	prot_addr    = 0x100000;
T
ths 已提交
673 674
    }

B
bellard 已提交
675
#if 0
T
ths 已提交
676
    fprintf(stderr,
677 678 679
	    "qemu: real_addr     = 0x" TARGET_FMT_plx "\n"
	    "qemu: cmdline_addr  = 0x" TARGET_FMT_plx "\n"
	    "qemu: prot_addr     = 0x" TARGET_FMT_plx "\n",
680 681 682
	    real_addr,
	    cmdline_addr,
	    prot_addr);
B
bellard 已提交
683
#endif
T
ths 已提交
684 685 686 687 688 689 690

    /* highest address for loading the initrd */
    if (protocol >= 0x203)
	initrd_max = ldl_p(header+0x22c);
    else
	initrd_max = 0x37ffffff;

G
Glauber Costa 已提交
691 692
    if (initrd_max >= max_ram_size-ACPI_DATA_SIZE)
    	initrd_max = max_ram_size-ACPI_DATA_SIZE-1;
T
ths 已提交
693

694 695 696 697 698
    fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr);
    fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, strlen(kernel_cmdline)+1);
    fw_cfg_add_bytes(fw_cfg, FW_CFG_CMDLINE_DATA,
                     (uint8_t*)strdup(kernel_cmdline),
                     strlen(kernel_cmdline)+1);
T
ths 已提交
699 700

    if (protocol >= 0x202) {
701
	stl_p(header+0x228, cmdline_addr);
T
ths 已提交
702 703 704 705 706
    } else {
	stw_p(header+0x20, 0xA33F);
	stw_p(header+0x22, cmdline_addr-real_addr);
    }

P
Pascal Terjan 已提交
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724
    /* handle vga= parameter */
    vmode = strstr(kernel_cmdline, "vga=");
    if (vmode) {
        unsigned int video_mode;
        /* skip "vga=" */
        vmode += 4;
        if (!strncmp(vmode, "normal", 6)) {
            video_mode = 0xffff;
        } else if (!strncmp(vmode, "ext", 3)) {
            video_mode = 0xfffe;
        } else if (!strncmp(vmode, "ask", 3)) {
            video_mode = 0xfffd;
        } else {
            video_mode = strtol(vmode, NULL, 0);
        }
        stw_p(header+0x1fa, video_mode);
    }

T
ths 已提交
725
    /* loader type */
S
Stefan Weil 已提交
726
    /* High nybble = B reserved for QEMU; low nybble is revision number.
T
ths 已提交
727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
       If this code is substantially changed, you may want to consider
       incrementing the revision. */
    if (protocol >= 0x200)
	header[0x210] = 0xB0;

    /* heap */
    if (protocol >= 0x201) {
	header[0x211] |= 0x80;	/* CAN_USE_HEAP */
	stw_p(header+0x224, cmdline_addr-real_addr-0x200);
    }

    /* load initrd */
    if (initrd_filename) {
	if (protocol < 0x200) {
	    fprintf(stderr, "qemu: linux kernel too old to load a ram disk\n");
	    exit(1);
	}

745
	initrd_size = get_image_size(initrd_filename);
M
M. Mohan Kumar 已提交
746 747 748 749 750 751
        if (initrd_size < 0) {
            fprintf(stderr, "qemu: error reading initrd %s\n",
                    initrd_filename);
            exit(1);
        }

752
        initrd_addr = (initrd_max-initrd_size) & ~4095;
753

754
        initrd_data = g_malloc(initrd_size);
755 756 757 758 759
        load_image(initrd_filename, initrd_data);

        fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr);
        fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size);
        fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, initrd_data, initrd_size);
T
ths 已提交
760

761
	stl_p(header+0x218, initrd_addr);
T
ths 已提交
762 763 764
	stl_p(header+0x21c, initrd_size);
    }

765
    /* load kernel and setup */
T
ths 已提交
766 767 768 769
    setup_size = header[0x1f1];
    if (setup_size == 0)
	setup_size = 4;
    setup_size = (setup_size+1)*512;
770
    kernel_size -= setup_size;
T
ths 已提交
771

772 773
    setup  = g_malloc(setup_size);
    kernel = g_malloc(kernel_size);
774
    fseek(f, 0, SEEK_SET);
775 776 777 778 779 780 781 782
    if (fread(setup, 1, setup_size, f) != setup_size) {
        fprintf(stderr, "fread() failed\n");
        exit(1);
    }
    if (fread(kernel, 1, kernel_size, f) != kernel_size) {
        fprintf(stderr, "fread() failed\n");
        exit(1);
    }
T
ths 已提交
783
    fclose(f);
784
    memcpy(setup, header, MIN(sizeof(header), setup_size));
785 786 787 788 789 790 791 792 793

    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
    fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
    fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);

    fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr);
    fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size);
    fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size);

G
Gleb Natapov 已提交
794 795
    option_rom[nb_option_roms].name = "linuxboot.bin";
    option_rom[nb_option_roms].bootindex = 0;
796
    nb_option_roms++;
T
ths 已提交
797 798
}

B
bellard 已提交
799 800
#define NE2000_NB_MAX 6

B
Blue Swirl 已提交
801 802 803
static const int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360,
                                              0x280, 0x380 };
static const int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
B
bellard 已提交
804

B
Blue Swirl 已提交
805 806
static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
807

808
void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd)
809 810 811 812 813
{
    static int nb_ne2k = 0;

    if (nb_ne2k == NE2000_NB_MAX)
        return;
814
    isa_ne2000_init(bus, ne2000_io[nb_ne2k],
G
Gerd Hoffmann 已提交
815
                    ne2000_irq[nb_ne2k], nd);
816 817 818
    nb_ne2k++;
}

B
Blue Swirl 已提交
819
DeviceState *cpu_get_current_apic(void)
820 821 822 823 824 825 826 827
{
    if (cpu_single_env) {
        return cpu_single_env->apic_state;
    } else {
        return NULL;
    }
}

828
void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
B
Blue Swirl 已提交
829
{
A
Andreas Färber 已提交
830
    CPUX86State *s = opaque;
B
Blue Swirl 已提交
831 832 833 834 835 836

    if (level) {
        cpu_interrupt(s, CPU_INTERRUPT_SMI);
    }
}

837
void pc_cpus_init(const char *cpu_model)
838 839 840 841 842 843 844 845 846 847 848 849
{
    int i;

    /* init CPUs */
    if (cpu_model == NULL) {
#ifdef TARGET_X86_64
        cpu_model = "qemu64";
#else
        cpu_model = "qemu32";
#endif
    }

850 851 852 853 854
    for (i = 0; i < smp_cpus; i++) {
        if (!cpu_x86_init(cpu_model)) {
            fprintf(stderr, "Unable to find x86 CPU definition\n");
            exit(1);
        }
855 856 857
    }
}

G
Gerd Hoffmann 已提交
858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880
void pc_acpi_init(const char *default_dsdt)
{
    char *filename = NULL, *arg = NULL;

    if (acpi_tables != NULL) {
        /* manually set via -acpitable, leave it alone */
        return;
    }

    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, default_dsdt);
    if (filename == NULL) {
        fprintf(stderr, "WARNING: failed to find %s\n", default_dsdt);
        return;
    }

    arg = g_strdup_printf("file=%s", filename);
    if (acpi_table_add(arg) != 0) {
        fprintf(stderr, "WARNING: failed to load %s\n", filename);
    }
    g_free(arg);
    g_free(filename);
}

881
void *pc_memory_init(MemoryRegion *system_memory,
A
Avi Kivity 已提交
882
                    const char *kernel_filename,
883 884
                    const char *kernel_cmdline,
                    const char *initrd_filename,
885
                    ram_addr_t below_4g_mem_size,
A
Avi Kivity 已提交
886
                    ram_addr_t above_4g_mem_size,
887
                    MemoryRegion *rom_memory,
A
Avi Kivity 已提交
888
                    MemoryRegion **ram_memory)
B
bellard 已提交
889
{
890 891
    int linux_boot, i;
    MemoryRegion *ram, *option_rom_mr;
892
    MemoryRegion *ram_below_4g, *ram_above_4g;
893
    void *fw_cfg;
894

B
bellard 已提交
895 896
    linux_boot = (kernel_filename != NULL);

897
    /* Allocate RAM.  We allocate it as a single memory region and use
D
Dong Xu Wang 已提交
898
     * aliases to address portions of it, mostly for backwards compatibility
899 900
     * with older qemus that used qemu_ram_alloc().
     */
901
    ram = g_malloc(sizeof(*ram));
902
    memory_region_init_ram(ram, "pc.ram",
903
                           below_4g_mem_size + above_4g_mem_size);
904
    vmstate_register_ram_global(ram);
A
Avi Kivity 已提交
905
    *ram_memory = ram;
906
    ram_below_4g = g_malloc(sizeof(*ram_below_4g));
907 908 909
    memory_region_init_alias(ram_below_4g, "ram-below-4g", ram,
                             0, below_4g_mem_size);
    memory_region_add_subregion(system_memory, 0, ram_below_4g);
910
    if (above_4g_mem_size > 0) {
911
        ram_above_4g = g_malloc(sizeof(*ram_above_4g));
912 913 914 915
        memory_region_init_alias(ram_above_4g, "ram-above-4g", ram,
                                 below_4g_mem_size, above_4g_mem_size);
        memory_region_add_subregion(system_memory, 0x100000000ULL,
                                    ram_above_4g);
916
    }
917

918 919 920

    /* Initialize PC system firmware */
    pc_system_firmware_init(rom_memory);
921

922
    option_rom_mr = g_malloc(sizeof(*option_rom_mr));
923 924
    memory_region_init_ram(option_rom_mr, "pc.rom", PC_ROM_SIZE);
    vmstate_register_ram_global(option_rom_mr);
925
    memory_region_add_subregion_overlap(rom_memory,
926 927 928
                                        PC_ROM_MIN_VGA,
                                        option_rom_mr,
                                        1);
929

A
Alexander Graf 已提交
930
    fw_cfg = bochs_bios_init();
G
Gerd Hoffmann 已提交
931
    rom_set_fw(fw_cfg);
A
Alexander Graf 已提交
932

933
    if (linux_boot) {
934
        load_linux(fw_cfg, kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size);
935 936 937
    }

    for (i = 0; i < nb_option_roms; i++) {
G
Gleb Natapov 已提交
938
        rom_add_option(option_rom[i].name, option_rom[i].bootindex);
939
    }
940
    return fw_cfg;
941 942
}

943 944 945 946 947
qemu_irq *pc_allocate_cpu_irq(void)
{
    return qemu_allocate_irqs(pic_irq_request, NULL, 1);
}

948
DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus)
949
{
950 951
    DeviceState *dev = NULL;

952 953 954 955 956 957
    if (pci_bus) {
        PCIDevice *pcidev = pci_vga_init(pci_bus);
        dev = pcidev ? &pcidev->qdev : NULL;
    } else if (isa_bus) {
        ISADevice *isadev = isa_vga_init(isa_bus);
        dev = isadev ? &isadev->qdev : NULL;
958
    }
959
    return dev;
960 961
}

B
Blue Swirl 已提交
962 963
static void cpu_request_exit(void *opaque, int irq, int level)
{
A
Andreas Färber 已提交
964
    CPUX86State *env = cpu_single_env;
B
Blue Swirl 已提交
965 966 967 968 969 970

    if (env && level) {
        cpu_exit(env);
    }
}

J
Julien Grall 已提交
971 972
static const MemoryRegionOps ioport80_io_ops = {
    .write = ioport80_write,
973
    .read = ioport80_read,
J
Julien Grall 已提交
974 975 976 977 978 979 980 981 982
    .endianness = DEVICE_NATIVE_ENDIAN,
    .impl = {
        .min_access_size = 1,
        .max_access_size = 1,
    },
};

static const MemoryRegionOps ioportF0_io_ops = {
    .write = ioportF0_write,
983
    .read = ioportF0_read,
J
Julien Grall 已提交
984 985 986 987 988 989 990
    .endianness = DEVICE_NATIVE_ENDIAN,
    .impl = {
        .min_access_size = 1,
        .max_access_size = 1,
    },
};

991
void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
992
                          ISADevice **rtc_state,
K
Kevin Wolf 已提交
993
                          ISADevice **floppy,
994
                          bool no_vmport)
995 996 997
{
    int i;
    DriveInfo *fd[MAX_FD];
998 999 1000
    DeviceState *hpet = NULL;
    int pit_isa_irq = 0;
    qemu_irq pit_alt_irq = NULL;
1001
    qemu_irq rtc_irq = NULL;
B
Blue Swirl 已提交
1002
    qemu_irq *a20_line;
1003
    ISADevice *i8042, *port92, *vmmouse, *pit = NULL;
B
Blue Swirl 已提交
1004
    qemu_irq *cpu_exit_irq;
J
Julien Grall 已提交
1005 1006
    MemoryRegion *ioport80_io = g_new(MemoryRegion, 1);
    MemoryRegion *ioportF0_io = g_new(MemoryRegion, 1);
1007

J
Julien Grall 已提交
1008 1009
    memory_region_init_io(ioport80_io, &ioport80_io_ops, NULL, "ioport80", 1);
    memory_region_add_subregion(isa_bus->address_space_io, 0x80, ioport80_io);
1010

J
Julien Grall 已提交
1011 1012
    memory_region_init_io(ioportF0_io, &ioportF0_io_ops, NULL, "ioportF0", 1);
    memory_region_add_subregion(isa_bus->address_space_io, 0xf0, ioportF0_io);
1013

1014 1015 1016 1017 1018 1019 1020
    /*
     * 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())) {
1021
        hpet = sysbus_try_create_simple("hpet", HPET_BASE, NULL);
J
Jan Kiszka 已提交
1022

B
Blue Swirl 已提交
1023
        if (hpet) {
J
Jan Kiszka 已提交
1024 1025
            for (i = 0; i < GSI_NUM_PINS; i++) {
                sysbus_connect_irq(sysbus_from_qdev(hpet), i, gsi[i]);
B
Blue Swirl 已提交
1026
            }
1027 1028 1029
            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);
J
Jan Kiszka 已提交
1030
        }
1031
    }
1032
    *rtc_state = rtc_init(isa_bus, 2000, rtc_irq);
1033 1034 1035

    qemu_register_boot_set(pc_boot_set, *rtc_state);

1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
    if (!xen_enabled()) {
        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);
1047
    }
1048 1049 1050

    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
        if (serial_hds[i]) {
1051
            serial_isa_init(isa_bus, i, serial_hds[i]);
1052 1053 1054 1055 1056
        }
    }

    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
        if (parallel_hds[i]) {
1057
            parallel_init(isa_bus, i, parallel_hds[i]);
1058 1059 1060
        }
    }

1061
    a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2);
1062
    i8042 = isa_create_simple(isa_bus, "i8042");
1063
    i8042_setup_a20_line(i8042, &a20_line[0]);
1064
    if (!no_vmport) {
1065 1066
        vmport_init(isa_bus);
        vmmouse = isa_try_create(isa_bus, "vmmouse");
1067 1068 1069
    } else {
        vmmouse = NULL;
    }
B
Blue Swirl 已提交
1070 1071
    if (vmmouse) {
        qdev_prop_set_ptr(&vmmouse->qdev, "ps2_mouse", i8042);
J
Jan Kiszka 已提交
1072
        qdev_init_nofail(&vmmouse->qdev);
B
Blue Swirl 已提交
1073
    }
1074
    port92 = isa_create_simple(isa_bus, "port92");
1075
    port92_init(port92, &a20_line[1]);
B
Blue Swirl 已提交
1076

B
Blue Swirl 已提交
1077 1078
    cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
    DMA_init(0, cpu_exit_irq);
1079 1080 1081 1082

    for(i = 0; i < MAX_FD; i++) {
        fd[i] = drive_get(IF_FLOPPY, 0, i);
    }
1083
    *floppy = fdctrl_init_isa(isa_bus, fd);
1084 1085
}

1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus)
{
    int i;

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

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

1101
void pc_pci_device_init(PCIBus *pci_bus)
1102 1103 1104 1105 1106 1107 1108 1109 1110
{
    int max_bus;
    int bus;

    max_bus = drive_get_max_bus(IF_SCSI);
    for (bus = 0; bus <= max_bus; bus++) {
        pci_create_simple(pci_bus, -1, "lsi53c895a");
    }
}
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134

void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name)
{
    DeviceState *dev;
    SysBusDevice *d;
    unsigned int i;

    if (kvm_irqchip_in_kernel()) {
        dev = qdev_create(NULL, "kvm-ioapic");
    } else {
        dev = qdev_create(NULL, "ioapic");
    }
    if (parent_name) {
        object_property_add_child(object_resolve_path(parent_name, NULL),
                                  "ioapic", OBJECT(dev), NULL);
    }
    qdev_init_nofail(dev);
    d = sysbus_from_qdev(dev);
    sysbus_mmio_map(d, 0, 0xfec00000);

    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
        gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i);
    }
}