You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'kvmarm-for-v4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD
KVM/arm updates for 4.19 - Support for Group0 interrupts in guests - Cache management optimizations for ARMv8.4 systems - Userspace interface for RAS, allowing error retrival and injection - Fault path optimization - Emulated physical timer fixes - Random cleanups
This commit is contained in:
@@ -835,11 +835,13 @@ struct kvm_clock_data {
|
||||
|
||||
Capability: KVM_CAP_VCPU_EVENTS
|
||||
Extended by: KVM_CAP_INTR_SHADOW
|
||||
Architectures: x86
|
||||
Type: vm ioctl
|
||||
Architectures: x86, arm, arm64
|
||||
Type: vcpu ioctl
|
||||
Parameters: struct kvm_vcpu_event (out)
|
||||
Returns: 0 on success, -1 on error
|
||||
|
||||
X86:
|
||||
|
||||
Gets currently pending exceptions, interrupts, and NMIs as well as related
|
||||
states of the vcpu.
|
||||
|
||||
@@ -881,15 +883,64 @@ Only two fields are defined in the flags field:
|
||||
- KVM_VCPUEVENT_VALID_SMM may be set in the flags field to signal that
|
||||
smi contains a valid state.
|
||||
|
||||
ARM/ARM64:
|
||||
|
||||
If the guest accesses a device that is being emulated by the host kernel in
|
||||
such a way that a real device would generate a physical SError, KVM may make
|
||||
a virtual SError pending for that VCPU. This system error interrupt remains
|
||||
pending until the guest takes the exception by unmasking PSTATE.A.
|
||||
|
||||
Running the VCPU may cause it to take a pending SError, or make an access that
|
||||
causes an SError to become pending. The event's description is only valid while
|
||||
the VPCU is not running.
|
||||
|
||||
This API provides a way to read and write the pending 'event' state that is not
|
||||
visible to the guest. To save, restore or migrate a VCPU the struct representing
|
||||
the state can be read then written using this GET/SET API, along with the other
|
||||
guest-visible registers. It is not possible to 'cancel' an SError that has been
|
||||
made pending.
|
||||
|
||||
A device being emulated in user-space may also wish to generate an SError. To do
|
||||
this the events structure can be populated by user-space. The current state
|
||||
should be read first, to ensure no existing SError is pending. If an existing
|
||||
SError is pending, the architecture's 'Multiple SError interrupts' rules should
|
||||
be followed. (2.5.3 of DDI0587.a "ARM Reliability, Availability, and
|
||||
Serviceability (RAS) Specification").
|
||||
|
||||
SError exceptions always have an ESR value. Some CPUs have the ability to
|
||||
specify what the virtual SError's ESR value should be. These systems will
|
||||
advertise KVM_CAP_ARM_SET_SERROR_ESR. In this case exception.has_esr will
|
||||
always have a non-zero value when read, and the agent making an SError pending
|
||||
should specify the ISS field in the lower 24 bits of exception.serror_esr. If
|
||||
the system supports KVM_CAP_ARM_SET_SERROR_ESR, but user-space sets the events
|
||||
with exception.has_esr as zero, KVM will choose an ESR.
|
||||
|
||||
Specifying exception.has_esr on a system that does not support it will return
|
||||
-EINVAL. Setting anything other than the lower 24bits of exception.serror_esr
|
||||
will return -EINVAL.
|
||||
|
||||
struct kvm_vcpu_events {
|
||||
struct {
|
||||
__u8 serror_pending;
|
||||
__u8 serror_has_esr;
|
||||
/* Align it to 8 bytes */
|
||||
__u8 pad[6];
|
||||
__u64 serror_esr;
|
||||
} exception;
|
||||
__u32 reserved[12];
|
||||
};
|
||||
|
||||
4.32 KVM_SET_VCPU_EVENTS
|
||||
|
||||
Capability: KVM_CAP_VCPU_EVENTS
|
||||
Extended by: KVM_CAP_INTR_SHADOW
|
||||
Architectures: x86
|
||||
Type: vm ioctl
|
||||
Architectures: x86, arm, arm64
|
||||
Type: vcpu ioctl
|
||||
Parameters: struct kvm_vcpu_event (in)
|
||||
Returns: 0 on success, -1 on error
|
||||
|
||||
X86:
|
||||
|
||||
Set pending exceptions, interrupts, and NMIs as well as related states of the
|
||||
vcpu.
|
||||
|
||||
@@ -910,6 +961,13 @@ shall be written into the VCPU.
|
||||
|
||||
KVM_VCPUEVENT_VALID_SMM can only be set if KVM_CAP_X86_SMM is available.
|
||||
|
||||
ARM/ARM64:
|
||||
|
||||
Set the pending SError exception state for this VCPU. It is not possible to
|
||||
'cancel' an Serror that has been made pending.
|
||||
|
||||
See KVM_GET_VCPU_EVENTS for the data structure.
|
||||
|
||||
|
||||
4.33 KVM_GET_DEBUGREGS
|
||||
|
||||
@@ -4690,3 +4748,17 @@ This capability indicates that KVM supports paravirtualized Hyper-V TLB Flush
|
||||
hypercalls:
|
||||
HvFlushVirtualAddressSpace, HvFlushVirtualAddressSpaceEx,
|
||||
HvFlushVirtualAddressList, HvFlushVirtualAddressListEx.
|
||||
|
||||
8.19 KVM_CAP_ARM_SET_SERROR_ESR
|
||||
|
||||
Architectures: arm, arm64
|
||||
|
||||
This capability indicates that userspace can specify (via the
|
||||
KVM_SET_VCPU_EVENTS ioctl) the syndrome value reported to the guest when it
|
||||
takes a virtual SError interrupt exception.
|
||||
If KVM advertises this capability, userspace can only specify the ISS field for
|
||||
the ESR syndrome. Other parts of the ESR, such as the EC are generated by the
|
||||
CPU when the exception is taken. If this virtual SError is taken to EL1 using
|
||||
AArch64, this value will be reported in the ISS field of ESR_ELx.
|
||||
|
||||
See KVM_CAP_VCPU_EVENTS for more details.
|
||||
|
||||
@@ -100,6 +100,14 @@ Groups:
|
||||
Note that distributor fields are not banked, but return the same value
|
||||
regardless of the mpidr used to access the register.
|
||||
|
||||
GICD_IIDR.Revision is updated when the KVM implementation is changed in a
|
||||
way directly observable by the guest or userspace. Userspace should read
|
||||
GICD_IIDR from KVM and write back the read value to confirm its expected
|
||||
behavior is aligned with the KVM implementation. Userspace should set
|
||||
GICD_IIDR before setting any other registers to ensure the expected
|
||||
behavior.
|
||||
|
||||
|
||||
The GICD_STATUSR and GICR_STATUSR registers are architecturally defined such
|
||||
that a write of a clear bit has no effect, whereas a write with a set bit
|
||||
clears that value. To allow userspace to freely set the values of these two
|
||||
|
||||
@@ -49,9 +49,15 @@ Groups:
|
||||
index is specified with the vcpu_index field. Note that most distributor
|
||||
fields are not banked, but return the same value regardless of the
|
||||
vcpu_index used to access the register.
|
||||
Limitations:
|
||||
- Priorities are not implemented, and registers are RAZ/WI
|
||||
- Currently only implemented for KVM_DEV_TYPE_ARM_VGIC_V2.
|
||||
|
||||
GICD_IIDR.Revision is updated when the KVM implementation of an emulated
|
||||
GICv2 is changed in a way directly observable by the guest or userspace.
|
||||
Userspace should read GICD_IIDR from KVM and write back the read value to
|
||||
confirm its expected behavior is aligned with the KVM implementation.
|
||||
Userspace should set GICD_IIDR before setting any other registers (both
|
||||
KVM_DEV_ARM_VGIC_GRP_DIST_REGS and KVM_DEV_ARM_VGIC_GRP_CPU_REGS) to ensure
|
||||
the expected behavior. Unless GICD_IIDR has been set from userspace, writes
|
||||
to the interrupt group registers (GICD_IGROUPR) are ignored.
|
||||
Errors:
|
||||
-ENXIO: Getting or setting this register is not yet supported
|
||||
-EBUSY: One or more VCPUs are running
|
||||
@@ -94,9 +100,6 @@ Groups:
|
||||
use the lower 5 bits to communicate with the KVM device and must shift the
|
||||
value left by 3 places to obtain the actual priority mask level.
|
||||
|
||||
Limitations:
|
||||
- Priorities are not implemented, and registers are RAZ/WI
|
||||
- Currently only implemented for KVM_DEV_TYPE_ARM_VGIC_V2.
|
||||
Errors:
|
||||
-ENXIO: Getting or setting this register is not yet supported
|
||||
-EBUSY: One or more VCPUs are running
|
||||
|
||||
@@ -107,9 +107,19 @@ static inline unsigned long *vcpu_hcr(const struct kvm_vcpu *vcpu)
|
||||
return (unsigned long *)&vcpu->arch.hcr;
|
||||
}
|
||||
|
||||
static inline void vcpu_clear_wfe_traps(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
vcpu->arch.hcr &= ~HCR_TWE;
|
||||
}
|
||||
|
||||
static inline void vcpu_set_wfe_traps(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
vcpu->arch.hcr |= HCR_TWE;
|
||||
}
|
||||
|
||||
static inline bool vcpu_mode_is_32bit(const struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline unsigned long *vcpu_pc(struct kvm_vcpu *vcpu)
|
||||
|
||||
@@ -216,6 +216,11 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
|
||||
int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
|
||||
unsigned long kvm_call_hyp(void *hypfn, ...);
|
||||
void force_vm_exit(const cpumask_t *mask);
|
||||
int __kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu,
|
||||
struct kvm_vcpu_events *events);
|
||||
|
||||
int __kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
|
||||
struct kvm_vcpu_events *events);
|
||||
|
||||
#define KVM_ARCH_WANT_MMU_NOTIFIER
|
||||
int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
|
||||
|
||||
@@ -75,17 +75,9 @@ phys_addr_t kvm_get_idmap_vector(void);
|
||||
int kvm_mmu_init(void);
|
||||
void kvm_clear_hyp_idmap(void);
|
||||
|
||||
static inline void kvm_set_pmd(pmd_t *pmd, pmd_t new_pmd)
|
||||
{
|
||||
*pmd = new_pmd;
|
||||
dsb(ishst);
|
||||
}
|
||||
|
||||
static inline void kvm_set_pte(pte_t *pte, pte_t new_pte)
|
||||
{
|
||||
*pte = new_pte;
|
||||
dsb(ishst);
|
||||
}
|
||||
#define kvm_mk_pmd(ptep) __pmd(__pa(ptep) | PMD_TYPE_TABLE)
|
||||
#define kvm_mk_pud(pmdp) __pud(__pa(pmdp) | PMD_TYPE_TABLE)
|
||||
#define kvm_mk_pgd(pudp) ({ BUILD_BUG(); 0; })
|
||||
|
||||
static inline pte_t kvm_s2pte_mkwrite(pte_t pte)
|
||||
{
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#define __KVM_HAVE_GUEST_DEBUG
|
||||
#define __KVM_HAVE_IRQ_LINE
|
||||
#define __KVM_HAVE_READONLY_MEM
|
||||
#define __KVM_HAVE_VCPU_EVENTS
|
||||
|
||||
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
|
||||
|
||||
@@ -125,6 +126,18 @@ struct kvm_sync_regs {
|
||||
struct kvm_arch_memory_slot {
|
||||
};
|
||||
|
||||
/* for KVM_GET/SET_VCPU_EVENTS */
|
||||
struct kvm_vcpu_events {
|
||||
struct {
|
||||
__u8 serror_pending;
|
||||
__u8 serror_has_esr;
|
||||
/* Align it to 8 bytes */
|
||||
__u8 pad[6];
|
||||
__u64 serror_esr;
|
||||
} exception;
|
||||
__u32 reserved[12];
|
||||
};
|
||||
|
||||
/* If you need to interpret the index values, here is the key: */
|
||||
#define KVM_REG_ARM_COPROC_MASK 0x000000000FFF0000
|
||||
#define KVM_REG_ARM_COPROC_SHIFT 16
|
||||
|
||||
+24
-1
@@ -246,6 +246,7 @@ static bool access_gic_sgi(struct kvm_vcpu *vcpu,
|
||||
const struct coproc_reg *r)
|
||||
{
|
||||
u64 reg;
|
||||
bool g1;
|
||||
|
||||
if (!p->is_write)
|
||||
return read_from_write_only(vcpu, p);
|
||||
@@ -253,7 +254,25 @@ static bool access_gic_sgi(struct kvm_vcpu *vcpu,
|
||||
reg = (u64)*vcpu_reg(vcpu, p->Rt2) << 32;
|
||||
reg |= *vcpu_reg(vcpu, p->Rt1) ;
|
||||
|
||||
vgic_v3_dispatch_sgi(vcpu, reg);
|
||||
/*
|
||||
* In a system where GICD_CTLR.DS=1, a ICC_SGI0R access generates
|
||||
* Group0 SGIs only, while ICC_SGI1R can generate either group,
|
||||
* depending on the SGI configuration. ICC_ASGI1R is effectively
|
||||
* equivalent to ICC_SGI0R, as there is no "alternative" secure
|
||||
* group.
|
||||
*/
|
||||
switch (p->Op1) {
|
||||
default: /* Keep GCC quiet */
|
||||
case 0: /* ICC_SGI1R */
|
||||
g1 = true;
|
||||
break;
|
||||
case 1: /* ICC_ASGI1R */
|
||||
case 2: /* ICC_SGI0R */
|
||||
g1 = false;
|
||||
break;
|
||||
}
|
||||
|
||||
vgic_v3_dispatch_sgi(vcpu, reg, g1);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -459,6 +478,10 @@ static const struct coproc_reg cp15_regs[] = {
|
||||
|
||||
/* ICC_SGI1R */
|
||||
{ CRm64(12), Op1( 0), is64, access_gic_sgi},
|
||||
/* ICC_ASGI1R */
|
||||
{ CRm64(12), Op1( 1), is64, access_gic_sgi},
|
||||
/* ICC_SGI0R */
|
||||
{ CRm64(12), Op1( 2), is64, access_gic_sgi},
|
||||
|
||||
/* VBAR: swapped by interrupt.S. */
|
||||
{ CRn(12), CRm( 0), Op1( 0), Op2( 0), is32,
|
||||
|
||||
@@ -261,6 +261,29 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
int __kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu,
|
||||
struct kvm_vcpu_events *events)
|
||||
{
|
||||
events->exception.serror_pending = !!(*vcpu_hcr(vcpu) & HCR_VA);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
|
||||
struct kvm_vcpu_events *events)
|
||||
{
|
||||
bool serror_pending = events->exception.serror_pending;
|
||||
bool has_esr = events->exception.serror_has_esr;
|
||||
|
||||
if (serror_pending && has_esr)
|
||||
return -EINVAL;
|
||||
else if (serror_pending)
|
||||
kvm_inject_vabt(vcpu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __attribute_const__ kvm_target_cpu(void)
|
||||
{
|
||||
switch (read_cpuid_part()) {
|
||||
|
||||
@@ -50,7 +50,8 @@
|
||||
#define ARM64_HW_DBM 29
|
||||
#define ARM64_SSBD 30
|
||||
#define ARM64_MISMATCHED_CACHE_TYPE 31
|
||||
#define ARM64_HAS_STAGE2_FWB 32
|
||||
|
||||
#define ARM64_NCAPS 32
|
||||
#define ARM64_NCAPS 33
|
||||
|
||||
#endif /* __ASM_CPUCAPS_H */
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <asm/types.h>
|
||||
|
||||
/* Hyp Configuration Register (HCR) bits */
|
||||
#define HCR_FWB (UL(1) << 46)
|
||||
#define HCR_TEA (UL(1) << 37)
|
||||
#define HCR_TERR (UL(1) << 36)
|
||||
#define HCR_TLOR (UL(1) << 35)
|
||||
|
||||
@@ -63,6 +63,8 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
|
||||
/* trap error record accesses */
|
||||
vcpu->arch.hcr_el2 |= HCR_TERR;
|
||||
}
|
||||
if (cpus_have_const_cap(ARM64_HAS_STAGE2_FWB))
|
||||
vcpu->arch.hcr_el2 |= HCR_FWB;
|
||||
|
||||
if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features))
|
||||
vcpu->arch.hcr_el2 &= ~HCR_RW;
|
||||
@@ -81,6 +83,21 @@ static inline unsigned long *vcpu_hcr(struct kvm_vcpu *vcpu)
|
||||
return (unsigned long *)&vcpu->arch.hcr_el2;
|
||||
}
|
||||
|
||||
static inline void vcpu_clear_wfe_traps(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
vcpu->arch.hcr_el2 &= ~HCR_TWE;
|
||||
}
|
||||
|
||||
static inline void vcpu_set_wfe_traps(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
vcpu->arch.hcr_el2 |= HCR_TWE;
|
||||
}
|
||||
|
||||
static inline unsigned long vcpu_get_vsesr(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return vcpu->arch.vsesr_el2;
|
||||
}
|
||||
|
||||
static inline void vcpu_set_vsesr(struct kvm_vcpu *vcpu, u64 vsesr)
|
||||
{
|
||||
vcpu->arch.vsesr_el2 = vsesr;
|
||||
|
||||
@@ -350,6 +350,11 @@ 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_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
|
||||
int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
|
||||
int __kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu,
|
||||
struct kvm_vcpu_events *events);
|
||||
|
||||
int __kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
|
||||
struct kvm_vcpu_events *events);
|
||||
|
||||
#define KVM_ARCH_WANT_MMU_NOTIFIER
|
||||
int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
|
||||
@@ -378,16 +383,23 @@ void handle_exit_early(struct kvm_vcpu *vcpu, struct kvm_run *run,
|
||||
int kvm_perf_init(void);
|
||||
int kvm_perf_teardown(void);
|
||||
|
||||
void kvm_set_sei_esr(struct kvm_vcpu *vcpu, u64 syndrome);
|
||||
|
||||
struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
|
||||
|
||||
void __kvm_set_tpidr_el2(u64 tpidr_el2);
|
||||
DECLARE_PER_CPU(kvm_cpu_context_t, kvm_host_cpu_state);
|
||||
|
||||
static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
|
||||
unsigned long hyp_stack_ptr,
|
||||
unsigned long vector_ptr)
|
||||
{
|
||||
u64 tpidr_el2;
|
||||
/*
|
||||
* Calculate the raw per-cpu offset without a translation from the
|
||||
* kernel's mapping to the linear mapping, and store it in tpidr_el2
|
||||
* so that we can use adr_l to access per-cpu variables in EL2.
|
||||
*/
|
||||
u64 tpidr_el2 = ((u64)this_cpu_ptr(&kvm_host_cpu_state) -
|
||||
(u64)kvm_ksym_ref(kvm_host_cpu_state));
|
||||
|
||||
/*
|
||||
* Call initialization code, and switch to the full blown HYP code.
|
||||
@@ -396,17 +408,7 @@ static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
|
||||
* cpus_have_const_cap() wrapper.
|
||||
*/
|
||||
BUG_ON(!static_branch_likely(&arm64_const_caps_ready));
|
||||
__kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr);
|
||||
|
||||
/*
|
||||
* Calculate the raw per-cpu offset without a translation from the
|
||||
* kernel's mapping to the linear mapping, and store it in tpidr_el2
|
||||
* so that we can use adr_l to access per-cpu variables in EL2.
|
||||
*/
|
||||
tpidr_el2 = (u64)this_cpu_ptr(&kvm_host_cpu_state)
|
||||
- (u64)kvm_ksym_ref(kvm_host_cpu_state);
|
||||
|
||||
kvm_call_hyp(__kvm_set_tpidr_el2, tpidr_el2);
|
||||
__kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr, tpidr_el2);
|
||||
}
|
||||
|
||||
static inline bool kvm_arch_check_sve_has_vhe(void)
|
||||
|
||||
@@ -169,8 +169,12 @@ phys_addr_t kvm_get_idmap_vector(void);
|
||||
int kvm_mmu_init(void);
|
||||
void kvm_clear_hyp_idmap(void);
|
||||
|
||||
#define kvm_set_pte(ptep, pte) set_pte(ptep, pte)
|
||||
#define kvm_set_pmd(pmdp, pmd) set_pmd(pmdp, pmd)
|
||||
#define kvm_mk_pmd(ptep) \
|
||||
__pmd(__phys_to_pmd_val(__pa(ptep)) | PMD_TYPE_TABLE)
|
||||
#define kvm_mk_pud(pmdp) \
|
||||
__pud(__phys_to_pud_val(__pa(pmdp)) | PMD_TYPE_TABLE)
|
||||
#define kvm_mk_pgd(pudp) \
|
||||
__pgd(__phys_to_pgd_val(__pa(pudp)) | PUD_TYPE_TABLE)
|
||||
|
||||
static inline pte_t kvm_s2pte_mkwrite(pte_t pte)
|
||||
{
|
||||
@@ -267,6 +271,15 @@ static inline void __clean_dcache_guest_page(kvm_pfn_t pfn, unsigned long size)
|
||||
{
|
||||
void *va = page_address(pfn_to_page(pfn));
|
||||
|
||||
/*
|
||||
* With FWB, we ensure that the guest always accesses memory using
|
||||
* cacheable attributes, and we don't have to clean to PoC when
|
||||
* faulting in pages. Furthermore, FWB implies IDC, so cleaning to
|
||||
* PoU is not required either in this case.
|
||||
*/
|
||||
if (cpus_have_const_cap(ARM64_HAS_STAGE2_FWB))
|
||||
return;
|
||||
|
||||
kvm_flush_dcache_to_poc(va, size);
|
||||
}
|
||||
|
||||
@@ -287,20 +300,26 @@ static inline void __invalidate_icache_guest_page(kvm_pfn_t pfn,
|
||||
|
||||
static inline void __kvm_flush_dcache_pte(pte_t pte)
|
||||
{
|
||||
struct page *page = pte_page(pte);
|
||||
kvm_flush_dcache_to_poc(page_address(page), PAGE_SIZE);
|
||||
if (!cpus_have_const_cap(ARM64_HAS_STAGE2_FWB)) {
|
||||
struct page *page = pte_page(pte);
|
||||
kvm_flush_dcache_to_poc(page_address(page), PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __kvm_flush_dcache_pmd(pmd_t pmd)
|
||||
{
|
||||
struct page *page = pmd_page(pmd);
|
||||
kvm_flush_dcache_to_poc(page_address(page), PMD_SIZE);
|
||||
if (!cpus_have_const_cap(ARM64_HAS_STAGE2_FWB)) {
|
||||
struct page *page = pmd_page(pmd);
|
||||
kvm_flush_dcache_to_poc(page_address(page), PMD_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __kvm_flush_dcache_pud(pud_t pud)
|
||||
{
|
||||
struct page *page = pud_page(pud);
|
||||
kvm_flush_dcache_to_poc(page_address(page), PUD_SIZE);
|
||||
if (!cpus_have_const_cap(ARM64_HAS_STAGE2_FWB)) {
|
||||
struct page *page = pud_page(pud);
|
||||
kvm_flush_dcache_to_poc(page_address(page), PUD_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
#define kvm_virt_to_phys(x) __pa_symbol(x)
|
||||
|
||||
@@ -155,6 +155,13 @@
|
||||
#define MT_S2_NORMAL 0xf
|
||||
#define MT_S2_DEVICE_nGnRE 0x1
|
||||
|
||||
/*
|
||||
* Memory types for Stage-2 translation when ID_AA64MMFR2_EL1.FWB is 0001
|
||||
* Stage-2 enforces Normal-WB and Device-nGnRE
|
||||
*/
|
||||
#define MT_S2_FWB_NORMAL 6
|
||||
#define MT_S2_FWB_DEVICE_nGnRE 1
|
||||
|
||||
#ifdef CONFIG_ARM64_4K_PAGES
|
||||
#define IOREMAP_MAX_ORDER (PUD_SHIFT)
|
||||
#else
|
||||
|
||||
@@ -67,8 +67,28 @@
|
||||
#define PAGE_HYP_RO __pgprot(_HYP_PAGE_DEFAULT | PTE_HYP | PTE_RDONLY | PTE_HYP_XN)
|
||||
#define PAGE_HYP_DEVICE __pgprot(PROT_DEVICE_nGnRE | PTE_HYP)
|
||||
|
||||
#define PAGE_S2 __pgprot(_PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDONLY | PTE_S2_XN)
|
||||
#define PAGE_S2_DEVICE __pgprot(_PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_DEVICE_nGnRE) | PTE_S2_RDONLY | PTE_S2_XN)
|
||||
#define PAGE_S2_MEMATTR(attr) \
|
||||
({ \
|
||||
u64 __val; \
|
||||
if (cpus_have_const_cap(ARM64_HAS_STAGE2_FWB)) \
|
||||
__val = PTE_S2_MEMATTR(MT_S2_FWB_ ## attr); \
|
||||
else \
|
||||
__val = PTE_S2_MEMATTR(MT_S2_ ## attr); \
|
||||
__val; \
|
||||
})
|
||||
|
||||
#define PAGE_S2_XN \
|
||||
({ \
|
||||
u64 __val; \
|
||||
if (cpus_have_const_cap(ARM64_HAS_CACHE_DIC)) \
|
||||
__val = 0; \
|
||||
else \
|
||||
__val = PTE_S2_XN; \
|
||||
__val; \
|
||||
})
|
||||
|
||||
#define PAGE_S2 __pgprot(_PROT_DEFAULT | PAGE_S2_MEMATTR(NORMAL) | PTE_S2_RDONLY | PAGE_S2_XN)
|
||||
#define PAGE_S2_DEVICE __pgprot(_PROT_DEFAULT | PAGE_S2_MEMATTR(DEVICE_nGnRE) | PTE_S2_RDONLY | PAGE_S2_XN)
|
||||
|
||||
#define PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_VALID) | PTE_PROT_NONE | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN)
|
||||
#define PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE)
|
||||
|
||||
@@ -314,6 +314,8 @@
|
||||
#define SYS_ICC_DIR_EL1 sys_reg(3, 0, 12, 11, 1)
|
||||
#define SYS_ICC_RPR_EL1 sys_reg(3, 0, 12, 11, 3)
|
||||
#define SYS_ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5)
|
||||
#define SYS_ICC_ASGI1R_EL1 sys_reg(3, 0, 12, 11, 6)
|
||||
#define SYS_ICC_SGI0R_EL1 sys_reg(3, 0, 12, 11, 7)
|
||||
#define SYS_ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0)
|
||||
#define SYS_ICC_EOIR1_EL1 sys_reg(3, 0, 12, 12, 1)
|
||||
#define SYS_ICC_HPPIR1_EL1 sys_reg(3, 0, 12, 12, 2)
|
||||
@@ -579,6 +581,7 @@
|
||||
#define ID_AA64MMFR1_VMIDBITS_16 2
|
||||
|
||||
/* id_aa64mmfr2 */
|
||||
#define ID_AA64MMFR2_FWB_SHIFT 40
|
||||
#define ID_AA64MMFR2_AT_SHIFT 32
|
||||
#define ID_AA64MMFR2_LVA_SHIFT 16
|
||||
#define ID_AA64MMFR2_IESB_SHIFT 12
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#define __KVM_HAVE_GUEST_DEBUG
|
||||
#define __KVM_HAVE_IRQ_LINE
|
||||
#define __KVM_HAVE_READONLY_MEM
|
||||
#define __KVM_HAVE_VCPU_EVENTS
|
||||
|
||||
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
|
||||
|
||||
@@ -154,6 +155,18 @@ struct kvm_sync_regs {
|
||||
struct kvm_arch_memory_slot {
|
||||
};
|
||||
|
||||
/* for KVM_GET/SET_VCPU_EVENTS */
|
||||
struct kvm_vcpu_events {
|
||||
struct {
|
||||
__u8 serror_pending;
|
||||
__u8 serror_has_esr;
|
||||
/* Align it to 8 bytes */
|
||||
__u8 pad[6];
|
||||
__u64 serror_esr;
|
||||
} exception;
|
||||
__u32 reserved[12];
|
||||
};
|
||||
|
||||
/* If you need to interpret the index values, here is the key: */
|
||||
#define KVM_REG_ARM_COPROC_MASK 0x000000000FFF0000
|
||||
#define KVM_REG_ARM_COPROC_SHIFT 16
|
||||
|
||||
@@ -192,6 +192,7 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr1[] = {
|
||||
};
|
||||
|
||||
static const struct arm64_ftr_bits ftr_id_aa64mmfr2[] = {
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_FWB_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_AT_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_LVA_SHIFT, 4, 0),
|
||||
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_IESB_SHIFT, 4, 0),
|
||||
@@ -1026,6 +1027,14 @@ static void cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void cpu_has_fwb(const struct arm64_cpu_capabilities *__unused)
|
||||
{
|
||||
u64 val = read_sysreg_s(SYS_CLIDR_EL1);
|
||||
|
||||
/* Check that CLIDR_EL1.LOU{U,IS} are both 0 */
|
||||
WARN_ON(val & (7 << 27 | 7 << 21));
|
||||
}
|
||||
|
||||
static const struct arm64_cpu_capabilities arm64_features[] = {
|
||||
{
|
||||
.desc = "GIC system register CPU interface",
|
||||
@@ -1182,6 +1191,17 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
|
||||
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
|
||||
.matches = has_cache_dic,
|
||||
},
|
||||
{
|
||||
.desc = "Stage-2 Force Write-Back",
|
||||
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
|
||||
.capability = ARM64_HAS_STAGE2_FWB,
|
||||
.sys_reg = SYS_ID_AA64MMFR2_EL1,
|
||||
.sign = FTR_UNSIGNED,
|
||||
.field_pos = ID_AA64MMFR2_FWB_SHIFT,
|
||||
.min_field_value = 1,
|
||||
.matches = has_cpuid_feature,
|
||||
.cpu_enable = cpu_has_fwb,
|
||||
},
|
||||
#ifdef CONFIG_ARM64_HW_AFDBM
|
||||
{
|
||||
/*
|
||||
|
||||
@@ -289,6 +289,39 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int __kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu,
|
||||
struct kvm_vcpu_events *events)
|
||||
{
|
||||
events->exception.serror_pending = !!(vcpu->arch.hcr_el2 & HCR_VSE);
|
||||
events->exception.serror_has_esr = cpus_have_const_cap(ARM64_HAS_RAS_EXTN);
|
||||
|
||||
if (events->exception.serror_pending && events->exception.serror_has_esr)
|
||||
events->exception.serror_esr = vcpu_get_vsesr(vcpu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
|
||||
struct kvm_vcpu_events *events)
|
||||
{
|
||||
bool serror_pending = events->exception.serror_pending;
|
||||
bool has_esr = events->exception.serror_has_esr;
|
||||
|
||||
if (serror_pending && has_esr) {
|
||||
if (!cpus_have_const_cap(ARM64_HAS_RAS_EXTN))
|
||||
return -EINVAL;
|
||||
|
||||
if (!((events->exception.serror_esr) & ~ESR_ELx_ISS_MASK))
|
||||
kvm_set_sei_esr(vcpu, events->exception.serror_esr);
|
||||
else
|
||||
return -EINVAL;
|
||||
} else if (serror_pending) {
|
||||
kvm_inject_vabt(vcpu);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __attribute_const__ kvm_target_cpu(void)
|
||||
{
|
||||
unsigned long implementor = read_cpuid_implementor();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user