Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions Documentation/arch/arm64/booting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,18 @@ Before jumping into the kernel, the following conditions must be met:

- MDCR_EL3.TPM (bit 6) must be initialized to 0b0

For CPUs with support for 64-byte loads and stores without status (FEAT_LS64):

- If the kernel is entered at EL1 and EL2 is present:

- HCRX_EL2.EnALS (bit 1) must be initialised to 0b1.

For CPUs with support for 64-byte stores with status (FEAT_LS64_V):

- If the kernel is entered at EL1 and EL2 is present:

- HCRX_EL2.EnASR (bit 2) must be initialised to 0b1.

The requirements described above for CPU mode, caches, MMUs, architected
timers, coherency and system registers apply to all CPUs. All CPUs must
enter the kernel in the same exception level. Where the values documented
Expand Down
7 changes: 7 additions & 0 deletions Documentation/arch/arm64/elf_hwcaps.rst
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,13 @@ HWCAP3_MTE_STORE_ONLY
HWCAP3_LSFE
Functionality implied by ID_AA64ISAR3_EL1.LSFE == 0b0001

HWCAP3_LS64
Functionality implied by ID_AA64ISAR1_EL1.LS64 == 0b0001. Note that
the function of instruction ld64b/st64b requires support by CPU, system
and target (device) memory location and HWCAP3_LS64 implies the support
of CPU. User should only use ld64b/st64b on supported target (device)
memory location, otherwise fallback to the non-atomic alternatives.


4. Unused AT_HWCAP bits
-----------------------
Expand Down
90 changes: 83 additions & 7 deletions Documentation/virt/kvm/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1303,12 +1303,13 @@ userspace, for example because of missing instruction syndrome decode
information or because there is no device mapped at the accessed IPA, then
userspace can ask the kernel to inject an external abort using the address
from the exiting fault on the VCPU. It is a programming error to set
ext_dabt_pending after an exit which was not either KVM_EXIT_MMIO or
KVM_EXIT_ARM_NISV. This feature is only available if the system supports
KVM_CAP_ARM_INJECT_EXT_DABT. This is a helper which provides commonality in
how userspace reports accesses for the above cases to guests, across different
userspace implementations. Nevertheless, userspace can still emulate all Arm
exceptions by manipulating individual registers using the KVM_SET_ONE_REG API.
ext_dabt_pending after an exit which was not either KVM_EXIT_MMIO,
KVM_EXIT_ARM_NISV, or KVM_EXIT_ARM_LDST64B. This feature is only available if
the system supports KVM_CAP_ARM_INJECT_EXT_DABT. This is a helper which
provides commonality in how userspace reports accesses for the above cases to
guests, across different userspace implementations. Nevertheless, userspace
can still emulate all Arm exceptions by manipulating individual registers
using the KVM_SET_ONE_REG API.

See KVM_GET_VCPU_EVENTS for the data structure.

Expand Down Expand Up @@ -7050,12 +7051,14 @@ in send_page or recv a buffer to recv_page).

::

/* KVM_EXIT_ARM_NISV */
/* KVM_EXIT_ARM_NISV / KVM_EXIT_ARM_LDST64B */
struct {
__u64 esr_iss;
__u64 fault_ipa;
} arm_nisv;

- KVM_EXIT_ARM_NISV:

Used on arm64 systems. If a guest accesses memory not in a memslot,
KVM will typically return to userspace and ask it to do MMIO emulation on its
behalf. However, for certain classes of instructions, no instruction decode
Expand Down Expand Up @@ -7089,6 +7092,32 @@ Note that although KVM_CAP_ARM_NISV_TO_USER will be reported if
queried outside of a protected VM context, the feature will not be
exposed if queried on a protected VM file descriptor.

- KVM_EXIT_ARM_LDST64B:

