lab.nexedi.com will be down from Thursday, 20 March 2025, 07:30:00 UTC for a duration of approximately 2 hours

Commit 0c021834 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm

Pull kvm updates from Paolo Bonzini:
 "ARM:

   - Clean up vCPU targets, always returning generic v8 as the preferred
     target

   - Trap forwarding infrastructure for nested virtualization (used for
     traps that are taken from an L2 guest and are needed by the L1
     hypervisor)

   - FEAT_TLBIRANGE support to only invalidate specific ranges of
     addresses when collapsing a table PTE to a block PTE. This avoids
     that the guest refills the TLBs again for addresses that aren't
     covered by the table PTE.

   - Fix vPMU issues related to handling of PMUver.

   - Don't unnecessary align non-stack allocations in the EL2 VA space

   - Drop HCR_VIRT_EXCP_MASK, which was never used...

   - Don't use smp_processor_id() in kvm_arch_vcpu_load(), but the cpu
     parameter instead

   - Drop redundant call to kvm_set_pfn_accessed() in user_mem_abort()

   - Remove prototypes without implementations

  RISC-V:

   - Zba, Zbs, Zicntr, Zicsr, Zifencei, and Zihpm support for guest

   - Added ONE_REG interface for SATP mode

   - Added ONE_REG interface to enable/disable multiple ISA extensions

   - Improved error codes returned by ONE_REG interfaces

   - Added KVM_GET_REG_LIST ioctl() implementation for KVM RISC-V

   - Added get-reg-list selftest for KVM RISC-V

  s390:

   - PV crypto passthrough enablement (Tony, Steffen, Viktor, Janosch)

     Allows a PV guest to use crypto cards. Card access is governed by
     the firmware and once a crypto queue is "bound" to a PV VM every
     other entity (PV or not) looses access until it is not bound
     anymore. Enablement is done via flags when creating the PV VM.

   - Guest debug fixes (Ilya)

  x86:

   - Clean up KVM's handling of Intel architectural events

   - Intel bugfixes

   - Add support for SEV-ES DebugSwap, allowing SEV-ES guests to use
     debug registers and generate/handle #DBs

   - Clean up LBR virtualization code

   - Fix a bug where KVM fails to set the target pCPU during an IRTE
     update

   - Fix fatal bugs in SEV-ES intrahost migration

   - Fix a bug where the recent (architecturally correct) change to
     reinject #BP and skip INT3 broke SEV guests (can't decode INT3 to
     skip it)

   - Retry APIC map recalculation if a vCPU is added/enabled

   - Overhaul emergency reboot code to bring SVM up to par with VMX, tie
     the "emergency disabling" behavior to KVM actually being loaded,
     and move all of the logic within KVM

   - Fix user triggerable WARNs in SVM where KVM incorrectly assumes the
     TSC ratio MSR cannot diverge from the default when TSC scaling is
     disabled up related code

   - Add a framework to allow "caching" feature flags so that KVM can
     check if the guest can use a feature without needing to search
     guest CPUID

   - Rip out the ancient MMU_DEBUG crud and replace the useful bits with
     CONFIG_KVM_PROVE_MMU

   - Fix KVM's handling of !visible guest roots to avoid premature
     triple fault injection

   - Overhaul KVM's page-track APIs, and KVMGT's usage, to reduce the
     API surface that is needed by external users (currently only
     KVMGT), and fix a variety of issues in the process

  Generic:

   - Wrap kvm_{gfn,hva}_range.pte in a union to allow mmu_notifier
     events to pass action specific data without needing to constantly
     update the main handlers.

   - Drop unused function declarations

  Selftests:

   - Add testcases to x86's sync_regs_test for detecting KVM TOCTOU bugs

   - Add support for printf() in guest code and covert all guest asserts
     to use printf-based reporting

   - Clean up the PMU event filter test and add new testcases

   - Include x86 selftests in the KVM x86 MAINTAINERS entry"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (279 commits)
  KVM: x86/mmu: Include mmu.h in spte.h
  KVM: x86/mmu: Use dummy root, backed by zero page, for !visible guest roots
  KVM: x86/mmu: Disallow guest from using !visible slots for page tables
  KVM: x86/mmu: Harden TDP MMU iteration against root w/o shadow page
  KVM: x86/mmu: Harden new PGD against roots without shadow pages
  KVM: x86/mmu: Add helper to convert root hpa to shadow page
  drm/i915/gvt: Drop final dependencies on KVM internal details
  KVM: x86/mmu: Handle KVM bookkeeping in page-track APIs, not callers
  KVM: x86/mmu: Drop @slot param from exported/external page-track APIs
  KVM: x86/mmu: Bug the VM if write-tracking is used but not enabled
  KVM: x86/mmu: Assert that correct locks are held for page write-tracking
  KVM: x86/mmu: Rename page-track APIs to reflect the new reality
  KVM: x86/mmu: Drop infrastructure for multiple page-track modes
  KVM: x86/mmu: Use page-track notifiers iff there are external users
  KVM: x86/mmu: Move KVM-only page-track declarations to internal header
  KVM: x86: Remove the unused page-track hook track_flush_slot()
  drm/i915/gvt: switch from ->track_flush_slot() to ->track_remove_region()
  KVM: x86: Add a new page-track hook to handle memslot deletion
  drm/i915/gvt: Don't bother removing write-protection on to-be-deleted slot
  KVM: x86: Reject memslot MOVE operations if KVMGT is attached
  ...
