Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c24a7be2 authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

Merge tag 'kvm-arm-for-v4.12' of...

Merge tag 'kvm-arm-for-v4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD

KVM/ARM Changes for v4.12.

Changes include:
 - Using the common sysreg definitions between KVM and arm64
 - Improved hyp-stub implementation with support for kexec and kdump on the 32-bit side
 - Proper PMU exception handling
 - Performance improvements of our GIC handling
 - Support for irqchip in userspace with in-kernel arch-timers and PMU support
 - A fix for a race condition in our PSCI code

Conflicts:
	Documentation/virtual/kvm/api.txt
	include/uapi/linux/kvm.h
parents 70f3aac9 1edb6321
Loading
Loading
Loading
Loading
+41 −0
Original line number Original line Diff line number Diff line
@@ -4120,3 +4120,44 @@ This capability indicates that guest using memory monotoring instructions
(MWAIT/MWAITX) to stop the virtual CPU will not cause a VM exit.  As such time
(MWAIT/MWAITX) to stop the virtual CPU will not cause a VM exit.  As such time
spent while virtual CPU is halted in this way will then be accounted for as
spent while virtual CPU is halted in this way will then be accounted for as
guest running time on the host (as opposed to e.g. HLT).
guest running time on the host (as opposed to e.g. HLT).

8.9 KVM_CAP_ARM_USER_IRQ

Architectures: arm, arm64
This capability, if KVM_CHECK_EXTENSION indicates that it is available, means
that if userspace creates a VM without an in-kernel interrupt controller, it
will be notified of changes to the output level of in-kernel emulated devices,
which can generate virtual interrupts, presented to the VM.
For such VMs, on every return to userspace, the kernel
updates the vcpu's run->s.regs.device_irq_level field to represent the actual
output level of the device.

Whenever kvm detects a change in the device output level, kvm guarantees at
least one return to userspace before running the VM.  This exit could either
be a KVM_EXIT_INTR or any other exit event, like KVM_EXIT_MMIO. This way,
userspace can always sample the device output level and re-compute the state of
the userspace interrupt controller.  Userspace should always check the state
of run->s.regs.device_irq_level on every kvm exit.
The value in run->s.regs.device_irq_level can represent both level and edge
triggered interrupt signals, depending on the device.  Edge triggered interrupt
signals will exit to userspace with the bit in run->s.regs.device_irq_level
set exactly once per edge signal.

The field run->s.regs.device_irq_level is available independent of
run->kvm_valid_regs or run->kvm_dirty_regs bits.

If KVM_CAP_ARM_USER_IRQ is supported, the KVM_CHECK_EXTENSION ioctl returns a
number larger than 0 indicating the version of this capability is implemented
and thereby which bits in in run->s.regs.device_irq_level can signal values.

Currently the following bits are defined for the device_irq_level bitmap:

  KVM_CAP_ARM_USER_IRQ >= 1:

    KVM_ARM_DEV_EL1_VTIMER -  EL1 virtual timer
    KVM_ARM_DEV_EL1_PTIMER -  EL1 physical timer
    KVM_ARM_DEV_PMU        -  ARM PMU overflow interrupt signal

Future versions of kvm may implement additional events. These will get
indicated by returning a higher number from KVM_CHECK_EXTENSION and will be
listed above.
+53 −0
Original line number Original line Diff line number Diff line
* 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.
+11 −1
Original line number Original line Diff line number Diff line
@@ -422,7 +422,17 @@ dtb_check_done:
		cmp	r0, #HYP_MODE
		cmp	r0, #HYP_MODE
		bne	1f
		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
		sub	r0, r0, r5
		add	r0, r0, r10
		add	r0, r0, r10
		bl	__hyp_set_vectors
		bl	__hyp_set_vectors
+4 −3
Original line number Original line Diff line number Diff line
@@ -33,7 +33,7 @@
#define ARM_EXCEPTION_IRQ	  5
#define ARM_EXCEPTION_IRQ	  5
#define ARM_EXCEPTION_FIQ	  6
#define ARM_EXCEPTION_FIQ	  6
#define ARM_EXCEPTION_HVC	  7
#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
 * The rr_lo_hi macro swaps a pair of registers depending on
 * current endianness. It is used in conjunction with ldrd and strd
 * current endianness. It is used in conjunction with ldrd and strd
@@ -72,10 +72,11 @@ extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu);


extern void __init_stage2_translation(void);
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_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);
extern void __vgic_v3_init_lrs(void);

#endif
#endif


#endif /* __ARM_KVM_ASM_H__ */
#endif /* __ARM_KVM_ASM_H__ */
+0 −6
Original line number Original line Diff line number Diff line
@@ -269,12 +269,6 @@ static inline void __cpu_init_stage2(void)
	kvm_call_hyp(__init_stage2_translation);
	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)
static inline int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext)
{
{
	return 0;
	return 0;
Loading