KVM/arm fixes for 4.18, take #1
- Lazy FPSIMD switching fixes - Really disable compat ioctls on architectures that don't want it - Disable compat on arm64 (it was never implemented...) - Rely on architectural requirements for GICV on GICv3 - Detect bad alignments in unmap_stage2_range -----BEGIN PGP SIGNATURE----- iQJJBAABCAAzFiEEn9UcU+C1Yxj9lZw9I9DQutE9ekMFAlss7fgVHG1hcmMuenlu Z2llckBhcm0uY29tAAoJECPQ0LrRPXpDjosQAKG9+NIpcKx15k6Rzw+WcpEwk3IY yx47MR9ndgfypQGrJ1bczbaP0xzMW/snErtN2iKGv/q8QdaKI0fj63XFkDMcfp+i RdsIrWyXkhATbFvChKvp2jUWPoDKAO+eUYpwKk60QqT/NEzo6JoLyRXcGwIruHoZ pzJEZXnmNUTwgAWnJlLGVCJ17lDVd39Gp9/z97MzOyjFCVpfJ61HsEWAtjmiCQr5 opHcdJ5KBW7XOU4uRqM4QEIruO3Hq56L9VJJWfRf2gdnFQowyMhKNErvuuSBpeBF jHA+1nEWbxph97aEEYcnXDQt7wh/o7hZ7kGdGqmW03gJWZdMhXeivlsavXihkxIq s3rUGRFhkIJ2+RwsmhSchlkkR9RFTItAAoMsRPwxAGcLA/2CBIPjdUFqbIse8O/h mWvXVrYa6uVQQzxJgtbtiOFFVdBOSxr9uE4eq+8vKNkS+3UTs0vUgueB6QtERNtM L1uyLGfyZVGuRvvIo5YTGO5vmRQdsBuPi4YtkJpdtks3TDZBw2bsf38ybyvPc963 0orsS065JiFbh/aCtcMUnD8nPkdfpWVEmSa470bsSNK0f7Wa311fawW+/wGGpGdh 2Jz/CIm5a29bIE+aR9k9B4QJIvXrX6uCiobfEHjQGJMC1DOJPVFvQhMn2JMnFc/F LlulbKhiYbdhxAnS =nzFZ -----END PGP SIGNATURE----- Merge tag 'kvmarm-fixes-for-4.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm KVM/arm fixes for 4.18, take #1 - Lazy FPSIMD switching fixes - Really disable compat ioctls on architectures that don't want it - Disable compat on arm64 (it was never implemented...) - Rely on architectural requirements for GICV on GICv3 - Detect bad alignments in unmap_stage2_range
This commit is contained in:
commit
5f9077cbae
|
@ -306,6 +306,7 @@ struct kvm_vcpu_arch {
|
|||
#define KVM_ARM64_FP_ENABLED (1 << 1) /* guest FP regs loaded */
|
||||
#define KVM_ARM64_FP_HOST (1 << 2) /* host FP regs loaded */
|
||||
#define KVM_ARM64_HOST_SVE_IN_USE (1 << 3) /* backup for host TIF_SVE */
|
||||
#define KVM_ARM64_HOST_SVE_ENABLED (1 << 4) /* SVE enabled for EL0 */
|
||||
|
||||
#define vcpu_gp_regs(v) (&(v)->arch.ctxt.gp_regs)
|
||||
|
||||
|
|
|
@ -728,6 +728,17 @@ asm(
|
|||
asm volatile("msr_s " __stringify(r) ", %x0" : : "rZ" (__val)); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Modify bits in a sysreg. Bits in the clear mask are zeroed, then bits in the
|
||||
* set mask are set. Other bits are left as-is.
|
||||
*/
|
||||
#define sysreg_clear_set(sysreg, clear, set) do { \
|
||||
u64 __scs_val = read_sysreg(sysreg); \
|
||||
u64 __scs_new = (__scs_val & ~(u64)(clear)) | (set); \
|
||||
if (__scs_new != __scs_val) \
|
||||
write_sysreg(__scs_new, sysreg); \
|
||||
} while (0)
|
||||
|
||||
static inline void config_sctlr_el1(u32 clear, u32 set)
|
||||
{
|
||||
u32 val;
|
||||
|
|
|
@ -5,13 +5,14 @@
|
|||
* Copyright 2018 Arm Limited
|
||||
* Author: Dave Martin <Dave.Martin@arm.com>
|
||||
*/
|
||||
#include <linux/bottom_half.h>
|
||||
#include <linux/irqflags.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/thread_info.h>
|
||||
#include <linux/kvm_host.h>
|
||||
#include <asm/kvm_asm.h>
|
||||
#include <asm/kvm_host.h>
|
||||
#include <asm/kvm_mmu.h>
|
||||
#include <asm/sysreg.h>
|
||||
|
||||
/*
|
||||
* Called on entry to KVM_RUN unless this vcpu previously ran at least
|
||||
|
@ -61,10 +62,16 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
|
|||
{
|
||||
BUG_ON(!current->mm);
|
||||
|
||||
vcpu->arch.flags &= ~(KVM_ARM64_FP_ENABLED | KVM_ARM64_HOST_SVE_IN_USE);
|
||||
vcpu->arch.flags &= ~(KVM_ARM64_FP_ENABLED |
|
||||
KVM_ARM64_HOST_SVE_IN_USE |
|
||||
KVM_ARM64_HOST_SVE_ENABLED);
|
||||
vcpu->arch.flags |= KVM_ARM64_FP_HOST;
|
||||
|
||||
if (test_thread_flag(TIF_SVE))
|
||||
vcpu->arch.flags |= KVM_ARM64_HOST_SVE_IN_USE;
|
||||
|
||||
if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
|
||||
vcpu->arch.flags |= KVM_ARM64_HOST_SVE_ENABLED;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -92,19 +99,30 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
|
|||
*/
|
||||
void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
local_bh_disable();
|
||||
unsigned long flags;
|
||||
|
||||
update_thread_flag(TIF_SVE,
|
||||
vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE);
|
||||
local_irq_save(flags);
|
||||
|
||||
if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
|
||||
/* Clean guest FP state to memory and invalidate cpu view */
|
||||
fpsimd_save();
|
||||
fpsimd_flush_cpu_state();
|
||||
} else if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) {
|
||||
/* Ensure user trap controls are correctly restored */
|
||||
fpsimd_bind_task_to_cpu();
|
||||
} else if (system_supports_sve()) {
|
||||
/*
|
||||
* The FPSIMD/SVE state in the CPU has not been touched, and we
|
||||
* have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been
|
||||
* reset to CPACR_EL1_DEFAULT by the Hyp code, disabling SVE
|
||||
* for EL0. To avoid spurious traps, restore the trap state
|
||||
* seen by kvm_arch_vcpu_load_fp():
|
||||
*/
|
||||
if (vcpu->arch.flags & KVM_ARM64_HOST_SVE_ENABLED)
|
||||
sysreg_clear_set(CPACR_EL1, 0, CPACR_EL1_ZEN_EL0EN);
|
||||
else
|
||||
sysreg_clear_set(CPACR_EL1, CPACR_EL1_ZEN_EL0EN, 0);
|
||||
}
|
||||
|
||||
local_bh_enable();
|
||||
update_thread_flag(TIF_SVE,
|
||||
vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE);
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ config KVM_GENERIC_DIRTYLOG_READ_PROTECT
|
|||
|
||||
config KVM_COMPAT
|
||||
def_bool y
|
||||
depends on KVM && COMPAT && !S390
|
||||
depends on KVM && COMPAT && !(S390 || ARM64)
|
||||
|
||||
config HAVE_KVM_IRQ_BYPASS
|
||||
bool
|
||||
|
|
|
@ -297,6 +297,8 @@ static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
|
|||
phys_addr_t next;
|
||||
|
||||
assert_spin_locked(&kvm->mmu_lock);
|
||||
WARN_ON(size & ~PAGE_MASK);
|
||||
|
||||
pgd = kvm->arch.pgd + stage2_pgd_index(addr);
|
||||
do {
|
||||
/*
|
||||
|
|
|
@ -617,11 +617,6 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
|
|||
pr_warn("GICV physical address 0x%llx not page aligned\n",
|
||||
(unsigned long long)info->vcpu.start);
|
||||
kvm_vgic_global_state.vcpu_base = 0;
|
||||
} else if (!PAGE_ALIGNED(resource_size(&info->vcpu))) {
|
||||
pr_warn("GICV size 0x%llx not a multiple of page size 0x%lx\n",
|
||||
(unsigned long long)resource_size(&info->vcpu),
|
||||
PAGE_SIZE);
|
||||
kvm_vgic_global_state.vcpu_base = 0;
|
||||
} else {
|
||||
kvm_vgic_global_state.vcpu_base = info->vcpu.start;
|
||||
kvm_vgic_global_state.can_emulate_gicv2 = true;
|
||||
|
|
|
@ -116,6 +116,11 @@ static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
|
|||
#ifdef CONFIG_KVM_COMPAT
|
||||
static long kvm_vcpu_compat_ioctl(struct file *file, unsigned int ioctl,
|
||||
unsigned long arg);
|
||||
#define KVM_COMPAT(c) .compat_ioctl = (c)
|
||||
#else
|
||||
static long kvm_no_compat_ioctl(struct file *file, unsigned int ioctl,
|
||||
unsigned long arg) { return -EINVAL; }
|
||||
#define KVM_COMPAT(c) .compat_ioctl = kvm_no_compat_ioctl
|
||||
#endif
|
||||
static int hardware_enable_all(void);
|
||||
static void hardware_disable_all(void);
|
||||
|
@ -2396,11 +2401,9 @@ static int kvm_vcpu_release(struct inode *inode, struct file *filp)
|
|||
static struct file_operations kvm_vcpu_fops = {
|
||||
.release = kvm_vcpu_release,
|
||||
.unlocked_ioctl = kvm_vcpu_ioctl,
|
||||
#ifdef CONFIG_KVM_COMPAT
|
||||
.compat_ioctl = kvm_vcpu_compat_ioctl,
|
||||
#endif
|
||||
.mmap = kvm_vcpu_mmap,
|
||||
.llseek = noop_llseek,
|
||||
KVM_COMPAT(kvm_vcpu_compat_ioctl),
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -2824,10 +2827,8 @@ static int kvm_device_release(struct inode *inode, struct file *filp)
|
|||
|
||||
static const struct file_operations kvm_device_fops = {
|
||||
.unlocked_ioctl = kvm_device_ioctl,
|
||||
#ifdef CONFIG_KVM_COMPAT
|
||||
.compat_ioctl = kvm_device_ioctl,
|
||||
#endif
|
||||
.release = kvm_device_release,
|
||||
KVM_COMPAT(kvm_device_ioctl),
|
||||
};
|
||||
|
||||
struct kvm_device *kvm_device_from_filp(struct file *filp)
|
||||
|
@ -3165,10 +3166,8 @@ static long kvm_vm_compat_ioctl(struct file *filp,
|
|||
static struct file_operations kvm_vm_fops = {
|
||||
.release = kvm_vm_release,
|
||||
.unlocked_ioctl = kvm_vm_ioctl,
|
||||
#ifdef CONFIG_KVM_COMPAT
|
||||
.compat_ioctl = kvm_vm_compat_ioctl,
|
||||
#endif
|
||||
.llseek = noop_llseek,
|
||||
KVM_COMPAT(kvm_vm_compat_ioctl),
|
||||
};
|
||||
|
||||
static int kvm_dev_ioctl_create_vm(unsigned long type)
|
||||
|
@ -3259,8 +3258,8 @@ out:
|
|||
|
||||
static struct file_operations kvm_chardev_ops = {
|
||||
.unlocked_ioctl = kvm_dev_ioctl,
|
||||
.compat_ioctl = kvm_dev_ioctl,
|
||||
.llseek = noop_llseek,
|
||||
KVM_COMPAT(kvm_dev_ioctl),
|
||||
};
|
||||
|
||||
static struct miscdevice kvm_dev = {
|
||||
|
|
Loading…
Reference in New Issue