parents 4a0fc73d d0111516
...@@ -2259,6 +2259,8 @@ Errors: ...@@ -2259,6 +2259,8 @@ Errors:
EINVAL invalid register ID, or no such register or used with VMs in EINVAL invalid register ID, or no such register or used with VMs in
protected virtualization mode on s390 protected virtualization mode on s390
EPERM (arm64) register access not allowed before vcpu finalization EPERM (arm64) register access not allowed before vcpu finalization
EBUSY (riscv) changing register value not allowed after the vcpu
has run at least once
====== ============================================================ ====== ============================================================
(These error codes are indicative only: do not rely on a specific error (These error codes are indicative only: do not rely on a specific error
...@@ -3499,7 +3501,7 @@ VCPU matching underlying host. ...@@ -3499,7 +3501,7 @@ VCPU matching underlying host.
--------------------- ---------------------
:Capability: basic :Capability: basic
:Architectures: arm64, mips :Architectures: arm64, mips, riscv
:Type: vcpu ioctl :Type: vcpu ioctl
:Parameters: struct kvm_reg_list (in/out) :Parameters: struct kvm_reg_list (in/out)
:Returns: 0 on success; -1 on error :Returns: 0 on success; -1 on error
......
...@@ -11589,6 +11589,8 @@ F: arch/x86/include/uapi/asm/svm.h ...@@ -11589,6 +11589,8 @@ F: arch/x86/include/uapi/asm/svm.h
F: arch/x86/include/uapi/asm/vmx.h F: arch/x86/include/uapi/asm/vmx.h
F: arch/x86/kvm/ F: arch/x86/kvm/
F: arch/x86/kvm/*/ F: arch/x86/kvm/*/
F: tools/testing/selftests/kvm/*/x86_64/
F: tools/testing/selftests/kvm/x86_64/
KERNFS KERNFS
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
......
...@@ -227,6 +227,8 @@ static inline bool kvm_set_pmuserenr(u64 val) ...@@ -227,6 +227,8 @@ static inline bool kvm_set_pmuserenr(u64 val)
return false; return false;
} }
static inline void kvm_vcpu_pmu_resync_el0(void) {}
/* PMU Version in DFR Register */ /* PMU Version in DFR Register */
#define ARMV8_PMU_DFR_VER_NI 0 #define ARMV8_PMU_DFR_VER_NI 0
#define ARMV8_PMU_DFR_VER_V3P4 0x5 #define ARMV8_PMU_DFR_VER_V3P4 0x5
......
...@@ -18,10 +18,19 @@ ...@@ -18,10 +18,19 @@
#define HCR_DCT (UL(1) << 57) #define HCR_DCT (UL(1) << 57)
#define HCR_ATA_SHIFT 56 #define HCR_ATA_SHIFT 56
#define HCR_ATA (UL(1) << HCR_ATA_SHIFT) #define HCR_ATA (UL(1) << HCR_ATA_SHIFT)
#define HCR_TTLBOS (UL(1) << 55)
#define HCR_TTLBIS (UL(1) << 54)
#define HCR_ENSCXT (UL(1) << 53)
#define HCR_TOCU (UL(1) << 52)
#define HCR_AMVOFFEN (UL(1) << 51) #define HCR_AMVOFFEN (UL(1) << 51)
#define HCR_TICAB (UL(1) << 50)
#define HCR_TID4 (UL(1) << 49) #define HCR_TID4 (UL(1) << 49)
#define HCR_FIEN (UL(1) << 47) #define HCR_FIEN (UL(1) << 47)
#define HCR_FWB (UL(1) << 46) #define HCR_FWB (UL(1) << 46)
#define HCR_NV2 (UL(1) << 45)
#define HCR_AT (UL(1) << 44)
#define HCR_NV1 (UL(1) << 43)
#define HCR_NV (UL(1) << 42)
#define HCR_API (UL(1) << 41) #define HCR_API (UL(1) << 41)
#define HCR_APK (UL(1) << 40) #define HCR_APK (UL(1) << 40)
#define HCR_TEA (UL(1) << 37) #define HCR_TEA (UL(1) << 37)
...@@ -89,7 +98,6 @@ ...@@ -89,7 +98,6 @@
HCR_BSU_IS | HCR_FB | HCR_TACR | \ HCR_BSU_IS | HCR_FB | HCR_TACR | \
HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR | \ HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR | \
HCR_FMO | HCR_IMO | HCR_PTW | HCR_TID3) HCR_FMO | HCR_IMO | HCR_PTW | HCR_TID3)
#define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF)
#define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK | HCR_ATA) #define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK | HCR_ATA)
#define HCR_HOST_NVHE_PROTECTED_FLAGS (HCR_HOST_NVHE_FLAGS | HCR_TSC) #define HCR_HOST_NVHE_PROTECTED_FLAGS (HCR_HOST_NVHE_FLAGS | HCR_TSC)
#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H) #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
...@@ -324,6 +332,47 @@ ...@@ -324,6 +332,47 @@
BIT(18) | \ BIT(18) | \
GENMASK(16, 15)) GENMASK(16, 15))
/*
* FGT register definitions
*
* RES0 and polarity masks as of DDI0487J.a, to be updated as needed.
* We're not using the generated masks as they are usually ahead of
* the published ARM ARM, which we use as a reference.
*
* Once we get to a point where the two describe the same thing, we'll
* merge the definitions. One day.
*/
#define __HFGRTR_EL2_RES0 (GENMASK(63, 56) | GENMASK(53, 51))
#define __HFGRTR_EL2_MASK GENMASK(49, 0)
#define __HFGRTR_EL2_nMASK (GENMASK(55, 54) | BIT(50))
#define __HFGWTR_EL2_RES0 (GENMASK(63, 56) | GENMASK(53, 51) | \
BIT(46) | BIT(42) | BIT(40) | BIT(28) | \
GENMASK(26, 25) | BIT(21) | BIT(18) | \
GENMASK(15, 14) | GENMASK(10, 9) | BIT(2))
#define __HFGWTR_EL2_MASK GENMASK(49, 0)
#define __HFGWTR_EL2_nMASK (GENMASK(55, 54) | BIT(50))
#define __HFGITR_EL2_RES0 GENMASK(63, 57)
#define __HFGITR_EL2_MASK GENMASK(54, 0)
#define __HFGITR_EL2_nMASK GENMASK(56, 55)
#define __HDFGRTR_EL2_RES0 (BIT(49) | BIT(42) | GENMASK(39, 38) | \
GENMASK(21, 20) | BIT(8))
#define __HDFGRTR_EL2_MASK ~__HDFGRTR_EL2_nMASK
#define __HDFGRTR_EL2_nMASK GENMASK(62, 59)
#define __HDFGWTR_EL2_RES0 (BIT(63) | GENMASK(59, 58) | BIT(51) | BIT(47) | \
BIT(43) | GENMASK(40, 38) | BIT(34) | BIT(30) | \
BIT(22) | BIT(9) | BIT(6))
#define __HDFGWTR_EL2_MASK ~__HDFGWTR_EL2_nMASK
#define __HDFGWTR_EL2_nMASK GENMASK(62, 60)
/* Similar definitions for HCRX_EL2 */
#define __HCRX_EL2_RES0 (GENMASK(63, 16) | GENMASK(13, 12))
#define __HCRX_EL2_MASK (0)
#define __HCRX_EL2_nMASK (GENMASK(15, 14) | GENMASK(4, 0))
/* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */ /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */
#define HPFAR_MASK (~UL(0xf)) #define HPFAR_MASK (~UL(0xf))
/* /*
......
...@@ -70,6 +70,7 @@ enum __kvm_host_smccc_func { ...@@ -70,6 +70,7 @@ enum __kvm_host_smccc_func {
__KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_ipa, __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_ipa,
__KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_ipa_nsh, __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_ipa_nsh,
__KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid, __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid,
__KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_range,
__KVM_HOST_SMCCC_FUNC___kvm_flush_cpu_context, __KVM_HOST_SMCCC_FUNC___kvm_flush_cpu_context,
__KVM_HOST_SMCCC_FUNC___kvm_timer_set_cntvoff, __KVM_HOST_SMCCC_FUNC___kvm_timer_set_cntvoff,
__KVM_HOST_SMCCC_FUNC___vgic_v3_read_vmcr, __KVM_HOST_SMCCC_FUNC___vgic_v3_read_vmcr,
...@@ -229,6 +230,8 @@ extern void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu, phys_addr_t ipa, ...@@ -229,6 +230,8 @@ extern void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu, phys_addr_t ipa,
extern void __kvm_tlb_flush_vmid_ipa_nsh(struct kvm_s2_mmu *mmu, extern void __kvm_tlb_flush_vmid_ipa_nsh(struct kvm_s2_mmu *mmu,
phys_addr_t ipa, phys_addr_t ipa,
int level); int level);
extern void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
phys_addr_t start, unsigned long pages);
extern void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu); extern void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu);
extern void __kvm_timer_set_cntvoff(u64 cntvoff); extern void __kvm_timer_set_cntvoff(u64 cntvoff);
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#define KVM_REQ_RELOAD_GICv4 KVM_ARCH_REQ(4) #define KVM_REQ_RELOAD_GICv4 KVM_ARCH_REQ(4)
#define KVM_REQ_RELOAD_PMU KVM_ARCH_REQ(5) #define KVM_REQ_RELOAD_PMU KVM_ARCH_REQ(5)
#define KVM_REQ_SUSPEND KVM_ARCH_REQ(6) #define KVM_REQ_SUSPEND KVM_ARCH_REQ(6)
#define KVM_REQ_RESYNC_PMU_EL0 KVM_ARCH_REQ(7)
#define KVM_DIRTY_LOG_MANUAL_CAPS (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \ #define KVM_DIRTY_LOG_MANUAL_CAPS (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
KVM_DIRTY_LOG_INITIALLY_SET) KVM_DIRTY_LOG_INITIALLY_SET)
...@@ -380,6 +381,7 @@ enum vcpu_sysreg { ...@@ -380,6 +381,7 @@ enum vcpu_sysreg {
CPTR_EL2, /* Architectural Feature Trap Register (EL2) */ CPTR_EL2, /* Architectural Feature Trap Register (EL2) */
HSTR_EL2, /* Hypervisor System Trap Register */ HSTR_EL2, /* Hypervisor System Trap Register */
HACR_EL2, /* Hypervisor Auxiliary Control Register */ HACR_EL2, /* Hypervisor Auxiliary Control Register */
HCRX_EL2, /* Extended Hypervisor Configuration Register */
TTBR0_EL2, /* Translation Table Base Register 0 (EL2) */ TTBR0_EL2, /* Translation Table Base Register 0 (EL2) */
TTBR1_EL2, /* Translation Table Base Register 1 (EL2) */ TTBR1_EL2, /* Translation Table Base Register 1 (EL2) */
TCR_EL2, /* Translation Control Register (EL2) */ TCR_EL2, /* Translation Control Register (EL2) */
...@@ -400,6 +402,11 @@ enum vcpu_sysreg { ...@@ -400,6 +402,11 @@ enum vcpu_sysreg {
TPIDR_EL2, /* EL2 Software Thread ID Register */ TPIDR_EL2, /* EL2 Software Thread ID Register */
CNTHCTL_EL2, /* Counter-timer Hypervisor Control register */ CNTHCTL_EL2, /* Counter-timer Hypervisor Control register */
SP_EL2, /* EL2 Stack Pointer */ SP_EL2, /* EL2 Stack Pointer */
HFGRTR_EL2,
HFGWTR_EL2,
HFGITR_EL2,
HDFGRTR_EL2,
HDFGWTR_EL2,
CNTHP_CTL_EL2, CNTHP_CTL_EL2,
CNTHP_CVAL_EL2, CNTHP_CVAL_EL2,
CNTHV_CTL_EL2, CNTHV_CTL_EL2,
...@@ -567,8 +574,7 @@ struct kvm_vcpu_arch { ...@@ -567,8 +574,7 @@ struct kvm_vcpu_arch {
/* Cache some mmu pages needed inside spinlock regions */ /* Cache some mmu pages needed inside spinlock regions */
struct kvm_mmu_memory_cache mmu_page_cache; struct kvm_mmu_memory_cache mmu_page_cache;
/* Target CPU and feature flags */ /* feature flags */
int target;
DECLARE_BITMAP(features, KVM_VCPU_MAX_FEATURES); DECLARE_BITMAP(features, KVM_VCPU_MAX_FEATURES);
/* Virtual SError ESR to restore when HCR_EL2.VSE is set */ /* Virtual SError ESR to restore when HCR_EL2.VSE is set */
...@@ -669,6 +675,8 @@ struct kvm_vcpu_arch { ...@@ -669,6 +675,8 @@ struct kvm_vcpu_arch {
#define VCPU_SVE_FINALIZED __vcpu_single_flag(cflags, BIT(1)) #define VCPU_SVE_FINALIZED __vcpu_single_flag(cflags, BIT(1))
/* PTRAUTH exposed to guest */ /* PTRAUTH exposed to guest */
#define GUEST_HAS_PTRAUTH __vcpu_single_flag(cflags, BIT(2)) #define GUEST_HAS_PTRAUTH __vcpu_single_flag(cflags, BIT(2))
/* KVM_ARM_VCPU_INIT completed */
#define VCPU_INITIALIZED __vcpu_single_flag(cflags, BIT(3))
/* Exception pending */ /* Exception pending */
#define PENDING_EXCEPTION __vcpu_single_flag(iflags, BIT(0)) #define PENDING_EXCEPTION __vcpu_single_flag(iflags, BIT(0))
...@@ -899,7 +907,6 @@ struct kvm_vcpu_stat { ...@@ -899,7 +907,6 @@ struct kvm_vcpu_stat {
u64 exits; u64 exits;
}; };
void kvm_vcpu_preferred_target(struct kvm_vcpu_init *init);
unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu); unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
...@@ -967,8 +974,6 @@ void kvm_arm_resume_guest(struct kvm *kvm); ...@@ -967,8 +974,6 @@ void kvm_arm_resume_guest(struct kvm *kvm);
#define kvm_call_hyp_nvhe(f, ...) f(__VA_ARGS__) #define kvm_call_hyp_nvhe(f, ...) f(__VA_ARGS__)
#endif /* __KVM_NVHE_HYPERVISOR__ */ #endif /* __KVM_NVHE_HYPERVISOR__ */
void force_vm_exit(const cpumask_t *mask);
int handle_exit(struct kvm_vcpu *vcpu, int exception_index); int handle_exit(struct kvm_vcpu *vcpu, int exception_index);
void handle_exit_early(struct kvm_vcpu *vcpu, int exception_index); void handle_exit_early(struct kvm_vcpu *vcpu, int exception_index);
...@@ -983,6 +988,7 @@ int kvm_handle_cp10_id(struct kvm_vcpu *vcpu); ...@@ -983,6 +988,7 @@ int kvm_handle_cp10_id(struct kvm_vcpu *vcpu);
void kvm_reset_sys_regs(struct kvm_vcpu *vcpu); void kvm_reset_sys_regs(struct kvm_vcpu *vcpu);
int __init kvm_sys_reg_table_init(void); int __init kvm_sys_reg_table_init(void);
int __init populate_nv_trap_config(void);
bool lock_all_vcpus(struct kvm *kvm); bool lock_all_vcpus(struct kvm *kvm);
void unlock_all_vcpus(struct kvm *kvm); void unlock_all_vcpus(struct kvm *kvm);
...@@ -1049,8 +1055,6 @@ static inline bool kvm_system_needs_idmapped_vectors(void) ...@@ -1049,8 +1055,6 @@ static inline bool kvm_system_needs_idmapped_vectors(void)
return cpus_have_const_cap(ARM64_SPECTRE_V3A); return cpus_have_const_cap(ARM64_SPECTRE_V3A);
} }
void kvm_arm_vcpu_ptrauth_trap(struct kvm_vcpu *vcpu);
static inline void kvm_arch_sync_events(struct kvm *kvm) {} static inline void kvm_arch_sync_events(struct kvm *kvm) {}
static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {} static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}
...@@ -1113,13 +1117,15 @@ int __init kvm_set_ipa_limit(void); ...@@ -1113,13 +1117,15 @@ int __init kvm_set_ipa_limit(void);
#define __KVM_HAVE_ARCH_VM_ALLOC #define __KVM_HAVE_ARCH_VM_ALLOC
struct kvm *kvm_arch_alloc_vm(void); struct kvm *kvm_arch_alloc_vm(void);
#define __KVM_HAVE_ARCH_FLUSH_REMOTE_TLBS
#define __KVM_HAVE_ARCH_FLUSH_REMOTE_TLBS_RANGE
static inline bool kvm_vm_is_protected(struct kvm *kvm) static inline bool kvm_vm_is_protected(struct kvm *kvm)
{ {
return false; return false;
} }
void kvm_init_protected_traps(struct kvm_vcpu *vcpu);
int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu, int feature); int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu, int feature);
bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu); bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu);
......
...@@ -168,6 +168,7 @@ int create_hyp_io_mappings(phys_addr_t phys_addr, size_t size, ...@@ -168,6 +168,7 @@ int create_hyp_io_mappings(phys_addr_t phys_addr, size_t size,
void __iomem **haddr); void __iomem **haddr);
int create_hyp_exec_mappings(phys_addr_t phys_addr, size_t size, int create_hyp_exec_mappings(phys_addr_t phys_addr, size_t size,
void **haddr); void **haddr);
int create_hyp_stack(phys_addr_t phys_addr, unsigned long *haddr);
void __init free_hyp_pgds(void); void __init free_hyp_pgds(void);
void stage2_unmap_vm(struct kvm *kvm); void stage2_unmap_vm(struct kvm *kvm);
......
...@@ -11,6 +11,8 @@ static inline bool vcpu_has_nv(const struct kvm_vcpu *vcpu) ...@@ -11,6 +11,8 @@ static inline bool vcpu_has_nv(const struct kvm_vcpu *vcpu)
test_bit(KVM_ARM_VCPU_HAS_EL2, vcpu->arch.features)); test_bit(KVM_ARM_VCPU_HAS_EL2, vcpu->arch.features));
} }
extern bool __check_nv_sr_forward(struct kvm_vcpu *vcpu);
struct sys_reg_params; struct sys_reg_params;
struct sys_reg_desc; struct sys_reg_desc;
......
...@@ -746,4 +746,14 @@ enum kvm_pgtable_prot kvm_pgtable_stage2_pte_prot(kvm_pte_t pte); ...@@ -746,4 +746,14 @@ enum kvm_pgtable_prot kvm_pgtable_stage2_pte_prot(kvm_pte_t pte);
* kvm_pgtable_prot format. * kvm_pgtable_prot format.
*/ */
enum kvm_pgtable_prot kvm_pgtable_hyp_pte_prot(kvm_pte_t pte); enum kvm_pgtable_prot kvm_pgtable_hyp_pte_prot(kvm_pte_t pte);
/**
* kvm_tlb_flush_vmid_range() - Invalidate/flush a range of TLB entries
*
* @mmu: Stage-2 KVM MMU struct
* @addr: The base Intermediate physical address from which to invalidate
* @size: Size of the range from the base to invalidate
*/
void kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
phys_addr_t addr, size_t size);
#endif /* __ARM64_KVM_PGTABLE_H__ */ #endif /* __ARM64_KVM_PGTABLE_H__ */
This diff is collapsed.
...@@ -335,14 +335,77 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch) ...@@ -335,14 +335,77 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
*/ */
#define MAX_TLBI_OPS PTRS_PER_PTE #define MAX_TLBI_OPS PTRS_PER_PTE
/*
* __flush_tlb_range_op - Perform TLBI operation upon a range
*
* @op: TLBI instruction that operates on a range (has 'r' prefix)
* @start: The start address of the range
* @pages: Range as the number of pages from 'start'
* @stride: Flush granularity
* @asid: The ASID of the task (0 for IPA instructions)
* @tlb_level: Translation Table level hint, if known
* @tlbi_user: If 'true', call an additional __tlbi_user()
* (typically for user ASIDs). 'flase' for IPA instructions
*
* When the CPU does not support TLB range operations, flush the TLB
* entries one by one at the granularity of 'stride'. If the TLB
* range ops are supported, then:
*
* 1. If 'pages' is odd, flush the first page through non-range
* operations;
*
* 2. For remaining pages: the minimum range granularity is decided
* by 'scale', so multiple range TLBI operations may be required.
* Start from scale = 0, flush the corresponding number of pages
* ((num+1)*2^(5*scale+1) starting from 'addr'), then increase it
* until no pages left.
*
* Note that certain ranges can be represented by either num = 31 and
* scale or num = 0 and scale + 1. The loop below favours the latter
* since num is limited to 30 by the __TLBI_RANGE_NUM() macro.
*/
#define __flush_tlb_range_op(op, start, pages, stride, \
asid, tlb_level, tlbi_user) \
do { \
int num = 0; \
int scale = 0; \
unsigned long addr; \
\
while (pages > 0) { \
if (!system_supports_tlb_range() || \
pages % 2 == 1) { \
addr = __TLBI_VADDR(start, asid); \
__tlbi_level(op, addr, tlb_level); \
if (tlbi_user) \
__tlbi_user_level(op, addr, tlb_level); \
start += stride; \
pages -= stride >> PAGE_SHIFT; \
continue; \
} \
\
num = __TLBI_RANGE_NUM(pages, scale); \
if (num >= 0) { \
addr = __TLBI_VADDR_RANGE(start, asid, scale, \
num, tlb_level); \
__tlbi(r##op, addr); \
if (tlbi_user) \
__tlbi_user(r##op, addr); \
start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT; \
pages -= __TLBI_RANGE_PAGES(num, scale); \
} \
scale++; \
} \
} while (0)
#define __flush_s2_tlb_range_op(op, start, pages, stride, tlb_level) \
__flush_tlb_range_op(op, start, pages, stride, 0, tlb_level, false)
static inline void __flush_tlb_range(struct vm_area_struct *vma, static inline void __flush_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end, unsigned long start, unsigned long end,
unsigned long stride, bool last_level, unsigned long stride, bool last_level,
int tlb_level) int tlb_level)
{ {
int num = 0; unsigned long asid, pages;
int scale = 0;
unsigned long asid, addr, pages;
start = round_down(start, stride); start = round_down(start, stride);
end = round_up(end, stride); end = round_up(end, stride);
...@@ -364,56 +427,11 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma, ...@@ -364,56 +427,11 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,
dsb(ishst); dsb(ishst);
asid = ASID(vma->vm_mm); asid = ASID(vma->vm_mm);
/* if (last_level)
* When the CPU does not support TLB range operations, flush the TLB __flush_tlb_range_op(vale1is, start, pages, stride, asid, tlb_level, true);
* entries one by one at the granularity of 'stride'. If the TLB else
* range ops are supported, then: __flush_tlb_range_op(vae1is, start, pages, stride, asid, tlb_level, true);
*
* 1. If 'pages' is odd, flush the first page through non-range
* operations;
*
* 2. For remaining pages: the minimum range granularity is decided
* by 'scale', so multiple range TLBI operations may be required.
* Start from scale = 0, flush the corresponding number of pages
* ((num+1)*2^(5*scale+1) starting from 'addr'), then increase it
* until no pages left.
*
* Note that certain ranges can be represented by either num = 31 and
* scale or num = 0 and scale + 1. The loop below favours the latter
* since num is limited to 30 by the __TLBI_RANGE_NUM() macro.
*/
while (pages > 0) {
if (!system_supports_tlb_range() ||
pages % 2 == 1) {
addr = __TLBI_VADDR(start, asid);
if (last_level) {
__tlbi_level(vale1is, addr, tlb_level);
__tlbi_user_level(vale1is, addr, tlb_level);
} else {
__tlbi_level(vae1is, addr, tlb_level);
__tlbi_user_level(vae1is, addr, tlb_level);
}
start += stride;
pages -= stride >> PAGE_SHIFT;
continue;
}
num = __TLBI_RANGE_NUM(pages, scale);
if (num >= 0) {
addr = __TLBI_VADDR_RANGE(start, asid, scale,
num, tlb_level);
if (last_level) {
__tlbi(rvale1is, addr);
__tlbi_user(rvale1is, addr);
} else {
__tlbi(rvae1is, addr);
__tlbi_user(rvae1is, addr);
}
start += __TLBI_RANGE_PAGES(num, scale) << PAGE_SHIFT;
pages -= __TLBI_RANGE_PAGES(num, scale);
}
scale++;
}
dsb(ish); dsb(ish);
mmu_notifier_arch_invalidate_secondary_tlbs(vma->vm_mm, start, end); mmu_notifier_arch_invalidate_secondary_tlbs(vma->vm_mm, start, end);
} }
......
...@@ -2627,6 +2627,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = { ...@@ -2627,6 +2627,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.matches = has_cpuid_feature, .matches = has_cpuid_feature,
ARM64_CPUID_FIELDS(ID_AA64ISAR1_EL1, LRCPC, IMP) ARM64_CPUID_FIELDS(ID_AA64ISAR1_EL1, LRCPC, IMP)
}, },
{
.desc = "Fine Grained Traps",
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
.capability = ARM64_HAS_FGT,
.matches = has_cpuid_feature,
ARM64_CPUID_FIELDS(ID_AA64MMFR0_EL1, FGT, IMP)
},
#ifdef CONFIG_ARM64_SME #ifdef CONFIG_ARM64_SME
{ {
.desc = "Scalable Matrix Extension", .desc = "Scalable Matrix Extension",
......
...@@ -25,7 +25,6 @@ menuconfig KVM ...@@ -25,7 +25,6 @@ menuconfig KVM
select MMU_NOTIFIER select MMU_NOTIFIER
select PREEMPT_NOTIFIERS select PREEMPT_NOTIFIERS
select HAVE_KVM_CPU_RELAX_INTERCEPT select HAVE_KVM_CPU_RELAX_INTERCEPT
select HAVE_KVM_ARCH_TLB_FLUSH_ALL
select KVM_MMIO select KVM_MMIO
select KVM_GENERIC_DIRTYLOG_READ_PROTECT select KVM_GENERIC_DIRTYLOG_READ_PROTECT
select KVM_XFER_TO_GUEST_WORK select KVM_XFER_TO_GUEST_WORK
...@@ -43,6 +42,7 @@ menuconfig KVM ...@@ -43,6 +42,7 @@ menuconfig KVM
select SCHED_INFO select SCHED_INFO
select GUEST_PERF_EVENTS if PERF_EVENTS select GUEST_PERF_EVENTS if PERF_EVENTS
select INTERVAL_TREE select INTERVAL_TREE
select XARRAY_MULTI
help help
Support hosting virtualized guest machines. Support hosting virtualized guest machines.
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <asm/kvm_arm.h> #include <asm/kvm_arm.h>
#include <asm/kvm_asm.h> #include <asm/kvm_asm.h>
#include <asm/kvm_mmu.h> #include <asm/kvm_mmu.h>
#include <asm/kvm_nested.h>
#include <asm/kvm_pkvm.h> #include <asm/kvm_pkvm.h>
#include <asm/kvm_emulate.h> #include <asm/kvm_emulate.h>
#include <asm/sections.h> #include <asm/sections.h>
...@@ -365,7 +366,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) ...@@ -365,7 +366,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
#endif #endif
/* Force users to call KVM_ARM_VCPU_INIT */ /* Force users to call KVM_ARM_VCPU_INIT */
vcpu->arch.target = -1; vcpu_clear_flag(vcpu, VCPU_INITIALIZED);
bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES); bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES);
vcpu->arch.mmu_page_cache.gfp_zero = __GFP_ZERO; vcpu->arch.mmu_page_cache.gfp_zero = __GFP_ZERO;
...@@ -462,7 +463,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) ...@@ -462,7 +463,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
vcpu_ptrauth_disable(vcpu); vcpu_ptrauth_disable(vcpu);
kvm_arch_vcpu_load_debug_state_flags(vcpu); kvm_arch_vcpu_load_debug_state_flags(vcpu);
if (!cpumask_test_cpu(smp_processor_id(), vcpu->kvm->arch.supported_cpus)) if (!cpumask_test_cpu(cpu, vcpu->kvm->arch.supported_cpus))
vcpu_set_on_unsupported_cpu(vcpu); vcpu_set_on_unsupported_cpu(vcpu);
} }
...@@ -574,7 +575,7 @@ unsigned long kvm_arch_vcpu_get_ip(struct kvm_vcpu *vcpu) ...@@ -574,7 +575,7 @@ unsigned long kvm_arch_vcpu_get_ip(struct kvm_vcpu *vcpu)
static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu) static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu)
{ {
return vcpu->arch.target >= 0; return vcpu_get_flag(vcpu, VCPU_INITIALIZED);
} }
/* /*
...@@ -803,6 +804,9 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu) ...@@ -803,6 +804,9 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu)
kvm_pmu_handle_pmcr(vcpu, kvm_pmu_handle_pmcr(vcpu,
__vcpu_sys_reg(vcpu, PMCR_EL0)); __vcpu_sys_reg(vcpu, PMCR_EL0));
if (kvm_check_request(KVM_REQ_RESYNC_PMU_EL0, vcpu))
kvm_vcpu_pmu_restore_guest(vcpu);
if (kvm_check_request(KVM_REQ_SUSPEND, vcpu)) if (kvm_check_request(KVM_REQ_SUSPEND, vcpu))
return kvm_vcpu_suspend(vcpu); return kvm_vcpu_suspend(vcpu);
...@@ -818,6 +822,9 @@ static bool vcpu_mode_is_bad_32bit(struct kvm_vcpu *vcpu) ...@@ -818,6 +822,9 @@ static bool vcpu_mode_is_bad_32bit(struct kvm_vcpu *vcpu)
if (likely(!vcpu_mode_is_32bit(vcpu))) if (likely(!vcpu_mode_is_32bit(vcpu)))
return false; return false;
if (vcpu_has_nv(vcpu))
return true;
return !kvm_supports_32bit_el0(); return !kvm_supports_32bit_el0();
} }
...@@ -1058,7 +1065,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) ...@@ -1058,7 +1065,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
* invalid. The VMM can try and fix it by issuing a * invalid. The VMM can try and fix it by issuing a
* KVM_ARM_VCPU_INIT if it really wants to. * KVM_ARM_VCPU_INIT if it really wants to.
*/ */
vcpu->arch.target = -1; vcpu_clear_flag(vcpu, VCPU_INITIALIZED);
ret = ARM_EXCEPTION_IL; ret = ARM_EXCEPTION_IL;
} }
...@@ -1219,8 +1226,7 @@ static bool kvm_vcpu_init_changed(struct kvm_vcpu *vcpu, ...@@ -1219,8 +1226,7 @@ static bool kvm_vcpu_init_changed(struct kvm_vcpu *vcpu,
{ {
unsigned long features = init->features[0]; unsigned long features = init->features[0];
return !bitmap_equal(vcpu->arch.features, &features, KVM_VCPU_MAX_FEATURES) || return !bitmap_equal(vcpu->arch.features, &features, KVM_VCPU_MAX_FEATURES);
vcpu->arch.target != init->target;
} }
static int __kvm_vcpu_set_target(struct kvm_vcpu *vcpu, static int __kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
...@@ -1236,20 +1242,18 @@ static int __kvm_vcpu_set_target(struct kvm_vcpu *vcpu, ...@@ -1236,20 +1242,18 @@ static int __kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
!bitmap_equal(kvm->arch.vcpu_features, &features, KVM_VCPU_MAX_FEATURES)) !bitmap_equal(kvm->arch.vcpu_features, &features, KVM_VCPU_MAX_FEATURES))
goto out_unlock; goto out_unlock;
vcpu->arch.target = init->target;
bitmap_copy(vcpu->arch.features, &features, KVM_VCPU_MAX_FEATURES); bitmap_copy(vcpu->arch.features, &features, KVM_VCPU_MAX_FEATURES);
/* Now we know what it is, we can reset it. */ /* Now we know what it is, we can reset it. */
ret = kvm_reset_vcpu(vcpu); ret = kvm_reset_vcpu(vcpu);
if (ret) { if (ret) {
vcpu->arch.target = -1;
bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES); bitmap_zero(vcpu->arch.features, KVM_VCPU_MAX_FEATURES);
goto out_unlock; goto out_unlock;
} }
bitmap_copy(kvm->arch.vcpu_features, &features, KVM_VCPU_MAX_FEATURES); bitmap_copy(kvm->arch.vcpu_features, &features, KVM_VCPU_MAX_FEATURES);
set_bit(KVM_ARCH_FLAG_VCPU_FEATURES_CONFIGURED, &kvm->arch.flags); set_bit(KVM_ARCH_FLAG_VCPU_FEATURES_CONFIGURED, &kvm->arch.flags);
vcpu_set_flag(vcpu, VCPU_INITIALIZED);
out_unlock: out_unlock:
mutex_unlock(&kvm->arch.config_lock); mutex_unlock(&kvm->arch.config_lock);
return ret; return ret;
...@@ -1260,14 +1264,15 @@ static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu, ...@@ -1260,14 +1264,15 @@ static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
{ {
int ret; int ret;
if (init->target != kvm_target_cpu()) if (init->target != KVM_ARM_TARGET_GENERIC_V8 &&
init->target != kvm_target_cpu())
return -EINVAL; return -EINVAL;
ret = kvm_vcpu_init_check_features(vcpu, init); ret = kvm_vcpu_init_check_features(vcpu, init);
if (ret) if (ret)
return ret; return ret;
if (vcpu->arch.target == -1) if (!kvm_vcpu_initialized(vcpu))
return __kvm_vcpu_set_target(vcpu, init); return __kvm_vcpu_set_target(vcpu, init);
if (kvm_vcpu_init_changed(vcpu, init)) if (kvm_vcpu_init_changed(vcpu, init))
...@@ -1532,12 +1537,6 @@ void kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot) ...@@ -1532,12 +1537,6 @@ void kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
} }
void kvm_arch_flush_remote_tlbs_memslot(struct kvm *kvm,
const struct kvm_memory_slot *memslot)
{
kvm_flush_remote_tlbs(kvm);
}
static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm, static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm,
struct kvm_arm_device_addr *dev_addr) struct kvm_arm_device_addr *dev_addr)
{ {
...@@ -1595,9 +1594,9 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) ...@@ -1595,9 +1594,9 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
return kvm_vm_ioctl_set_device_addr(kvm, &dev_addr); return kvm_vm_ioctl_set_device_addr(kvm, &dev_addr);
} }
case KVM_ARM_PREFERRED_TARGET: { case KVM_ARM_PREFERRED_TARGET: {
struct kvm_vcpu_init init; struct kvm_vcpu_init init = {
.target = KVM_ARM_TARGET_GENERIC_V8,
kvm_vcpu_preferred_target(&init); };
if (copy_to_user(argp, &init, sizeof(init))) if (copy_to_user(argp, &init, sizeof(init)))
return -EFAULT; return -EFAULT;
...@@ -2276,30 +2275,8 @@ static int __init init_hyp_mode(void) ...@@ -2276,30 +2275,8 @@ static int __init init_hyp_mode(void)
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
struct kvm_nvhe_init_params *params = per_cpu_ptr_nvhe_sym(kvm_init_params, cpu); struct kvm_nvhe_init_params *params = per_cpu_ptr_nvhe_sym(kvm_init_params, cpu);
char *stack_page = (char *)per_cpu(kvm_arm_hyp_stack_page, cpu); char *stack_page = (char *)per_cpu(kvm_arm_hyp_stack_page, cpu);
unsigned long hyp_addr;
/* err = create_hyp_stack(__pa(stack_page), &params->stack_hyp_va);
* Allocate a contiguous HYP private VA range for the stack
* and guard page. The allocation is also aligned based on
* the order of its size.
*/
err = hyp_alloc_private_va_range(PAGE_SIZE * 2, &hyp_addr);
if (err) {
kvm_err("Cannot allocate hyp stack guard page\n");
goto out_err;
}
/*
* Since the stack grows downwards, map the stack to the page
* at the higher address and leave the lower guard page
* unbacked.
*
* Any valid stack address now has the PAGE_SHIFT bit as 1
* and addresses corresponding to the guard page have the
* PAGE_SHIFT bit as 0 - this is used for overflow detection.
*/
err = __create_hyp_mappings(hyp_addr + PAGE_SIZE, PAGE_SIZE,
__pa(stack_page), PAGE_HYP);
if (err) { if (err) {
kvm_err("Cannot map hyp stack\n"); kvm_err("Cannot map hyp stack\n");
goto out_err; goto out_err;
...@@ -2312,8 +2289,6 @@ static int __init init_hyp_mode(void) ...@@ -2312,8 +2289,6 @@ static int __init init_hyp_mode(void)
* has been mapped in the flexible private VA space. * has been mapped in the flexible private VA space.
*/ */
params->stack_pa = __pa(stack_page); params->stack_pa = __pa(stack_page);
params->stack_hyp_va = hyp_addr + (2 * PAGE_SIZE);
} }
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
......
This diff is collapsed.
...@@ -884,21 +884,6 @@ u32 __attribute_const__ kvm_target_cpu(void) ...@@ -884,21 +884,6 @@ u32 __attribute_const__ kvm_target_cpu(void)
return KVM_ARM_TARGET_GENERIC_V8; return KVM_ARM_TARGET_GENERIC_V8;
} }
void kvm_vcpu_preferred_target(struct kvm_vcpu_init *init)
{
u32 target = kvm_target_cpu();
memset(init, 0, sizeof(*init));
/*
* For now, we don't return any features.
* In future, we might use features to return target
* specific features available for the preferred
* target type.
*/
init->target = (__u32)target;
}
int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
{ {
return -EINVAL; return -EINVAL;
......
...@@ -222,7 +222,33 @@ static int kvm_handle_eret(struct kvm_vcpu *vcpu) ...@@ -222,7 +222,33 @@ static int kvm_handle_eret(struct kvm_vcpu *vcpu)
if (kvm_vcpu_get_esr(vcpu) & ESR_ELx_ERET_ISS_ERET) if (kvm_vcpu_get_esr(vcpu) & ESR_ELx_ERET_ISS_ERET)
return kvm_handle_ptrauth(vcpu); return kvm_handle_ptrauth(vcpu);
kvm_emulate_nested_eret(vcpu); /*
* If we got here, two possibilities:
*
* - the guest is in EL2, and we need to fully emulate ERET
*
* - the guest is in EL1, and we need to reinject the
* exception into the L1 hypervisor.
*
* If KVM ever traps ERET for its own use, we'll have to
* revisit this.
*/
if (is_hyp_ctxt(vcpu))
kvm_emulate_nested_eret(vcpu);
else
kvm_inject_nested_sync(vcpu, kvm_vcpu_get_esr(vcpu));
return 1;
}
static int handle_svc(struct kvm_vcpu *vcpu)
{
/*
* So far, SVC traps only for NV via HFGITR_EL2. A SVC from a
* 32bit guest would be caught by vpcu_mode_is_bad_32bit(), so
* we should only have to deal with a 64 bit exception.
*/
kvm_inject_nested_sync(vcpu, kvm_vcpu_get_esr(vcpu));
return 1; return 1;
} }
...@@ -239,6 +265,7 @@ static exit_handle_fn arm_exit_handlers[] = { ...@@ -239,6 +265,7 @@ static exit_handle_fn arm_exit_handlers[] = {
[ESR_ELx_EC_SMC32] = handle_smc, [ESR_ELx_EC_SMC32] = handle_smc,
[ESR_ELx_EC_HVC64] = handle_hvc, [ESR_ELx_EC_HVC64] = handle_hvc,
[ESR_ELx_EC_SMC64] = handle_smc, [ESR_ELx_EC_SMC64] = handle_smc,
[ESR_ELx_EC_SVC64] = handle_svc,
[ESR_ELx_EC_SYS64] = kvm_handle_sys_reg, [ESR_ELx_EC_SYS64] = kvm_handle_sys_reg,
[ESR_ELx_EC_SVE] = handle_sve, [ESR_ELx_EC_SVE] = handle_sve,
[ESR_ELx_EC_ERET] = kvm_handle_eret, [ESR_ELx_EC_ERET] = kvm_handle_eret,
......
...@@ -70,20 +70,26 @@ static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu) ...@@ -70,20 +70,26 @@ static inline void __activate_traps_fpsimd32(struct kvm_vcpu *vcpu)
} }
} }
static inline bool __hfgxtr_traps_required(void) #define compute_clr_set(vcpu, reg, clr, set) \
{ do { \
if (cpus_have_final_cap(ARM64_SME)) u64 hfg; \
return true; hfg = __vcpu_sys_reg(vcpu, reg) & ~__ ## reg ## _RES0; \
set |= hfg & __ ## reg ## _MASK; \
if (cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38)) clr |= ~hfg & __ ## reg ## _nMASK; \
return true; } while(0)
return false;
}
static inline void __activate_traps_hfgxtr(void) static inline void __activate_traps_hfgxtr(struct kvm_vcpu *vcpu)
{ {
struct kvm_cpu_context *hctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
u64 r_clr = 0, w_clr = 0, r_set = 0, w_set = 0, tmp; u64 r_clr = 0, w_clr = 0, r_set = 0, w_set = 0, tmp;
u64 r_val, w_val;
if (!cpus_have_final_cap(ARM64_HAS_FGT))
return;
ctxt_sys_reg(hctxt, HFGRTR_EL2) = read_sysreg_s(SYS_HFGRTR_EL2);
ctxt_sys_reg(hctxt, HFGWTR_EL2) = read_sysreg_s(SYS_HFGWTR_EL2);
if (cpus_have_final_cap(ARM64_SME)) { if (cpus_have_final_cap(ARM64_SME)) {
tmp = HFGxTR_EL2_nSMPRI_EL1_MASK | HFGxTR_EL2_nTPIDR2_EL0_MASK; tmp = HFGxTR_EL2_nSMPRI_EL1_MASK | HFGxTR_EL2_nTPIDR2_EL0_MASK;
...@@ -98,26 +104,72 @@ static inline void __activate_traps_hfgxtr(void) ...@@ -98,26 +104,72 @@ static inline void __activate_traps_hfgxtr(void)
if (cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38)) if (cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38))
w_set |= HFGxTR_EL2_TCR_EL1_MASK; w_set |= HFGxTR_EL2_TCR_EL1_MASK;
sysreg_clear_set_s(SYS_HFGRTR_EL2, r_clr, r_set); if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) {
sysreg_clear_set_s(SYS_HFGWTR_EL2, w_clr, w_set); compute_clr_set(vcpu, HFGRTR_EL2, r_clr, r_set);
compute_clr_set(vcpu, HFGWTR_EL2, w_clr, w_set);
}
/* The default is not to trap anything but ACCDATA_EL1 */
r_val = __HFGRTR_EL2_nMASK & ~HFGxTR_EL2_nACCDATA_EL1;
r_val |= r_set;
r_val &= ~r_clr;
w_val = __HFGWTR_EL2_nMASK & ~HFGxTR_EL2_nACCDATA_EL1;
w_val |= w_set;
w_val &= ~w_clr;
write_sysreg_s(r_val, SYS_HFGRTR_EL2);
write_sysreg_s(w_val, SYS_HFGWTR_EL2);
if (!vcpu_has_nv(vcpu) || is_hyp_ctxt(vcpu))
return;
ctxt_sys_reg(hctxt, HFGITR_EL2) = read_sysreg_s(SYS_HFGITR_EL2);
r_set = r_clr = 0;
compute_clr_set(vcpu, HFGITR_EL2, r_clr, r_set);
r_val = __HFGITR_EL2_nMASK;
r_val |= r_set;
r_val &= ~r_clr;
write_sysreg_s(r_val, SYS_HFGITR_EL2);
ctxt_sys_reg(hctxt, HDFGRTR_EL2) = read_sysreg_s(SYS_HDFGRTR_EL2);
ctxt_sys_reg(hctxt, HDFGWTR_EL2) = read_sysreg_s(SYS_HDFGWTR_EL2);
r_clr = r_set = w_clr = w_set = 0;
compute_clr_set(vcpu, HDFGRTR_EL2, r_clr, r_set);
compute_clr_set(vcpu, HDFGWTR_EL2, w_clr, w_set);
r_val = __HDFGRTR_EL2_nMASK;
r_val |= r_set;
r_val &= ~r_clr;
w_val = __HDFGWTR_EL2_nMASK;
w_val |= w_set;
w_val &= ~w_clr;
write_sysreg_s(r_val, SYS_HDFGRTR_EL2);
write_sysreg_s(w_val, SYS_HDFGWTR_EL2);
} }
static inline void __deactivate_traps_hfgxtr(void) static inline void __deactivate_traps_hfgxtr(struct kvm_vcpu *vcpu)
{ {
u64 r_clr = 0, w_clr = 0, r_set = 0, w_set = 0, tmp; struct kvm_cpu_context *hctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
if (cpus_have_final_cap(ARM64_SME)) { if (!cpus_have_final_cap(ARM64_HAS_FGT))
tmp = HFGxTR_EL2_nSMPRI_EL1_MASK | HFGxTR_EL2_nTPIDR2_EL0_MASK; return;
r_set |= tmp; write_sysreg_s(ctxt_sys_reg(hctxt, HFGRTR_EL2), SYS_HFGRTR_EL2);
w_set |= tmp; write_sysreg_s(ctxt_sys_reg(hctxt, HFGWTR_EL2), SYS_HFGWTR_EL2);
}
if (cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_38)) if (!vcpu_has_nv(vcpu) || is_hyp_ctxt(vcpu))
w_clr |= HFGxTR_EL2_TCR_EL1_MASK; return;
sysreg_clear_set_s(SYS_HFGRTR_EL2, r_clr, r_set); write_sysreg_s(ctxt_sys_reg(hctxt, HFGITR_EL2), SYS_HFGITR_EL2);
sysreg_clear_set_s(SYS_HFGWTR_EL2, w_clr, w_set); write_sysreg_s(ctxt_sys_reg(hctxt, HDFGRTR_EL2), SYS_HDFGRTR_EL2);
write_sysreg_s(ctxt_sys_reg(hctxt, HDFGWTR_EL2), SYS_HDFGWTR_EL2);
} }
static inline void __activate_traps_common(struct kvm_vcpu *vcpu) static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
...@@ -145,8 +197,21 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu) ...@@ -145,8 +197,21 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
vcpu->arch.mdcr_el2_host = read_sysreg(mdcr_el2); vcpu->arch.mdcr_el2_host = read_sysreg(mdcr_el2);
write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2); write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
if (__hfgxtr_traps_required()) if (cpus_have_final_cap(ARM64_HAS_HCX)) {
__activate_traps_hfgxtr(); u64 hcrx = HCRX_GUEST_FLAGS;
if (vcpu_has_nv(vcpu) && !is_hyp_ctxt(vcpu)) {
u64 clr = 0, set = 0;
compute_clr_set(vcpu, HCRX_EL2, clr, set);
hcrx |= set;
hcrx &= ~clr;
}
write_sysreg_s(hcrx, SYS_HCRX_EL2);
}
__activate_traps_hfgxtr(vcpu);
} }
static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu) static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)
...@@ -162,8 +227,10 @@ static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu) ...@@ -162,8 +227,10 @@ static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)
vcpu_clear_flag(vcpu, PMUSERENR_ON_CPU); vcpu_clear_flag(vcpu, PMUSERENR_ON_CPU);
} }
if (__hfgxtr_traps_required()) if (cpus_have_final_cap(ARM64_HAS_HCX))
__deactivate_traps_hfgxtr(); write_sysreg_s(HCRX_HOST_FLAGS, SYS_HCRX_EL2);
__deactivate_traps_hfgxtr(vcpu);
} }
static inline void ___activate_traps(struct kvm_vcpu *vcpu) static inline void ___activate_traps(struct kvm_vcpu *vcpu)
...@@ -177,9 +244,6 @@ static inline void ___activate_traps(struct kvm_vcpu *vcpu) ...@@ -177,9 +244,6 @@ static inline void ___activate_traps(struct kvm_vcpu *vcpu)
if (cpus_have_final_cap(ARM64_HAS_RAS_EXTN) && (hcr & HCR_VSE)) if (cpus_have_final_cap(ARM64_HAS_RAS_EXTN) && (hcr & HCR_VSE))
write_sysreg_s(vcpu->arch.vsesr_el2, SYS_VSESR_EL2); write_sysreg_s(vcpu->arch.vsesr_el2, SYS_VSESR_EL2);
if (cpus_have_final_cap(ARM64_HAS_HCX))
write_sysreg_s(HCRX_GUEST_FLAGS, SYS_HCRX_EL2);
} }
static inline void ___deactivate_traps(struct kvm_vcpu *vcpu) static inline void ___deactivate_traps(struct kvm_vcpu *vcpu)
...@@ -194,9 +258,6 @@ static inline void ___deactivate_traps(struct kvm_vcpu *vcpu) ...@@ -194,9 +258,6 @@ static inline void ___deactivate_traps(struct kvm_vcpu *vcpu)
vcpu->arch.hcr_el2 &= ~HCR_VSE; vcpu->arch.hcr_el2 &= ~HCR_VSE;
vcpu->arch.hcr_el2 |= read_sysreg(hcr_el2) & HCR_VSE; vcpu->arch.hcr_el2 |= read_sysreg(hcr_el2) & HCR_VSE;
} }
if (cpus_have_final_cap(ARM64_HAS_HCX))
write_sysreg_s(HCRX_HOST_FLAGS, SYS_HCRX_EL2);
} }
static inline bool __populate_fault_info(struct kvm_vcpu *vcpu) static inline bool __populate_fault_info(struct kvm_vcpu *vcpu)
......
...@@ -26,6 +26,7 @@ int pkvm_create_mappings_locked(void *from, void *to, enum kvm_pgtable_prot prot ...@@ -26,6 +26,7 @@ int pkvm_create_mappings_locked(void *from, void *to, enum kvm_pgtable_prot prot
int __pkvm_create_private_mapping(phys_addr_t phys, size_t size, int __pkvm_create_private_mapping(phys_addr_t phys, size_t size,
enum kvm_pgtable_prot prot, enum kvm_pgtable_prot prot,
unsigned long *haddr); unsigned long *haddr);
int pkvm_create_stack(phys_addr_t phys, unsigned long *haddr);
int pkvm_alloc_private_va_range(size_t size, unsigned long *haddr); int pkvm_alloc_private_va_range(size_t size, unsigned long *haddr);
#endif /* __KVM_HYP_MM_H */ #endif /* __KVM_HYP_MM_H */
...@@ -135,6 +135,16 @@ static void handle___kvm_tlb_flush_vmid_ipa_nsh(struct kvm_cpu_context *host_ctx ...@@ -135,6 +135,16 @@ static void handle___kvm_tlb_flush_vmid_ipa_nsh(struct kvm_cpu_context *host_ctx
__kvm_tlb_flush_vmid_ipa_nsh(kern_hyp_va(mmu), ipa, level); __kvm_tlb_flush_vmid_ipa_nsh(kern_hyp_va(mmu), ipa, level);
} }
static void
handle___kvm_tlb_flush_vmid_range(struct kvm_cpu_context *host_ctxt)
{
DECLARE_REG(struct kvm_s2_mmu *, mmu, host_ctxt, 1);
DECLARE_REG(phys_addr_t, start, host_ctxt, 2);
DECLARE_REG(unsigned long, pages, host_ctxt, 3);
__kvm_tlb_flush_vmid_range(kern_hyp_va(mmu), start, pages);
}
static void handle___kvm_tlb_flush_vmid(struct kvm_cpu_context *host_ctxt) static void handle___kvm_tlb_flush_vmid(struct kvm_cpu_context *host_ctxt)
{ {
DECLARE_REG(struct kvm_s2_mmu *, mmu, host_ctxt, 1); DECLARE_REG(struct kvm_s2_mmu *, mmu, host_ctxt, 1);
...@@ -327,6 +337,7 @@ static const hcall_t host_hcall[] = { ...@@ -327,6 +337,7 @@ static const hcall_t host_hcall[] = {
HANDLE_FUNC(__kvm_tlb_flush_vmid_ipa), HANDLE_FUNC(__kvm_tlb_flush_vmid_ipa),
HANDLE_FUNC(__kvm_tlb_flush_vmid_ipa_nsh), HANDLE_FUNC(__kvm_tlb_flush_vmid_ipa_nsh),
HANDLE_FUNC(__kvm_tlb_flush_vmid), HANDLE_FUNC(__kvm_tlb_flush_vmid),
HANDLE_FUNC(__kvm_tlb_flush_vmid_range),
HANDLE_FUNC(__kvm_flush_cpu_context), HANDLE_FUNC(__kvm_flush_cpu_context),
HANDLE_FUNC(__kvm_timer_set_cntvoff), HANDLE_FUNC(__kvm_timer_set_cntvoff),
HANDLE_FUNC(__vgic_v3_read_vmcr), HANDLE_FUNC(__vgic_v3_read_vmcr),
......
...@@ -44,6 +44,27 @@ static int __pkvm_create_mappings(unsigned long start, unsigned long size, ...@@ -44,6 +44,27 @@ static int __pkvm_create_mappings(unsigned long start, unsigned long size,
return err; return err;
} }
static int __pkvm_alloc_private_va_range(unsigned long start, size_t size)
{
unsigned long cur;
hyp_assert_lock_held(&pkvm_pgd_lock);
if (!start || start < __io_map_base)
return -EINVAL;
/* The allocated size is always a multiple of PAGE_SIZE */
cur = start + PAGE_ALIGN(size);
/* Are we overflowing on the vmemmap ? */
if (cur > __hyp_vmemmap)
return -ENOMEM;
__io_map_base = cur;
return 0;
}
/** /**
* pkvm_alloc_private_va_range - Allocates a private VA range. * pkvm_alloc_private_va_range - Allocates a private VA range.
* @size: The size of the VA range to reserve. * @size: The size of the VA range to reserve.
...@@ -56,27 +77,16 @@ static int __pkvm_create_mappings(unsigned long start, unsigned long size, ...@@ -56,27 +77,16 @@ static int __pkvm_create_mappings(unsigned long start, unsigned long size,
*/ */
int pkvm_alloc_private_va_range(size_t size, unsigned long *haddr) int pkvm_alloc_private_va_range(size_t size, unsigned long *haddr)
{ {
unsigned long base, addr; unsigned long addr;
int ret = 0; int ret;
hyp_spin_lock(&pkvm_pgd_lock); hyp_spin_lock(&pkvm_pgd_lock);
addr = __io_map_base;
/* Align the allocation based on the order of its size */ ret = __pkvm_alloc_private_va_range(addr, size);
addr = ALIGN(__io_map_base, PAGE_SIZE << get_order(size));
/* The allocated size is always a multiple of PAGE_SIZE */
base = addr + PAGE_ALIGN(size);
/* Are we overflowing on the vmemmap ? */
if (!addr || base > __hyp_vmemmap)
ret = -ENOMEM;
else {
__io_map_base = base;
*haddr = addr;
}
hyp_spin_unlock(&pkvm_pgd_lock); hyp_spin_unlock(&pkvm_pgd_lock);
*haddr = addr;
return ret; return ret;
} }
...@@ -340,6 +350,45 @@ int hyp_create_idmap(u32 hyp_va_bits) ...@@ -340,6 +350,45 @@ int hyp_create_idmap(u32 hyp_va_bits)
return __pkvm_create_mappings(start, end - start, start, PAGE_HYP_EXEC); return __pkvm_create_mappings(start, end - start, start, PAGE_HYP_EXEC);
} }
int pkvm_create_stack(phys_addr_t phys, unsigned long *haddr)
{
unsigned long addr, prev_base;
size_t size;
int ret;
hyp_spin_lock(&pkvm_pgd_lock);
prev_base = __io_map_base;
/*
* Efficient stack verification using the PAGE_SHIFT bit implies
* an alignment of our allocation on the order of the size.
*/
size = PAGE_SIZE * 2;
addr = ALIGN(__io_map_base, size);
ret = __pkvm_alloc_private_va_range(addr, size);
if (!ret) {
/*
* Since the stack grows downwards, map the stack to the page
* at the higher address and leave the lower guard page
* unbacked.
*
* Any valid stack address now has the PAGE_SHIFT bit as 1
* and addresses corresponding to the guard page have the
* PAGE_SHIFT bit as 0 - this is used for overflow detection.
*/
ret = kvm_pgtable_hyp_map(&pkvm_pgtable, addr + PAGE_SIZE,
PAGE_SIZE, phys, PAGE_HYP);
if (ret)
__io_map_base = prev_base;
}
hyp_spin_unlock(&pkvm_pgd_lock);
*haddr = addr + size;
return ret;
}
static void *admit_host_page(void *arg) static void *admit_host_page(void *arg)
{ {
struct kvm_hyp_memcache *host_mc = arg; struct kvm_hyp_memcache *host_mc = arg;
......
...@@ -113,7 +113,6 @@ static int recreate_hyp_mappings(phys_addr_t phys, unsigned long size, ...@@ -113,7 +113,6 @@ static int recreate_hyp_mappings(phys_addr_t phys, unsigned long size,
for (i = 0; i < hyp_nr_cpus; i++) { for (i = 0; i < hyp_nr_cpus; i++) {
struct kvm_nvhe_init_params *params = per_cpu_ptr(&kvm_init_params, i); struct kvm_nvhe_init_params *params = per_cpu_ptr(&kvm_init_params, i);
unsigned long hyp_addr;
start = (void *)kern_hyp_va(per_cpu_base[i]); start = (void *)kern_hyp_va(per_cpu_base[i]);
end = start + PAGE_ALIGN(hyp_percpu_size); end = start + PAGE_ALIGN(hyp_percpu_size);
...@@ -121,33 +120,9 @@ static int recreate_hyp_mappings(phys_addr_t phys, unsigned long size, ...@@ -121,33 +120,9 @@ static int recreate_hyp_mappings(phys_addr_t phys, unsigned long size,
if (ret) if (ret)
return ret; return ret;
/* ret = pkvm_create_stack(params->stack_pa, &params->stack_hyp_va);
* Allocate a contiguous HYP private VA range for the stack
* and guard page. The allocation is also aligned based on
* the order of its size.
*/
ret = pkvm_alloc_private_va_range(PAGE_SIZE * 2, &hyp_addr);
if (ret) if (ret)
return ret; return ret;
/*
* Since the stack grows downwards, map the stack to the page
* at the higher address and leave the lower guard page
* unbacked.
*
* Any valid stack address now has the PAGE_SHIFT bit as 1
* and addresses corresponding to the guard page have the
* PAGE_SHIFT bit as 0 - this is used for overflow detection.
*/
hyp_spin_lock(&pkvm_pgd_lock);
ret = kvm_pgtable_hyp_map(&pkvm_pgtable, hyp_addr + PAGE_SIZE,
PAGE_SIZE, params->stack_pa, PAGE_HYP);
hyp_spin_unlock(&pkvm_pgd_lock);
if (ret)
return ret;
/* Update stack_hyp_va to end of the stack's private VA range */
params->stack_hyp_va = hyp_addr + (2 * PAGE_SIZE);
} }
/* /*
......
...@@ -236,7 +236,7 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code) ...@@ -236,7 +236,7 @@ static void early_exit_filter(struct kvm_vcpu *vcpu, u64 *exit_code)
* KVM_ARM_VCPU_INIT, however, this is likely not possible for * KVM_ARM_VCPU_INIT, however, this is likely not possible for
* protected VMs. * protected VMs.
*/ */
vcpu->arch.target = -1; vcpu_clear_flag(vcpu, VCPU_INITIALIZED);
*exit_code &= BIT(ARM_EXIT_WITH_SERROR_BIT); *exit_code &= BIT(ARM_EXIT_WITH_SERROR_BIT);
*exit_code |= ARM_EXCEPTION_IL; *exit_code |= ARM_EXCEPTION_IL;
} }
......
...@@ -182,6 +182,36 @@ void __kvm_tlb_flush_vmid_ipa_nsh(struct kvm_s2_mmu *mmu, ...@@ -182,6 +182,36 @@ void __kvm_tlb_flush_vmid_ipa_nsh(struct kvm_s2_mmu *mmu,
__tlb_switch_to_host(&cxt); __tlb_switch_to_host(&cxt);
} }
void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
phys_addr_t start, unsigned long pages)
{
struct tlb_inv_context cxt;
unsigned long stride;
/*
* Since the range of addresses may not be mapped at
* the same level, assume the worst case as PAGE_SIZE
*/
stride = PAGE_SIZE;
start = round_down(start, stride);
/* Switch to requested VMID */
__tlb_switch_to_guest(mmu, &cxt, false);
__flush_s2_tlb_range_op(ipas2e1is, start, pages, stride, 0);
dsb(ish);
__tlbi(vmalle1is);
dsb(ish);
isb();
/* See the comment in __kvm_tlb_flush_vmid_ipa() */
if (icache_is_vpipt())
icache_inval_all_pou();
__tlb_switch_to_host(&cxt);
}
void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu) void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu)
{ {
struct tlb_inv_context cxt; struct tlb_inv_context cxt;
......
...@@ -670,6 +670,26 @@ static bool stage2_has_fwb(struct kvm_pgtable *pgt) ...@@ -670,6 +670,26 @@ static bool stage2_has_fwb(struct kvm_pgtable *pgt)
return !(pgt->flags & KVM_PGTABLE_S2_NOFWB); return !(pgt->flags & KVM_PGTABLE_S2_NOFWB);
} }
void kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
phys_addr_t addr, size_t size)
{
unsigned long pages, inval_pages;
if (!system_supports_tlb_range()) {
kvm_call_hyp(__kvm_tlb_flush_vmid, mmu);
return;
}
pages = size >> PAGE_SHIFT;
while (pages > 0) {
inval_pages = min(pages, MAX_TLBI_RANGE_PAGES);
kvm_call_hyp(__kvm_tlb_flush_vmid_range, mmu, addr, inval_pages);
addr += inval_pages << PAGE_SHIFT;
pages -= inval_pages;
}
}
#define KVM_S2_MEMATTR(pgt, attr) PAGE_S2_MEMATTR(attr, stage2_has_fwb(pgt)) #define KVM_S2_MEMATTR(pgt, attr) PAGE_S2_MEMATTR(attr, stage2_has_fwb(pgt))
static int stage2_set_prot_attr(struct kvm_pgtable *pgt, enum kvm_pgtable_prot prot, static int stage2_set_prot_attr(struct kvm_pgtable *pgt, enum kvm_pgtable_prot prot,
...@@ -786,7 +806,8 @@ static bool stage2_try_break_pte(const struct kvm_pgtable_visit_ctx *ctx, ...@@ -786,7 +806,8 @@ static bool stage2_try_break_pte(const struct kvm_pgtable_visit_ctx *ctx,
* evicted pte value (if any). * evicted pte value (if any).
*/ */
if (kvm_pte_table(ctx->old, ctx->level)) if (kvm_pte_table(ctx->old, ctx->level))
kvm_call_hyp(__kvm_tlb_flush_vmid, mmu); kvm_tlb_flush_vmid_range(mmu, ctx->addr,
kvm_granule_size(ctx->level));
else if (kvm_pte_valid(ctx->old)) else if (kvm_pte_valid(ctx->old))
kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu,
ctx->addr, ctx->level); ctx->addr, ctx->level);
...@@ -810,16 +831,36 @@ static void stage2_make_pte(const struct kvm_pgtable_visit_ctx *ctx, kvm_pte_t n ...@@ -810,16 +831,36 @@ static void stage2_make_pte(const struct kvm_pgtable_visit_ctx *ctx, kvm_pte_t n
smp_store_release(ctx->ptep, new); smp_store_release(ctx->ptep, new);
} }
static void stage2_put_pte(const struct kvm_pgtable_visit_ctx *ctx, struct kvm_s2_mmu *mmu, static bool stage2_unmap_defer_tlb_flush(struct kvm_pgtable *pgt)
struct kvm_pgtable_mm_ops *mm_ops) {
/*
* If FEAT_TLBIRANGE is implemented, defer the individual
* TLB invalidations until the entire walk is finished, and
* then use the range-based TLBI instructions to do the
* invalidations. Condition deferred TLB invalidation on the
* system supporting FWB as the optimization is entirely
* pointless when the unmap walker needs to perform CMOs.
*/
return system_supports_tlb_range() && stage2_has_fwb(pgt);
}
static void stage2_unmap_put_pte(const struct kvm_pgtable_visit_ctx *ctx,
struct kvm_s2_mmu *mmu,
struct kvm_pgtable_mm_ops *mm_ops)
{ {
struct kvm_pgtable *pgt = ctx->arg;
/* /*
* Clear the existing PTE, and perform break-before-make with * Clear the existing PTE, and perform break-before-make if it was
* TLB maintenance if it was valid. * valid. Depending on the system support, defer the TLB maintenance
* for the same until the entire unmap walk is completed.
*/ */
if (kvm_pte_valid(ctx->old)) { if (kvm_pte_valid(ctx->old)) {
kvm_clear_pte(ctx->ptep); kvm_clear_pte(ctx->ptep);
kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu, ctx->addr, ctx->level);
if (!stage2_unmap_defer_tlb_flush(pgt))
kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu,
ctx->addr, ctx->level);
} }
mm_ops->put_page(ctx->ptep); mm_ops->put_page(ctx->ptep);
...@@ -1077,7 +1118,7 @@ static int stage2_unmap_walker(const struct kvm_pgtable_visit_ctx *ctx, ...@@ -1077,7 +1118,7 @@ static int stage2_unmap_walker(const struct kvm_pgtable_visit_ctx *ctx,
* block entry and rely on the remaining portions being faulted * block entry and rely on the remaining portions being faulted
* back lazily. * back lazily.
*/ */
stage2_put_pte(ctx, mmu, mm_ops); stage2_unmap_put_pte(ctx, mmu, mm_ops);
if (need_flush && mm_ops->dcache_clean_inval_poc) if (need_flush && mm_ops->dcache_clean_inval_poc)
mm_ops->dcache_clean_inval_poc(kvm_pte_follow(ctx->old, mm_ops), mm_ops->dcache_clean_inval_poc(kvm_pte_follow(ctx->old, mm_ops),
...@@ -1091,13 +1132,19 @@ static int stage2_unmap_walker(const struct kvm_pgtable_visit_ctx *ctx, ...@@ -1091,13 +1132,19 @@ static int stage2_unmap_walker(const struct kvm_pgtable_visit_ctx *ctx,
int kvm_pgtable_stage2_unmap(struct kvm_pgtable *pgt, u64 addr, u64 size) int kvm_pgtable_stage2_unmap(struct kvm_pgtable *pgt, u64 addr, u64 size)
{ {
int ret;
struct kvm_pgtable_walker walker = { struct kvm_pgtable_walker walker = {
.cb = stage2_unmap_walker, .cb = stage2_unmap_walker,
.arg = pgt, .arg = pgt,
.flags = KVM_PGTABLE_WALK_LEAF | KVM_PGTABLE_WALK_TABLE_POST, .flags = KVM_PGTABLE_WALK_LEAF | KVM_PGTABLE_WALK_TABLE_POST,
}; };
return kvm_pgtable_walk(pgt, addr, size, &walker); ret = kvm_pgtable_walk(pgt, addr, size, &walker);
if (stage2_unmap_defer_tlb_flush(pgt))
/* Perform the deferred TLB invalidations */
kvm_tlb_flush_vmid_range(pgt->mmu, addr, size);
return ret;
} }
struct stage2_attr_data { struct stage2_attr_data {
......
...@@ -143,6 +143,34 @@ void __kvm_tlb_flush_vmid_ipa_nsh(struct kvm_s2_mmu *mmu, ...@@ -143,6 +143,34 @@ void __kvm_tlb_flush_vmid_ipa_nsh(struct kvm_s2_mmu *mmu,
__tlb_switch_to_host(&cxt); __tlb_switch_to_host(&cxt);
} }
void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
phys_addr_t start, unsigned long pages)
{
struct tlb_inv_context cxt;
unsigned long stride;
/*
* Since the range of addresses may not be mapped at
* the same level, assume the worst case as PAGE_SIZE
*/
stride = PAGE_SIZE;
start = round_down(start, stride);
dsb(ishst);
/* Switch to requested VMID */
__tlb_switch_to_guest(mmu, &cxt);
__flush_s2_tlb_range_op(ipas2e1is, start, pages, stride, 0);
dsb(ish);
__tlbi(vmalle1is);
dsb(ish);
isb();
__tlb_switch_to_host(&cxt);
}
void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu) void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu)
{ {
struct tlb_inv_context cxt; struct tlb_inv_context cxt;
......
...@@ -161,15 +161,23 @@ static bool memslot_is_logging(struct kvm_memory_slot *memslot) ...@@ -161,15 +161,23 @@ static bool memslot_is_logging(struct kvm_memory_slot *memslot)
} }
/** /**
* kvm_flush_remote_tlbs() - flush all VM TLB entries for v7/8 * kvm_arch_flush_remote_tlbs() - flush all VM TLB entries for v7/8
* @kvm: pointer to kvm structure. * @kvm: pointer to kvm structure.
* *
* Interface to HYP function to flush all VM TLB entries * Interface to HYP function to flush all VM TLB entries
*/ */
void kvm_flush_remote_tlbs(struct kvm *kvm) int kvm_arch_flush_remote_tlbs(struct kvm *kvm)
{ {
++kvm->stat.generic.remote_tlb_flush_requests;
kvm_call_hyp(__kvm_tlb_flush_vmid, &kvm->arch.mmu); kvm_call_hyp(__kvm_tlb_flush_vmid, &kvm->arch.mmu);
return 0;
}
int kvm_arch_flush_remote_tlbs_range(struct kvm *kvm,
gfn_t gfn, u64 nr_pages)
{
kvm_tlb_flush_vmid_range(&kvm->arch.mmu,
gfn << PAGE_SHIFT, nr_pages << PAGE_SHIFT);
return 0;
} }
static bool kvm_is_device_pfn(unsigned long pfn) static bool kvm_is_device_pfn(unsigned long pfn)
...@@ -592,6 +600,25 @@ int create_hyp_mappings(void *from, void *to, enum kvm_pgtable_prot prot) ...@@ -592,6 +600,25 @@ int create_hyp_mappings(void *from, void *to, enum kvm_pgtable_prot prot)
return 0; return 0;
} }
static int __hyp_alloc_private_va_range(unsigned long base)
{
lockdep_assert_held(&kvm_hyp_pgd_mutex);
if (!PAGE_ALIGNED(base))
return -EINVAL;
/*
* Verify that BIT(VA_BITS - 1) hasn't been flipped by
* allocating the new area, as it would indicate we've
* overflowed the idmap/IO address range.
*/
if ((base ^ io_map_base) & BIT(VA_BITS - 1))
return -ENOMEM;
io_map_base = base;
return 0;
}
/** /**
* hyp_alloc_private_va_range - Allocates a private VA range. * hyp_alloc_private_va_range - Allocates a private VA range.
...@@ -612,26 +639,16 @@ int hyp_alloc_private_va_range(size_t size, unsigned long *haddr) ...@@ -612,26 +639,16 @@ int hyp_alloc_private_va_range(size_t size, unsigned long *haddr)
/* /*
* This assumes that we have enough space below the idmap * This assumes that we have enough space below the idmap
* page to allocate our VAs. If not, the check below will * page to allocate our VAs. If not, the check in
* kick. A potential alternative would be to detect that * __hyp_alloc_private_va_range() will kick. A potential
* overflow and switch to an allocation above the idmap. * alternative would be to detect that overflow and switch
* to an allocation above the idmap.
* *
* The allocated size is always a multiple of PAGE_SIZE. * The allocated size is always a multiple of PAGE_SIZE.
*/ */
base = io_map_base - PAGE_ALIGN(size); size = PAGE_ALIGN(size);
base = io_map_base - size;
/* Align the allocation based on the order of its size */ ret = __hyp_alloc_private_va_range(base);
base = ALIGN_DOWN(base, PAGE_SIZE << get_order(size));
/*
* Verify that BIT(VA_BITS - 1) hasn't been flipped by
* allocating the new area, as it would indicate we've
* overflowed the idmap/IO address range.
*/
if ((base ^ io_map_base) & BIT(VA_BITS - 1))
ret = -ENOMEM;
else
*haddr = io_map_base = base;
mutex_unlock(&kvm_hyp_pgd_mutex); mutex_unlock(&kvm_hyp_pgd_mutex);
...@@ -668,6 +685,48 @@ static int __create_hyp_private_mapping(phys_addr_t phys_addr, size_t size, ...@@ -668,6 +685,48 @@ static int __create_hyp_private_mapping(phys_addr_t phys_addr, size_t size,
return ret; return ret;
} }
int create_hyp_stack(phys_addr_t phys_addr, unsigned long *haddr)
{
unsigned long base;
size_t size;
int ret;
mutex_lock(&kvm_hyp_pgd_mutex);
/*
* Efficient stack verification using the PAGE_SHIFT bit implies
* an alignment of our allocation on the order of the size.
*/
size = PAGE_SIZE * 2;
base = ALIGN_DOWN(io_map_base - size, size);
ret = __hyp_alloc_private_va_range(base);
mutex_unlock(&kvm_hyp_pgd_mutex);
if (ret) {
kvm_err("Cannot allocate hyp stack guard page\n");
return ret;
}
/*
* Since the stack grows downwards, map the stack to the page
* at the higher address and leave the lower guard page
* unbacked.
*
* Any valid stack address now has the PAGE_SHIFT bit as 1
* and addresses corresponding to the guard page have the
* PAGE_SHIFT bit as 0 - this is used for overflow detection.
*/
ret = __create_hyp_mappings(base + PAGE_SIZE, PAGE_SIZE, phys_addr,
PAGE_HYP);
if (ret)
kvm_err("Cannot map hyp stack\n");
*haddr = base + size;
return ret;
}
/** /**
* create_hyp_io_mappings - Map IO into both kernel and HYP * create_hyp_io_mappings - Map IO into both kernel and HYP
* @phys_addr: The physical start address which gets mapped * @phys_addr: The physical start address which gets mapped
...@@ -1075,7 +1134,7 @@ static void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot) ...@@ -1075,7 +1134,7 @@ static void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot)
write_lock(&kvm->mmu_lock); write_lock(&kvm->mmu_lock);
stage2_wp_range(&kvm->arch.mmu, start, end); stage2_wp_range(&kvm->arch.mmu, start, end);
write_unlock(&kvm->mmu_lock); write_unlock(&kvm->mmu_lock);
kvm_flush_remote_tlbs(kvm); kvm_flush_remote_tlbs_memslot(kvm, memslot);
} }
/** /**
...@@ -1541,7 +1600,6 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, ...@@ -1541,7 +1600,6 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
out_unlock: out_unlock:
read_unlock(&kvm->mmu_lock); read_unlock(&kvm->mmu_lock);
kvm_set_pfn_accessed(pfn);
kvm_release_pfn_clean(pfn); kvm_release_pfn_clean(pfn);
return ret != -EAGAIN ? ret : 0; return ret != -EAGAIN ? ret : 0;
} }
...@@ -1721,7 +1779,7 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range) ...@@ -1721,7 +1779,7 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range) bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
{ {
kvm_pfn_t pfn = pte_pfn(range->pte); kvm_pfn_t pfn = pte_pfn(range->arg.pte);
if (!kvm->arch.mmu.pgt) if (!kvm->arch.mmu.pgt)
return false; return false;
......
...@@ -71,8 +71,9 @@ void access_nested_id_reg(struct kvm_vcpu *v, struct sys_reg_params *p, ...@@ -71,8 +71,9 @@ void access_nested_id_reg(struct kvm_vcpu *v, struct sys_reg_params *p,
break; break;
case SYS_ID_AA64MMFR0_EL1: case SYS_ID_AA64MMFR0_EL1:
/* Hide ECV, FGT, ExS, Secure Memory */ /* Hide ECV, ExS, Secure Memory */
val &= ~(GENMASK_ULL(63, 43) | val &= ~(NV_FTR(MMFR0, ECV) |
NV_FTR(MMFR0, EXS) |
NV_FTR(MMFR0, TGRAN4_2) | NV_FTR(MMFR0, TGRAN4_2) |
NV_FTR(MMFR0, TGRAN16_2) | NV_FTR(MMFR0, TGRAN16_2) |
NV_FTR(MMFR0, TGRAN64_2) | NV_FTR(MMFR0, TGRAN64_2) |
...@@ -116,7 +117,8 @@ void access_nested_id_reg(struct kvm_vcpu *v, struct sys_reg_params *p, ...@@ -116,7 +117,8 @@ void access_nested_id_reg(struct kvm_vcpu *v, struct sys_reg_params *p,
break; break;
case SYS_ID_AA64MMFR1_EL1: case SYS_ID_AA64MMFR1_EL1:
val &= (NV_FTR(MMFR1, PAN) | val &= (NV_FTR(MMFR1, HCX) |
NV_FTR(MMFR1, PAN) |
NV_FTR(MMFR1, LO) | NV_FTR(MMFR1, LO) |
NV_FTR(MMFR1, HPDS) | NV_FTR(MMFR1, HPDS) |
NV_FTR(MMFR1, VH) | NV_FTR(MMFR1, VH) |
...@@ -124,8 +126,7 @@ void access_nested_id_reg(struct kvm_vcpu *v, struct sys_reg_params *p, ...@@ -124,8 +126,7 @@ void access_nested_id_reg(struct kvm_vcpu *v, struct sys_reg_params *p,
break; break;
case SYS_ID_AA64MMFR2_EL1: case SYS_ID_AA64MMFR2_EL1:
val &= ~(NV_FTR(MMFR2, EVT) | val &= ~(NV_FTR(MMFR2, BBM) |
NV_FTR(MMFR2, BBM) |
NV_FTR(MMFR2, TTL) | NV_FTR(MMFR2, TTL) |
GENMASK_ULL(47, 44) | GENMASK_ULL(47, 44) |
NV_FTR(MMFR2, ST) | NV_FTR(MMFR2, ST) |
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <asm/kvm_emulate.h> #include <asm/kvm_emulate.h>
#include <kvm/arm_pmu.h> #include <kvm/arm_pmu.h>
#include <kvm/arm_vgic.h> #include <kvm/arm_vgic.h>
#include <asm/arm_pmuv3.h>
#define PERF_ATTR_CFG1_COUNTER_64BIT BIT(0) #define PERF_ATTR_CFG1_COUNTER_64BIT BIT(0)
...@@ -35,12 +36,8 @@ static struct kvm_pmc *kvm_vcpu_idx_to_pmc(struct kvm_vcpu *vcpu, int cnt_idx) ...@@ -35,12 +36,8 @@ static struct kvm_pmc *kvm_vcpu_idx_to_pmc(struct kvm_vcpu *vcpu, int cnt_idx)
return &vcpu->arch.pmu.pmc[cnt_idx]; return &vcpu->arch.pmu.pmc[cnt_idx];
} }
static u32 kvm_pmu_event_mask(struct kvm *kvm) static u32 __kvm_pmu_event_mask(unsigned int pmuver)
{ {
unsigned int pmuver;
pmuver = kvm->arch.arm_pmu->pmuver;
switch (pmuver) { switch (pmuver) {
case ID_AA64DFR0_EL1_PMUVer_IMP: case ID_AA64DFR0_EL1_PMUVer_IMP:
return GENMASK(9, 0); return GENMASK(9, 0);
...@@ -55,6 +52,14 @@ static u32 kvm_pmu_event_mask(struct kvm *kvm) ...@@ -55,6 +52,14 @@ static u32 kvm_pmu_event_mask(struct kvm *kvm)
} }
} }
static u32 kvm_pmu_event_mask(struct kvm *kvm)
{
u64 dfr0 = IDREG(kvm, SYS_ID_AA64DFR0_EL1);
u8 pmuver = SYS_FIELD_GET(ID_AA64DFR0_EL1, PMUVer, dfr0);
return __kvm_pmu_event_mask(pmuver);
}
/** /**
* kvm_pmc_is_64bit - determine if counter is 64bit * kvm_pmc_is_64bit - determine if counter is 64bit
* @pmc: counter context * @pmc: counter context
...@@ -672,8 +677,11 @@ void kvm_host_pmu_init(struct arm_pmu *pmu) ...@@ -672,8 +677,11 @@ void kvm_host_pmu_init(struct arm_pmu *pmu)
{ {
struct arm_pmu_entry *entry; struct arm_pmu_entry *entry;
if (pmu->pmuver == ID_AA64DFR0_EL1_PMUVer_NI || /*
pmu->pmuver == ID_AA64DFR0_EL1_PMUVer_IMP_DEF) * Check the sanitised PMU version for the system, as KVM does not
* support implementations where PMUv3 exists on a subset of CPUs.
*/
if (!pmuv3_implemented(kvm_arm_pmu_get_pmuver_limit()))
return; return;
mutex_lock(&arm_pmus_lock); mutex_lock(&arm_pmus_lock);
...@@ -750,11 +758,12 @@ u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1) ...@@ -750,11 +758,12 @@ u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)
} else { } else {
val = read_sysreg(pmceid1_el0); val = read_sysreg(pmceid1_el0);
/* /*
* Don't advertise STALL_SLOT, as PMMIR_EL0 is handled * Don't advertise STALL_SLOT*, as PMMIR_EL0 is handled
* as RAZ * as RAZ
*/ */
if (vcpu->kvm->arch.arm_pmu->pmuver >= ID_AA64DFR0_EL1_PMUVer_V3P4) val &= ~(BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT - 32) |
val &= ~BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT - 32); BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT_FRONTEND - 32) |
BIT_ULL(ARMV8_PMUV3_PERFCTR_STALL_SLOT_BACKEND - 32));
base = 32; base = 32;
} }
...@@ -950,11 +959,17 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) ...@@ -950,11 +959,17 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
return 0; return 0;
} }
case KVM_ARM_VCPU_PMU_V3_FILTER: { case KVM_ARM_VCPU_PMU_V3_FILTER: {
u8 pmuver = kvm_arm_pmu_get_pmuver_limit();
struct kvm_pmu_event_filter __user *uaddr; struct kvm_pmu_event_filter __user *uaddr;
struct kvm_pmu_event_filter filter; struct kvm_pmu_event_filter filter;
int nr_events; int nr_events;
nr_events = kvm_pmu_event_mask(kvm) + 1; /*
* Allow userspace to specify an event filter for the entire
* event range supported by PMUVer of the hardware, rather
* than the guest's PMUVer for KVM backward compatibility.
*/
nr_events = __kvm_pmu_event_mask(pmuver) + 1;
uaddr = (struct kvm_pmu_event_filter __user *)(long)attr->addr; uaddr = (struct kvm_pmu_event_filter __user *)(long)attr->addr;
......
...@@ -236,3 +236,21 @@ bool kvm_set_pmuserenr(u64 val) ...@@ -236,3 +236,21 @@ bool kvm_set_pmuserenr(u64 val)
ctxt_sys_reg(hctxt, PMUSERENR_EL0) = val; ctxt_sys_reg(hctxt, PMUSERENR_EL0) = val;
return true; return true;
} }
/*
* If we interrupted the guest to update the host PMU context, make
* sure we re-apply the guest EL0 state.
*/
void kvm_vcpu_pmu_resync_el0(void)
{
struct kvm_vcpu *vcpu;
if (!has_vhe() || !in_interrupt())
return;
vcpu = kvm_get_running_vcpu();
if (!vcpu)
return;
kvm_make_request(KVM_REQ_RESYNC_PMU_EL0, vcpu);
}
...@@ -248,21 +248,16 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) ...@@ -248,21 +248,16 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
} }
} }
switch (vcpu->arch.target) { if (vcpu_el1_is_32bit(vcpu))
default: pstate = VCPU_RESET_PSTATE_SVC;
if (vcpu_el1_is_32bit(vcpu)) { else if (vcpu_has_nv(vcpu))
pstate = VCPU_RESET_PSTATE_SVC; pstate = VCPU_RESET_PSTATE_EL2;
} else if (vcpu_has_nv(vcpu)) { else
pstate = VCPU_RESET_PSTATE_EL2; pstate = VCPU_RESET_PSTATE_EL1;
} else {
pstate = VCPU_RESET_PSTATE_EL1; if (kvm_vcpu_has_pmu(vcpu) && !kvm_arm_support_pmu_v3()) {
} ret = -EINVAL;
goto out;
if (kvm_vcpu_has_pmu(vcpu) && !kvm_arm_support_pmu_v3()) {
ret = -EINVAL;
goto out;
}
break;
} }
/* Reset core registers */ /* Reset core registers */
......
...@@ -2151,6 +2151,8 @@ static const struct sys_reg_desc sys_reg_descs[] = { ...@@ -2151,6 +2151,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
{ SYS_DESC(SYS_CONTEXTIDR_EL1), access_vm_reg, reset_val, CONTEXTIDR_EL1, 0 }, { SYS_DESC(SYS_CONTEXTIDR_EL1), access_vm_reg, reset_val, CONTEXTIDR_EL1, 0 },
{ SYS_DESC(SYS_TPIDR_EL1), NULL, reset_unknown, TPIDR_EL1 }, { SYS_DESC(SYS_TPIDR_EL1), NULL, reset_unknown, TPIDR_EL1 },
{ SYS_DESC(SYS_ACCDATA_EL1), undef_access },
{ SYS_DESC(SYS_SCXTNUM_EL1), undef_access }, { SYS_DESC(SYS_SCXTNUM_EL1), undef_access },
{ SYS_DESC(SYS_CNTKCTL_EL1), NULL, reset_val, CNTKCTL_EL1, 0}, { SYS_DESC(SYS_CNTKCTL_EL1), NULL, reset_val, CNTKCTL_EL1, 0},
...@@ -2365,8 +2367,13 @@ static const struct sys_reg_desc sys_reg_descs[] = { ...@@ -2365,8 +2367,13 @@ static const struct sys_reg_desc sys_reg_descs[] = {
EL2_REG(MDCR_EL2, access_rw, reset_val, 0), EL2_REG(MDCR_EL2, access_rw, reset_val, 0),
EL2_REG(CPTR_EL2, access_rw, reset_val, CPTR_NVHE_EL2_RES1), EL2_REG(CPTR_EL2, access_rw, reset_val, CPTR_NVHE_EL2_RES1),
EL2_REG(HSTR_EL2, access_rw, reset_val, 0), EL2_REG(HSTR_EL2, access_rw, reset_val, 0),
EL2_REG(HFGRTR_EL2, access_rw, reset_val, 0),
EL2_REG(HFGWTR_EL2, access_rw, reset_val, 0),
EL2_REG(HFGITR_EL2, access_rw, reset_val, 0),
EL2_REG(HACR_EL2, access_rw, reset_val, 0), EL2_REG(HACR_EL2, access_rw, reset_val, 0),
EL2_REG(HCRX_EL2, access_rw, reset_val, 0),
EL2_REG(TTBR0_EL2, access_rw, reset_val, 0), EL2_REG(TTBR0_EL2, access_rw, reset_val, 0),
EL2_REG(TTBR1_EL2, access_rw, reset_val, 0), EL2_REG(TTBR1_EL2, access_rw, reset_val, 0),
EL2_REG(TCR_EL2, access_rw, reset_val, TCR_EL2_RES1), EL2_REG(TCR_EL2, access_rw, reset_val, TCR_EL2_RES1),
...@@ -2374,6 +2381,8 @@ static const struct sys_reg_desc sys_reg_descs[] = { ...@@ -2374,6 +2381,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
EL2_REG(VTCR_EL2, access_rw, reset_val, 0), EL2_REG(VTCR_EL2, access_rw, reset_val, 0),
{ SYS_DESC(SYS_DACR32_EL2), NULL, reset_unknown, DACR32_EL2 }, { SYS_DESC(SYS_DACR32_EL2), NULL, reset_unknown, DACR32_EL2 },
EL2_REG(HDFGRTR_EL2, access_rw, reset_val, 0),
EL2_REG(HDFGWTR_EL2, access_rw, reset_val, 0),
EL2_REG(SPSR_EL2, access_rw, reset_val, 0), EL2_REG(SPSR_EL2, access_rw, reset_val, 0),
EL2_REG(ELR_EL2, access_rw, reset_val, 0), EL2_REG(ELR_EL2, access_rw, reset_val, 0),
{ SYS_DESC(SYS_SP_EL1), access_sp_el1}, { SYS_DESC(SYS_SP_EL1), access_sp_el1},
...@@ -3170,6 +3179,9 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu) ...@@ -3170,6 +3179,9 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu)
trace_kvm_handle_sys_reg(esr); trace_kvm_handle_sys_reg(esr);
if (__check_nv_sr_forward(vcpu))
return 1;
params = esr_sys64_to_params(esr); params = esr_sys64_to_params(esr);
params.regval = vcpu_get_reg(vcpu, Rt); params.regval = vcpu_get_reg(vcpu, Rt);
...@@ -3587,5 +3599,8 @@ int __init kvm_sys_reg_table_init(void) ...@@ -3587,5 +3599,8 @@ int __init kvm_sys_reg_table_init(void)
if (!first_idreg) if (!first_idreg)
return -EINVAL; return -EINVAL;
if (kvm_get_mode() == KVM_MODE_NV)
return populate_nv_trap_config();
return 0; return 0;
} }
...@@ -364,6 +364,32 @@ TRACE_EVENT(kvm_inject_nested_exception, ...@@ -364,6 +364,32 @@ TRACE_EVENT(kvm_inject_nested_exception,
__entry->hcr_el2) __entry->hcr_el2)
); );
TRACE_EVENT(kvm_forward_sysreg_trap,
TP_PROTO(struct kvm_vcpu *vcpu, u32 sysreg, bool is_read),
TP_ARGS(vcpu, sysreg, is_read),
TP_STRUCT__entry(
__field(u64, pc)
__field(u32, sysreg)
__field(bool, is_read)
),
TP_fast_assign(
__entry->pc = *vcpu_pc(vcpu);
__entry->sysreg = sysreg;
__entry->is_read = is_read;
),
TP_printk("%llx %c (%d,%d,%d,%d,%d)",
__entry->pc,
__entry->is_read ? 'R' : 'W',
sys_reg_Op0(__entry->sysreg),
sys_reg_Op1(__entry->sysreg),
sys_reg_CRn(__entry->sysreg),
sys_reg_CRm(__entry->sysreg),
sys_reg_Op2(__entry->sysreg))
);
#endif /* _TRACE_ARM_ARM64_KVM_H */ #endif /* _TRACE_ARM_ARM64_KVM_H */
#undef TRACE_INCLUDE_PATH #undef TRACE_INCLUDE_PATH
......
...@@ -199,7 +199,6 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu); ...@@ -199,7 +199,6 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr); void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr); void vgic_v2_clear_lr(struct kvm_vcpu *vcpu, int lr);
void vgic_v2_set_underflow(struct kvm_vcpu *vcpu); void vgic_v2_set_underflow(struct kvm_vcpu *vcpu);
void vgic_v2_set_npie(struct kvm_vcpu *vcpu);
int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr); int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr);
int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write, int vgic_v2_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
int offset, u32 *val); int offset, u32 *val);
...@@ -233,7 +232,6 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu); ...@@ -233,7 +232,6 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu);
void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr); void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr); void vgic_v3_clear_lr(struct kvm_vcpu *vcpu, int lr);
void vgic_v3_set_underflow(struct kvm_vcpu *vcpu); void vgic_v3_set_underflow(struct kvm_vcpu *vcpu);
void vgic_v3_set_npie(struct kvm_vcpu *vcpu);
void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr); void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr); void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
void vgic_v3_enable(struct kvm_vcpu *vcpu); void vgic_v3_enable(struct kvm_vcpu *vcpu);
......
...@@ -26,6 +26,7 @@ HAS_ECV ...@@ -26,6 +26,7 @@ HAS_ECV
HAS_ECV_CNTPOFF HAS_ECV_CNTPOFF
HAS_EPAN HAS_EPAN
HAS_EVT HAS_EVT
HAS_FGT
HAS_GENERIC_AUTH HAS_GENERIC_AUTH
HAS_GENERIC_AUTH_ARCH_QARMA3 HAS_GENERIC_AUTH_ARCH_QARMA3
HAS_GENERIC_AUTH_ARCH_QARMA5 HAS_GENERIC_AUTH_ARCH_QARMA5
......
...@@ -2156,6 +2156,135 @@ Field 1 ICIALLU ...@@ -2156,6 +2156,135 @@ Field 1 ICIALLU
Field 0 ICIALLUIS Field 0 ICIALLUIS
EndSysreg EndSysreg
Sysreg HDFGRTR_EL2 3 4 3 1 4
Field 63 PMBIDR_EL1
Field 62 nPMSNEVFR_EL1
Field 61 nBRBDATA
Field 60 nBRBCTL
Field 59 nBRBIDR
Field 58 PMCEIDn_EL0
Field 57 PMUSERENR_EL0
Field 56 TRBTRG_EL1
Field 55 TRBSR_EL1
Field 54 TRBPTR_EL1
Field 53 TRBMAR_EL1
Field 52 TRBLIMITR_EL1
Field 51 TRBIDR_EL1
Field 50 TRBBASER_EL1
Res0 49
Field 48 TRCVICTLR
Field 47 TRCSTATR
Field 46 TRCSSCSRn
Field 45 TRCSEQSTR
Field 44 TRCPRGCTLR
Field 43 TRCOSLSR
Res0 42
Field 41 TRCIMSPECn
Field 40 TRCID
Res0 39:38
Field 37 TRCCNTVRn
Field 36 TRCCLAIM
Field 35 TRCAUXCTLR
Field 34 TRCAUTHSTATUS
Field 33 TRC
Field 32 PMSLATFR_EL1
Field 31 PMSIRR_EL1
Field 30 PMSIDR_EL1
Field 29 PMSICR_EL1
Field 28 PMSFCR_EL1
Field 27 PMSEVFR_EL1
Field 26 PMSCR_EL1
Field 25 PMBSR_EL1
Field 24 PMBPTR_EL1
Field 23 PMBLIMITR_EL1
Field 22 PMMIR_EL1
Res0 21:20
Field 19 PMSELR_EL0
Field 18 PMOVS
Field 17 PMINTEN
Field 16 PMCNTEN
Field 15 PMCCNTR_EL0
Field 14 PMCCFILTR_EL0
Field 13 PMEVTYPERn_EL0
Field 12 PMEVCNTRn_EL0
Field 11 OSDLR_EL1
Field 10 OSECCR_EL1
Field 9 OSLSR_EL1
Res0 8
Field 7 DBGPRCR_EL1
Field 6 DBGAUTHSTATUS_EL1
Field 5 DBGCLAIM
Field 4 MDSCR_EL1
Field 3 DBGWVRn_EL1
Field 2 DBGWCRn_EL1
Field 1 DBGBVRn_EL1
Field 0 DBGBCRn_EL1
EndSysreg
Sysreg HDFGWTR_EL2 3 4 3 1 5
Res0 63
Field 62 nPMSNEVFR_EL1
Field 61 nBRBDATA
Field 60 nBRBCTL
Res0 59:58
Field 57 PMUSERENR_EL0
Field 56 TRBTRG_EL1
Field 55 TRBSR_EL1
Field 54 TRBPTR_EL1
Field 53 TRBMAR_EL1
Field 52 TRBLIMITR_EL1
Res0 51
Field 50 TRBBASER_EL1
Field 49 TRFCR_EL1
Field 48 TRCVICTLR
Res0 47
Field 46 TRCSSCSRn
Field 45 TRCSEQSTR
Field 44 TRCPRGCTLR
Res0 43
Field 42 TRCOSLAR
Field 41 TRCIMSPECn
Res0 40:38
Field 37 TRCCNTVRn
Field 36 TRCCLAIM
Field 35 TRCAUXCTLR
Res0 34
Field 33 TRC
Field 32 PMSLATFR_EL1
Field 31 PMSIRR_EL1
Res0 30
Field 29 PMSICR_EL1
Field 28 PMSFCR_EL1
Field 27 PMSEVFR_EL1
Field 26 PMSCR_EL1
Field 25 PMBSR_EL1
Field 24 PMBPTR_EL1
Field 23 PMBLIMITR_EL1
Res0 22
Field 21 PMCR_EL0
Field 20 PMSWINC_EL0
Field 19 PMSELR_EL0
Field 18 PMOVS
Field 17 PMINTEN
Field 16 PMCNTEN
Field 15 PMCCNTR_EL0
Field 14 PMCCFILTR_EL0
Field 13 PMEVTYPERn_EL0
Field 12 PMEVCNTRn_EL0
Field 11 OSDLR_EL1
Field 10 OSECCR_EL1
Res0 9
Field 8 OSLAR_EL1
Field 7 DBGPRCR_EL1
Res0 6
Field 5 DBGCLAIM
Field 4 MDSCR_EL1
Field 3 DBGWVRn_EL1
Field 2 DBGWCRn_EL1
Field 1 DBGBVRn_EL1
Field 0 DBGBCRn_EL1
EndSysreg
Sysreg ZCR_EL2 3 4 1 2 0 Sysreg ZCR_EL2 3 4 1 2 0
Fields ZCR_ELx Fields ZCR_ELx
EndSysreg EndSysreg
......
...@@ -896,7 +896,6 @@ static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {} ...@@ -896,7 +896,6 @@ static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}
static inline void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) {} static inline void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) {}
static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) {} static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) {}
#define __KVM_HAVE_ARCH_FLUSH_REMOTE_TLB #define __KVM_HAVE_ARCH_FLUSH_REMOTE_TLBS
int kvm_arch_flush_remote_tlb(struct kvm *kvm);
#endif /* __MIPS_KVM_HOST_H__ */ #endif /* __MIPS_KVM_HOST_H__ */
...@@ -199,7 +199,7 @@ void kvm_arch_flush_shadow_memslot(struct kvm *kvm, ...@@ -199,7 +199,7 @@ void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
/* Flush slot from GPA */ /* Flush slot from GPA */
kvm_mips_flush_gpa_pt(kvm, slot->base_gfn, kvm_mips_flush_gpa_pt(kvm, slot->base_gfn,
slot->base_gfn + slot->npages - 1); slot->base_gfn + slot->npages - 1);
kvm_arch_flush_remote_tlbs_memslot(kvm, slot); kvm_flush_remote_tlbs_memslot(kvm, slot);
spin_unlock(&kvm->mmu_lock); spin_unlock(&kvm->mmu_lock);
} }
...@@ -235,7 +235,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, ...@@ -235,7 +235,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
needs_flush = kvm_mips_mkclean_gpa_pt(kvm, new->base_gfn, needs_flush = kvm_mips_mkclean_gpa_pt(kvm, new->base_gfn,
new->base_gfn + new->npages - 1); new->base_gfn + new->npages - 1);
if (needs_flush) if (needs_flush)
kvm_arch_flush_remote_tlbs_memslot(kvm, new); kvm_flush_remote_tlbs_memslot(kvm, new);
spin_unlock(&kvm->mmu_lock); spin_unlock(&kvm->mmu_lock);
} }
} }
...@@ -981,18 +981,12 @@ void kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot) ...@@ -981,18 +981,12 @@ void kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
} }
int kvm_arch_flush_remote_tlb(struct kvm *kvm) int kvm_arch_flush_remote_tlbs(struct kvm *kvm)
{ {
kvm_mips_callbacks->prepare_flush_shadow(kvm); kvm_mips_callbacks->prepare_flush_shadow(kvm);
return 1; return 1;
} }
void kvm_arch_flush_remote_tlbs_memslot(struct kvm *kvm,
const struct kvm_memory_slot *memslot)
{
kvm_flush_remote_tlbs(kvm);
}
int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
{ {
int r; int r;
......
...@@ -447,7 +447,7 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range) ...@@ -447,7 +447,7 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range) bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
{ {
gpa_t gpa = range->start << PAGE_SHIFT; gpa_t gpa = range->start << PAGE_SHIFT;
pte_t hva_pte = range->pte; pte_t hva_pte = range->arg.pte;
pte_t *gpa_pte = kvm_mips_pte_for_gpa(kvm, NULL, gpa); pte_t *gpa_pte = kvm_mips_pte_for_gpa(kvm, NULL, gpa);
pte_t old_pte; pte_t old_pte;
......
...@@ -54,6 +54,7 @@ ...@@ -54,6 +54,7 @@
#ifndef CONFIG_64BIT #ifndef CONFIG_64BIT
#define SATP_PPN _AC(0x003FFFFF, UL) #define SATP_PPN _AC(0x003FFFFF, UL)
#define SATP_MODE_32 _AC(0x80000000, UL) #define SATP_MODE_32 _AC(0x80000000, UL)
#define SATP_MODE_SHIFT 31
#define SATP_ASID_BITS 9 #define SATP_ASID_BITS 9
#define SATP_ASID_SHIFT 22 #define SATP_ASID_SHIFT 22
#define SATP_ASID_MASK _AC(0x1FF, UL) #define SATP_ASID_MASK _AC(0x1FF, UL)
...@@ -62,6 +63,7 @@ ...@@ -62,6 +63,7 @@
#define SATP_MODE_39 _AC(0x8000000000000000, UL) #define SATP_MODE_39 _AC(0x8000000000000000, UL)
#define SATP_MODE_48 _AC(0x9000000000000000, UL) #define SATP_MODE_48 _AC(0x9000000000000000, UL)
#define SATP_MODE_57 _AC(0xa000000000000000, UL) #define SATP_MODE_57 _AC(0xa000000000000000, UL)
#define SATP_MODE_SHIFT 60
#define SATP_ASID_BITS 16 #define SATP_ASID_BITS 16
#define SATP_ASID_SHIFT 44 #define SATP_ASID_SHIFT 44
#define SATP_ASID_MASK _AC(0xFFFF, UL) #define SATP_ASID_MASK _AC(0xFFFF, UL)
......
...@@ -337,6 +337,15 @@ int kvm_riscv_vcpu_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, ...@@ -337,6 +337,15 @@ int kvm_riscv_vcpu_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
void __kvm_riscv_switch_to(struct kvm_vcpu_arch *vcpu_arch); void __kvm_riscv_switch_to(struct kvm_vcpu_arch *vcpu_arch);
void kvm_riscv_vcpu_setup_isa(struct kvm_vcpu *vcpu);
unsigned long kvm_riscv_vcpu_num_regs(struct kvm_vcpu *vcpu);
int kvm_riscv_vcpu_copy_reg_indices(struct kvm_vcpu *vcpu,
u64 __user *uindices);
int kvm_riscv_vcpu_get_reg(struct kvm_vcpu *vcpu,
const struct kvm_one_reg *reg);
int kvm_riscv_vcpu_set_reg(struct kvm_vcpu *vcpu,
const struct kvm_one_reg *reg);
int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq); int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq);
int kvm_riscv_vcpu_unset_interrupt(struct kvm_vcpu *vcpu, unsigned int irq); int kvm_riscv_vcpu_unset_interrupt(struct kvm_vcpu *vcpu, unsigned int irq);
void kvm_riscv_vcpu_flush_interrupts(struct kvm_vcpu *vcpu); void kvm_riscv_vcpu_flush_interrupts(struct kvm_vcpu *vcpu);
......
...@@ -74,9 +74,7 @@ static inline void kvm_riscv_vcpu_free_vector_context(struct kvm_vcpu *vcpu) ...@@ -74,9 +74,7 @@ static inline void kvm_riscv_vcpu_free_vector_context(struct kvm_vcpu *vcpu)
#endif #endif
int kvm_riscv_vcpu_get_reg_vector(struct kvm_vcpu *vcpu, int kvm_riscv_vcpu_get_reg_vector(struct kvm_vcpu *vcpu,
const struct kvm_one_reg *reg, const struct kvm_one_reg *reg);
unsigned long rtype);
int kvm_riscv_vcpu_set_reg_vector(struct kvm_vcpu *vcpu, int kvm_riscv_vcpu_set_reg_vector(struct kvm_vcpu *vcpu,
const struct kvm_one_reg *reg, const struct kvm_one_reg *reg);
unsigned long rtype);
#endif #endif
...@@ -55,6 +55,7 @@ struct kvm_riscv_config { ...@@ -55,6 +55,7 @@ struct kvm_riscv_config {
unsigned long marchid; unsigned long marchid;
unsigned long mimpid; unsigned long mimpid;
unsigned long zicboz_block_size; unsigned long zicboz_block_size;
unsigned long satp_mode;
}; };
/* CORE registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */ /* CORE registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */
...@@ -124,6 +125,12 @@ enum KVM_RISCV_ISA_EXT_ID { ...@@ -124,6 +125,12 @@ enum KVM_RISCV_ISA_EXT_ID {
KVM_RISCV_ISA_EXT_SSAIA, KVM_RISCV_ISA_EXT_SSAIA,
KVM_RISCV_ISA_EXT_V, KVM_RISCV_ISA_EXT_V,
KVM_RISCV_ISA_EXT_SVNAPOT, KVM_RISCV_ISA_EXT_SVNAPOT,
KVM_RISCV_ISA_EXT_ZBA,
KVM_RISCV_ISA_EXT_ZBS,
KVM_RISCV_ISA_EXT_ZICNTR,
KVM_RISCV_ISA_EXT_ZICSR,
KVM_RISCV_ISA_EXT_ZIFENCEI,
KVM_RISCV_ISA_EXT_ZIHPM,
KVM_RISCV_ISA_EXT_MAX, KVM_RISCV_ISA_EXT_MAX,
}; };
...@@ -193,6 +200,15 @@ enum KVM_RISCV_SBI_EXT_ID { ...@@ -193,6 +200,15 @@ enum KVM_RISCV_SBI_EXT_ID {
/* ISA Extension registers are mapped as type 7 */ /* ISA Extension registers are mapped as type 7 */
#define KVM_REG_RISCV_ISA_EXT (0x07 << KVM_REG_RISCV_TYPE_SHIFT) #define KVM_REG_RISCV_ISA_EXT (0x07 << KVM_REG_RISCV_TYPE_SHIFT)
#define KVM_REG_RISCV_ISA_SINGLE (0x0 << KVM_REG_RISCV_SUBTYPE_SHIFT)
#define KVM_REG_RISCV_ISA_MULTI_EN (0x1 << KVM_REG_RISCV_SUBTYPE_SHIFT)
#define KVM_REG_RISCV_ISA_MULTI_DIS (0x2 << KVM_REG_RISCV_SUBTYPE_SHIFT)
#define KVM_REG_RISCV_ISA_MULTI_REG(__ext_id) \
((__ext_id) / __BITS_PER_LONG)
#define KVM_REG_RISCV_ISA_MULTI_MASK(__ext_id) \
(1UL << ((__ext_id) % __BITS_PER_LONG))
#define KVM_REG_RISCV_ISA_MULTI_REG_LAST \
KVM_REG_RISCV_ISA_MULTI_REG(KVM_RISCV_ISA_EXT_MAX - 1)
/* SBI extension registers are mapped as type 8 */ /* SBI extension registers are mapped as type 8 */
#define KVM_REG_RISCV_SBI_EXT (0x08 << KVM_REG_RISCV_TYPE_SHIFT) #define KVM_REG_RISCV_SBI_EXT (0x08 << KVM_REG_RISCV_TYPE_SHIFT)
......
...@@ -19,6 +19,7 @@ kvm-y += vcpu_exit.o ...@@ -19,6 +19,7 @@ kvm-y += vcpu_exit.o
kvm-y += vcpu_fp.o kvm-y += vcpu_fp.o
kvm-y += vcpu_vector.o kvm-y += vcpu_vector.o
kvm-y += vcpu_insn.o kvm-y += vcpu_insn.o
kvm-y += vcpu_onereg.o
kvm-y += vcpu_switch.o kvm-y += vcpu_switch.o
kvm-y += vcpu_sbi.o kvm-y += vcpu_sbi.o
kvm-$(CONFIG_RISCV_SBI_V01) += vcpu_sbi_v01.o kvm-$(CONFIG_RISCV_SBI_V01) += vcpu_sbi_v01.o
......
...@@ -176,7 +176,7 @@ int kvm_riscv_vcpu_aia_get_csr(struct kvm_vcpu *vcpu, ...@@ -176,7 +176,7 @@ int kvm_riscv_vcpu_aia_get_csr(struct kvm_vcpu *vcpu,
struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr; struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
if (reg_num >= sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long)) if (reg_num >= sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long))
return -EINVAL; return -ENOENT;
*out_val = 0; *out_val = 0;
if (kvm_riscv_aia_available()) if (kvm_riscv_aia_available())
...@@ -192,7 +192,7 @@ int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu, ...@@ -192,7 +192,7 @@ int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu,
struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr; struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
if (reg_num >= sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long)) if (reg_num >= sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long))
return -EINVAL; return -ENOENT;
if (kvm_riscv_aia_available()) { if (kvm_riscv_aia_available()) {
((unsigned long *)csr)[reg_num] = val; ((unsigned long *)csr)[reg_num] = val;
......
...@@ -406,12 +406,6 @@ void kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot) ...@@ -406,12 +406,6 @@ void kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
{ {
} }
void kvm_arch_flush_remote_tlbs_memslot(struct kvm *kvm,
const struct kvm_memory_slot *memslot)
{
kvm_flush_remote_tlbs(kvm);
}
void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free) void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free)
{ {
} }
...@@ -559,7 +553,7 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range) ...@@ -559,7 +553,7 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range) bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
{ {
int ret; int ret;
kvm_pfn_t pfn = pte_pfn(range->pte); kvm_pfn_t pfn = pte_pfn(range->arg.pte);
if (!kvm->arch.pgd) if (!kvm->arch.pgd)
return false; return false;
......
This diff is collapsed.
...@@ -96,7 +96,7 @@ int kvm_riscv_vcpu_get_reg_fp(struct kvm_vcpu *vcpu, ...@@ -96,7 +96,7 @@ int kvm_riscv_vcpu_get_reg_fp(struct kvm_vcpu *vcpu,
reg_num <= KVM_REG_RISCV_FP_F_REG(f[31])) reg_num <= KVM_REG_RISCV_FP_F_REG(f[31]))
reg_val = &cntx->fp.f.f[reg_num]; reg_val = &cntx->fp.f.f[reg_num];
else else
return -EINVAL; return -ENOENT;
} else if ((rtype == KVM_REG_RISCV_FP_D) && } else if ((rtype == KVM_REG_RISCV_FP_D) &&
riscv_isa_extension_available(vcpu->arch.isa, d)) { riscv_isa_extension_available(vcpu->arch.isa, d)) {
if (reg_num == KVM_REG_RISCV_FP_D_REG(fcsr)) { if (reg_num == KVM_REG_RISCV_FP_D_REG(fcsr)) {
...@@ -109,9 +109,9 @@ int kvm_riscv_vcpu_get_reg_fp(struct kvm_vcpu *vcpu, ...@@ -109,9 +109,9 @@ int kvm_riscv_vcpu_get_reg_fp(struct kvm_vcpu *vcpu,
return -EINVAL; return -EINVAL;
reg_val = &cntx->fp.d.f[reg_num]; reg_val = &cntx->fp.d.f[reg_num];
} else } else
return -EINVAL; return -ENOENT;
} else } else
return -EINVAL; return -ENOENT;
if (copy_to_user(uaddr, reg_val, KVM_REG_SIZE(reg->id))) if (copy_to_user(uaddr, reg_val, KVM_REG_SIZE(reg->id)))
return -EFAULT; return -EFAULT;
...@@ -141,7 +141,7 @@ int kvm_riscv_vcpu_set_reg_fp(struct kvm_vcpu *vcpu, ...@@ -141,7 +141,7 @@ int kvm_riscv_vcpu_set_reg_fp(struct kvm_vcpu *vcpu,
reg_num <= KVM_REG_RISCV_FP_F_REG(f[31])) reg_num <= KVM_REG_RISCV_FP_F_REG(f[31]))
reg_val = &cntx->fp.f.f[reg_num]; reg_val = &cntx->fp.f.f[reg_num];
else else
return -EINVAL; return -ENOENT;
} else if ((rtype == KVM_REG_RISCV_FP_D) && } else if ((rtype == KVM_REG_RISCV_FP_D) &&
riscv_isa_extension_available(vcpu->arch.isa, d)) { riscv_isa_extension_available(vcpu->arch.isa, d)) {
if (reg_num == KVM_REG_RISCV_FP_D_REG(fcsr)) { if (reg_num == KVM_REG_RISCV_FP_D_REG(fcsr)) {
...@@ -154,9 +154,9 @@ int kvm_riscv_vcpu_set_reg_fp(struct kvm_vcpu *vcpu, ...@@ -154,9 +154,9 @@ int kvm_riscv_vcpu_set_reg_fp(struct kvm_vcpu *vcpu,
return -EINVAL; return -EINVAL;
reg_val = &cntx->fp.d.f[reg_num]; reg_val = &cntx->fp.d.f[reg_num];
} else } else
return -EINVAL; return -ENOENT;
} else } else
return -EINVAL; return -ENOENT;
if (copy_from_user(reg_val, uaddr, KVM_REG_SIZE(reg->id))) if (copy_from_user(reg_val, uaddr, KVM_REG_SIZE(reg->id)))
return -EFAULT; return -EFAULT;
......
This diff is collapsed.
...@@ -140,8 +140,10 @@ static int riscv_vcpu_set_sbi_ext_single(struct kvm_vcpu *vcpu, ...@@ -140,8 +140,10 @@ static int riscv_vcpu_set_sbi_ext_single(struct kvm_vcpu *vcpu,
const struct kvm_riscv_sbi_extension_entry *sext = NULL; const struct kvm_riscv_sbi_extension_entry *sext = NULL;
struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context; struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
if (reg_num >= KVM_RISCV_SBI_EXT_MAX || if (reg_num >= KVM_RISCV_SBI_EXT_MAX)
(reg_val != 1 && reg_val != 0)) return -ENOENT;
if (reg_val != 1 && reg_val != 0)
return -EINVAL; return -EINVAL;
for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) { for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
...@@ -175,7 +177,7 @@ static int riscv_vcpu_get_sbi_ext_single(struct kvm_vcpu *vcpu, ...@@ -175,7 +177,7 @@ static int riscv_vcpu_get_sbi_ext_single(struct kvm_vcpu *vcpu,
struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context; struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
if (reg_num >= KVM_RISCV_SBI_EXT_MAX) if (reg_num >= KVM_RISCV_SBI_EXT_MAX)
return -EINVAL; return -ENOENT;
for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) { for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
if (sbi_ext[i].ext_idx == reg_num) { if (sbi_ext[i].ext_idx == reg_num) {
...@@ -206,7 +208,7 @@ static int riscv_vcpu_set_sbi_ext_multi(struct kvm_vcpu *vcpu, ...@@ -206,7 +208,7 @@ static int riscv_vcpu_set_sbi_ext_multi(struct kvm_vcpu *vcpu,
unsigned long i, ext_id; unsigned long i, ext_id;
if (reg_num > KVM_REG_RISCV_SBI_MULTI_REG_LAST) if (reg_num > KVM_REG_RISCV_SBI_MULTI_REG_LAST)
return -EINVAL; return -ENOENT;
for_each_set_bit(i, &reg_val, BITS_PER_LONG) { for_each_set_bit(i, &reg_val, BITS_PER_LONG) {
ext_id = i + reg_num * BITS_PER_LONG; ext_id = i + reg_num * BITS_PER_LONG;
...@@ -226,7 +228,7 @@ static int riscv_vcpu_get_sbi_ext_multi(struct kvm_vcpu *vcpu, ...@@ -226,7 +228,7 @@ static int riscv_vcpu_get_sbi_ext_multi(struct kvm_vcpu *vcpu,
unsigned long i, ext_id, ext_val; unsigned long i, ext_id, ext_val;
if (reg_num > KVM_REG_RISCV_SBI_MULTI_REG_LAST) if (reg_num > KVM_REG_RISCV_SBI_MULTI_REG_LAST)
return -EINVAL; return -ENOENT;
for (i = 0; i < BITS_PER_LONG; i++) { for (i = 0; i < BITS_PER_LONG; i++) {
ext_id = i + reg_num * BITS_PER_LONG; ext_id = i + reg_num * BITS_PER_LONG;
...@@ -272,7 +274,7 @@ int kvm_riscv_vcpu_set_reg_sbi_ext(struct kvm_vcpu *vcpu, ...@@ -272,7 +274,7 @@ int kvm_riscv_vcpu_set_reg_sbi_ext(struct kvm_vcpu *vcpu,
case KVM_REG_RISCV_SBI_MULTI_DIS: case KVM_REG_RISCV_SBI_MULTI_DIS:
return riscv_vcpu_set_sbi_ext_multi(vcpu, reg_num, reg_val, false); return riscv_vcpu_set_sbi_ext_multi(vcpu, reg_num, reg_val, false);
default: default:
return -EINVAL; return -ENOENT;
} }
return 0; return 0;
...@@ -307,7 +309,7 @@ int kvm_riscv_vcpu_get_reg_sbi_ext(struct kvm_vcpu *vcpu, ...@@ -307,7 +309,7 @@ int kvm_riscv_vcpu_get_reg_sbi_ext(struct kvm_vcpu *vcpu,
reg_val = ~reg_val; reg_val = ~reg_val;
break; break;
default: default:
rc = -EINVAL; rc = -ENOENT;
} }
if (rc) if (rc)
return rc; return rc;
......
...@@ -170,7 +170,7 @@ int kvm_riscv_vcpu_get_reg_timer(struct kvm_vcpu *vcpu, ...@@ -170,7 +170,7 @@ int kvm_riscv_vcpu_get_reg_timer(struct kvm_vcpu *vcpu,
if (KVM_REG_SIZE(reg->id) != sizeof(u64)) if (KVM_REG_SIZE(reg->id) != sizeof(u64))
return -EINVAL; return -EINVAL;
if (reg_num >= sizeof(struct kvm_riscv_timer) / sizeof(u64)) if (reg_num >= sizeof(struct kvm_riscv_timer) / sizeof(u64))
return -EINVAL; return -ENOENT;
switch (reg_num) { switch (reg_num) {
case KVM_REG_RISCV_TIMER_REG(frequency): case KVM_REG_RISCV_TIMER_REG(frequency):
...@@ -187,7 +187,7 @@ int kvm_riscv_vcpu_get_reg_timer(struct kvm_vcpu *vcpu, ...@@ -187,7 +187,7 @@ int kvm_riscv_vcpu_get_reg_timer(struct kvm_vcpu *vcpu,
KVM_RISCV_TIMER_STATE_OFF; KVM_RISCV_TIMER_STATE_OFF;
break; break;
default: default:
return -EINVAL; return -ENOENT;
} }
if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id))) if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id)))
...@@ -211,14 +211,15 @@ int kvm_riscv_vcpu_set_reg_timer(struct kvm_vcpu *vcpu, ...@@ -211,14 +211,15 @@ int kvm_riscv_vcpu_set_reg_timer(struct kvm_vcpu *vcpu,
if (KVM_REG_SIZE(reg->id) != sizeof(u64)) if (KVM_REG_SIZE(reg->id) != sizeof(u64))
return -EINVAL; return -EINVAL;
if (reg_num >= sizeof(struct kvm_riscv_timer) / sizeof(u64)) if (reg_num >= sizeof(struct kvm_riscv_timer) / sizeof(u64))
return -EINVAL; return -ENOENT;
if (copy_from_user(&reg_val, uaddr, KVM_REG_SIZE(reg->id))) if (copy_from_user(&reg_val, uaddr, KVM_REG_SIZE(reg->id)))
return -EFAULT; return -EFAULT;
switch (reg_num) { switch (reg_num) {
case KVM_REG_RISCV_TIMER_REG(frequency): case KVM_REG_RISCV_TIMER_REG(frequency):
ret = -EOPNOTSUPP; if (reg_val != riscv_timebase)
return -EINVAL;
break; break;
case KVM_REG_RISCV_TIMER_REG(time): case KVM_REG_RISCV_TIMER_REG(time):
gt->time_delta = reg_val - get_cycles64(); gt->time_delta = reg_val - get_cycles64();
...@@ -233,7 +234,7 @@ int kvm_riscv_vcpu_set_reg_timer(struct kvm_vcpu *vcpu, ...@@ -233,7 +234,7 @@ int kvm_riscv_vcpu_set_reg_timer(struct kvm_vcpu *vcpu,
ret = kvm_riscv_vcpu_timer_cancel(t); ret = kvm_riscv_vcpu_timer_cancel(t);
break; break;
default: default:
ret = -EINVAL; ret = -ENOENT;
break; break;
} }
......
...@@ -91,95 +91,93 @@ void kvm_riscv_vcpu_free_vector_context(struct kvm_vcpu *vcpu) ...@@ -91,95 +91,93 @@ void kvm_riscv_vcpu_free_vector_context(struct kvm_vcpu *vcpu)
} }
#endif #endif
static void *kvm_riscv_vcpu_vreg_addr(struct kvm_vcpu *vcpu, static int kvm_riscv_vcpu_vreg_addr(struct kvm_vcpu *vcpu,
unsigned long reg_num, unsigned long reg_num,
size_t reg_size) size_t reg_size,
void **reg_addr)
{ {
struct kvm_cpu_context *cntx = &vcpu->arch.guest_context; struct kvm_cpu_context *cntx = &vcpu->arch.guest_context;
void *reg_val;
size_t vlenb = riscv_v_vsize / 32; size_t vlenb = riscv_v_vsize / 32;
if (reg_num < KVM_REG_RISCV_VECTOR_REG(0)) { if (reg_num < KVM_REG_RISCV_VECTOR_REG(0)) {
if (reg_size != sizeof(unsigned long)) if (reg_size != sizeof(unsigned long))
return NULL; return -EINVAL;
switch (reg_num) { switch (reg_num) {
case KVM_REG_RISCV_VECTOR_CSR_REG(vstart): case KVM_REG_RISCV_VECTOR_CSR_REG(vstart):
reg_val = &cntx->vector.vstart; *reg_addr = &cntx->vector.vstart;
break; break;
case KVM_REG_RISCV_VECTOR_CSR_REG(vl): case KVM_REG_RISCV_VECTOR_CSR_REG(vl):
reg_val = &cntx->vector.vl; *reg_addr = &cntx->vector.vl;
break; break;
case KVM_REG_RISCV_VECTOR_CSR_REG(vtype): case KVM_REG_RISCV_VECTOR_CSR_REG(vtype):
reg_val = &cntx->vector.vtype; *reg_addr = &cntx->vector.vtype;
break; break;
case KVM_REG_RISCV_VECTOR_CSR_REG(vcsr): case KVM_REG_RISCV_VECTOR_CSR_REG(vcsr):
reg_val = &cntx->vector.vcsr; *reg_addr = &cntx->vector.vcsr;
break; break;
case KVM_REG_RISCV_VECTOR_CSR_REG(datap): case KVM_REG_RISCV_VECTOR_CSR_REG(datap):
default: default:
return NULL; return -ENOENT;
} }
} else if (reg_num <= KVM_REG_RISCV_VECTOR_REG(31)) { } else if (reg_num <= KVM_REG_RISCV_VECTOR_REG(31)) {
if (reg_size != vlenb) if (reg_size != vlenb)
return NULL; return -EINVAL;
reg_val = cntx->vector.datap *reg_addr = cntx->vector.datap +
+ (reg_num - KVM_REG_RISCV_VECTOR_REG(0)) * vlenb; (reg_num - KVM_REG_RISCV_VECTOR_REG(0)) * vlenb;
} else { } else {
return NULL; return -ENOENT;
} }
return reg_val; return 0;
} }
int kvm_riscv_vcpu_get_reg_vector(struct kvm_vcpu *vcpu, int kvm_riscv_vcpu_get_reg_vector(struct kvm_vcpu *vcpu,
const struct kvm_one_reg *reg, const struct kvm_one_reg *reg)
unsigned long rtype)
{ {
unsigned long *isa = vcpu->arch.isa; unsigned long *isa = vcpu->arch.isa;
unsigned long __user *uaddr = unsigned long __user *uaddr =
(unsigned long __user *)(unsigned long)reg->addr; (unsigned long __user *)(unsigned long)reg->addr;
unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
KVM_REG_SIZE_MASK | KVM_REG_SIZE_MASK |
rtype); KVM_REG_RISCV_VECTOR);
void *reg_val = NULL;
size_t reg_size = KVM_REG_SIZE(reg->id); size_t reg_size = KVM_REG_SIZE(reg->id);
void *reg_addr;
int rc;
if (rtype == KVM_REG_RISCV_VECTOR && if (!riscv_isa_extension_available(isa, v))
riscv_isa_extension_available(isa, v)) { return -ENOENT;
reg_val = kvm_riscv_vcpu_vreg_addr(vcpu, reg_num, reg_size);
}
if (!reg_val) rc = kvm_riscv_vcpu_vreg_addr(vcpu, reg_num, reg_size, &reg_addr);
return -EINVAL; if (rc)
return rc;
if (copy_to_user(uaddr, reg_val, reg_size)) if (copy_to_user(uaddr, reg_addr, reg_size))
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
int kvm_riscv_vcpu_set_reg_vector(struct kvm_vcpu *vcpu, int kvm_riscv_vcpu_set_reg_vector(struct kvm_vcpu *vcpu,
const struct kvm_one_reg *reg, const struct kvm_one_reg *reg)
unsigned long rtype)
{ {
unsigned long *isa = vcpu->arch.isa; unsigned long *isa = vcpu->arch.isa;
unsigned long __user *uaddr = unsigned long __user *uaddr =
(unsigned long __user *)(unsigned long)reg->addr; (unsigned long __user *)(unsigned long)reg->addr;
unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
KVM_REG_SIZE_MASK | KVM_REG_SIZE_MASK |
rtype); KVM_REG_RISCV_VECTOR);
void *reg_val = NULL;
size_t reg_size = KVM_REG_SIZE(reg->id); size_t reg_size = KVM_REG_SIZE(reg->id);
void *reg_addr;
int rc;
if (rtype == KVM_REG_RISCV_VECTOR && if (!riscv_isa_extension_available(isa, v))
riscv_isa_extension_available(isa, v)) { return -ENOENT;
reg_val = kvm_riscv_vcpu_vreg_addr(vcpu, reg_num, reg_size);
}
if (!reg_val) rc = kvm_riscv_vcpu_vreg_addr(vcpu, reg_num, reg_size, &reg_addr);
return -EINVAL; if (rc)
return rc;
if (copy_from_user(reg_val, uaddr, reg_size)) if (copy_from_user(reg_addr, uaddr, reg_size))
return -EFAULT; return -EFAULT;
return 0; return 0;
......
...@@ -817,6 +817,8 @@ struct kvm_s390_cpu_model { ...@@ -817,6 +817,8 @@ struct kvm_s390_cpu_model {
__u64 *fac_list; __u64 *fac_list;
u64 cpuid; u64 cpuid;
unsigned short ibc; unsigned short ibc;
/* subset of available UV-features for pv-guests enabled by user space */
struct kvm_s390_vm_cpu_uv_feat uv_feat_guest;
}; };
typedef int (*crypto_hook)(struct kvm_vcpu *vcpu); typedef int (*crypto_hook)(struct kvm_vcpu *vcpu);
......
...@@ -99,6 +99,8 @@ enum uv_cmds_inst { ...@@ -99,6 +99,8 @@ enum uv_cmds_inst {
enum uv_feat_ind { enum uv_feat_ind {
BIT_UV_FEAT_MISC = 0, BIT_UV_FEAT_MISC = 0,
BIT_UV_FEAT_AIV = 1, BIT_UV_FEAT_AIV = 1,
BIT_UV_FEAT_AP = 4,
BIT_UV_FEAT_AP_INTR = 5,
}; };
struct uv_cb_header { struct uv_cb_header {
...@@ -159,7 +161,15 @@ struct uv_cb_cgc { ...@@ -159,7 +161,15 @@ struct uv_cb_cgc {
u64 guest_handle; u64 guest_handle;
u64 conf_base_stor_origin; u64 conf_base_stor_origin;
u64 conf_virt_stor_origin; u64 conf_virt_stor_origin;
u64 reserved30; u8 reserved30[6];
union {
struct {
u16 : 14;
u16 ap_instr_intr : 1;
u16 ap_allow_instr : 1;
};
u16 raw;
} flags;
u64 guest_stor_origin; u64 guest_stor_origin;
u64 guest_stor_len; u64 guest_stor_len;
u64 guest_sca; u64 guest_sca;
...@@ -397,6 +407,13 @@ struct uv_info { ...@@ -397,6 +407,13 @@ struct uv_info {
extern struct uv_info uv_info; extern struct uv_info uv_info;
static inline bool uv_has_feature(u8 feature_bit)
{
if (feature_bit >= sizeof(uv_info.uv_feature_indications) * 8)
return false;
return test_bit_inv(feature_bit, &uv_info.uv_feature_indications);
}
#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST #ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
extern int prot_virt_guest; extern int prot_virt_guest;
......
...@@ -159,6 +159,22 @@ struct kvm_s390_vm_cpu_subfunc { ...@@ -159,6 +159,22 @@ struct kvm_s390_vm_cpu_subfunc {
__u8 reserved[1728]; __u8 reserved[1728];
}; };
#define KVM_S390_VM_CPU_PROCESSOR_UV_FEAT_GUEST 6
#define KVM_S390_VM_CPU_MACHINE_UV_FEAT_GUEST 7
#define KVM_S390_VM_CPU_UV_FEAT_NR_BITS 64
struct kvm_s390_vm_cpu_uv_feat {
union {
struct {
__u64 : 4;
__u64 ap : 1; /* bit 4 */
__u64 ap_intr : 1; /* bit 5 */
__u64 : 58;
};
__u64 feat;
};
};
/* kvm attributes for crypto */ /* kvm attributes for crypto */
#define KVM_S390_VM_CRYPTO_ENABLE_AES_KW 0 #define KVM_S390_VM_CRYPTO_ENABLE_AES_KW 0
#define KVM_S390_VM_CRYPTO_ENABLE_DEA_KW 1 #define KVM_S390_VM_CRYPTO_ENABLE_DEA_KW 1
......
...@@ -258,7 +258,7 @@ static bool should_export_before_import(struct uv_cb_header *uvcb, struct mm_str ...@@ -258,7 +258,7 @@ static bool should_export_before_import(struct uv_cb_header *uvcb, struct mm_str
* shared page from a different protected VM will automatically also * shared page from a different protected VM will automatically also
* transfer its ownership. * transfer its ownership.
*/ */
if (test_bit_inv(BIT_UV_FEAT_MISC, &uv_info.uv_feature_indications)) if (uv_has_feature(BIT_UV_FEAT_MISC))
return false; return false;
if (uvcb->cmd == UVC_CMD_UNPIN_PAGE_SHARED) if (uvcb->cmd == UVC_CMD_UNPIN_PAGE_SHARED)
return false; return false;
......
This diff is collapsed.
...@@ -1392,6 +1392,7 @@ int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu) ...@@ -1392,6 +1392,7 @@ int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
{ {
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
int rc = 0; int rc = 0;
bool delivered = false;
unsigned long irq_type; unsigned long irq_type;
unsigned long irqs; unsigned long irqs;
...@@ -1465,6 +1466,19 @@ int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu) ...@@ -1465,6 +1466,19 @@ int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
WARN_ONCE(1, "Unknown pending irq type %ld", irq_type); WARN_ONCE(1, "Unknown pending irq type %ld", irq_type);
clear_bit(irq_type, &li->pending_irqs); clear_bit(irq_type, &li->pending_irqs);
} }
delivered |= !rc;
}
/*
* We delivered at least one interrupt and modified the PC. Force a
* singlestep event now.
*/
if (delivered && guestdbg_sstep_enabled(vcpu)) {
struct kvm_debug_exit_arch *debug_exit = &vcpu->run->debug.arch;
debug_exit->addr = vcpu->arch.sie_block->gpsw.addr;
debug_exit->type = KVM_SINGLESTEP;
vcpu->guest_debug |= KVM_GUESTDBG_EXIT_PENDING;
} }
set_intercept_indicators(vcpu); set_intercept_indicators(vcpu);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment