Blame view
virt/kvm/ioapic.c
10.9 KB
1fd4f2a5e KVM: In-kernel I/... |
1 2 |
/* * Copyright (C) 2001 MandrakeSoft S.A. |
221d059d1 KVM: Update Red H... |
3 |
* Copyright 2010 Red Hat, Inc. and/or its affiliates. |
1fd4f2a5e KVM: In-kernel I/... |
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
* * MandrakeSoft S.A. * 43, rue d'Aboukir * 75002 Paris - France * http://www.linux-mandrake.com/ * http://www.mandrakesoft.com/ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Yunhong Jiang <yunhong.jiang@intel.com> * Yaozu (Eddie) Dong <eddie.dong@intel.com> * Based on Xen 3.1 code. */ |
edf884172 KVM: Move arch de... |
29 |
#include <linux/kvm_host.h> |
1fd4f2a5e KVM: In-kernel I/... |
30 31 32 33 34 35 |
#include <linux/kvm.h> #include <linux/mm.h> #include <linux/highmem.h> #include <linux/smp.h> #include <linux/hrtimer.h> #include <linux/io.h> |
5a0e3ad6a include cleanup: ... |
36 |
#include <linux/slab.h> |
1fd4f2a5e KVM: In-kernel I/... |
37 |
#include <asm/processor.h> |
1fd4f2a5e KVM: In-kernel I/... |
38 39 |
#include <asm/page.h> #include <asm/current.h> |
1000ff8d8 KVM: Add trace po... |
40 |
#include <trace/events/kvm.h> |
82470196f KVM: Move irqchip... |
41 42 43 |
#include "ioapic.h" #include "lapic.h" |
f52447261 KVM: irq ack noti... |
44 |
#include "irq.h" |
82470196f KVM: Move irqchip... |
45 |
|
e25e3ed56 KVM: Add some \n ... |
46 47 48 |
#if 0 #define ioapic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg) #else |
1fd4f2a5e KVM: In-kernel I/... |
49 |
#define ioapic_debug(fmt, arg...) |
e25e3ed56 KVM: Add some \n ... |
50 |
#endif |
ff4b9df87 KVM: IOAPIC: only... |
51 |
static int ioapic_deliver(struct kvm_ioapic *vioapic, int irq); |
1fd4f2a5e KVM: In-kernel I/... |
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic, unsigned long addr, unsigned long length) { unsigned long result = 0; switch (ioapic->ioregsel) { case IOAPIC_REG_VERSION: result = ((((IOAPIC_NUM_PINS - 1) & 0xff) << 16) | (IOAPIC_VERSION_ID & 0xff)); break; case IOAPIC_REG_APIC_ID: case IOAPIC_REG_ARB_ID: result = ((ioapic->id & 0xf) << 24); break; default: { u32 redir_index = (ioapic->ioregsel - 0x10) >> 1; u64 redir_content; ASSERT(redir_index < IOAPIC_NUM_PINS); redir_content = ioapic->redirtbl[redir_index].bits; result = (ioapic->ioregsel & 0x1) ? (redir_content >> 32) & 0xffffffff : redir_content & 0xffffffff; break; } } return result; } |
4925663a0 KVM: Report IRQ i... |
87 |
static int ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) |
1fd4f2a5e KVM: In-kernel I/... |
88 |
{ |
cf9e4e15e KVM: Split IOAPIC... |
89 |
union kvm_ioapic_redirect_entry *pent; |
4925663a0 KVM: Report IRQ i... |
90 |
int injected = -1; |
1fd4f2a5e KVM: In-kernel I/... |
91 92 93 94 |
pent = &ioapic->redirtbl[idx]; if (!pent->fields.mask) { |
4925663a0 KVM: Report IRQ i... |
95 |
injected = ioapic_deliver(ioapic, idx); |
ff4b9df87 KVM: IOAPIC: only... |
96 |
if (injected && pent->fields.trig_mode == IOAPIC_LEVEL_TRIG) |
1fd4f2a5e KVM: In-kernel I/... |
97 98 |
pent->fields.remote_irr = 1; } |
4925663a0 KVM: Report IRQ i... |
99 100 |
return injected; |
1fd4f2a5e KVM: In-kernel I/... |
101 |
} |
46a929bc1 KVM: avoid taking... |
102 103 104 105 106 107 108 109 110 111 112 113 |
static void update_handled_vectors(struct kvm_ioapic *ioapic) { DECLARE_BITMAP(handled_vectors, 256); int i; memset(handled_vectors, 0, sizeof(handled_vectors)); for (i = 0; i < IOAPIC_NUM_PINS; ++i) __set_bit(ioapic->redirtbl[i].fields.vector, handled_vectors); memcpy(ioapic->handled_vectors, handled_vectors, sizeof(handled_vectors)); smp_wmb(); } |
1fd4f2a5e KVM: In-kernel I/... |
114 115 116 |
static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) { unsigned index; |
75858a84a KVM: Interrupt ma... |
117 |
bool mask_before, mask_after; |
70f93dae3 KVM: Use temporar... |
118 |
union kvm_ioapic_redirect_entry *e; |
1fd4f2a5e KVM: In-kernel I/... |
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
switch (ioapic->ioregsel) { case IOAPIC_REG_VERSION: /* Writes are ignored. */ break; case IOAPIC_REG_APIC_ID: ioapic->id = (val >> 24) & 0xf; break; case IOAPIC_REG_ARB_ID: break; default: index = (ioapic->ioregsel - 0x10) >> 1; |
e25e3ed56 KVM: Add some \n ... |
134 135 |
ioapic_debug("change redir index %x val %x ", index, val); |
1fd4f2a5e KVM: In-kernel I/... |
136 137 |
if (index >= IOAPIC_NUM_PINS) return; |
70f93dae3 KVM: Use temporar... |
138 139 |
e = &ioapic->redirtbl[index]; mask_before = e->fields.mask; |
1fd4f2a5e KVM: In-kernel I/... |
140 |
if (ioapic->ioregsel & 1) { |
70f93dae3 KVM: Use temporar... |
141 142 |
e->bits &= 0xffffffff; e->bits |= (u64) val << 32; |
1fd4f2a5e KVM: In-kernel I/... |
143 |
} else { |
70f93dae3 KVM: Use temporar... |
144 145 146 |
e->bits &= ~0xffffffffULL; e->bits |= (u32) val; e->fields.remote_irr = 0; |
1fd4f2a5e KVM: In-kernel I/... |
147 |
} |
46a929bc1 KVM: avoid taking... |
148 |
update_handled_vectors(ioapic); |
70f93dae3 KVM: Use temporar... |
149 |
mask_after = e->fields.mask; |
75858a84a KVM: Interrupt ma... |
150 |
if (mask_before != mask_after) |
4a994358b KVM: Convert mask... |
151 |
kvm_fire_mask_notifiers(ioapic->kvm, KVM_IRQCHIP_IOAPIC, index, mask_after); |
70f93dae3 KVM: Use temporar... |
152 |
if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG |
b4a2f5e72 KVM: Avoid redeli... |
153 |
&& ioapic->irr & (1 << index)) |
1fd4f2a5e KVM: In-kernel I/... |
154 155 156 157 |
ioapic_service(ioapic, index); break; } } |
a53c17d21 KVM: ioapic/msi i... |
158 159 |
static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) { |
58c2dde17 KVM: APIC: get ri... |
160 161 |
union kvm_ioapic_redirect_entry *entry = &ioapic->redirtbl[irq]; struct kvm_lapic_irq irqe; |
a53c17d21 KVM: ioapic/msi i... |
162 163 164 165 |
ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x " "vector=%x trig_mode=%x ", |
a38f84ca8 KVM: ioapic: Fix ... |
166 |
entry->fields.dest_id, entry->fields.dest_mode, |
58c2dde17 KVM: APIC: get ri... |
167 168 169 170 171 172 173 174 175 176 |
entry->fields.delivery_mode, entry->fields.vector, entry->fields.trig_mode); irqe.dest_id = entry->fields.dest_id; irqe.vector = entry->fields.vector; irqe.dest_mode = entry->fields.dest_mode; irqe.trig_mode = entry->fields.trig_mode; irqe.delivery_mode = entry->fields.delivery_mode << 8; irqe.level = 1; irqe.shorthand = 0; |
a53c17d21 KVM: ioapic/msi i... |
177 178 179 180 |
#ifdef CONFIG_X86 /* Always delivery PIT interrupt to vcpu 0 */ if (irq == 0) { |
58c2dde17 KVM: APIC: get ri... |
181 |
irqe.dest_mode = 0; /* Physical mode. */ |
c5af89b68 KVM: Introduce kv... |
182 183 |
/* need to read apic_id from apic regiest since * it can be rewritten */ |
d546cb406 KVM: drop bsp_vcp... |
184 |
irqe.dest_id = ioapic->kvm->bsp_vcpu_id; |
a53c17d21 KVM: ioapic/msi i... |
185 186 |
} #endif |
58c2dde17 KVM: APIC: get ri... |
187 |
return kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe); |
a53c17d21 KVM: ioapic/msi i... |
188 |
} |
4925663a0 KVM: Report IRQ i... |
189 |
int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) |
1fd4f2a5e KVM: In-kernel I/... |
190 |
{ |
07dc7263b KVM: read apic->i... |
191 |
u32 old_irr; |
1fd4f2a5e KVM: In-kernel I/... |
192 |
u32 mask = 1 << irq; |
cf9e4e15e KVM: Split IOAPIC... |
193 |
union kvm_ioapic_redirect_entry entry; |
4925663a0 KVM: Report IRQ i... |
194 |
int ret = 1; |
1fd4f2a5e KVM: In-kernel I/... |
195 |
|
46a47b1ed KVM: convert ioap... |
196 |
spin_lock(&ioapic->lock); |
07dc7263b KVM: read apic->i... |
197 |
old_irr = ioapic->irr; |
1fd4f2a5e KVM: In-kernel I/... |
198 199 200 201 202 203 |
if (irq >= 0 && irq < IOAPIC_NUM_PINS) { entry = ioapic->redirtbl[irq]; level ^= entry.fields.polarity; if (!level) ioapic->irr &= ~mask; else { |
b4a2f5e72 KVM: Avoid redeli... |
204 |
int edge = (entry.fields.trig_mode == IOAPIC_EDGE_TRIG); |
1fd4f2a5e KVM: In-kernel I/... |
205 |
ioapic->irr |= mask; |
b4a2f5e72 KVM: Avoid redeli... |
206 207 |
if ((edge && old_irr != ioapic->irr) || (!edge && !entry.fields.remote_irr)) |
4925663a0 KVM: Report IRQ i... |
208 |
ret = ioapic_service(ioapic, irq); |
65a822116 KVM: Fix coalesce... |
209 210 |
else ret = 0; /* report coalesced interrupt */ |
1fd4f2a5e KVM: In-kernel I/... |
211 |
} |
1000ff8d8 KVM: Add trace po... |
212 |
trace_kvm_ioapic_set_irq(entry.bits, irq, ret == 0); |
1fd4f2a5e KVM: In-kernel I/... |
213 |
} |
46a47b1ed KVM: convert ioap... |
214 |
spin_unlock(&ioapic->lock); |
eba0226bd KVM: Move IO APIC... |
215 |
|
4925663a0 KVM: Report IRQ i... |
216 |
return ret; |
1fd4f2a5e KVM: In-kernel I/... |
217 |
} |
eba0226bd KVM: Move IO APIC... |
218 219 |
static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int vector, int trigger_mode) |
1fd4f2a5e KVM: In-kernel I/... |
220 |
{ |
eba0226bd KVM: Move IO APIC... |
221 222 223 224 |
int i; for (i = 0; i < IOAPIC_NUM_PINS; i++) { union kvm_ioapic_redirect_entry *ent = &ioapic->redirtbl[i]; |
1fd4f2a5e KVM: In-kernel I/... |
225 |
|
eba0226bd KVM: Move IO APIC... |
226 227 |
if (ent->fields.vector != vector) continue; |
1fd4f2a5e KVM: In-kernel I/... |
228 |
|
eba0226bd KVM: Move IO APIC... |
229 230 231 232 233 234 235 236 |
/* * We are dropping lock while calling ack notifiers because ack * notifier callbacks for assigned devices call into IOAPIC * recursively. Since remote_irr is cleared only after call * to notifiers if the same vector will be delivered while lock * is dropped it will be put into irr and will be delivered * after ack notifier returns. */ |
46a47b1ed KVM: convert ioap... |
237 |
spin_unlock(&ioapic->lock); |
eba0226bd KVM: Move IO APIC... |
238 |
kvm_notify_acked_irq(ioapic->kvm, KVM_IRQCHIP_IOAPIC, i); |
46a47b1ed KVM: convert ioap... |
239 |
spin_lock(&ioapic->lock); |
eba0226bd KVM: Move IO APIC... |
240 241 242 |
if (trigger_mode != IOAPIC_LEVEL_TRIG) continue; |
f52447261 KVM: irq ack noti... |
243 |
|
f52447261 KVM: irq ack noti... |
244 245 |
ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG); ent->fields.remote_irr = 0; |
eba0226bd KVM: Move IO APIC... |
246 247 |
if (!ent->fields.mask && (ioapic->irr & (1 << i))) ioapic_service(ioapic, i); |
f52447261 KVM: irq ack noti... |
248 |
} |
1fd4f2a5e KVM: In-kernel I/... |
249 |
} |
f52447261 KVM: irq ack noti... |
250 |
void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode) |
4fa6b9c5d KVM: ioapic: fix ... |
251 252 |
{ struct kvm_ioapic *ioapic = kvm->arch.vioapic; |
4fa6b9c5d KVM: ioapic: fix ... |
253 |
|
46a929bc1 KVM: avoid taking... |
254 255 256 |
smp_rmb(); if (!test_bit(vector, ioapic->handled_vectors)) return; |
46a47b1ed KVM: convert ioap... |
257 |
spin_lock(&ioapic->lock); |
eba0226bd KVM: Move IO APIC... |
258 |
__kvm_ioapic_update_eoi(ioapic, vector, trigger_mode); |
46a47b1ed KVM: convert ioap... |
259 |
spin_unlock(&ioapic->lock); |
4fa6b9c5d KVM: ioapic: fix ... |
260 |
} |
d76685c4a KVM: cleanup io_d... |
261 262 263 264 |
static inline struct kvm_ioapic *to_ioapic(struct kvm_io_device *dev) { return container_of(dev, struct kvm_ioapic, dev); } |
bda9020e2 KVM: remove in_ra... |
265 |
static inline int ioapic_in_range(struct kvm_ioapic *ioapic, gpa_t addr) |
1fd4f2a5e KVM: In-kernel I/... |
266 |
{ |
1fd4f2a5e KVM: In-kernel I/... |
267 268 269 |
return ((addr >= ioapic->base_address && (addr < ioapic->base_address + IOAPIC_MEM_LENGTH))); } |
bda9020e2 KVM: remove in_ra... |
270 271 |
static int ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len, void *val) |
1fd4f2a5e KVM: In-kernel I/... |
272 |
{ |
d76685c4a KVM: cleanup io_d... |
273 |
struct kvm_ioapic *ioapic = to_ioapic(this); |
1fd4f2a5e KVM: In-kernel I/... |
274 |
u32 result; |
bda9020e2 KVM: remove in_ra... |
275 276 |
if (!ioapic_in_range(ioapic, addr)) return -EOPNOTSUPP; |
1fd4f2a5e KVM: In-kernel I/... |
277 |
|
e25e3ed56 KVM: Add some \n ... |
278 279 |
ioapic_debug("addr %lx ", (unsigned long)addr); |
1fd4f2a5e KVM: In-kernel I/... |
280 281 282 |
ASSERT(!(addr & 0xf)); /* check alignment */ addr &= 0xff; |
46a47b1ed KVM: convert ioap... |
283 |
spin_lock(&ioapic->lock); |
1fd4f2a5e KVM: In-kernel I/... |
284 285 286 287 288 289 290 291 292 293 294 295 296 |
switch (addr) { case IOAPIC_REG_SELECT: result = ioapic->ioregsel; break; case IOAPIC_REG_WINDOW: result = ioapic_read_indirect(ioapic, addr, len); break; default: result = 0; break; } |
46a47b1ed KVM: convert ioap... |
297 |
spin_unlock(&ioapic->lock); |
eba0226bd KVM: Move IO APIC... |
298 |
|
1fd4f2a5e KVM: In-kernel I/... |
299 300 301 302 303 304 305 306 307 308 309 310 311 |
switch (len) { case 8: *(u64 *) val = result; break; case 1: case 2: case 4: memcpy(val, (char *)&result, len); break; default: printk(KERN_WARNING "ioapic: wrong length %d ", len); } |
bda9020e2 KVM: remove in_ra... |
312 |
return 0; |
1fd4f2a5e KVM: In-kernel I/... |
313 |
} |
bda9020e2 KVM: remove in_ra... |
314 315 |
static int ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len, const void *val) |
1fd4f2a5e KVM: In-kernel I/... |
316 |
{ |
d76685c4a KVM: cleanup io_d... |
317 |
struct kvm_ioapic *ioapic = to_ioapic(this); |
1fd4f2a5e KVM: In-kernel I/... |
318 |
u32 data; |
bda9020e2 KVM: remove in_ra... |
319 320 |
if (!ioapic_in_range(ioapic, addr)) return -EOPNOTSUPP; |
1fd4f2a5e KVM: In-kernel I/... |
321 |
|
e25e3ed56 KVM: Add some \n ... |
322 323 324 |
ioapic_debug("ioapic_mmio_write addr=%p len=%d val=%p ", (void*)addr, len, val); |
1fd4f2a5e KVM: In-kernel I/... |
325 |
ASSERT(!(addr & 0xf)); /* check alignment */ |
60eead79a KVM: introduce ir... |
326 |
|
d77fe6354 KVM: Allow aligne... |
327 328 329 |
switch (len) { case 8: case 4: |
1fd4f2a5e KVM: In-kernel I/... |
330 |
data = *(u32 *) val; |
d77fe6354 KVM: Allow aligne... |
331 332 333 334 335 336 337 338 |
break; case 2: data = *(u16 *) val; break; case 1: data = *(u8 *) val; break; default: |
1fd4f2a5e KVM: In-kernel I/... |
339 340 |
printk(KERN_WARNING "ioapic: Unsupported size %d ", len); |
eba0226bd KVM: Move IO APIC... |
341 |
return 0; |
1fd4f2a5e KVM: In-kernel I/... |
342 343 344 |
} addr &= 0xff; |
46a47b1ed KVM: convert ioap... |
345 |
spin_lock(&ioapic->lock); |
1fd4f2a5e KVM: In-kernel I/... |
346 347 |
switch (addr) { case IOAPIC_REG_SELECT: |
d77fe6354 KVM: Allow aligne... |
348 |
ioapic->ioregsel = data & 0xFF; /* 8-bit register */ |
1fd4f2a5e KVM: In-kernel I/... |
349 350 351 352 353 |
break; case IOAPIC_REG_WINDOW: ioapic_write_indirect(ioapic, data); break; |
b1fd3d30b KVM: Extend ioapi... |
354 355 |
#ifdef CONFIG_IA64 case IOAPIC_REG_EOI: |
eba0226bd KVM: Move IO APIC... |
356 |
__kvm_ioapic_update_eoi(ioapic, data, IOAPIC_LEVEL_TRIG); |
b1fd3d30b KVM: Extend ioapi... |
357 358 |
break; #endif |
1fd4f2a5e KVM: In-kernel I/... |
359 360 361 362 |
default: break; } |
46a47b1ed KVM: convert ioap... |
363 |
spin_unlock(&ioapic->lock); |
bda9020e2 KVM: remove in_ra... |
364 |
return 0; |
1fd4f2a5e KVM: In-kernel I/... |
365 |
} |
8c392696e KVM: Split IOAPIC... |
366 367 368 369 370 371 372 373 374 375 |
void kvm_ioapic_reset(struct kvm_ioapic *ioapic) { int i; for (i = 0; i < IOAPIC_NUM_PINS; i++) ioapic->redirtbl[i].fields.mask = 1; ioapic->base_address = IOAPIC_DEFAULT_BASE_ADDRESS; ioapic->ioregsel = 0; ioapic->irr = 0; ioapic->id = 0; |
46a929bc1 KVM: avoid taking... |
376 |
update_handled_vectors(ioapic); |
8c392696e KVM: Split IOAPIC... |
377 |
} |
d76685c4a KVM: cleanup io_d... |
378 379 380 |
static const struct kvm_io_device_ops ioapic_mmio_ops = { .read = ioapic_mmio_read, .write = ioapic_mmio_write, |
d76685c4a KVM: cleanup io_d... |
381 |
}; |
1fd4f2a5e KVM: In-kernel I/... |
382 383 384 |
int kvm_ioapic_init(struct kvm *kvm) { struct kvm_ioapic *ioapic; |
090b7aff2 KVM: make io_bus ... |
385 |
int ret; |
1fd4f2a5e KVM: In-kernel I/... |
386 387 388 389 |
ioapic = kzalloc(sizeof(struct kvm_ioapic), GFP_KERNEL); if (!ioapic) return -ENOMEM; |
46a47b1ed KVM: convert ioap... |
390 |
spin_lock_init(&ioapic->lock); |
d7deeeb02 KVM: Portability:... |
391 |
kvm->arch.vioapic = ioapic; |
8c392696e KVM: Split IOAPIC... |
392 |
kvm_ioapic_reset(ioapic); |
d76685c4a KVM: cleanup io_d... |
393 |
kvm_iodevice_init(&ioapic->dev, &ioapic_mmio_ops); |
1fd4f2a5e KVM: In-kernel I/... |
394 |
ioapic->kvm = kvm; |
79fac95ec KVM: convert slot... |
395 |
mutex_lock(&kvm->slots_lock); |
743eeb0b0 KVM: Intelligent ... |
396 397 |
ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, ioapic->base_address, IOAPIC_MEM_LENGTH, &ioapic->dev); |
79fac95ec KVM: convert slot... |
398 |
mutex_unlock(&kvm->slots_lock); |
1ae77badc KVM: kvm->arch.vi... |
399 400 |
if (ret < 0) { kvm->arch.vioapic = NULL; |
090b7aff2 KVM: make io_bus ... |
401 |
kfree(ioapic); |
1ae77badc KVM: kvm->arch.vi... |
402 |
} |
090b7aff2 KVM: make io_bus ... |
403 404 |
return ret; |
1fd4f2a5e KVM: In-kernel I/... |
405 |
} |
75858a84a KVM: Interrupt ma... |
406 |
|
72bb2fcd2 KVM: cleanup the ... |
407 408 409 410 411 412 413 414 415 416 |
void kvm_ioapic_destroy(struct kvm *kvm) { struct kvm_ioapic *ioapic = kvm->arch.vioapic; if (ioapic) { kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, &ioapic->dev); kvm->arch.vioapic = NULL; kfree(ioapic); } } |
eba0226bd KVM: Move IO APIC... |
417 418 419 420 421 |
int kvm_get_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state) { struct kvm_ioapic *ioapic = ioapic_irqchip(kvm); if (!ioapic) return -EINVAL; |
46a47b1ed KVM: convert ioap... |
422 |
spin_lock(&ioapic->lock); |
eba0226bd KVM: Move IO APIC... |
423 |
memcpy(state, ioapic, sizeof(struct kvm_ioapic_state)); |
46a47b1ed KVM: convert ioap... |
424 |
spin_unlock(&ioapic->lock); |
eba0226bd KVM: Move IO APIC... |
425 426 427 428 429 430 431 432 |
return 0; } int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state) { struct kvm_ioapic *ioapic = ioapic_irqchip(kvm); if (!ioapic) return -EINVAL; |
46a47b1ed KVM: convert ioap... |
433 |
spin_lock(&ioapic->lock); |
eba0226bd KVM: Move IO APIC... |
434 |
memcpy(ioapic, state, sizeof(struct kvm_ioapic_state)); |
46a929bc1 KVM: avoid taking... |
435 |
update_handled_vectors(ioapic); |
46a47b1ed KVM: convert ioap... |
436 |
spin_unlock(&ioapic->lock); |
eba0226bd KVM: Move IO APIC... |
437 438 |
return 0; } |