~ubuntu-branches/ubuntu/saucy/qemu/saucy-proposed

« back to all changes in this revision

Viewing changes to hw/intc/ioapic.c

  • Committer: Package Import Robot
  • Author(s): Serge Hallyn
  • Date: 2013-05-28 08:18:30 UTC
  • mfrom: (1.8.2) (10.1.37 sid)
  • Revision ID: package-import@ubuntu.com-20130528081830-87xl2z9fq516a814
Tags: 1.5.0+dfsg-2ubuntu1
* Merge 1.5.0+dfs-2 from debian unstable.  Remaining changes:
  - debian/control
    * update maintainer
    * remove libiscsi, usb-redir, vde, vnc-jpeg, and libssh2-1-dev
      from build-deps
    * enable rbd
    * add qemu-system and qemu-common B/R to qemu-keymaps
    * add D:udev, R:qemu, R:qemu-common and B:qemu-common to
      qemu-system-common
    * qemu-system-arm, qemu-system-ppc, qemu-system-sparc:
      - add qemu-kvm to Provides
      - add qemu-common, qemu-kvm, kvm to B/R
      - remove openbios-sparc from qemu-system-sparc D
    * qemu-system-x86:
      - add qemu-common to Breaks/Replaces.
      - add cpu-checker to Recommends.
    * qemu-user: add B/R:qemu-kvm
    * qemu-kvm:
      - add armhf armel powerpc sparc to Architecture
      - C/R/P: qemu-kvm-spice
    * add qemu-common package
    * drop qemu-slof which is not packaged in ubuntu
  - add qemu-system-common.links for tap ifup/down scripts and OVMF link.
  - qemu-system-x86.links:
    * remove pxe rom links which are in kvm-ipxe
    * add symlink for kvm.1 manpage
  - debian/rules
    * add kvm-spice symlink to qemu-kvm
    * call dh_installmodules for qemu-system-x86
    * update dh_installinit to install upstart script
    * run dh_installman (Closes: #709241) (cherrypicked from 1.5.0+dfsg-2)
  - Add qemu-utils.links for kvm-* symlinks.
  - Add qemu-system-x86.qemu-kvm.upstart and .default
  - Add qemu-system-x86.modprobe to set nesting=1
  - Add qemu-system-common.preinst to add kvm group
  - qemu-system-common.postinst: remove bad group acl if there, then have
    udev relabel /dev/kvm.
  - Dropped patches:
    * 0001-fix-wrong-output-with-info-chardev-for-tcp-socket.patch
  - Kept patches:
    * expose_vms_qemu64cpu.patch - updated
    * gridcentric patch - updated
    * linaro arm patches from qemu-linaro rebasing branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  ioapic.c IOAPIC emulation logic
 
3
 *
 
4
 *  Copyright (c) 2004-2005 Fabrice Bellard
 
5
 *
 
6
 *  Split the ioapic logic from apic.c
 
7
 *  Xiantao Zhang <xiantao.zhang@intel.com>
 
8
 *
 
9
 * This library is free software; you can redistribute it and/or
 
10
 * modify it under the terms of the GNU Lesser General Public
 
11
 * License as published by the Free Software Foundation; either
 
12
 * version 2 of the License, or (at your option) any later version.
 
13
 *
 
14
 * This library is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
17
 * Lesser General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU Lesser General Public
 
20
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 
21
 */
 
22
 
 
23
#include "hw/hw.h"
 
24
#include "hw/i386/pc.h"
 
25
#include "hw/i386/ioapic.h"
 
26
#include "hw/i386/ioapic_internal.h"
 
27
 
 
28
//#define DEBUG_IOAPIC
 
29
 
 
30
#ifdef DEBUG_IOAPIC
 
31
#define DPRINTF(fmt, ...)                                       \
 
32
    do { printf("ioapic: " fmt , ## __VA_ARGS__); } while (0)
 
33
#else
 
34
#define DPRINTF(fmt, ...)
 
35
#endif
 
36
 
 
37
static IOAPICCommonState *ioapics[MAX_IOAPICS];
 
38
 
 
39
static void ioapic_service(IOAPICCommonState *s)
 
40
{
 
41
    uint8_t i;
 
42
    uint8_t trig_mode;
 
43
    uint8_t vector;
 
44
    uint8_t delivery_mode;
 
45
    uint32_t mask;
 
46
    uint64_t entry;
 
47
    uint8_t dest;
 
48
    uint8_t dest_mode;
 
49
 
 
50
    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
 
51
        mask = 1 << i;
 
52
        if (s->irr & mask) {
 
53
            entry = s->ioredtbl[i];
 
54
            if (!(entry & IOAPIC_LVT_MASKED)) {
 
55
                trig_mode = ((entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1);
 
56
                dest = entry >> IOAPIC_LVT_DEST_SHIFT;
 
57
                dest_mode = (entry >> IOAPIC_LVT_DEST_MODE_SHIFT) & 1;
 
58
                delivery_mode =
 
59
                    (entry >> IOAPIC_LVT_DELIV_MODE_SHIFT) & IOAPIC_DM_MASK;
 
60
                if (trig_mode == IOAPIC_TRIGGER_EDGE) {
 
61
                    s->irr &= ~mask;
 
62
                } else {
 
63
                    s->ioredtbl[i] |= IOAPIC_LVT_REMOTE_IRR;
 
64
                }
 
65
                if (delivery_mode == IOAPIC_DM_EXTINT) {
 
66
                    vector = pic_read_irq(isa_pic);
 
67
                } else {
 
68
                    vector = entry & IOAPIC_VECTOR_MASK;
 
69
                }
 
70
                apic_deliver_irq(dest, dest_mode, delivery_mode,
 
71
                                 vector, trig_mode);
 
72
            }
 
73
        }
 
74
    }
 
75
}
 
76
 
 
77
static void ioapic_set_irq(void *opaque, int vector, int level)
 
78
{
 
79
    IOAPICCommonState *s = opaque;
 
80
 
 
81
    /* ISA IRQs map to GSI 1-1 except for IRQ0 which maps
 
82
     * to GSI 2.  GSI maps to ioapic 1-1.  This is not
 
83
     * the cleanest way of doing it but it should work. */
 
84
 
 
85
    DPRINTF("%s: %s vec %x\n", __func__, level ? "raise" : "lower", vector);
 
86
    if (vector == 0) {
 
87
        vector = 2;
 
88
    }
 
89
    if (vector >= 0 && vector < IOAPIC_NUM_PINS) {
 
90
        uint32_t mask = 1 << vector;
 
91
        uint64_t entry = s->ioredtbl[vector];
 
92
 
 
93
        if (entry & (1 << IOAPIC_LVT_POLARITY_SHIFT)) {
 
94
            level = !level;
 
95
        }
 
96
        if (((entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1) ==
 
97
            IOAPIC_TRIGGER_LEVEL) {
 
98
            /* level triggered */
 
99
            if (level) {
 
100
                s->irr |= mask;
 
101
                ioapic_service(s);
 
102
            } else {
 
103
                s->irr &= ~mask;
 
104
            }
 
105
        } else {
 
106
            /* According to the 82093AA manual, we must ignore edge requests
 
107
             * if the input pin is masked. */
 
108
            if (level && !(entry & IOAPIC_LVT_MASKED)) {
 
109
                s->irr |= mask;
 
110
                ioapic_service(s);
 
111
            }
 
112
        }
 
113
    }
 
114
}
 
115
 
 
116
void ioapic_eoi_broadcast(int vector)
 
117
{
 
118
    IOAPICCommonState *s;
 
119
    uint64_t entry;
 
120
    int i, n;
 
121
 
 
122
    for (i = 0; i < MAX_IOAPICS; i++) {
 
123
        s = ioapics[i];
 
124
        if (!s) {
 
125
            continue;
 
126
        }
 
127
        for (n = 0; n < IOAPIC_NUM_PINS; n++) {
 
128
            entry = s->ioredtbl[n];
 
129
            if ((entry & IOAPIC_LVT_REMOTE_IRR)
 
130
                && (entry & IOAPIC_VECTOR_MASK) == vector) {
 
131
                s->ioredtbl[n] = entry & ~IOAPIC_LVT_REMOTE_IRR;
 
132
                if (!(entry & IOAPIC_LVT_MASKED) && (s->irr & (1 << n))) {
 
133
                    ioapic_service(s);
 
134
                }
 
135
            }
 
136
        }
 
137
    }
 
138
}
 
139
 
 
140
static uint64_t
 
141
ioapic_mem_read(void *opaque, hwaddr addr, unsigned int size)
 
142
{
 
143
    IOAPICCommonState *s = opaque;
 
144
    int index;
 
145
    uint32_t val = 0;
 
146
 
 
147
    switch (addr & 0xff) {
 
148
    case IOAPIC_IOREGSEL:
 
149
        val = s->ioregsel;
 
150
        break;
 
151
    case IOAPIC_IOWIN:
 
152
        if (size != 4) {
 
153
            break;
 
154
        }
 
155
        switch (s->ioregsel) {
 
156
        case IOAPIC_REG_ID:
 
157
            val = s->id << IOAPIC_ID_SHIFT;
 
158
            break;
 
159
        case IOAPIC_REG_VER:
 
160
            val = IOAPIC_VERSION |
 
161
                ((IOAPIC_NUM_PINS - 1) << IOAPIC_VER_ENTRIES_SHIFT);
 
162
            break;
 
163
        case IOAPIC_REG_ARB:
 
164
            val = 0;
 
165
            break;
 
166
        default:
 
167
            index = (s->ioregsel - IOAPIC_REG_REDTBL_BASE) >> 1;
 
168
            if (index >= 0 && index < IOAPIC_NUM_PINS) {
 
169
                if (s->ioregsel & 1) {
 
170
                    val = s->ioredtbl[index] >> 32;
 
171
                } else {
 
172
                    val = s->ioredtbl[index] & 0xffffffff;
 
173
                }
 
174
            }
 
175
        }
 
176
        DPRINTF("read: %08x = %08x\n", s->ioregsel, val);
 
177
        break;
 
178
    }
 
179
    return val;
 
180
}
 
181
 
 
182
static void
 
183
ioapic_mem_write(void *opaque, hwaddr addr, uint64_t val,
 
184
                 unsigned int size)
 
185
{
 
186
    IOAPICCommonState *s = opaque;
 
187
    int index;
 
188
 
 
189
    switch (addr & 0xff) {
 
190
    case IOAPIC_IOREGSEL:
 
191
        s->ioregsel = val;
 
192
        break;
 
193
    case IOAPIC_IOWIN:
 
194
        if (size != 4) {
 
195
            break;
 
196
        }
 
197
        DPRINTF("write: %08x = %08" PRIx64 "\n", s->ioregsel, val);
 
198
        switch (s->ioregsel) {
 
199
        case IOAPIC_REG_ID:
 
200
            s->id = (val >> IOAPIC_ID_SHIFT) & IOAPIC_ID_MASK;
 
201
            break;
 
202
        case IOAPIC_REG_VER:
 
203
        case IOAPIC_REG_ARB:
 
204
            break;
 
205
        default:
 
206
            index = (s->ioregsel - IOAPIC_REG_REDTBL_BASE) >> 1;
 
207
            if (index >= 0 && index < IOAPIC_NUM_PINS) {
 
208
                if (s->ioregsel & 1) {
 
209
                    s->ioredtbl[index] &= 0xffffffff;
 
210
                    s->ioredtbl[index] |= (uint64_t)val << 32;
 
211
                } else {
 
212
                    s->ioredtbl[index] &= ~0xffffffffULL;
 
213
                    s->ioredtbl[index] |= val;
 
214
                }
 
215
                ioapic_service(s);
 
216
            }
 
217
        }
 
218
        break;
 
219
    }
 
220
}
 
221
 
 
222
static const MemoryRegionOps ioapic_io_ops = {
 
223
    .read = ioapic_mem_read,
 
224
    .write = ioapic_mem_write,
 
225
    .endianness = DEVICE_NATIVE_ENDIAN,
 
226
};
 
227
 
 
228
static void ioapic_init(IOAPICCommonState *s, int instance_no)
 
229
{
 
230
    memory_region_init_io(&s->io_memory, &ioapic_io_ops, s, "ioapic", 0x1000);
 
231
 
 
232
    qdev_init_gpio_in(&s->busdev.qdev, ioapic_set_irq, IOAPIC_NUM_PINS);
 
233
 
 
234
    ioapics[instance_no] = s;
 
235
}
 
236
 
 
237
static void ioapic_class_init(ObjectClass *klass, void *data)
 
238
{
 
239
    IOAPICCommonClass *k = IOAPIC_COMMON_CLASS(klass);
 
240
    DeviceClass *dc = DEVICE_CLASS(klass);
 
241
 
 
242
    k->init = ioapic_init;
 
243
    dc->reset = ioapic_reset_common;
 
244
}
 
245
 
 
246
static const TypeInfo ioapic_info = {
 
247
    .name          = "ioapic",
 
248
    .parent        = TYPE_IOAPIC_COMMON,
 
249
    .instance_size = sizeof(IOAPICCommonState),
 
250
    .class_init    = ioapic_class_init,
 
251
};
 
252
 
 
253
static void ioapic_register_types(void)
 
254
{
 
255
    type_register_static(&ioapic_info);
 
256
}
 
257
 
 
258
type_init(ioapic_register_types)