Used on arm64 systems. When a guest using a LD64B, ST64B, ST64BV, ST64BV0,
outside of a memslot, KVM will return to userspace with KVM_EXIT_ARM_LDST64B,
exposing the relevant ESR_EL2 information and faulting IPA, similarly to
KVM_EXIT_ARM_NISV.

Userspace is supposed to fully emulate the instructions, which includes:

- fetch of the operands for a store, including ACCDATA_EL1 in the case
of a ST64BV0 instruction
- deal with the endianness if the guest is big-endian
- emulate the access, including the delivery of an exception if the
access didn't succeed
- provide a return value in the case of ST64BV/ST64BV0
- return the data in the case of a load
- increment PC if the instruction was successfully executed

Note that there is no expectation of performance for this emulation, as it
involves a large number of interaction with the guest state. It is, however,
expected that the instruction's semantics are preserved, specially the
single-copy atomicity property of the 64 byte access.

This exit reason must be handled if userspace sets ID_AA64ISAR1_EL1.LS64 to a
non-zero value, indicating that FEAT_LS64* is enabled.

::

/* KVM_EXIT_X86_RDMSR / KVM_EXIT_X86_WRMSR */
Expand Down Expand Up @@ -7286,6 +7315,41 @@ exit, even without calls to ``KVM_ENABLE_CAP`` or similar. In this case,
it will enter with output fields already valid; in the common case, the
``unknown.ret`` field of the union will be ``TDVMCALL_STATUS_SUBFUNC_UNSUPPORTED``.
Userspace need not do anything if it does not wish to support a TDVMCALL.

::

/* KVM_EXIT_ARM_SEA */
struct {
#define KVM_EXIT_ARM_SEA_FLAG_GPA_VALID (1ULL << 0)
__u64 flags;
__u64 esr;
__u64 gva;
__u64 gpa;
} arm_sea;

Used on arm64 systems. When the VM capability ``KVM_CAP_ARM_SEA_TO_USER`` is
enabled, a KVM exits to userspace if a guest access causes a synchronous
external abort (SEA) and the host APEI fails to handle the SEA.

``esr`` is set to a sanitized value of ESR_EL2 from the exception taken to KVM,
consisting of the following fields:

- ``ESR_EL2.EC``
- ``ESR_EL2.IL``
- ``ESR_EL2.FnV``
- ``ESR_EL2.EA``
- ``ESR_EL2.CM``
- ``ESR_EL2.WNR``
- ``ESR_EL2.FSC``
- ``ESR_EL2.SET`` (when FEAT_RAS is implemented for the VM)

``gva`` is set to the value of FAR_EL2 from the exception taken to KVM when
``ESR_EL2.FnV == 0``. Otherwise, the value of ``gva`` is unknown.

``gpa`` is set to the faulting IPA from the exception taken to KVM when
the ``KVM_EXIT_ARM_SEA_FLAG_GPA_VALID`` flag is set. Otherwise, the value of
``gpa`` is unknown.

::

/* Fix the size of the union. */
Expand Down Expand Up @@ -8703,6 +8767,18 @@ This capability indicate to the userspace whether a PFNMAP memory region
can be safely mapped as cacheable. This relies on the presence of
force write back (FWB) feature support on the hardware.

7.45 KVM_CAP_ARM_SEA_TO_USER
----------------------------

:Architecture: arm64
:Target: VM
:Parameters: none
:Returns: 0 on success, -EINVAL if unsupported.

When this capability is enabled, KVM may exit to userspace for SEAs taken to
EL2 resulting from a guest access. See ``KVM_EXIT_ARM_SEA`` for more
information.

8. Other capabilities.
======================

Expand Down
30 changes: 30 additions & 0 deletions arch/arm64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1695,6 +1695,36 @@ config ARM64_TAGGED_ADDR_ABI
to system calls as pointer arguments. For details, see
Documentation/arch/arm64/tagged-address-abi.rst.

