Skip to content

Commit

Permalink
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Browse files Browse the repository at this point in the history
Pull KVM updates from Paolo Bonzini:
 "ARM:
   - HYP mode stub supports kexec/kdump on 32-bit
   - improved PMU support
   - virtual interrupt controller performance improvements
   - support for userspace virtual interrupt controller (slower, but
     necessary for KVM on the weird Broadcom SoCs used by the Raspberry
     Pi 3)

  MIPS:
   - basic support for hardware virtualization (ImgTec P5600/P6600/I6400
     and Cavium Octeon III)

  PPC:
   - in-kernel acceleration for VFIO

  s390:
   - support for guests without storage keys
   - adapter interruption suppression

  x86:
   - usual range of nVMX improvements, notably nested EPT support for
     accessed and dirty bits
   - emulation of CPL3 CPUID faulting

  generic:
   - first part of VCPU thread request API
   - kvm_stat improvements"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (227 commits)
  kvm: nVMX: Don't validate disabled secondary controls
  KVM: put back #ifndef CONFIG_S390 around kvm_vcpu_kick
  Revert "KVM: Support vCPU-based gfn->hva cache"
  tools/kvm: fix top level makefile
  KVM: x86: don't hold kvm->lock in KVM_SET_GSI_ROUTING
  KVM: Documentation: remove VM mmap documentation
  kvm: nVMX: Remove superfluous VMX instruction fault checks
  KVM: x86: fix emulation of RSM and IRET instructions
  KVM: mark requests that need synchronization
  KVM: return if kvm_vcpu_wake_up() did wake up the VCPU
  KVM: add explicit barrier to kvm_vcpu_kick
  KVM: perform a wake_up in kvm_make_all_cpus_request
  KVM: mark requests that do not need a wakeup
  KVM: remove #ifndef CONFIG_S390 around kvm_vcpu_wake_up
  KVM: x86: always use kvm_make_request instead of set_bit
  KVM: add kvm_{test,clear}_request to replace {test,clear}_bit
  s390: kvm: Cpu model support for msa6, msa7 and msa8
  KVM: x86: remove irq disablement around KVM_SET_CLOCK/KVM_GET_CLOCK
  kvm: better MWAIT emulation for guests
  KVM: x86: virtualize cpuid faulting
  ...
  • Loading branch information
torvalds committed May 8, 2017
2 parents 9c6ee01 + 2e5b0bd commit 2d3e486
Show file tree
Hide file tree
Showing 150 changed files with 9,189 additions and 3,843 deletions.
367 changes: 157 additions & 210 deletions Documentation/virtual/kvm/api.txt

Large diffs are not rendered by default.

53 changes: 53 additions & 0 deletions Documentation/virtual/kvm/arm/hyp-abi.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
* Internal ABI between the kernel and HYP

This file documents the interaction between the Linux kernel and the
hypervisor layer when running Linux as a hypervisor (for example
KVM). It doesn't cover the interaction of the kernel with the
hypervisor when running as a guest (under Xen, KVM or any other
hypervisor), or any hypervisor-specific interaction when the kernel is
used as a host.

On arm and arm64 (without VHE), the kernel doesn't run in hypervisor
mode, but still needs to interact with it, allowing a built-in
hypervisor to be either installed or torn down.

In order to achieve this, the kernel must be booted at HYP (arm) or
EL2 (arm64), allowing it to install a set of stubs before dropping to
SVC/EL1. These stubs are accessible by using a 'hvc #0' instruction,
and only act on individual CPUs.

Unless specified otherwise, any built-in hypervisor must implement
these functions (see arch/arm{,64}/include/asm/virt.h):

* r0/x0 = HVC_SET_VECTORS
r1/x1 = vectors

Set HVBAR/VBAR_EL2 to 'vectors' to enable a hypervisor. 'vectors'
must be a physical address, and respect the alignment requirements
of the architecture. Only implemented by the initial stubs, not by
Linux hypervisors.

* r0/x0 = HVC_RESET_VECTORS

Turn HYP/EL2 MMU off, and reset HVBAR/VBAR_EL2 to the initials
stubs' exception vector value. This effectively disables an existing
hypervisor.

* r0/x0 = HVC_SOFT_RESTART
r1/x1 = restart address
x2 = x0's value when entering the next payload (arm64)
x3 = x1's value when entering the next payload (arm64)
x4 = x2's value when entering the next payload (arm64)

Mask all exceptions, disable the MMU, move the arguments into place
(arm64 only), and jump to the restart address while at HYP/EL2. This
hypercall is not expected to return to its caller.

Any other value of r0/x0 triggers a hypervisor-specific handling,
which is not documented here.

