Deleted Added
full compact
vioapic.c (262350) vioapic.c (266339)
1/*-
2 * Copyright (c) 2013 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
3 * Copyright (c) 2013 Neel Natu <neel@freebsd.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 10 unchanged lines hidden (view full) ---

19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
1/*-
2 * Copyright (c) 2013 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
3 * Copyright (c) 2013 Neel Natu <neel@freebsd.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 10 unchanged lines hidden (view full) ---

19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD: stable/10/sys/amd64/vmm/io/vioapic.c 262350 2014-02-23 00:46:05Z jhb $
27 * $FreeBSD: stable/10/sys/amd64/vmm/io/vioapic.c 266339 2014-05-17 19:11:08Z jhb $
28 */
29
30#include <sys/cdefs.h>
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: stable/10/sys/amd64/vmm/io/vioapic.c 262350 2014-02-23 00:46:05Z jhb $");
31__FBSDID("$FreeBSD: stable/10/sys/amd64/vmm/io/vioapic.c 266339 2014-05-17 19:11:08Z jhb $");
32
33#include <sys/param.h>
34#include <sys/queue.h>
35#include <sys/cpuset.h>
36#include <sys/lock.h>
37#include <sys/mutex.h>
38#include <sys/systm.h>
39#include <sys/kernel.h>

--- 177 unchanged lines hidden (view full) ---

217
218int
219vioapic_pulse_irq(struct vm *vm, int irq)
220{
221
222 return (vioapic_set_irqstate(vm, irq, IRQSTATE_PULSE));
223}
224
32
33#include <sys/param.h>
34#include <sys/queue.h>
35#include <sys/cpuset.h>
36#include <sys/lock.h>
37#include <sys/mutex.h>
38#include <sys/systm.h>
39#include <sys/kernel.h>

--- 177 unchanged lines hidden (view full) ---