config ARM64_WORKAROUND_NC_TO_NGNRE
bool "Workaround: Convert MT_NORMAL_NC to Device-nGnRE"
default y
help
This option enables a workaround that converts the MT_NORMAL_NC
(Non-Cacheable) memory attribute to Device-nGnRE memory type in
MAIR_EL1 (Memory Attribute Indirection Register).

This workaround is useful for hardware that requires stricter
memory ordering or has issues with Non-Cacheable memory mappings.

A new memory type index MT_NORMAL_NC_DMA (Attr5) has been introduced
specifically for DMA coherent memory mappings (pgprot_dmacoherent),
configured with the same Normal Non-Cacheable attribute (0x44) as
MT_NORMAL_NC (Attr2). When this workaround is enabled, it converts
the NC attribute to Device-nGnRE (0x04), and pgprot_dmacoherent
behavior remains the same as before.

The workaround uses the ARM64 alternatives framework for efficient
runtime patching with no performance overhead when disabled.

This workaround can only be enabled at boot time via kernel command
line parameter. Runtime changes are not supported because CPU
alternatives cannot be re-patched after boot.

Boot-time activation (kernel command line):
mair_el1_nc_to_ngnre=1

If unsure, say Y.

menuconfig COMPAT
bool "Kernel support for 32-bit EL0"
depends on ARM64_4K_PAGES || EXPERT
Expand Down
2 changes: 2 additions & 0 deletions arch/arm64/include/asm/cpucaps.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ cpucap_is_possible(const unsigned int cap)
return true;
case ARM64_HAS_PMUV3:
return IS_ENABLED(CONFIG_HW_PERF_EVENTS);
case ARM64_WORKAROUND_NC_TO_NGNRE:
return IS_ENABLED(CONFIG_ARM64_WORKAROUND_NC_TO_NGNRE);
}

return true;
Expand Down
12 changes: 11 additions & 1 deletion arch/arm64/include/asm/el2_setup.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,19 @@
/* Enable GCS if supported */
mrs_s x1, SYS_ID_AA64PFR1_EL1
ubfx x1, x1, #ID_AA64PFR1_EL1_GCS_SHIFT, #4
cbz x1, .Lset_hcrx_\@
cbz x1, .Lskip_gcs_hcrx_\@
orr x0, x0, #HCRX_EL2_GCSEn

.Lskip_gcs_hcrx_\@:
/* Enable LS64, LS64_V if supported */
mrs_s x1, SYS_ID_AA64ISAR1_EL1
ubfx x1, x1, #ID_AA64ISAR1_EL1_LS64_SHIFT, #4
cbz x1, .Lset_hcrx_\@
orr x0, x0, #HCRX_EL2_EnALS
cmp x1, #ID_AA64ISAR1_EL1_LS64_LS64_V
b.lt .Lset_hcrx_\@
orr x0, x0, #HCRX_EL2_EnASR

.Lset_hcrx_\@:
msr_s SYS_HCRX_EL2, x0
.Lskip_hcrx_\@:
Expand Down
8 changes: 8 additions & 0 deletions arch/arm64/include/asm/esr.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
#define ESR_ELx_FSC_SEA_TTW(n) (0x14 + (n))
#define ESR_ELx_FSC_SECC (0x18)
#define ESR_ELx_FSC_SECC_TTW(n) (0x1c + (n))
#define ESR_ELx_FSC_EXCL_ATOMIC (0x35)
#define ESR_ELx_FSC_ADDRSZ (0x00)

