2019-06-03 05:44:50 +00:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
2012-12-10 15:35:24 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2012,2013 - ARM Ltd
|
|
|
|
* Author: Marc Zyngier <marc.zyngier@arm.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __ARM64_KVM_MMU_H__
|
|
|
|
#define __ARM64_KVM_MMU_H__
|
|
|
|
|
|
|
|
#include <asm/page.h>
|
|
|
|
#include <asm/memory.h>
|
2020-09-28 10:45:24 +00:00
|
|
|
#include <asm/mmu.h>
|
2015-11-16 11:28:18 +00:00
|
|
|
#include <asm/cpufeature.h>
|
2012-12-10 15:35:24 +00:00
|
|
|
|
|
|
|
/*
|
2015-01-29 13:50:34 +00:00
|
|
|
* As ARMv8.0 only has the TTBR0_EL2 register, we cannot express
|
2012-12-10 15:35:24 +00:00
|
|
|
* "negative" addresses. This makes it impossible to directly share
|
|
|
|
* mappings with the kernel.
|
|
|
|
*
|
|
|
|
* Instead, give the HYP mode its own VA region at a fixed offset from
|
|
|
|
* the kernel by just masking the top bits (which are all ones for a
|
2016-06-30 17:40:34 +00:00
|
|
|
* kernel address). We need to find out how many bits to mask.
|
2015-01-29 13:50:34 +00:00
|
|
|
*
|
2016-06-30 17:40:34 +00:00
|
|
|
* We want to build a set of page tables that cover both parts of the
|
|
|
|
* idmap (the trampoline page used to initialize EL2), and our normal
|
|
|
|
* runtime VA space, at the same time.
|
|
|
|
*
|
|
|
|
* Given that the kernel uses VA_BITS for its entire address space,
|
|
|
|
* and that half of that space (VA_BITS - 1) is used for the linear
|
|
|
|
* mapping, we can also limit the EL2 space to (VA_BITS - 1).
|
|
|
|
*
|
|
|
|
* The main question is "Within the VA_BITS space, does EL2 use the
|
|
|
|
* top or the bottom half of that space to shadow the kernel's linear
|
|
|
|
* mapping?". As we need to idmap the trampoline page, this is
|
|
|
|
* determined by the range in which this page lives.
|
|
|
|
*
|
|
|
|
* If the page is in the bottom half, we have to use the top half. If
|
|
|
|
* the page is in the top half, we have to use the bottom half:
|
|
|
|
*
|
2017-01-10 21:35:49 +00:00
|
|
|
* T = __pa_symbol(__hyp_idmap_text_start)
|
2016-06-30 17:40:34 +00:00
|
|
|
* if (T & BIT(VA_BITS - 1))
|
|
|
|
* HYP_VA_MIN = 0 //idmap in upper half
|
|
|
|
* else
|
|
|
|
* HYP_VA_MIN = 1 << (VA_BITS - 1)
|
|
|
|
* HYP_VA_MAX = HYP_VA_MIN + (1 << (VA_BITS - 1)) - 1
|
|
|
|
*
|
|
|
|
* When using VHE, there are no separate hyp mappings and all KVM
|
|
|
|
* functionality is already mapped as part of the main kernel
|
|
|
|
* mappings, and none of this applies in that case.
|
2012-12-10 15:35:24 +00:00
|
|
|
*/
|
2016-06-30 17:40:39 +00:00
|
|
|
|
2012-12-10 15:35:24 +00:00
|
|
|
#ifdef __ASSEMBLY__
|
|
|
|
|
2015-01-29 13:50:34 +00:00
|
|
|
#include <asm/alternative.h>
|
|
|
|
|
2012-12-10 15:35:24 +00:00
|
|
|
/*
|
|
|
|
* Convert a kernel VA into a HYP VA.
|
|
|
|
* reg: VA to be converted.
|
2016-06-30 17:40:40 +00:00
|
|
|
*
|
2017-12-03 17:36:55 +00:00
|
|
|
* The actual code generation takes place in kvm_update_va_mask, and
|
|
|
|
* the instructions below are only there to reserve the space and
|
|
|
|
* perform the register allocation (kvm_update_va_mask uses the
|
|
|
|
* specific registers encoded in the instructions).
|
2012-12-10 15:35:24 +00:00
|
|
|
*/
|
|
|
|
.macro kern_hyp_va reg
|
2017-12-03 17:36:55 +00:00
|
|
|
alternative_cb kvm_update_va_mask
|
arm64: KVM: Introduce EL2 VA randomisation
The main idea behind randomising the EL2 VA is that we usually have
a few spare bits between the most significant bit of the VA mask
and the most significant bit of the linear mapping.
Those bits could be a bunch of zeroes, and could be useful
to move things around a bit. Of course, the more memory you have,
the less randomisation you get...
Alternatively, these bits could be the result of KASLR, in which
case they are already random. But it would be nice to have a
*different* randomization, just to make the job of a potential
attacker a bit more difficult.
Inserting these random bits is a bit involved. We don't have a spare
register (short of rewriting all the kern_hyp_va call sites), and
the immediate we want to insert is too random to be used with the
ORR instruction. The best option I could come up with is the following
sequence:
and x0, x0, #va_mask
ror x0, x0, #first_random_bit
add x0, x0, #(random & 0xfff)
add x0, x0, #(random >> 12), lsl #12
ror x0, x0, #(63 - first_random_bit)
making it a fairly long sequence, but one that a decent CPU should
be able to execute without breaking a sweat. It is of course NOPed
out on VHE. The last 4 instructions can also be turned into NOPs
if it appears that there is no free bits to use.
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Reviewed-by: James Morse <james.morse@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2017-12-03 18:22:49 +00:00
|
|
|
and \reg, \reg, #1 /* mask with va_mask */
|
|
|
|
ror \reg, \reg, #1 /* rotate to the first tag bit */
|
|
|
|
add \reg, \reg, #0 /* insert the low 12 bits of the tag */
|
|
|
|
add \reg, \reg, #0, lsl 12 /* insert the top 12 bits of the tag */
|
|
|
|
ror \reg, \reg, #63 /* rotate back */
|
2017-12-03 17:36:55 +00:00
|
|
|
alternative_cb_end
|
2012-12-10 15:35:24 +00:00
|
|
|
.endm
|
|
|
|
|
2020-10-24 15:33:38 +00:00
|
|
|
/*
|
2021-01-05 18:05:39 +00:00
|
|
|
* Convert a hypervisor VA to a PA
|
|
|
|
* reg: hypervisor address to be converted in place
|
2020-10-24 15:33:38 +00:00
|
|
|
* tmp: temporary register
|
|
|
|
*/
|
2021-01-05 18:05:39 +00:00
|
|
|
.macro hyp_pa reg, tmp
|
|
|
|
ldr_l \tmp, hyp_physvirt_offset
|
|
|
|
add \reg, \reg, \tmp
|
2020-10-24 15:33:38 +00:00
|
|
|
.endm
|
|
|
|
|
2020-12-02 18:41:05 +00:00
|
|
|
/*
|
2021-01-05 18:05:39 +00:00
|
|
|
* Convert a hypervisor VA to a kernel image address
|
|
|
|
* reg: hypervisor address to be converted in place
|
2020-12-02 18:41:05 +00:00
|
|
|
* tmp: temporary register
|
|
|
|
*
|
|
|
|
* The actual code generation takes place in kvm_get_kimage_voffset, and
|
|
|
|
* the instructions below are only there to reserve the space and
|
2021-01-05 18:05:39 +00:00
|
|
|
* perform the register allocation (kvm_get_kimage_voffset uses the
|
2020-12-02 18:41:05 +00:00
|
|
|
* specific registers encoded in the instructions).
|
|
|
|
*/
|
2021-01-05 18:05:39 +00:00
|
|
|
.macro hyp_kimg_va reg, tmp
|
|
|
|
/* Convert hyp VA -> PA. */
|
|
|
|
hyp_pa \reg, \tmp
|
|
|
|
|
|
|
|
/* Load kimage_voffset. */
|
|
|
|
alternative_cb kvm_get_kimage_voffset
|
2020-12-02 18:41:05 +00:00
|
|
|
movz \tmp, #0
|
|
|
|
movk \tmp, #0, lsl #16
|
|
|
|
movk \tmp, #0, lsl #32
|
|
|
|
movk \tmp, #0, lsl #48
|
|
|
|
alternative_cb_end
|
|
|
|
|
2021-01-05 18:05:39 +00:00
|
|
|
/* Convert PA -> kimg VA. */
|
|
|
|
add \reg, \reg, \tmp
|
2020-12-02 18:41:05 +00:00
|
|
|
.endm
|
|
|
|
|
2012-12-10 15:35:24 +00:00
|
|
|
#else
|
|
|
|
|
2020-06-09 04:32:42 +00:00
|
|
|
#include <linux/pgtable.h>
|
2014-10-10 10:14:28 +00:00
|
|
|
#include <asm/pgalloc.h>
|
2017-03-10 20:32:23 +00:00
|
|
|
#include <asm/cache.h>
|
2012-12-10 15:35:24 +00:00
|
|
|
#include <asm/cacheflush.h>
|
2015-03-19 16:42:28 +00:00
|
|
|
#include <asm/mmu_context.h>
|
2012-12-10 15:35:24 +00:00
|
|
|
|
2017-12-03 17:36:55 +00:00
|
|
|
void kvm_update_va_mask(struct alt_instr *alt,
|
|
|
|
__le32 *origptr, __le32 *updptr, int nr_inst);
|
2019-11-28 19:58:05 +00:00
|
|
|
void kvm_compute_layout(void);
|
2021-01-05 18:05:38 +00:00
|
|
|
void kvm_apply_hyp_relocations(void);
|
2017-12-03 17:36:55 +00:00
|
|
|
|
2020-02-20 16:58:37 +00:00
|
|
|
static __always_inline unsigned long __kern_hyp_va(unsigned long v)
|
2016-06-30 17:40:40 +00:00
|
|
|
{
|
arm64: KVM: Introduce EL2 VA randomisation
The main idea behind randomising the EL2 VA is that we usually have
a few spare bits between the most significant bit of the VA mask
and the most significant bit of the linear mapping.
Those bits could be a bunch of zeroes, and could be useful
to move things around a bit. Of course, the more memory you have,
the less randomisation you get...
Alternatively, these bits could be the result of KASLR, in which
case they are already random. But it would be nice to have a
*different* randomization, just to make the job of a potential
attacker a bit more difficult.
Inserting these random bits is a bit involved. We don't have a spare
register (short of rewriting all the kern_hyp_va call sites), and
the immediate we want to insert is too random to be used with the
ORR instruction. The best option I could come up with is the following
sequence:
and x0, x0, #va_mask
ror x0, x0, #first_random_bit
add x0, x0, #(random & 0xfff)
add x0, x0, #(random >> 12), lsl #12
ror x0, x0, #(63 - first_random_bit)
making it a fairly long sequence, but one that a decent CPU should
be able to execute without breaking a sweat. It is of course NOPed
out on VHE. The last 4 instructions can also be turned into NOPs
if it appears that there is no free bits to use.
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Reviewed-by: James Morse <james.morse@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2017-12-03 18:22:49 +00:00
|
|
|
asm volatile(ALTERNATIVE_CB("and %0, %0, #1\n"
|
|
|
|
"ror %0, %0, #1\n"
|
|
|
|
"add %0, %0, #0\n"
|
|
|
|
"add %0, %0, #0, lsl 12\n"
|
|
|
|
"ror %0, %0, #63\n",
|
2017-12-03 17:36:55 +00:00
|
|
|
kvm_update_va_mask)
|
|
|
|
: "+r" (v));
|
2016-06-30 17:40:40 +00:00
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2016-10-18 17:37:49 +00:00
|
|
|
#define kern_hyp_va(v) ((typeof(v))(__kern_hyp_va((unsigned long)(v))))
|
2012-12-10 15:35:24 +00:00
|
|
|
|
|
|
|
/*
|
2019-02-14 01:45:46 +00:00
|
|
|
* We currently support using a VM-specified IPA size. For backward
|
|
|
|
* compatibility, the default IPA size is fixed to 40bits.
|
2012-12-10 15:35:24 +00:00
|
|
|
*/
|
2014-07-09 16:17:04 +00:00
|
|
|
#define KVM_PHYS_SHIFT (40)
|
2018-09-26 16:32:44 +00:00
|
|
|
|
2018-09-26 16:32:49 +00:00
|
|
|
#define kvm_phys_shift(kvm) VTCR_EL2_IPA(kvm->arch.vtcr)
|
2018-09-26 16:32:44 +00:00
|
|
|
#define kvm_phys_size(kvm) (_AC(1, ULL) << kvm_phys_shift(kvm))
|
|
|
|
#define kvm_phys_mask(kvm) (kvm_phys_size(kvm) - _AC(1, ULL))
|
2012-12-10 15:35:24 +00:00
|
|
|
|
2020-09-11 13:25:12 +00:00
|
|
|
#include <asm/kvm_pgtable.h>
|
2016-03-22 14:16:52 +00:00
|
|
|
#include <asm/stage2_pgtable.h>
|
|
|
|
|
2020-09-11 13:25:12 +00:00
|
|
|
int create_hyp_mappings(void *from, void *to, enum kvm_pgtable_prot prot);
|
2017-12-04 16:26:09 +00:00
|
|
|
int create_hyp_io_mappings(phys_addr_t phys_addr, size_t size,
|
2017-12-04 16:43:23 +00:00
|
|
|
void __iomem **kaddr,
|
|
|
|
void __iomem **haddr);
|
2018-02-13 11:00:29 +00:00
|
|
|
int create_hyp_exec_mappings(phys_addr_t phys_addr, size_t size,
|
|
|
|
void **haddr);
|
2012-12-10 15:35:24 +00:00
|
|
|
void free_hyp_pgds(void);
|
|
|
|
|
2014-11-27 09:35:03 +00:00
|
|
|
void stage2_unmap_vm(struct kvm *kvm);
|
2019-01-04 20:09:05 +00:00
|
|
|
int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu);
|
|
|
|
void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu);
|
2012-12-10 15:35:24 +00:00
|
|
|
int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
|
2014-09-17 21:56:18 +00:00
|
|
|
phys_addr_t pa, unsigned long size, bool writable);
|
2012-12-10 15:35:24 +00:00
|
|
|
|
2020-06-23 13:14:15 +00:00
|
|
|
int kvm_handle_guest_abort(struct kvm_vcpu *vcpu);
|
2012-12-10 15:35:24 +00:00
|
|
|
|
|
|
|
phys_addr_t kvm_mmu_get_httbr(void);
|
|
|
|
phys_addr_t kvm_get_idmap_vector(void);
|
2021-03-19 10:01:26 +00:00
|
|
|
int kvm_mmu_init(u32 *hyp_va_bits);
|
2020-06-04 23:46:23 +00:00
|
|
|
|
2021-03-19 10:01:23 +00:00
|
|
|
static inline void *__kvm_vector_slot2addr(void *base,
|
|
|
|
enum arm64_hyp_spectre_vector slot)
|
|
|
|
{
|
|
|
|
int idx = slot - (slot != HYP_VECTOR_DIRECT);
|
|
|
|
|
|
|
|
return base + (idx * SZ_2K);
|
|
|
|
}
|
|
|
|
|
2012-12-10 15:35:24 +00:00
|
|
|
struct kvm;
|
|
|
|
|
2014-01-14 19:13:10 +00:00
|
|
|
#define kvm_flush_dcache_to_poc(a,l) __flush_dcache_area((a), (l))
|
|
|
|
|
|
|
|
static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu)
|
2012-12-10 15:35:24 +00:00
|
|
|
{
|
2016-03-16 14:38:53 +00:00
|
|
|
return (vcpu_read_sys_reg(vcpu, SCTLR_EL1) & 0b101) == 0b101;
|
2014-01-14 19:13:10 +00:00
|
|
|
}
|
|
|
|
|
2017-10-23 16:11:22 +00:00
|
|
|
static inline void __clean_dcache_guest_page(kvm_pfn_t pfn, unsigned long size)
|
2014-01-14 19:13:10 +00:00
|
|
|
{
|
arm/arm64: KVM: Use kernel mapping to perform invalidation on page fault
When handling a fault in stage-2, we need to resync I$ and D$, just
to be sure we don't leave any old cache line behind.
That's very good, except that we do so using the *user* address.
Under heavy load (swapping like crazy), we may end up in a situation
where the page gets mapped in stage-2 while being unmapped from
userspace by another CPU.
At that point, the DC/IC instructions can generate a fault, which
we handle with kvm->mmu_lock held. The box quickly deadlocks, user
is unhappy.
Instead, perform this invalidation through the kernel mapping,
which is guaranteed to be present. The box is much happier, and so
am I.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-01-05 21:13:24 +00:00
|
|
|
void *va = page_address(pfn_to_page(pfn));
|
|
|
|
|
2018-04-06 11:27:28 +00:00
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
|
2017-01-25 12:29:59 +00:00
|
|
|
kvm_flush_dcache_to_poc(va, size);
|
2017-10-23 16:11:15 +00:00
|
|
|
}
|
2014-01-14 19:13:10 +00:00
|
|
|
|
2017-10-23 16:11:22 +00:00
|
|
|
static inline void __invalidate_icache_guest_page(kvm_pfn_t pfn,
|
2017-10-23 16:11:15 +00:00
|
|
|
unsigned long size)
|
|
|
|
{
|
2017-03-10 20:32:25 +00:00
|
|
|
if (icache_is_aliasing()) {
|
2012-12-10 15:35:24 +00:00
|
|
|
/* any kind of VIPT cache */
|
|
|
|
__flush_icache_all();
|
2017-03-10 20:32:25 +00:00
|
|
|
} else if (is_kernel_in_hyp_mode() || !icache_is_vpipt()) {
|
|
|
|
/* PIPT or VPIPT at EL2 (see comment in __kvm_tlb_flush_vmid_ipa) */
|
2017-10-23 16:11:15 +00:00
|
|
|
void *va = page_address(pfn_to_page(pfn));
|
|
|
|
|
2017-10-23 16:11:16 +00:00
|
|
|
invalidate_icache_range((unsigned long)va,
|
|
|
|
(unsigned long)va + size);
|
2012-12-10 15:35:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-19 16:05:31 +00:00
|
|
|
void kvm_set_way_flush(struct kvm_vcpu *vcpu);
|
|
|
|
void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled);
|
2014-01-15 12:50:23 +00:00
|
|
|
|
2015-11-16 11:28:18 +00:00
|
|
|
static inline unsigned int kvm_get_vmid_bits(void)
|
|
|
|
{
|
2017-03-23 15:14:39 +00:00
|
|
|
int reg = read_sanitised_ftr_reg(SYS_ID_AA64MMFR1_EL1);
|
2015-11-16 11:28:18 +00:00
|
|
|
|
2020-05-12 01:57:27 +00:00
|
|
|
return get_vmid_bits(reg);
|
2015-11-16 11:28:18 +00:00
|
|
|
}
|
|
|
|
|
2018-05-11 14:20:14 +00:00
|
|
|
/*
|
|
|
|
* We are not in the kvm->srcu critical section most of the time, so we take
|
|
|
|
* the SRCU read lock here. Since we copy the data from the user page, we
|
|
|
|
* can immediately drop the lock again.
|
|
|
|
*/
|
|
|
|
static inline int kvm_read_guest_lock(struct kvm *kvm,
|
|
|
|
gpa_t gpa, void *data, unsigned long len)
|
|
|
|
{
|
|
|
|
int srcu_idx = srcu_read_lock(&kvm->srcu);
|
|
|
|
int ret = kvm_read_guest(kvm, gpa, data, len);
|
|
|
|
|
|
|
|
srcu_read_unlock(&kvm->srcu, srcu_idx);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
KVM: arm/arm64: vgic-its: Take the srcu lock when writing to guest memory
When halting a guest, QEMU flushes the virtual ITS caches, which
amounts to writing to the various tables that the guest has allocated.
When doing this, we fail to take the srcu lock, and the kernel
shouts loudly if running a lockdep kernel:
[ 69.680416] =============================
[ 69.680819] WARNING: suspicious RCU usage
[ 69.681526] 5.1.0-rc1-00008-g600025238f51-dirty #18 Not tainted
[ 69.682096] -----------------------------
[ 69.682501] ./include/linux/kvm_host.h:605 suspicious rcu_dereference_check() usage!
[ 69.683225]
[ 69.683225] other info that might help us debug this:
[ 69.683225]
[ 69.683975]
[ 69.683975] rcu_scheduler_active = 2, debug_locks = 1
[ 69.684598] 6 locks held by qemu-system-aar/4097:
[ 69.685059] #0: 0000000034196013 (&kvm->lock){+.+.}, at: vgic_its_set_attr+0x244/0x3a0
[ 69.686087] #1: 00000000f2ed935e (&its->its_lock){+.+.}, at: vgic_its_set_attr+0x250/0x3a0
[ 69.686919] #2: 000000005e71ea54 (&vcpu->mutex){+.+.}, at: lock_all_vcpus+0x64/0xd0
[ 69.687698] #3: 00000000c17e548d (&vcpu->mutex){+.+.}, at: lock_all_vcpus+0x64/0xd0
[ 69.688475] #4: 00000000ba386017 (&vcpu->mutex){+.+.}, at: lock_all_vcpus+0x64/0xd0
[ 69.689978] #5: 00000000c2c3c335 (&vcpu->mutex){+.+.}, at: lock_all_vcpus+0x64/0xd0
[ 69.690729]
[ 69.690729] stack backtrace:
[ 69.691151] CPU: 2 PID: 4097 Comm: qemu-system-aar Not tainted 5.1.0-rc1-00008-g600025238f51-dirty #18
[ 69.691984] Hardware name: rockchip evb_rk3399/evb_rk3399, BIOS 2019.04-rc3-00124-g2feec69fb1 03/15/2019
[ 69.692831] Call trace:
[ 69.694072] lockdep_rcu_suspicious+0xcc/0x110
[ 69.694490] gfn_to_memslot+0x174/0x190
[ 69.694853] kvm_write_guest+0x50/0xb0
[ 69.695209] vgic_its_save_tables_v0+0x248/0x330
[ 69.695639] vgic_its_set_attr+0x298/0x3a0
[ 69.696024] kvm_device_ioctl_attr+0x9c/0xd8
[ 69.696424] kvm_device_ioctl+0x8c/0xf8
[ 69.696788] do_vfs_ioctl+0xc8/0x960
[ 69.697128] ksys_ioctl+0x8c/0xa0
[ 69.697445] __arm64_sys_ioctl+0x28/0x38
[ 69.697817] el0_svc_common+0xd8/0x138
[ 69.698173] el0_svc_handler+0x38/0x78
[ 69.698528] el0_svc+0x8/0xc
The fix is to obviously take the srcu lock, just like we do on the
read side of things since bf308242ab98. One wonders why this wasn't
fixed at the same time, but hey...
Fixes: bf308242ab98 ("KVM: arm/arm64: VGIC/ITS: protect kvm_read_guest() calls with SRCU lock")
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2019-03-19 12:47:11 +00:00
|
|
|
static inline int kvm_write_guest_lock(struct kvm *kvm, gpa_t gpa,
|
|
|
|
const void *data, unsigned long len)
|
|
|
|
{
|
|
|
|
int srcu_idx = srcu_read_lock(&kvm->srcu);
|
|
|
|
int ret = kvm_write_guest(kvm, gpa, data, len);
|
|
|
|
|
|
|
|
srcu_read_unlock(&kvm->srcu, srcu_idx);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-12-13 17:07:18 +00:00
|
|
|
#define kvm_phys_to_vttbr(addr) phys_to_ttbr(addr)
|
|
|
|
|
2019-01-04 20:09:05 +00:00
|
|
|
static __always_inline u64 kvm_get_vttbr(struct kvm_s2_mmu *mmu)
|
2018-07-31 13:08:57 +00:00
|
|
|
{
|
2019-01-04 20:09:05 +00:00
|
|
|
struct kvm_vmid *vmid = &mmu->vmid;
|
2018-12-11 14:26:31 +00:00
|
|
|
u64 vmid_field, baddr;
|
|
|
|
u64 cnp = system_supports_cnp() ? VTTBR_CNP_BIT : 0;
|
|
|
|
|
2019-01-04 20:09:05 +00:00
|
|
|
baddr = mmu->pgd_phys;
|
2018-12-11 14:26:31 +00:00
|
|
|
vmid_field = (u64)vmid->vmid << VTTBR_VMID_SHIFT;
|
|
|
|
return kvm_phys_to_vttbr(baddr) | vmid_field | cnp;
|
2018-07-31 13:08:57 +00:00
|
|
|
}
|
|
|
|
|
2020-05-28 13:12:59 +00:00
|
|
|
/*
|
|
|
|
* Must be called from hyp code running at EL2 with an updated VTTBR
|
|
|
|
* and interrupts disabled.
|
|
|
|
*/
|
2021-03-19 10:01:31 +00:00
|
|
|
static __always_inline void __load_stage2(struct kvm_s2_mmu *mmu, unsigned long vtcr)
|
2020-05-28 13:12:59 +00:00
|
|
|
{
|
2021-03-19 10:01:31 +00:00
|
|
|
write_sysreg(vtcr, vtcr_el2);
|
2019-01-04 20:09:05 +00:00
|
|
|
write_sysreg(kvm_get_vttbr(mmu), vttbr_el2);
|
2020-05-28 13:12:59 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* ARM errata 1165522 and 1530923 require the actual execution of the
|
|
|
|
* above before we can switch to the EL1/EL0 translation regime used by
|
|
|
|
* the guest.
|
|
|
|
*/
|
|
|
|
asm(ALTERNATIVE("nop", "isb", ARM64_WORKAROUND_SPECULATIVE_AT));
|
|
|
|
}
|
|
|
|
|
2021-03-19 10:01:31 +00:00
|
|
|
static __always_inline void __load_guest_stage2(struct kvm_s2_mmu *mmu)
|
|
|
|
{
|
|
|
|
__load_stage2(mmu, kern_hyp_va(mmu->arch)->vtcr);
|
|
|
|
}
|
|
|
|
|
2021-03-19 10:01:28 +00:00
|
|
|
static inline struct kvm *kvm_s2_mmu_to_kvm(struct kvm_s2_mmu *mmu)
|
|
|
|
{
|
|
|
|
return container_of(mmu->arch, struct kvm, arch);
|
|
|
|
}
|
2012-12-10 15:35:24 +00:00
|
|
|
#endif /* __ASSEMBLY__ */
|
|
|
|
#endif /* __ARM64_KVM_MMU_H__ */
|