Statistics
| Branch: | Revision:

root / hw / kvm / ioapic.c @ a39c1d47

History | View | Annotate | Download (2.8 kB)

1
/*
2
 * KVM in-kernel IOPIC support
3
 *
4
 * Copyright (c) 2011 Siemens AG
5
 *
6
 * Authors:
7
 *  Jan Kiszka          <jan.kiszka@siemens.com>
8
 *
9
 * This work is licensed under the terms of the GNU GPL version 2.
10
 * See the COPYING file in the top-level directory.
11
 */
12

    
13
#include "hw/pc.h"
14
#include "hw/ioapic_internal.h"
15
#include "hw/apic_internal.h"
16
#include "kvm.h"
17

    
18
typedef struct KVMIOAPICState KVMIOAPICState;
19

    
20
struct KVMIOAPICState {
21
    IOAPICCommonState ioapic;
22
    uint32_t kvm_gsi_base;
23
};
24

    
25
static void kvm_ioapic_get(IOAPICCommonState *s)
26
{
27
    struct kvm_irqchip chip;
28
    struct kvm_ioapic_state *kioapic;
29
    int ret, i;
30

    
31
    chip.chip_id = KVM_IRQCHIP_IOAPIC;
32
    ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, &chip);
33
    if (ret < 0) {
34
        fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret));
35
        abort();
36
    }
37

    
38
    kioapic = &chip.chip.ioapic;
39

    
40
    s->id = kioapic->id;
41
    s->ioregsel = kioapic->ioregsel;
42
    s->irr = kioapic->irr;
43
    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
44
        s->ioredtbl[i] = kioapic->redirtbl[i].bits;
45
    }
46
}
47

    
48
static void kvm_ioapic_put(IOAPICCommonState *s)
49
{
50
    struct kvm_irqchip chip;
51
    struct kvm_ioapic_state *kioapic;
52
    int ret, i;
53

    
54
    chip.chip_id = KVM_IRQCHIP_IOAPIC;
55
    kioapic = &chip.chip.ioapic;
56

    
57
    kioapic->id = s->id;
58
    kioapic->ioregsel = s->ioregsel;
59
    kioapic->base_address = s->busdev.mmio[0].addr;
60
    kioapic->irr = s->irr;
61
    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
62
        kioapic->redirtbl[i].bits = s->ioredtbl[i];
63
    }
64

    
65
    ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, &chip);
66
    if (ret < 0) {
67
        fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret));
68
        abort();
69
    }
70
}
71

    
72
static void kvm_ioapic_reset(DeviceState *dev)
73
{
74
    IOAPICCommonState *s = DO_UPCAST(IOAPICCommonState, busdev.qdev, dev);
75

    
76
    ioapic_reset_common(dev);
77
    kvm_ioapic_put(s);
78
}
79

    
80
static void kvm_ioapic_set_irq(void *opaque, int irq, int level)
81
{
82
    KVMIOAPICState *s = opaque;
83
    int delivered;
84

    
85
    delivered = kvm_irqchip_set_irq(kvm_state, s->kvm_gsi_base + irq, level);
86
    apic_report_irq_delivered(delivered);
87
}
88

    
89
static void kvm_ioapic_init(IOAPICCommonState *s, int instance_no)
90
{
91
    memory_region_init_reservation(&s->io_memory, "kvm-ioapic", 0x1000);
92

    
93
    qdev_init_gpio_in(&s->busdev.qdev, kvm_ioapic_set_irq, IOAPIC_NUM_PINS);
94
}
95

    
96
static IOAPICCommonInfo kvm_ioapic_info = {
97
    .busdev.qdev.name  = "kvm-ioapic",
98
    .busdev.qdev.size = sizeof(KVMIOAPICState),
99
    .busdev.qdev.reset = kvm_ioapic_reset,
100
    .busdev.qdev.props = (Property[]) {
101
        DEFINE_PROP_UINT32("gsi_base", KVMIOAPICState, kvm_gsi_base, 0),
102
        DEFINE_PROP_END_OF_LIST()
103
    },
104
    .init      = kvm_ioapic_init,
105
    .pre_save  = kvm_ioapic_get,
106
    .post_load = kvm_ioapic_put,
107
};
108

    
109
static void kvm_ioapic_register_device(void)
110
{
111
    ioapic_qdev_register(&kvm_ioapic_info);
112
}
113

    
114
device_init(kvm_ioapic_register_device)