zephyr/include/drivers/sysapic.h
Gustavo Lima Chaves 9bb07ff69a jailhouse: add support for x2APIC mode for all LOAPIC accesses
Besides the fact that we did not have that for the current supported
boards, that makes sense for this new, virtualized mode, that is meant
to be run on top of full-fledged x86 64 CPUs.

By having xAPIC mode access only, Jailhouse has to intercept those MMIO
reads and writes, in order to examine what they do and arbitrate if it's
safe or not (e.g. not all values are accepted to ICR register). This
means that we can't run away from having a VM-exit event for each and
every access to APIC memory region and this impacts the latency the
guest OS observes over bare metal a lot.

When in x2APIC mode, Jailhouse does not require VM-exits for MSR
accesses other that writes to the ICR register, so the latency the guest
observes is reduced to almost zero.

Here are some outputs of the the command line

  $ sudo ./tools/jailhouse cell stats tiny-demo

on a Jailhouse's root cell console, for one of the Zephyr demos using
LOAPIC timers, left for a couple of seconds:

Statistics for tiny-demo cell (x2APIC root, x2APIC inmate)

COUNTER                              SUM   PER SEC
vmexits_total                          7         0
vmexits_management                     3         0
vmexits_cr                             2         0
vmexits_cpuid                          1         0
vmexits_msr                            1         0
vmexits_exception                      0         0
vmexits_hypercall                      0         0
vmexits_mmio                           0         0
vmexits_pio                            0         0
vmexits_xapic                          0         0
vmexits_xsetbv                         0         0

Statistics for tiny-demo cell (xAPIC root, xAPIC inmate)

COUNTER                              SUM   PER SEC
vmexits_total                       4087        40
vmexits_xapic                       4080        40
vmexits_management                     3         0
vmexits_cr                             2         0
vmexits_cpuid                          1         0
vmexits_msr                            1         0
vmexits_exception                      0         0
vmexits_hypercall                      0         0
vmexits_mmio                           0         0
vmexits_pio                            0         0
vmexits_xsetbv                         0         0

Statistics for tiny-demo cell (xAPIC root, x2APIC inmate)

COUNTER                              SUM   PER SEC
vmexits_total                       4087        40
vmexits_msr                         4080        40
vmexits_management                     3         0
vmexits_cr                             2         0
vmexits_cpuid                          1         0
vmexits_exception                      0         0
vmexits_hypercall                      0         0
vmexits_mmio                           0         0
vmexits_pio                            0         0
vmexits_xapic                          0         0
vmexits_xsetbv                         0         0

See that under x2APIC mode on both Jailhouse/root-cell and guest, the
interruptions from the hypervisor are minimal. That is not the case when
Jailhouse is on xAPIC mode, though. Note also that, as a plus, x2APIC
accesses on the guest will map to xAPIC MMIO on the hypervisor just
fine.

Signed-off-by: Gustavo Lima Chaves <gustavo.lima.chaves@intel.com>
2017-11-07 08:58:49 -05:00

64 lines
1.4 KiB
C

/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __INC_SYS_APIC_H
#define __INC_SYS_APIC_H
#include <drivers/loapic.h>
#define _IRQ_TRIGGER_EDGE IOAPIC_EDGE
#define _IRQ_TRIGGER_LEVEL IOAPIC_LEVEL
#define _IRQ_POLARITY_HIGH IOAPIC_HIGH
#define _IRQ_POLARITY_LOW IOAPIC_LOW
#ifndef _ASMLANGUAGE
#include <zephyr/types.h>
#define LOAPIC_IRQ_BASE CONFIG_IOAPIC_NUM_RTES
#define LOAPIC_IRQ_COUNT 6 /* Default to LOAPIC_TIMER to LOAPIC_ERROR */
/* irq_controller.h interface */
void __irq_controller_irq_config(unsigned int vector, unsigned int irq,
u32_t flags);
int __irq_controller_isr_vector_get(void);
#ifdef CONFIG_JAILHOUSE_X2APIC
void _jailhouse_eoi(void);
#endif
static inline void __irq_controller_eoi(void)
{
#if CONFIG_EOI_FORWARDING_BUG
_lakemont_eoi();
#else
*(volatile int *)(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_EOI) = 0;
#endif
}
#else /* _ASMLANGUAGE */
#if CONFIG_EOI_FORWARDING_BUG
.macro __irq_controller_eoi_macro
call _lakemont_eoi
.endm
#else
.macro __irq_controller_eoi_macro
#ifdef CONFIG_JAILHOUSE_X2APIC
call _jailhouse_eoi
#else
xorl %eax, %eax /* zeroes eax */
loapic_eoi_reg = (CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_EOI)
movl %eax, loapic_eoi_reg /* tell LOAPIC the IRQ is handled */
#endif
.endm
#endif /* CONFIG_EOI_FORWARDING_BUG */
#endif /* _ASMLANGUAGE */
#endif /* __INC_SYS_APIC_H */