The return value of a stub hypercall is held by r0/x0, and is 0 on
success, and HVC_STUB_ERR on error. A stub hypercall is allowed to
clobber any of the caller-saved registers (x0-x18 on arm64, r0-r3 and
ip on arm). It is thus recommended to use a function call to perform
the hypercall.
41 changes: 38 additions & 3 deletions Documentation/virtual/kvm/devices/s390_flic.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ FLIC provides support to
- purge one pending floating I/O interrupt (KVM_DEV_FLIC_CLEAR_IO_IRQ)
- enable/disable for the guest transparent async page faults
- register and modify adapter interrupt sources (KVM_DEV_FLIC_ADAPTER_*)
- modify AIS (adapter-interruption-suppression) mode state (KVM_DEV_FLIC_AISM)
- inject adapter interrupts on a specified adapter (KVM_DEV_FLIC_AIRQ_INJECT)

Groups:
KVM_DEV_FLIC_ENQUEUE
Expand Down Expand Up @@ -64,12 +66,18 @@ struct kvm_s390_io_adapter {
__u8 isc;
__u8 maskable;
__u8 swap;
__u8 pad;
__u8 flags;
};

id contains the unique id for the adapter, isc the I/O interruption subclass
to use, maskable whether this adapter may be masked (interrupts turned off)
and swap whether the indicators need to be byte swapped.
to use, maskable whether this adapter may be masked (interrupts turned off),
swap whether the indicators need to be byte swapped, and flags contains
further characteristics of the adapter.
Currently defined values for 'flags' are:
- KVM_S390_ADAPTER_SUPPRESSIBLE: adapter is subject to AIS
(adapter-interrupt-suppression) facility. This flag only has an effect if
the AIS capability is enabled.
Unknown flag values are ignored.