217
218int
219vioapic_pulse_irq(struct vm *vm, int irq)
220{
221
222 return (vioapic_set_irqstate(vm, irq, IRQSTATE_PULSE));
223}
224
225/*
226 * Reset the vlapic's trigger-mode register to reflect the ioapic pin
227 * configuration.
228 */
229static void
230vioapic_update_tmr(struct vm *vm, int vcpuid, void *arg)
231{
232 struct vioapic *vioapic;
233 struct vlapic *vlapic;
234 uint32_t low, high, dest;
235 int delmode, pin, vector;
236 bool level, phys;
237
238 vlapic = vm_lapic(vm, vcpuid);
239 vioapic = vm_ioapic(vm);
240
241 VIOAPIC_LOCK(vioapic);
242 /*
243 * Reset all vectors to be edge-triggered.
244 */
245 vlapic_reset_tmr(vlapic);
246 for (pin = 0; pin < REDIR_ENTRIES; pin++) {
247 low = vioapic->rtbl[pin].reg;
248 high = vioapic->rtbl[pin].reg >> 32;
249
250 level = low & IOART_TRGRLVL ? true : false;
251 if (!level)
252 continue;
253
254 /*
255 * For a level-triggered 'pin' let the vlapic figure out if
256 * an assertion on this 'pin' would result in an interrupt
257 * being delivered to it. If yes, then it will modify the
258 * TMR bit associated with this vector to level-triggered.
259 */
260 phys = ((low & IOART_DESTMOD) == IOART_DESTPHY);
261 delmode = low & IOART_DELMOD;
262 vector = low & IOART_INTVEC;
263 dest = high >> APIC_ID_SHIFT;
264 vlapic_set_tmr_level(vlapic, dest, phys, delmode, vector);
265 }
266 VIOAPIC_UNLOCK(vioapic);
267}
268
225static uint32_t
269static uint32_t
226vioapic_read(struct vioapic *vioapic, uint32_t addr)
270vioapic_read(struct vioapic *vioapic, int vcpuid, uint32_t addr)
227{
228 int regnum, pin, rshift;
229
230 regnum = addr & 0xff;
231 switch (regnum) {
232 case IOAPIC_ID:
233 return (vioapic->id);
234 break;

--- 18 unchanged lines hidden (view full) ---

253
254 return (vioapic->rtbl[pin].reg >> rshift);
255 }
256
257 return (0);
258}
259
260static void
271{
272 int regnum, pin, rshift;
273
274 regnum = addr & 0xff;
275 switch (regnum) {
276 case IOAPIC_ID:
277 return (vioapic->id);
278 break;

--- 18 unchanged lines hidden (view full) ---

297
298 return (vioapic->rtbl[pin].reg >> rshift);
299 }
300
301 return (0);
302}
303
304static void
261vioapic_write(struct vioapic *vioapic, uint32_t addr, uint32_t data)
305vioapic_write(struct vioapic *vioapic, int vcpuid, uint32_t addr, uint32_t data)
262{
263 uint64_t data64, mask64;
306{
307 uint64_t data64, mask64;
308 uint64_t last, changed;
264 int regnum, pin, lshift;
309 int regnum, pin, lshift;
310 cpuset_t allvcpus;
265
266 regnum = addr & 0xff;
267 switch (regnum) {
268 case IOAPIC_ID:
269 vioapic->id = data & APIC_ID_MASK;
270 break;
271 case IOAPIC_VER:
272 case IOAPIC_ARB:

--- 7 unchanged lines hidden (view full) ---

280 if (regnum >= IOAPIC_REDTBL &&
281 regnum < IOAPIC_REDTBL + REDIR_ENTRIES * 2) {
282 pin = (regnum - IOAPIC_REDTBL) / 2;
283 if ((regnum - IOAPIC_REDTBL) % 2)
284 lshift = 32;
285 else
286 lshift = 0;
287
311
312 regnum = addr & 0xff;
313 switch (regnum) {
314 case IOAPIC_ID:
315 vioapic->id = data & APIC_ID_MASK;
316 break;
317 case IOAPIC_VER:
318 case IOAPIC_ARB:

--- 7 unchanged lines hidden (view full) ---

326 if (regnum >= IOAPIC_REDTBL &&
327 regnum < IOAPIC_REDTBL + REDIR_ENTRIES * 2) {
328 pin = (regnum - IOAPIC_REDTBL) / 2;
329 if ((regnum - IOAPIC_REDTBL) % 2)
330 lshift = 32;
331 else
332 lshift = 0;
333
334 last = vioapic->rtbl[pin].reg;
335
288 data64 = (uint64_t)data << lshift;
289 mask64 = (uint64_t)0xffffffff << lshift;
290 vioapic->rtbl[pin].reg &= ~mask64 | RTBL_RO_BITS;
291 vioapic->rtbl[pin].reg |= data64 & ~RTBL_RO_BITS;
292
293 VIOAPIC_CTR2(vioapic, "ioapic pin%d: redir table entry %#lx",
294 pin, vioapic->rtbl[pin].reg);
295
296 /*
336 data64 = (uint64_t)data << lshift;
337 mask64 = (uint64_t)0xffffffff << lshift;
338 vioapic->rtbl[pin].reg &= ~mask64 | RTBL_RO_BITS;
339 vioapic->rtbl[pin].reg |= data64 & ~RTBL_RO_BITS;
340
341 VIOAPIC_CTR2(vioapic, "ioapic pin%d: redir table entry %#lx",
342 pin, vioapic->rtbl[pin].reg);
343
344 /*
345 * If any fields in the redirection table entry (except mask
346 * or polarity) have changed then rendezvous all the vcpus
347 * to update their vlapic trigger-mode registers.
348 */
349 changed = last ^ vioapic->rtbl[pin].reg;
350 if (changed & ~(IOART_INTMASK | IOART_INTPOL)) {
351 VIOAPIC_CTR1(vioapic, "ioapic pin%d: recalculate "
352 "vlapic trigger-mode register", pin);
353 VIOAPIC_UNLOCK(vioapic);
354 allvcpus = vm_active_cpus(vioapic->vm);
355 vm_smp_rendezvous(vioapic->vm, vcpuid, allvcpus,
356 vioapic_update_tmr, NULL);
357 VIOAPIC_LOCK(vioapic);
358 }
359
360 /*
297 * Generate an interrupt if the following conditions are met:
298 * - pin is not masked
299 * - previous interrupt has been EOIed
300 * - pin level is asserted
301 */
302 if ((vioapic->rtbl[pin].reg & IOART_INTMASK) == IOART_INTMCLR &&
303 (vioapic->rtbl[pin].reg & IOART_REM_IRR) == 0 &&
304 (vioapic->rtbl[pin].acnt > 0)) {
305 VIOAPIC_CTR2(vioapic, "ioapic pin%d: asserted at rtbl "
306 "write, acnt %d", pin, vioapic->rtbl[pin].acnt);
307 vioapic_send_intr(vioapic, pin);
308 }
309 }
310}
311
312static int
361 * Generate an interrupt if the following conditions are met:
362 * - pin is not masked
363 * - previous interrupt has been EOIed
364 * - pin level is asserted
365 */
366 if ((vioapic->rtbl[pin].reg & IOART_INTMASK) == IOART_INTMCLR &&
367 (vioapic->rtbl[pin].reg & IOART_REM_IRR) == 0 &&
368 (vioapic->rtbl[pin].acnt > 0)) {
369 VIOAPIC_CTR2(vioapic, "ioapic pin%d: asserted at rtbl "
370 "write, acnt %d", pin, vioapic->rtbl[pin].acnt);
371 vioapic_send_intr(vioapic, pin);
372 }
373 }
374}
375
376static int
313vioapic_mmio_rw(struct vioapic *vioapic, uint64_t gpa, uint64_t *data,
314 int size, bool doread)
377vioapic_mmio_rw(struct vioapic *vioapic, int vcpuid, uint64_t gpa,
378 uint64_t *data, int size, bool doread)
315{
316 uint64_t offset;
317
318 offset = gpa - VIOAPIC_BASE;
319
320 /*
321 * The IOAPIC specification allows 32-bit wide accesses to the
322 * IOREGSEL (offset 0) and IOWIN (offset 16) registers.

--- 6 unchanged lines hidden (view full) ---

329
330 VIOAPIC_LOCK(vioapic);
331 if (offset == IOREGSEL) {
332 if (doread)
333 *data = vioapic->ioregsel;
334 else
335 vioapic->ioregsel = *data;
336 } else {
379{
380 uint64_t offset;
381
382 offset = gpa - VIOAPIC_BASE;
383
384 /*
385 * The IOAPIC specification allows 32-bit wide accesses to the
386 * IOREGSEL (offset 0) and IOWIN (offset 16) registers.

--- 6 unchanged lines hidden (view full) ---

393
394 VIOAPIC_LOCK(vioapic);
395 if (offset == IOREGSEL) {
396 if (doread)
397 *data = vioapic->ioregsel;
398 else
399 vioapic->ioregsel = *data;
400 } else {
337 if (doread)
338 *data = vioapic_read(vioapic, vioapic->ioregsel);
339 else
340 vioapic_write(vioapic, vioapic->ioregsel, *data);
401 if (doread) {
402 *data = vioapic_read(vioapic, vcpuid,
403 vioapic->ioregsel);
404 } else {
405 vioapic_write(vioapic, vcpuid, vioapic->ioregsel,
406 *data);
407 }
341 }
342 VIOAPIC_UNLOCK(vioapic);
343
344 return (0);
345}
346
347int
348vioapic_mmio_read(void *vm, int vcpuid, uint64_t gpa, uint64_t *rval,
349 int size, void *arg)
350{
351 int error;
352 struct vioapic *vioapic;
353
354 vioapic = vm_ioapic(vm);
408 }
409 VIOAPIC_UNLOCK(vioapic);
410
411 return (0);
412}
413
414int
415vioapic_mmio_read(void *vm, int vcpuid, uint64_t gpa, uint64_t *rval,
416 int size, void *arg)
417{
418 int error;
419 struct vioapic *vioapic;
420
421 vioapic = vm_ioapic(vm);
355 error = vioapic_mmio_rw(vioapic, gpa, rval, size, true);
422 error = vioapic_mmio_rw(vioapic, vcpuid, gpa, rval, size, true);
356 return (error);
357}
358
359int
360vioapic_mmio_write(void *vm, int vcpuid, uint64_t gpa, uint64_t wval,
361 int size, void *arg)
362{
363 int error;
364 struct vioapic *vioapic;
365
366 vioapic = vm_ioapic(vm);
423 return (error);
424}
425
426int
427vioapic_mmio_write(void *vm, int vcpuid, uint64_t gpa, uint64_t wval,
428 int size, void *arg)
429{
430 int error;
431 struct vioapic *vioapic;
432
433 vioapic = vm_ioapic(vm);
367 error = vioapic_mmio_rw(vioapic, gpa, &wval, size, false);
434 error = vioapic_mmio_rw(vioapic, vcpuid, gpa, &wval, size, false);
368 return (error);
369}
370
371void
372vioapic_process_eoi(struct vm *vm, int vcpuid, int vector)
373{
374 struct vioapic *vioapic;
375 int pin;

--- 58 unchanged lines hidden ---
435 return (error);
436}
437
438void
439vioapic_process_eoi(struct vm *vm, int vcpuid, int vector)
440{
441 struct vioapic *vioapic;
442 int pin;

--- 58 unchanged lines hidden ---