/*
Expand Down Expand Up @@ -488,6 +489,13 @@ static inline bool esr_fsc_is_access_flag_fault(unsigned long esr)
(esr == ESR_ELx_FSC_ACCESS_L(0));
}

static inline bool esr_fsc_is_excl_atomic_fault(unsigned long esr)
{
esr = esr & ESR_ELx_FSC;

return esr == ESR_ELx_FSC_EXCL_ATOMIC;
}

static inline bool esr_fsc_is_addr_sz_fault(unsigned long esr)
{
esr &= ESR_ELx_FSC;
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/include/asm/hwcap.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@
#define KERNEL_HWCAP_MTE_FAR __khwcap3_feature(MTE_FAR)
#define KERNEL_HWCAP_MTE_STORE_ONLY __khwcap3_feature(MTE_STORE_ONLY)
#define KERNEL_HWCAP_LSFE __khwcap3_feature(LSFE)
#define KERNEL_HWCAP_LS64 __khwcap3_feature(LS64)

/*
* This yields a mask that user programs can use to figure out what
Expand Down
7 changes: 7 additions & 0 deletions arch/arm64/include/asm/kvm_emulate.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ void kvm_skip_instr32(struct kvm_vcpu *vcpu);
void kvm_inject_undefined(struct kvm_vcpu *vcpu);
int kvm_inject_serror_esr(struct kvm_vcpu *vcpu, u64 esr);
int kvm_inject_sea(struct kvm_vcpu *vcpu, bool iabt, u64 addr);
int kvm_inject_dabt_excl_atomic(struct kvm_vcpu *vcpu, u64 addr);
void kvm_inject_size_fault(struct kvm_vcpu *vcpu);

static inline int kvm_inject_sea_dabt(struct kvm_vcpu *vcpu, u64 addr)
Expand Down Expand Up @@ -694,6 +695,12 @@ static inline void vcpu_set_hcrx(struct kvm_vcpu *vcpu)

if (kvm_has_sctlr2(kvm))
vcpu->arch.hcrx_el2 |= HCRX_EL2_SCTLR2En;

if (kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64))
vcpu->arch.hcrx_el2 |= HCRX_EL2_EnALS;

if (kvm_has_feat(kvm, ID_AA64ISAR1_EL1, LS64, LS64_V))
vcpu->arch.hcrx_el2 |= HCRX_EL2_EnASR;
}
}
#endif /* __ARM64_KVM_EMULATE_H__ */
2 changes: 2 additions & 0 deletions arch/arm64/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,8 @@ struct kvm_arch {
#define KVM_ARCH_FLAG_GUEST_HAS_SVE 9
/* MIDR_EL1, REVIDR_EL1, and AIDR_EL1 are writable from userspace */
#define KVM_ARCH_FLAG_WRITABLE_IMP_ID_REGS 10
/* Unhandled SEAs are taken to userspace */
#define KVM_ARCH_FLAG_EXIT_SEA 11
unsigned long flags;

/* VM-wide vCPU feature set */
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/include/asm/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@
#define MT_NORMAL_NC 2
#define MT_DEVICE_nGnRnE 3
#define MT_DEVICE_nGnRE 4
#define MT_NORMAL_NC_DMA 5

/*
* Memory types for Stage-2 translation
Expand Down
6 changes: 6 additions & 0 deletions arch/arm64/include/asm/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -800,9 +800,15 @@ static inline void __set_puds(struct mm_struct *mm,
* requires strict alignment and can also force write responses to come from the
* endpoint.
*/
#ifdef CONFIG_ARM64_WORKAROUND_NC_TO_NGNRE
#define pgprot_dmacoherent(prot) \
__pgprot_modify(prot, PTE_ATTRINDX_MASK, \
PTE_ATTRINDX(MT_NORMAL_NC_DMA) | PTE_PXN | PTE_UXN)
#else
#define pgprot_dmacoherent(prot) \
__pgprot_modify(prot, PTE_ATTRINDX_MASK, \
PTE_ATTRINDX(MT_NORMAL_NC) | PTE_PXN | PTE_UXN)
#endif

#define __HAVE_PHYS_MEM_ACCESS_PROT
struct file;
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/include/uapi/asm/hwcap.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,5 +146,6 @@
#define HWCAP3_MTE_FAR (1UL << 0)
#define HWCAP3_MTE_STORE_ONLY (1UL << 1)
#define HWCAP3_LSFE (1UL << 2)
#define HWCAP3_LS64 (1UL << 3)

#endif /* _UAPI__ASM_HWCAP_H */
Loading