KVM_DEV_FLIC_ADAPTER_MODIFY
Expand Down Expand Up @@ -101,6 +109,33 @@ struct kvm_s390_io_adapter_req {
release a userspace page for the translated address specified in addr
from the list of mappings

KVM_DEV_FLIC_AISM
modify the adapter-interruption-suppression mode for a given isc if the
AIS capability is enabled. Takes a kvm_s390_ais_req describing:

struct kvm_s390_ais_req {
__u8 isc;
__u16 mode;
};

isc contains the target I/O interruption subclass, mode the target
adapter-interruption-suppression mode. The following modes are
currently supported:
- KVM_S390_AIS_MODE_ALL: ALL-Interruptions Mode, i.e. airq injection
is always allowed;
- KVM_S390_AIS_MODE_SINGLE: SINGLE-Interruption Mode, i.e. airq
injection is only allowed once and the following adapter interrupts
will be suppressed until the mode is set again to ALL-Interruptions
or SINGLE-Interruption mode.

KVM_DEV_FLIC_AIRQ_INJECT
Inject adapter interrupts on a specified adapter.
attr->attr contains the unique id for the adapter, which allows for
adapter-specific checks and actions.
For adapters subject to AIS, handle the airq injection suppression for
an isc according to the adapter-interruption-suppression mode on condition
that the AIS capability is enabled.

Note: The KVM_SET_DEVICE_ATTR/KVM_GET_DEVICE_ATTR device ioctls executed on
FLIC with an unknown group or attribute gives the error code EINVAL (instead of
ENXIO, as specified in the API documentation). It is not possible to conclude
Expand Down
18 changes: 16 additions & 2 deletions Documentation/virtual/kvm/devices/vfio.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,21 @@ Groups:

KVM_DEV_VFIO_GROUP attributes:
KVM_DEV_VFIO_GROUP_ADD: Add a VFIO group to VFIO-KVM device tracking
kvm_device_attr.addr points to an int32_t file descriptor
for the VFIO group.
KVM_DEV_VFIO_GROUP_DEL: Remove a VFIO group from VFIO-KVM device tracking
kvm_device_attr.addr points to an int32_t file descriptor
for the VFIO group.
KVM_DEV_VFIO_GROUP_SET_SPAPR_TCE: attaches a guest visible TCE table
allocated by sPAPR KVM.
kvm_device_attr.addr points to a struct:

For each, kvm_device_attr.addr points to an int32_t file descriptor
for the VFIO group.
struct kvm_vfio_spapr_tce {
__s32 groupfd;
__s32 tablefd;
};

where
@groupfd is a file descriptor for a VFIO group;
@tablefd is a file descriptor for a TCE table allocated via
KVM_CREATE_SPAPR_TCE.
3 changes: 2 additions & 1 deletion Documentation/virtual/kvm/devices/vm.txt
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ struct kvm_s390_vm_cpu_subfunc {
u8 kmo[16]; # valid with Message-Security-Assist-Extension 4
u8 pcc[16]; # valid with Message-Security-Assist-Extension 4
u8 ppno[16]; # valid with Message-Security-Assist-Extension 5
u8 reserved[1824]; # reserved for future instructions
u8 kma[16]; # valid with Message-Security-Assist-Extension 8
u8 reserved[1808]; # reserved for future instructions
};

Parameters: address of a buffer to load the subfunction blocks from.
Expand Down
5 changes: 5 additions & 0 deletions Documentation/virtual/kvm/hypercalls.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ S390:
property inside the device tree's /hypervisor node.
For more information refer to Documentation/virtual/kvm/ppc-pv.txt

MIPS:
KVM hypercalls use the HYPCALL instruction with code 0 and the hypercall
number in $2 (v0). Up to four arguments may be placed in $4-$7 (a0-a3) and
the return value is placed in $2 (v0).

KVM Hypercalls Documentation
===========================
The template for each hypercall is:
Expand Down
12 changes: 11 additions & 1 deletion arch/arm/boot/compressed/head.S
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,17 @@ dtb_check_done:
cmp r0, #HYP_MODE
bne 1f

bl __hyp_get_vectors
/*
* Compute the address of the hyp vectors after relocation.
* This requires some arithmetic since we cannot directly
* reference __hyp_stub_vectors in a PC-relative way.
* Call __hyp_set_vectors with the new address so that we
* can HVC again after the copy.
*/
0: adr r0, 0b
movw r1, #:lower16:__hyp_stub_vectors - 0b
movt r1, #:upper16:__hyp_stub_vectors - 0b
add r0, r0, r1
sub r0, r0, r5
add r0, r0, r10
bl __hyp_set_vectors
Expand Down
7 changes: 4 additions & 3 deletions arch/arm/include/asm/kvm_asm.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#define ARM_EXCEPTION_IRQ 5
#define ARM_EXCEPTION_FIQ 6
#define ARM_EXCEPTION_HVC 7

#define ARM_EXCEPTION_HYP_GONE HVC_STUB_ERR
/*
* The rr_lo_hi macro swaps a pair of registers depending on
* current endianness. It is used in conjunction with ldrd and strd
Expand Down Expand Up @@ -72,10 +72,11 @@ extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);

extern void __init_stage2_translation(void);

extern void __kvm_hyp_reset(unsigned long);

extern u64 __vgic_v3_get_ich_vtr_el2(void);
extern u64 __vgic_v3_read_vmcr(void);
extern void __vgic_v3_write_vmcr(u32 vmcr);
extern void __vgic_v3_init_lrs(void);

#endif

#endif /* __ARM_KVM_ASM_H__ */
9 changes: 1 addition & 8 deletions arch/arm/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
#define __KVM_HAVE_ARCH_INTC_INITIALIZED

#define KVM_USER_MEM_SLOTS 32
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
#define KVM_HAVE_ONE_REG
#define KVM_HALT_POLL_NS_DEFAULT 500000

Expand All @@ -45,7 +44,7 @@
#define KVM_MAX_VCPUS VGIC_V2_MAX_CPUS
#endif

#define KVM_REQ_VCPU_EXIT 8
#define KVM_REQ_VCPU_EXIT (8 | KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)

u32 *kvm_vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num, u32 mode);
int __attribute_const__ kvm_target_cpu(void);
Expand Down Expand Up @@ -270,12 +269,6 @@ static inline void __cpu_init_stage2(void)
kvm_call_hyp(__init_stage2_translation);
}

static inline void __cpu_reset_hyp_mode(unsigned long vector_ptr,
phys_addr_t phys_idmap_start)
{
kvm_call_hyp((void *)virt_to_idmap(__kvm_hyp_reset), vector_ptr);
}

static inline int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext)
{
return 0;
Expand Down
1 change: 0 additions & 1 deletion arch/arm/include/asm/kvm_mmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu);

phys_addr_t kvm_mmu_get_httbr(void);
phys_addr_t kvm_get_idmap_vector(void);
phys_addr_t kvm_get_idmap_start(void);
int kvm_mmu_init(void);
void kvm_clear_hyp_idmap(void);

Expand Down
4 changes: 2 additions & 2 deletions arch/arm/include/asm/proc-fns.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ extern struct processor {
/*
* Special stuff for a reset
*/
void (*reset)(unsigned long addr) __attribute__((noreturn));
void (*reset)(unsigned long addr, bool hvc) __attribute__((noreturn));
/*
* Idle the processor
*/
Expand Down Expand Up @@ -88,7 +88,7 @@ extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte);
#else
extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);
#endif
extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
extern void cpu_reset(unsigned long addr, bool hvc) __attribute__((noreturn));

