Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
dc2286f3
Commit
dc2286f3
authored
Nov 27, 2020
by
Marc Zyngier
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'kvm-arm64/vector-rework' into kvmarm-master/next
Signed-off-by:
Marc Zyngier
<
maz@kernel.org
>
parents
6e5d8c71
4f6a36fe
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
215 additions
and
260 deletions
+215
-260
Documentation/arm64/memory.rst
Documentation/arm64/memory.rst
+1
-1
arch/arm64/include/asm/cpucaps.h
arch/arm64/include/asm/cpucaps.h
+1
-1
arch/arm64/include/asm/kvm_asm.h
arch/arm64/include/asm/kvm_asm.h
+0
-5
arch/arm64/include/asm/kvm_mmu.h
arch/arm64/include/asm/kvm_mmu.h
+0
-46
arch/arm64/include/asm/mmu.h
arch/arm64/include/asm/mmu.h
+0
-29
arch/arm64/include/asm/spectre.h
arch/arm64/include/asm/spectre.h
+63
-0
arch/arm64/kernel/cpu_errata.c
arch/arm64/kernel/cpu_errata.c
+6
-13
arch/arm64/kernel/proton-pack.c
arch/arm64/kernel/proton-pack.c
+33
-51
arch/arm64/kvm/arm.c
arch/arm64/kvm/arm.c
+68
-34
arch/arm64/kvm/hyp/Makefile
arch/arm64/kvm/hyp/Makefile
+1
-1
arch/arm64/kvm/hyp/hyp-entry.S
arch/arm64/kvm/hyp/hyp-entry.S
+40
-31
arch/arm64/kvm/hyp/smccc_wa.S
arch/arm64/kvm/hyp/smccc_wa.S
+0
-32
arch/arm64/kvm/va_layout.c
arch/arm64/kvm/va_layout.c
+2
-16
No files found.
Documentation/arm64/memory.rst
View file @
dc2286f3
...
...
@@ -100,7 +100,7 @@ hypervisor maps kernel pages in EL2 at a fixed (and potentially
random) offset from the linear mapping. See the kern_hyp_va macro and
kvm_update_va_mask function for more details. MMIO devices such as
GICv2 gets mapped next to the HYP idmap page, as do vectors when
ARM64_
HARDEN_EL2_VECTORS is select
ed for particular CPUs.
ARM64_
SPECTRE_V3A is enabl
ed for particular CPUs.
When using KVM with the Virtualization Host Extensions, no additional
mappings are created, since the host kernel runs directly in EL2.
...
...
arch/arm64/include/asm/cpucaps.h
View file @
dc2286f3
...
...
@@ -21,7 +21,7 @@
#define ARM64_HAS_VIRT_HOST_EXTN 11
#define ARM64_WORKAROUND_CAVIUM_27456 12
#define ARM64_HAS_32BIT_EL0 13
#define ARM64_
HARDEN_EL2_VECTORS
14
#define ARM64_
SPECTRE_V3A
14
#define ARM64_HAS_CNP 15
#define ARM64_HAS_NO_FPSIMD 16
#define ARM64_WORKAROUND_REPEAT_TLBI 17
...
...
arch/arm64/include/asm/kvm_asm.h
View file @
dc2286f3
...
...
@@ -34,8 +34,6 @@
*/
#define KVM_VECTOR_PREAMBLE (2 * AARCH64_INSN_SIZE)
#define __SMCCC_WORKAROUND_1_SMC_SZ 36
#define KVM_HOST_SMCCC_ID(id) \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
ARM_SMCCC_SMC_64, \
...
...
@@ -175,7 +173,6 @@ extern unsigned long kvm_arm_hyp_percpu_base[NR_CPUS];
DECLARE_KVM_NVHE_SYM
(
__per_cpu_start
);
DECLARE_KVM_NVHE_SYM
(
__per_cpu_end
);
extern
atomic_t
arm64_el2_vector_last_slot
;
DECLARE_KVM_HYP_SYM
(
__bp_harden_hyp_vecs
);
#define __bp_harden_hyp_vecs CHOOSE_HYP_SYM(__bp_harden_hyp_vecs)
...
...
@@ -196,8 +193,6 @@ extern void __vgic_v3_init_lrs(void);
extern
u32
__kvm_get_mdcr_el2
(
void
);
extern
char
__smccc_workaround_1_smc
[
__SMCCC_WORKAROUND_1_SMC_SZ
];
/*
* Obtain the PC-relative address of a kernel symbol
* s: symbol
...
...
arch/arm64/include/asm/kvm_mmu.h
View file @
dc2286f3
...
...
@@ -248,52 +248,6 @@ static inline int kvm_write_guest_lock(struct kvm *kvm, gpa_t gpa,
return
ret
;
}
/*
* EL2 vectors can be mapped and rerouted in a number of ways,
* depending on the kernel configuration and CPU present:
*
* - If the CPU is affected by Spectre-v2, the hardening sequence is
* placed in one of the vector slots, which is executed before jumping
* to the real vectors.
*
* - If the CPU also has the ARM64_HARDEN_EL2_VECTORS cap, the slot
* containing the hardening sequence is mapped next to the idmap page,
* and executed before jumping to the real vectors.
*
* - If the CPU only has the ARM64_HARDEN_EL2_VECTORS cap, then an
* empty slot is selected, mapped next to the idmap page, and
* executed before jumping to the real vectors.
*
* Note that ARM64_HARDEN_EL2_VECTORS is somewhat incompatible with
* VHE, as we don't have hypervisor-specific mappings. If the system
* is VHE and yet selects this capability, it will be ignored.
*/
extern
void
*
__kvm_bp_vect_base
;
extern
int
__kvm_harden_el2_vector_slot
;
static
inline
void
*
kvm_get_hyp_vector
(
void
)
{
struct
bp_hardening_data
*
data
=
arm64_get_bp_hardening_data
();
void
*
vect
=
kern_hyp_va
(
kvm_ksym_ref
(
__kvm_hyp_vector
));
int
slot
=
-
1
;
if
(
cpus_have_const_cap
(
ARM64_SPECTRE_V2
)
&&
data
->
fn
)
{
vect
=
kern_hyp_va
(
kvm_ksym_ref
(
__bp_harden_hyp_vecs
));
slot
=
data
->
hyp_vectors_slot
;
}
if
(
this_cpu_has_cap
(
ARM64_HARDEN_EL2_VECTORS
)
&&
!
has_vhe
())
{
vect
=
__kvm_bp_vect_base
;
if
(
slot
==
-
1
)
slot
=
__kvm_harden_el2_vector_slot
;
}
if
(
slot
!=
-
1
)
vect
+=
slot
*
SZ_2K
;
return
vect
;
}
#define kvm_phys_to_vttbr(addr) phys_to_ttbr(addr)
static
__always_inline
u64
kvm_get_vttbr
(
struct
kvm_s2_mmu
*
mmu
)
...
...
arch/arm64/include/asm/mmu.h
View file @
dc2286f3
...
...
@@ -12,9 +12,6 @@
#define USER_ASID_FLAG (UL(1) << USER_ASID_BIT)
#define TTBR_ASID_MASK (UL(0xffff) << 48)
#define BP_HARDEN_EL2_SLOTS 4
#define __BP_HARDEN_HYP_VECS_SZ (BP_HARDEN_EL2_SLOTS * SZ_2K)
#ifndef __ASSEMBLY__
#include <linux/refcount.h>
...
...
@@ -41,32 +38,6 @@ static inline bool arm64_kernel_unmapped_at_el0(void)
return
cpus_have_const_cap
(
ARM64_UNMAP_KERNEL_AT_EL0
);
}
typedef
void
(
*
bp_hardening_cb_t
)(
void
);
struct
bp_hardening_data
{
int
hyp_vectors_slot
;
bp_hardening_cb_t
fn
;
};
DECLARE_PER_CPU_READ_MOSTLY
(
struct
bp_hardening_data
,
bp_hardening_data
);
static
inline
struct
bp_hardening_data
*
arm64_get_bp_hardening_data
(
void
)
{
return
this_cpu_ptr
(
&
bp_hardening_data
);
}
static
inline
void
arm64_apply_bp_hardening
(
void
)
{
struct
bp_hardening_data
*
d
;
if
(
!
cpus_have_const_cap
(
ARM64_SPECTRE_V2
))
return
;
d
=
arm64_get_bp_hardening_data
();
if
(
d
->
fn
)
d
->
fn
();
}
extern
void
arm64_memblock_init
(
void
);
extern
void
paging_init
(
void
);
extern
void
bootmem_init
(
void
);
...
...
arch/arm64/include/asm/spectre.h
View file @
dc2286f3
...
...
@@ -9,7 +9,15 @@
#ifndef __ASM_SPECTRE_H
#define __ASM_SPECTRE_H
#define BP_HARDEN_EL2_SLOTS 4
#define __BP_HARDEN_HYP_VECS_SZ ((BP_HARDEN_EL2_SLOTS - 1) * SZ_2K)
#ifndef __ASSEMBLY__
#include <linux/percpu.h>
#include <asm/cpufeature.h>
#include <asm/virt.h>
/* Watch out, ordering is important here. */
enum
mitigation_state
{
...
...
@@ -20,13 +28,68 @@ enum mitigation_state {
struct
task_struct
;
/*
* Note: the order of this enum corresponds to __bp_harden_hyp_vecs and
* we rely on having the direct vectors first.
*/
enum
arm64_hyp_spectre_vector
{
/*
* Take exceptions directly to __kvm_hyp_vector. This must be
* 0 so that it used by default when mitigations are not needed.
*/
HYP_VECTOR_DIRECT
,
/*
* Bounce via a slot in the hypervisor text mapping of
* __bp_harden_hyp_vecs, which contains an SMC call.
*/
HYP_VECTOR_SPECTRE_DIRECT
,
/*
* Bounce via a slot in a special mapping of __bp_harden_hyp_vecs
* next to the idmap page.
*/
HYP_VECTOR_INDIRECT
,
/*
* Bounce via a slot in a special mapping of __bp_harden_hyp_vecs
* next to the idmap page, which contains an SMC call.
*/
HYP_VECTOR_SPECTRE_INDIRECT
,
};
typedef
void
(
*
bp_hardening_cb_t
)(
void
);
struct
bp_hardening_data
{
enum
arm64_hyp_spectre_vector
slot
;
bp_hardening_cb_t
fn
;
};
DECLARE_PER_CPU_READ_MOSTLY
(
struct
bp_hardening_data
,
bp_hardening_data
);
static
inline
void
arm64_apply_bp_hardening
(
void
)
{
struct
bp_hardening_data
*
d
;
if
(
!
cpus_have_const_cap
(
ARM64_SPECTRE_V2
))
return
;
d
=
this_cpu_ptr
(
&
bp_hardening_data
);
if
(
d
->
fn
)
d
->
fn
();
}
enum
mitigation_state
arm64_get_spectre_v2_state
(
void
);
bool
has_spectre_v2
(
const
struct
arm64_cpu_capabilities
*
cap
,
int
scope
);
void
spectre_v2_enable_mitigation
(
const
struct
arm64_cpu_capabilities
*
__unused
);
bool
has_spectre_v3a
(
const
struct
arm64_cpu_capabilities
*
cap
,
int
scope
);
void
spectre_v3a_enable_mitigation
(
const
struct
arm64_cpu_capabilities
*
__unused
);
enum
mitigation_state
arm64_get_spectre_v4_state
(
void
);
bool
has_spectre_v4
(
const
struct
arm64_cpu_capabilities
*
cap
,
int
scope
);
void
spectre_v4_enable_mitigation
(
const
struct
arm64_cpu_capabilities
*
__unused
);
void
spectre_v4_enable_task_mitigation
(
struct
task_struct
*
tsk
);
#endif
/* __ASSEMBLY__ */
#endif
/* __ASM_SPECTRE_H */
arch/arm64/kernel/cpu_errata.c
View file @
dc2286f3
...
...
@@ -196,16 +196,6 @@ has_neoverse_n1_erratum_1542419(const struct arm64_cpu_capabilities *entry,
return
is_midr_in_range
(
midr
,
&
range
)
&&
has_dic
;
}
#ifdef CONFIG_RANDOMIZE_BASE
static
const
struct
midr_range
ca57_a72
[]
=
{
MIDR_ALL_VERSIONS
(
MIDR_CORTEX_A57
),
MIDR_ALL_VERSIONS
(
MIDR_CORTEX_A72
),
{},
};
#endif
#ifdef CONFIG_ARM64_WORKAROUND_REPEAT_TLBI
static
const
struct
arm64_cpu_capabilities
arm64_repeat_tlbi_list
[]
=
{
#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1009
...
...
@@ -461,9 +451,12 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
},
#ifdef CONFIG_RANDOMIZE_BASE
{
.
desc
=
"EL2 vector hardening"
,
.
capability
=
ARM64_HARDEN_EL2_VECTORS
,
ERRATA_MIDR_RANGE_LIST
(
ca57_a72
),
/* Must come after the Spectre-v2 entry */
.
desc
=
"Spectre-v3a"
,
.
capability
=
ARM64_SPECTRE_V3A
,
.
type
=
ARM64_CPUCAP_LOCAL_CPU_ERRATUM
,
.
matches
=
has_spectre_v3a
,
.
cpu_enable
=
spectre_v3a_enable_mitigation
,
},
#endif
{
...
...
arch/arm64/kernel/proton-pack.c
View file @
dc2286f3
// SPDX-License-Identifier: GPL-2.0-only
/*
* Handle detection, reporting and mitigation of Spectre v1, v2 and v4, as
* Handle detection, reporting and mitigation of Spectre v1, v2
, v3a
and v4, as
* detailed at:
*
* https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability
...
...
@@ -26,6 +26,7 @@
#include <asm/spectre.h>
#include <asm/traps.h>
#include <asm/virt.h>
/*
* We try to ensure that the mitigation state can never change as the result of
...
...
@@ -170,72 +171,26 @@ bool has_spectre_v2(const struct arm64_cpu_capabilities *entry, int scope)
return
true
;
}
DEFINE_PER_CPU_READ_MOSTLY
(
struct
bp_hardening_data
,
bp_hardening_data
);
enum
mitigation_state
arm64_get_spectre_v2_state
(
void
)
{
return
spectre_v2_state
;
}
#ifdef CONFIG_KVM
#include <asm/cacheflush.h>
#include <asm/kvm_asm.h>
atomic_t
arm64_el2_vector_last_slot
=
ATOMIC_INIT
(
-
1
);
static
void
__copy_hyp_vect_bpi
(
int
slot
,
const
char
*
hyp_vecs_start
,
const
char
*
hyp_vecs_end
)
{
void
*
dst
=
lm_alias
(
__bp_harden_hyp_vecs
+
slot
*
SZ_2K
);
int
i
;
for
(
i
=
0
;
i
<
SZ_2K
;
i
+=
0x80
)
memcpy
(
dst
+
i
,
hyp_vecs_start
,
hyp_vecs_end
-
hyp_vecs_start
);
__flush_icache_range
((
uintptr_t
)
dst
,
(
uintptr_t
)
dst
+
SZ_2K
);
}
DEFINE_PER_CPU_READ_MOSTLY
(
struct
bp_hardening_data
,
bp_hardening_data
);
static
void
install_bp_hardening_cb
(
bp_hardening_cb_t
fn
)
{
static
DEFINE_RAW_SPINLOCK
(
bp_lock
);
int
cpu
,
slot
=
-
1
;
const
char
*
hyp_vecs_start
=
__smccc_workaround_1_smc
;
const
char
*
hyp_vecs_end
=
__smccc_workaround_1_smc
+
__SMCCC_WORKAROUND_1_SMC_SZ
;
__this_cpu_write
(
bp_hardening_data
.
fn
,
fn
);
/*
* Vinz Clortho takes the hyp_vecs start/end "keys" at
* the door when we're a guest. Skip the hyp-vectors work.
*/
if
(
!
is_hyp_mode_available
())
{
__this_cpu_write
(
bp_hardening_data
.
fn
,
fn
);
if
(
!
is_hyp_mode_available
())
return
;
}
raw_spin_lock
(
&
bp_lock
);
for_each_possible_cpu
(
cpu
)
{
if
(
per_cpu
(
bp_hardening_data
.
fn
,
cpu
)
==
fn
)
{
slot
=
per_cpu
(
bp_hardening_data
.
hyp_vectors_slot
,
cpu
);
break
;
}
}
if
(
slot
==
-
1
)
{
slot
=
atomic_inc_return
(
&
arm64_el2_vector_last_slot
);
BUG_ON
(
slot
>=
BP_HARDEN_EL2_SLOTS
);
__copy_hyp_vect_bpi
(
slot
,
hyp_vecs_start
,
hyp_vecs_end
);
}
__this_cpu_write
(
bp_hardening_data
.
hyp_vectors_slot
,
slot
);
__this_cpu_write
(
bp_hardening_data
.
fn
,
fn
);
raw_spin_unlock
(
&
bp_lock
);
}
#else
static
void
install_bp_hardening_cb
(
bp_hardening_cb_t
fn
)
{
__this_cpu_write
(
bp_hardening_data
.
fn
,
fn
);
__this_cpu_write
(
bp_hardening_data
.
slot
,
HYP_VECTOR_SPECTRE_DIRECT
);
}
#endif
/* CONFIG_KVM */
static
void
call_smc_arch_workaround_1
(
void
)
{
...
...
@@ -316,6 +271,33 @@ void spectre_v2_enable_mitigation(const struct arm64_cpu_capabilities *__unused)
update_mitigation_state
(
&
spectre_v2_state
,
state
);
}
/*
* Spectre-v3a.
*
* Phew, there's not an awful lot to do here! We just instruct EL2 to use
* an indirect trampoline for the hyp vectors so that guests can't read
* VBAR_EL2 to defeat randomisation of the hypervisor VA layout.
*/
bool
has_spectre_v3a
(
const
struct
arm64_cpu_capabilities
*
entry
,
int
scope
)
{
static
const
struct
midr_range
spectre_v3a_unsafe_list
[]
=
{
MIDR_ALL_VERSIONS
(
MIDR_CORTEX_A57
),
MIDR_ALL_VERSIONS
(
MIDR_CORTEX_A72
),
{},
};
WARN_ON
(
scope
!=
SCOPE_LOCAL_CPU
||
preemptible
());
return
is_midr_in_range_list
(
read_cpuid_id
(),
spectre_v3a_unsafe_list
);
}
void
spectre_v3a_enable_mitigation
(
const
struct
arm64_cpu_capabilities
*
__unused
)
{
struct
bp_hardening_data
*
data
=
this_cpu_ptr
(
&
bp_hardening_data
);
if
(
this_cpu_has_cap
(
ARM64_SPECTRE_V3A
))
data
->
slot
+=
HYP_VECTOR_INDIRECT
;
}
/*
* Spectre v4.
*
...
...
arch/arm64/kvm/arm.c
View file @
dc2286f3
...
...
@@ -1310,37 +1310,44 @@ static unsigned long nvhe_percpu_order(void)
return
size
?
get_order
(
size
)
:
0
;
}
static
int
kvm_map_vectors
(
void
)
/* A lookup table holding the hypervisor VA for each vector slot */
static
void
*
hyp_spectre_vector_selector
[
BP_HARDEN_EL2_SLOTS
];
static
int
__kvm_vector_slot2idx
(
enum
arm64_hyp_spectre_vector
slot
)
{
/*
* SV2 = ARM64_SPECTRE_V2
* HEL2 = ARM64_HARDEN_EL2_VECTORS
*
* !SV2 + !HEL2 -> use direct vectors
* SV2 + !HEL2 -> use hardened vectors in place
* !SV2 + HEL2 -> allocate one vector slot and use exec mapping
* SV2 + HEL2 -> use hardened vectors and use exec mapping
*/
if
(
cpus_have_const_cap
(
ARM64_SPECTRE_V2
))
{
__kvm_bp_vect_base
=
kvm_ksym_ref
(
__bp_harden_hyp_vecs
);
__kvm_bp_vect_base
=
kern_hyp_va
(
__kvm_bp_vect_base
);
}
return
slot
-
(
slot
!=
HYP_VECTOR_DIRECT
);
}
if
(
cpus_have_const_cap
(
ARM64_HARDEN_EL2_VECTORS
))
{
phys_addr_t
vect_pa
=
__pa_symbol
(
__bp_harden_hyp_vecs
);
unsigned
long
size
=
__BP_HARDEN_HYP_VECS_SZ
;
static
void
kvm_init_vector_slot
(
void
*
base
,
enum
arm64_hyp_spectre_vector
slot
)
{
int
idx
=
__kvm_vector_slot2idx
(
slot
)
;
/*
* Always allocate a spare vector slot, as we don't
* know yet which CPUs have a BP hardening slot that
* we can reuse.
*/
__kvm_harden_el2_vector_slot
=
atomic_inc_return
(
&
arm64_el2_vector_last_slot
);
BUG_ON
(
__kvm_harden_el2_vector_slot
>=
BP_HARDEN_EL2_SLOTS
);
return
create_hyp_exec_mappings
(
vect_pa
,
size
,
&
__kvm_bp_vect_base
);
hyp_spectre_vector_selector
[
slot
]
=
base
+
(
idx
*
SZ_2K
);
}
static
int
kvm_init_vector_slots
(
void
)
{
int
err
;
void
*
base
;
base
=
kern_hyp_va
(
kvm_ksym_ref
(
__kvm_hyp_vector
));
kvm_init_vector_slot
(
base
,
HYP_VECTOR_DIRECT
);
base
=
kern_hyp_va
(
kvm_ksym_ref
(
__bp_harden_hyp_vecs
));
kvm_init_vector_slot
(
base
,
HYP_VECTOR_SPECTRE_DIRECT
);
if
(
!
cpus_have_const_cap
(
ARM64_SPECTRE_V3A
))
return
0
;
if
(
!
has_vhe
())
{
err
=
create_hyp_exec_mappings
(
__pa_symbol
(
__bp_harden_hyp_vecs
),
__BP_HARDEN_HYP_VECS_SZ
,
&
base
);
if
(
err
)
return
err
;
}
kvm_init_vector_slot
(
base
,
HYP_VECTOR_INDIRECT
);
kvm_init_vector_slot
(
base
,
HYP_VECTOR_SPECTRE_INDIRECT
);
return
0
;
}
...
...
@@ -1395,13 +1402,40 @@ static void cpu_hyp_reset(void)
__hyp_reset_vectors
();
}
/*
* EL2 vectors can be mapped and rerouted in a number of ways,
* depending on the kernel configuration and CPU present:
*
* - If the CPU is affected by Spectre-v2, the hardening sequence is
* placed in one of the vector slots, which is executed before jumping
* to the real vectors.
*
* - If the CPU also has the ARM64_SPECTRE_V3A cap, the slot
* containing the hardening sequence is mapped next to the idmap page,
* and executed before jumping to the real vectors.
*
* - If the CPU only has the ARM64_SPECTRE_V3A cap, then an
* empty slot is selected, mapped next to the idmap page, and
* executed before jumping to the real vectors.
*
* Note that ARM64_SPECTRE_V3A is somewhat incompatible with
* VHE, as we don't have hypervisor-specific mappings. If the system
* is VHE and yet selects this capability, it will be ignored.
*/
static
void
cpu_set_hyp_vector
(
void
)
{
struct
bp_hardening_data
*
data
=
this_cpu_ptr
(
&
bp_hardening_data
);
void
*
vector
=
hyp_spectre_vector_selector
[
data
->
slot
];
*
this_cpu_ptr_hyp_sym
(
kvm_hyp_vector
)
=
(
unsigned
long
)
vector
;
}
static
void
cpu_hyp_reinit
(
void
)
{
kvm_init_host_cpu_context
(
&
this_cpu_ptr_hyp_sym
(
kvm_host_data
)
->
host_ctxt
);
cpu_hyp_reset
();
*
this_cpu_ptr_hyp_sym
(
kvm_hyp_vector
)
=
(
unsigned
long
)
kvm_get_hyp_vector
();
cpu_set_hyp_vector
();
if
(
is_kernel_in_hyp_mode
())
kvm_timer_init_vhe
();
...
...
@@ -1631,12 +1665,6 @@ static int init_hyp_mode(void)
goto
out_err
;
}
err
=
kvm_map_vectors
();
if
(
err
)
{
kvm_err
(
"Cannot map vectors
\n
"
);
goto
out_err
;
}
/*
* Map the Hyp stack pages
*/
...
...
@@ -1780,6 +1808,12 @@ int kvm_arch_init(void *opaque)
goto
out_err
;
}
err
=
kvm_init_vector_slots
();
if
(
err
)
{
kvm_err
(
"Cannot initialise vector slots
\n
"
);
goto
out_err
;
}
err
=
init_subsystems
();
if
(
err
)
goto
out_hyp
;
...
...
arch/arm64/kvm/hyp/Makefile
View file @
dc2286f3
...
...
@@ -10,4 +10,4 @@ subdir-ccflags-y := -I$(incdir) \
-DDISABLE_BRANCH_PROFILING
\
$(DISABLE_STACKLEAK_PLUGIN)
obj-$(CONFIG_KVM)
+=
vhe/ nvhe/ pgtable.o
smccc_wa.o
obj-$(CONFIG_KVM)
+=
vhe/ nvhe/ pgtable.o
arch/arm64/kvm/hyp/hyp-entry.S
View file @
dc2286f3
...
...
@@ -13,6 +13,7 @@
#include <asm/kvm_arm.h>
#include <asm/kvm_asm.h>
#include <asm/mmu.h>
#include <asm/spectre.h>
.
macro
save_caller_saved_regs_vect
/
*
x0
and
x1
were
saved
in
the
vector
entry
*/
...
...
@@ -187,52 +188,60 @@ SYM_CODE_START(__kvm_hyp_vector)
valid_vect
el1_error
//
Error
32
-
bit
EL1
SYM_CODE_END
(
__kvm_hyp_vector
)
.
macro
hyp_ventry
.
align
7
.
macro
spectrev2_smccc_wa1_smc
sub
sp
,
sp
,
#(
8
*
4
)
stp
x2
,
x3
,
[
sp
,
#(
8
*
0
)]
stp
x0
,
x1
,
[
sp
,
#(
8
*
2
)]
mov
w0
,
#
ARM_SMCCC_ARCH_WORKAROUND_1
smc
#
0
ldp
x2
,
x3
,
[
sp
,
#(
8
*
0
)]
add
sp
,
sp
,
#(
8
*
2
)
.
endm
.
macro
hyp_ventry
indirect
,
spectrev2
.
align
7
1
:
esb
.
rept
26
nop
.
endr
/*
*
The
default
sequence
is
to
directly
branch
to
the
KVM
vectors
,
*
using
the
computed
offset
.
This
applies
for
VHE
as
well
as
*
!
ARM64_HARDEN_EL2_VECTORS
.
The
first
vector
must
always
run
the
preamble
.
*
*
For
ARM64_HARDEN_EL2_VECTORS
configurations
,
this
gets
replaced
*
with
:
*
*
stp
x0
,
x1
,
[
sp
,
#-
16
]!
*
movz
x0
,
#(
addr
&
0xffff
)
*
movk
x0
,
#((
addr
>>
16
)
&
0xffff
),
lsl
#
16
*
movk
x0
,
#((
addr
>>
32
)
&
0xffff
),
lsl
#
32
*
br
x0
*
*
Where
:
*
addr
=
kern_hyp_va
(
__kvm_hyp_vector
)
+
vector
-
offset
+
KVM_VECTOR_PREAMBLE
.
*
See
kvm_patch_vector_branch
for
details
.
*/
alternative_cb
kvm_patch_vector_branch
.
if
\
spectrev2
!=
0
spectrev2_smccc_wa1_smc
.
else
stp
x0
,
x1
,
[
sp
,
#-
16
]!
b
__kvm_hyp_vector
+
(
1
b
-
0
b
+
KVM_VECTOR_PREAMBLE
)
.
endif
.
if
\
indirect
!=
0
alternative_cb
kvm_patch_vector_branch
/
*
*
For
ARM64_SPECTRE_V3A
configurations
,
these
NOPs
get
replaced
with
:
*
*
movz
x0
,
#(
addr
&
0xffff
)
*
movk
x0
,
#((
addr
>>
16
)
&
0xffff
),
lsl
#
16
*
movk
x0
,
#((
addr
>>
32
)
&
0xffff
),
lsl
#
32
*
br
x0
*
*
Where
:
*
addr
=
kern_hyp_va
(
__kvm_hyp_vector
)
+
vector
-
offset
+
KVM_VECTOR_PREAMBLE
.
*
See
kvm_patch_vector_branch
for
details
.
*/
nop
nop
nop
alternative_cb_end
nop
alternative_cb_end
.
endif
b
__kvm_hyp_vector
+
(
1
b
-
0
b
+
KVM_VECTOR_PREAMBLE
)
.
endm
.
macro
generate_vectors
.
macro
generate_vectors
indirect
,
spectrev2
0
:
.
rept
16
hyp_ventry
hyp_ventry
\
indirect
,
\
spectrev2
.
endr
.
org
0
b
+
SZ_2K
//
Safety
measure
.
endm
.
align
11
SYM_CODE_START
(
__bp_harden_hyp_vecs
)
.
rept
BP_HARDEN_EL2_SLOTS
generate_vectors
.
endr
generate_vectors
indirect
=
0
,
spectrev2
=
1
//
HYP_VECTOR_SPECTRE_DIRECT
generate_vectors
indirect
=
1
,
spectrev2
=
0
//
HYP_VECTOR_INDIRECT
generate_vectors
indirect
=
1
,
spectrev2
=
1
//
HYP_VECTOR_SPECTRE_INDIRECT
1
:
.
org
__bp_harden_hyp_vecs
+
__BP_HARDEN_HYP_VECS_SZ
.
org
1
b
SYM_CODE_END
(
__bp_harden_hyp_vecs
)
arch/arm64/kvm/hyp/smccc_wa.S
deleted
100644 → 0
View file @
6e5d8c71
/*
SPDX
-
License
-
Identifier
:
GPL
-
2
.0
-
only
*/
/*
*
Copyright
(
C
)
2015
-
2018
-
ARM
Ltd
*
Author
:
Marc
Zyngier
<
marc
.
zyngier
@
arm
.
com
>
*/
#include <linux/arm-smccc.h>
#include <linux/linkage.h>
#include <asm/kvm_asm.h>
#include <asm/kvm_mmu.h>
/
*
*
This
is
not
executed
directly
and
is
instead
copied
into
the
vectors
*
by
install_bp_hardening_cb
()
.
*/
.
data
.
pushsection
.
rodata
.
global
__smccc_workaround_1_smc
SYM_DATA_START
(
__smccc_workaround_1_smc
)
esb
sub
sp
,
sp
,
#(
8
*
4
)
stp
x2
,
x3
,
[
sp
,
#(
8
*
0
)]
stp
x0
,
x1
,
[
sp
,
#(
8
*
2
)]
mov
w0
,
#
ARM_SMCCC_ARCH_WORKAROUND_1
smc
#
0
ldp
x2
,
x3
,
[
sp
,
#(
8
*
0
)]
ldp
x0
,
x1
,
[
sp
,
#(
8
*
2
)]
add
sp
,
sp
,
#(
8
*
4
)
1
:
.
org
__smccc_workaround_1_smc
+
__SMCCC_WORKAROUND_1_SMC_SZ
.
org
1
b
SYM_DATA_END
(
__smccc_workaround_1_smc
)
arch/arm64/kvm/va_layout.c
View file @
dc2286f3
...
...
@@ -132,21 +132,16 @@ void __init kvm_update_va_mask(struct alt_instr *alt,
}
}
void
*
__kvm_bp_vect_base
;
int
__kvm_harden_el2_vector_slot
;
void
kvm_patch_vector_branch
(
struct
alt_instr
*
alt
,
__le32
*
origptr
,
__le32
*
updptr
,
int
nr_inst
)
{
u64
addr
;
u32
insn
;
BUG_ON
(
nr_inst
!=
5
);
BUG_ON
(
nr_inst
!=
4
);
if
(
has_vhe
()
||
!
cpus_have_const_cap
(
ARM64_HARDEN_EL2_VECTORS
))
{
WARN_ON_ONCE
(
cpus_have_const_cap
(
ARM64_HARDEN_EL2_VECTORS
));
if
(
!
cpus_have_const_cap
(
ARM64_SPECTRE_V3A
)
||
WARN_ON_ONCE
(
has_vhe
()))
return
;
}
/*
* Compute HYP VA by using the same computation as kern_hyp_va()
...
...
@@ -164,15 +159,6 @@ void kvm_patch_vector_branch(struct alt_instr *alt,
*/
addr
+=
KVM_VECTOR_PREAMBLE
;
/* stp x0, x1, [sp, #-16]! */
insn
=
aarch64_insn_gen_load_store_pair
(
AARCH64_INSN_REG_0
,
AARCH64_INSN_REG_1
,
AARCH64_INSN_REG_SP
,
-
16
,
AARCH64_INSN_VARIANT_64BIT
,
AARCH64_INSN_LDST_STORE_PAIR_PRE_INDEX
);
*
updptr
++
=
cpu_to_le32
(
insn
);
/* movz x0, #(addr & 0xffff) */
insn
=
aarch64_insn_gen_movewide
(
AARCH64_INSN_REG_0
,
(
u16
)
addr
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment