x86: Choose a hypercall instruction in run-time

VMX and SVM use different instructions to make a hypercall (vmcall and
vmmcall, respectively). Jailhouse abstracts hypercall instructions with
inlined functions in jailhouse_hypercall.h, and these need to be able to
differentiate between VMX and SVM. For this reason, jailhouse_use_vmcall
global variable was introduced that is stored and filled by the driver.
Inmates will require similar initialization. This is left out as inmates
do not make use of hypercalls at this point.

As jailhouse_call_*() functions are never called on a CPU without VM
extensions (the driver checks if Jailhouse is enabled before issuing a
hypercall, and inmates do not run outside cells), it is safe to assume
that the CPU without VMX support is an SVM one.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
[Jan: dropped inmate initialization,
      switched to bool for jailhouse_use_vmcall,
      refactored init_use_vmcall_flag to init_hypercall]
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Enable Extended Interrupt LVT

Extended Interrupt LVTs are vendor-specific APIC registers (0x50-0x53),
defined by AMD (see APMv2, Sect. 16.3.2). Jailhouse lists this MMIO
range as reserved, as it is not used on Intel systems. On AMD systems,
Extended Interrupt LVT is no more "privileged" than other LVT registers,
so we enable them in corresponding vcpu_init() much the same way it is
currently done for xAPIC mode. Note this also required to make
apic_reserved_bits[] non-static.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Add AMD-V definitions and data structures

AMD-V data structures (VMCB, exit codes, flags etc) were adapted
from the Xvisor code. See http://xhypervisor.org for details.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Setup VMCB for Linux CPUs

Configure VMCB so that Linux can continue run safely on the Jailhouse-managed
CPU. This is done mostly the same way as for VMX (except CPUID is not intercepted
and only CR0 writes that change paging state are trapped). AMD-V guests can also
use ASID to tag TLB entries; as Jailhouse cells run on the same CPUs during all
their lifespan, it is assigned a static value (1).

AVIC is not present in any known AMD chip, so it is not configured yet.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
[Jan: adjust overlapping entries in msrpm, add comment about x2APIC]
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Add AMD-V initialization routines

Implemented functions responsible for checking AMD-V features present and
enabling/disabling SVM mode. Nested Page Tables (NPT) support is required,
and Decode Assists can optionally be used if available. For AVIC, only a
backing page is allocated.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Add AMD-V memory management functions

Implemented functions to map and unmap memory regions in NPT, get guest page
tables (including "fake" identity mappings if the guest runs in real mode), and
also to translate guest physical to host physical address. For TLB flush, only
mappings for the guest and not Jailhouse itself are cleaned, if possible.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Add AMD-V cell initialization/exit code

AMD-V vendor-specific parts of vcpu_cell_init() and vcpu_cell_exit() are
implemented.

On startup, if AVIC is not available (which is usually the case) APIC is
mapped to cells read-only so only register writes are trapped and emulated.

On cell exits, the mapping is destroyed.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Add vcpu_handle_exit() function for AMD-V

Add the infrastructure required to handle VM exits. It is mostly boilerplate
code in its current state, and any VM exit will cause a CPU to dump registers
and halt.

Appropriate handlers are added in subsequent commits.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Add vcpu_skip_emulated_instruction() for AMD-V

Many VM exit handlers need a way to skip the instruction they emulated.
Add vcpu_skip_emulated_instruction() that does this for AMD-V guests.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Implement vcpu_get_guest_bytes() for AMD-V

mmio_parse() can use accelerated guest memory access function, if the one
is provided in vendor-specific code. If Decode Assists are available on a
given CPU, we can avoid a costly page table walk and read guest instruction
directly from VMCB. However, since Decode Assists are optional as they may
not be advertised in nested SVM setup, a fallback route is provided as well.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Add AMD-V hypercall handler

Provide a way for guests to call into Jailhouse on AMD-V systems. Real work
is delegated to generic vcpu_handle_hypercall() handler.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Trap MSR access for AMD-V cells

Jailhouse traps read and write MSR access for two main purposes:

 * Emulating x2APIC on xAPIC-only hardware (all real-world AMD CPUs)
 * Preventing cells from clearing EFER.SVME bit

In the latter case, TLB also needs to be flushed.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Trap xAPIC register writes under AMD-V

Jailhouse maps APIC MMIO page to cells read-only, so it only needs to handle
register writes, which are translated to Nested Page Faults. The real work is
delegated to generic apic_mmio_access(), which requires guest page tables to
work. These are obtained with vcpu_get_guest_paging_structs(), which supports
real mode cells as well.

As there is no AVIC support for any known AMD hardware, AVIC-related VM exits
are nor intercepted neither handled in Jailhouse.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Add generic NPF handler for AMD-V code

This completes Nested Page Fault handler introduced in the previous commit
with generic NPF handling route. The actual handling code is shared between
VMX and SVM, so we simply need to call vcpu_handle_pt_violation() and
implement the appropriate data wrapper.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Add AMD-V port-based I/O VM exit handler

This is just the same as NPF handler: all real work is done in
vcpu_handle_io_access().

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Implement AMD-V NMI handler and CPU reset

NMIs originate from the hypervisor which uses them to manage cells. As a part
of this management task, the CPU can be reset. This is performed in vcpu_reset().

Jailhouse runs with GIF set, and it needs to be cleared shortly to let the CPU
to consume pending interrupt and allow further NMIs trigger VM exits. Otherwise,
current NMI would be delivered to the guest on the next VM entry.

NMI can trigger in host mode only if Jailhouse explicitly clears the GIF to
consume the pending interrupt. There is nothing to handle in this case, so
vcpu_nmi_handler() simply prints a message that the NMI was consumed.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Add AMD-V handler for guests CR0 access

Guest CR0 writes are intercepted if they change bits other than CR0.TS
or CR0.MP. The main purpose for this is to activate Long mode for
Jailhouse cells. As Decode Assists are optional in Jailhouse, if they
are not present the instruction is decoded manually. All current Jailhouse
inmates are first changing CR0 while they are in real mode, so having
real mode support in vcpu_get_guest_paging_structs() is essential.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Intercept guest XSETBV instruction in AMD-V

This adds XSETBV instruction emulation. The code is almost the same as in
VMX, and is barely tested as the instruction is rarely used in real-world
scenarios.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Implement vcpu_[de]activate_vmm() for AMD-V

Compared to VMX, vcpu_activate_vmm() and vcpu_deativate_vmm() for AMD-V
systems have several notable differences.

First, additional MSRs (part of VMCB but not VMCS) need to be set and
restored. Then, host state area is opaque in AMD-V, so vcpu_activate_vmm()
remembers host stack pointer and essentially begins a VMRUN/#VMEXIT loop
implemented in svm-vmexit.S. Third, as RAX register is part of VMCB, it is
copied to guest_regs on each VM exit and written back before VM entry.

As Jailhouse runs with GIF set, it needs to be cleared on VMM deactivation.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
x86: Implement vcpu_park() for AMD-V CPUs

When a CPU is parked, it is halted in guest mode with interrupts off. This way,
only NMI sent from the hypervisor can "unpark" the CPU to run another cell.

AMD-V provides no VMX guest activity states equivalent, thus there is no easy way
to halt a CPU in guest mode waiting for NMI. To overcome this, when a CPU is parked,
its memory is temporarily switched to shared "parked mode NPT" which contains
"parking code" (cli; hlt) mapped at the Jailhouse custom reset vector (0xffff0).
The guest is directed to continue at this address. When NMI occurs, vcpu_reset()
restores original NPTs.

Signed-off-by: Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>