/* These three are private to arch/arm/kernel/suspend.c */
extern void cpu_do_suspend(void *);
Expand Down
14 changes: 13 additions & 1 deletion arch/arm/include/asm/virt.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ static inline void sync_boot_mode(void)
}

void __hyp_set_vectors(unsigned long phys_vector_base);
unsigned long __hyp_get_vectors(void);
void __hyp_reset_vectors(void);
#else
#define __boot_cpu_mode (SVC_MODE)
#define sync_boot_mode()
Expand Down Expand Up @@ -94,6 +94,18 @@ extern char __hyp_text_start[];
extern char __hyp_text_end[];
#endif

#else

/* Only assembly code should need those */

#define HVC_SET_VECTORS 0
#define HVC_SOFT_RESTART 1
#define HVC_RESET_VECTORS 2

#define HVC_STUB_HCALL_NR 3

#endif /* __ASSEMBLY__ */

#define HVC_STUB_ERR 0xbadca11

#endif /* ! VIRT_H */
4 changes: 4 additions & 0 deletions arch/arm/include/uapi/asm/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#define __KVM_HAVE_IRQ_LINE
#define __KVM_HAVE_READONLY_MEM

#define KVM_COALESCED_MMIO_PAGE_OFFSET 1

#define KVM_REG_SIZE(id) \
(1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))

Expand Down Expand Up @@ -114,6 +116,8 @@ struct kvm_debug_exit_arch {
};

struct kvm_sync_regs {
/* Used with KVM_CAP_ARM_USER_IRQ */
__u64 device_irq_level;
};

struct kvm_arch_memory_slot {
Expand Down
43 changes: 34 additions & 9 deletions arch/arm/kernel/hyp-stub.S
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ ENTRY(__hyp_stub_install_secondary)
* (see safe_svcmode_maskall).
*/
@ Now install the hypervisor stub:
adr r7, __hyp_stub_vectors
W(adr) r7, __hyp_stub_vectors
mcr p15, 4, r7, c12, c0, 0 @ set hypervisor vector base (HVBAR)

@ Disable all traps, so we don't get any nasty surprise
Expand Down Expand Up @@ -202,9 +202,23 @@ ARM_BE8(orr r7, r7, #(1 << 25)) @ HSCTLR.EE
ENDPROC(__hyp_stub_install_secondary)

__hyp_stub_do_trap:
cmp r0, #-1
mrceq p15, 4, r0, c12, c0, 0 @ get HVBAR
mcrne p15, 4, r0, c12, c0, 0 @ set HVBAR
teq r0, #HVC_SET_VECTORS
bne 1f
mcr p15, 4, r1, c12, c0, 0 @ set HVBAR
b __hyp_stub_exit

1: teq r0, #HVC_SOFT_RESTART
bne 1f
bx r1

1: teq r0, #HVC_RESET_VECTORS
beq __hyp_stub_exit

ldr r0, =HVC_STUB_ERR
__ERET

__hyp_stub_exit:
mov r0, #0
__ERET
ENDPROC(__hyp_stub_do_trap)

Expand All @@ -230,23 +244,34 @@ ENDPROC(__hyp_stub_do_trap)
* so you will need to set that to something sensible at the new hypervisor's
* initialisation entry point.
*/
ENTRY(__hyp_get_vectors)
mov r0, #-1
ENDPROC(__hyp_get_vectors)
@ fall through
ENTRY(__hyp_set_vectors)
mov r1, r0
mov r0, #HVC_SET_VECTORS
__HVC(0)
ret lr
ENDPROC(__hyp_set_vectors)

ENTRY(__hyp_soft_restart)
mov r1, r0
mov r0, #HVC_SOFT_RESTART
__HVC(0)
ret lr
ENDPROC(__hyp_soft_restart)

ENTRY(__hyp_reset_vectors)
mov r0, #HVC_RESET_VECTORS
__HVC(0)
ret lr
ENDPROC(__hyp_reset_vectors)

#ifndef ZIMAGE
.align 2
.L__boot_cpu_mode_offset:
.long __boot_cpu_mode - .
#endif

.align 5
__hyp_stub_vectors:
ENTRY(__hyp_stub_vectors)
__hyp_stub_reset: W(b) .
__hyp_stub_und: W(b) .
__hyp_stub_svc: W(b) .
Expand Down
Loading

0 comments on commit 2d3e486

Please sign in to comment.