kvmarm.lists.cs.columbia.edu archive mirror
 help / color / mirror / Atom feed
From: Quentin Perret <qperret@google.com>
To: Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will@kernel.org>,  Marc Zyngier <maz@kernel.org>,
	James Morse <james.morse@arm.com>,
	 Julien Thierry <julien.thierry.kdev@gmail.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	 Rob Herring <robh+dt@kernel.org>,
	Frank Rowand <frowand.list@gmail.com>
Cc: "open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE"
	<devicetree@vger.kernel.org>,
	android-kvm@google.com, open list <linux-kernel@vger.kernel.org>,
	kernel-team@android.com,
	"open list:KERNEL VIRTUAL MACHINE FOR ARM64 \(KVM/arm64\)"
	<kvmarm@lists.cs.columbia.edu>,
	"moderated list:ARM64 PORT \(AARCH64 ARCHITECTURE\)"
	<linux-arm-kernel@lists.infradead.org>
Subject: [RFC PATCH 17/27] KVM: arm64: Elevate Hyp mappings creation at EL2
Date: Tue, 17 Nov 2020 18:15:57 +0000	[thread overview]
Message-ID: <20201117181607.1761516-18-qperret@google.com> (raw)
In-Reply-To: <20201117181607.1761516-1-qperret@google.com>

Previous commits have introduced infrastructure at EL2 to enable the Hyp
code to manage its own memory, and more specifically its stage 1 page
tables. However, this was preliminary work, and none of it is currently
in use.

Put all of this together by elevating the hyp mappings creation at EL2
when memory protection is enabled. In this case, the host kernel running
at EL1 still creates _temporary_ Hyp mappings, only used while
initializing the hypervisor, but frees them right after, and flips a
static key marking the new 'protected' mode of operation.

As such, all calls to create_hyp_mappings() after kvm init has finished
turn into hypercalls, as the host now has no 'legal' way to modify the
hypevisor page tables directly.

Signed-off-by: Quentin Perret <qperret@google.com>
---
 arch/arm64/include/asm/kvm_mmu.h |  1 -
 arch/arm64/kvm/arm.c             | 51 ++++++++++++++++++++++++++++++--
 arch/arm64/kvm/mmu.c             | 34 +++++++++++++++++++++
 3 files changed, 82 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index cb104443d8e4..bb756757b51c 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -285,6 +285,5 @@ static __always_inline void __load_guest_stage2(struct kvm_s2_mmu *mmu)
 	 */
 	asm(ALTERNATIVE("nop", "isb", ARM64_WORKAROUND_SPECULATIVE_AT));
 }
-
 #endif /* __ASSEMBLY__ */
 #endif /* __ARM64_KVM_MMU_H__ */
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index b1e1747e4bbf..cfe5cc55b425 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -1373,7 +1373,7 @@ static void cpu_prepare_hyp_mode(int cpu)
 	__flush_dcache_area(params, sizeof(*params));
 }
 
-static void cpu_init_hyp_mode(void)
+static void kvm_set_hyp_vector(void)
 {
 	struct kvm_nvhe_init_params *params;
 	struct arm_smccc_res res;
@@ -1391,6 +1391,11 @@ static void cpu_init_hyp_mode(void)
 	params = this_cpu_ptr_nvhe_sym(kvm_init_params);
 	arm_smccc_1_1_hvc(KVM_HOST_SMCCC_FUNC(__kvm_hyp_init), virt_to_phys(params), &res);
 	WARN_ON(res.a0 != SMCCC_RET_SUCCESS);
+}
+
+static void cpu_init_hyp_mode(void)
+{
+	kvm_set_hyp_vector();
 
 	/*
 	 * Disabling SSBD on a non-VHE system requires us to enable SSBS
@@ -1433,7 +1438,10 @@ 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;
+	if (!is_protected_kvm_enabled())
+		*this_cpu_ptr_hyp_sym(kvm_hyp_vector) = (unsigned long)vector;
+	else
+		kvm_call_hyp_nvhe(__hyp_cpu_set_vector, data->slot);
 }
 
 static void cpu_hyp_reinit(void)
@@ -1441,13 +1449,14 @@ static void cpu_hyp_reinit(void)
 	kvm_init_host_cpu_context(&this_cpu_ptr_hyp_sym(kvm_host_data)->host_ctxt);
 
 	cpu_hyp_reset();
-	cpu_set_hyp_vector();
 
 	if (is_kernel_in_hyp_mode())
 		kvm_timer_init_vhe();
 	else
 		cpu_init_hyp_mode();
 
+	cpu_set_hyp_vector();
+
 	kvm_arm_init_debug();
 
 	if (vgic_present)
@@ -1653,6 +1662,36 @@ static int copy_cpu_ftr_regs(void)
 	return 0;
 }
 
+static int kvm_hyp_enable_protection(void)
+{
+	void *per_cpu_base = kvm_ksym_ref(kvm_arm_hyp_percpu_base);
+	int ret, cpu;
+	void *addr;
+
+	if (!is_protected_kvm_enabled())
+		return 0;
+
+	if (!hyp_mem_base)
+		return -ENOMEM;
+
+	addr = phys_to_virt(hyp_mem_base);
+	ret = create_hyp_mappings(addr, addr + hyp_mem_size - 1, PAGE_HYP);
+	if (ret)
+		return ret;
+
+	kvm_set_hyp_vector();
+	ret = kvm_call_hyp_nvhe(__kvm_hyp_protect, hyp_mem_base, hyp_mem_size,
+				num_possible_cpus(), kern_hyp_va(per_cpu_base));
+	if (ret)
+		return ret;
+
+	free_hyp_pgds();
+	for_each_possible_cpu(cpu)
+		free_page(per_cpu(kvm_arm_hyp_stack_page, cpu));
+
+	return 0;
+}
+
 /**
  * Inits Hyp-mode on all online CPUs
  */
@@ -1789,6 +1828,12 @@ static int init_hyp_mode(void)
 	for_each_possible_cpu(cpu)
 		cpu_prepare_hyp_mode(cpu);
 
+	err = kvm_hyp_enable_protection();
+	if (err) {
+		kvm_err("Failed to enable hyp memory protection: %d\n", err);
+		goto out_err;
+	}
+
 	return 0;
 
 out_err:
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 3cf9397dabdb..5c2e0feb9689 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -225,15 +225,39 @@ void free_hyp_pgds(void)
 	if (hyp_pgtable) {
 		kvm_pgtable_hyp_destroy(hyp_pgtable);
 		kfree(hyp_pgtable);
+		hyp_pgtable = NULL;
 	}
 	mutex_unlock(&kvm_hyp_pgd_mutex);
 }
 
+static bool kvm_host_owns_hyp_mappings(void)
+{
+	if (static_branch_likely(&kvm_protected_mode_initialized))
+		return false;
+
+	/*
+	 * This can happen at boot time when __create_hyp_mappings() is called
+	 * after the hyp protection has been enabled, but the static key has
+	 * not been flipped yet.
+	 */
+	if (!hyp_pgtable && is_protected_kvm_enabled())
+		return false;
+
+	BUG_ON(!hyp_pgtable);
+
+	return true;
+}
+
 static int __create_hyp_mappings(unsigned long start, unsigned long size,
 				 unsigned long phys, enum kvm_pgtable_prot prot)
 {
 	int err;
 
+	if (!kvm_host_owns_hyp_mappings()) {
+		return kvm_call_hyp_nvhe(__hyp_create_mappings,
+					 start, size, phys, prot);
+	}
+
 	mutex_lock(&kvm_hyp_pgd_mutex);
 	err = kvm_pgtable_hyp_map(hyp_pgtable, start, size, phys, prot);
 	mutex_unlock(&kvm_hyp_pgd_mutex);
@@ -295,6 +319,16 @@ static int __create_hyp_private_mapping(phys_addr_t phys_addr, size_t size,
 	unsigned long base;
 	int ret = 0;
 
+	if (!kvm_host_owns_hyp_mappings()) {
+		base = kvm_call_hyp_nvhe(__hyp_create_private_mapping,
+					 phys_addr, size, prot);
+		if (!base)
+			return -ENOMEM;
+		*haddr = base;
+
+		return 0;
+	}
+
 	mutex_lock(&kvm_hyp_pgd_mutex);
 
 	/*
-- 
2.29.2.299.gdc1121823c-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

  parent reply	other threads:[~2020-11-17 18:17 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-17 18:15 [RFC PATCH 00/27] KVM/arm64: A stage 2 for the host Quentin Perret
2020-11-17 18:15 ` [RFC PATCH 01/27] arm64: lib: Annotate {clear, copy}_page() as position-independent Quentin Perret
2020-11-17 18:15 ` [RFC PATCH 02/27] KVM: arm64: Link position-independent string routines into .hyp.text Quentin Perret
2020-11-23 12:34   ` David Brazdil
2020-11-23 14:06     ` Quentin Perret
2020-11-17 18:15 ` [RFC PATCH 03/27] KVM: arm64: Add standalone ticket spinlock implementation for use at hyp Quentin Perret
2020-11-17 18:15 ` [RFC PATCH 04/27] KVM: arm64: Initialize kvm_nvhe_init_params early Quentin Perret
2020-11-17 18:15 ` [RFC PATCH 05/27] KVM: arm64: Avoid free_page() in page-table allocator Quentin Perret
2020-11-17 18:15 ` [RFC PATCH 06/27] KVM: arm64: Factor memory allocation out of pgtable.c Quentin Perret
2020-11-17 18:15 ` [RFC PATCH 07/27] KVM: arm64: Introduce a BSS section for use at Hyp Quentin Perret
2020-11-17 18:15 ` [RFC PATCH 08/27] KVM: arm64: Make kvm_call_hyp() a function call " Quentin Perret
2020-11-23 12:51   ` David Brazdil
2020-11-17 18:15 ` [RFC PATCH 09/27] KVM: arm64: Allow using kvm_nvhe_sym() in hyp code Quentin Perret
2020-11-23 12:57   ` David Brazdil
2020-11-23 14:02     ` Quentin Perret
2020-11-23 14:54       ` David Brazdil
2020-11-17 18:15 ` [RFC PATCH 10/27] KVM: arm64: Introduce an early Hyp page allocator Quentin Perret
2020-11-17 18:15 ` [RFC PATCH 11/27] KVM: arm64: Stub CONFIG_DEBUG_LIST at Hyp Quentin Perret
2020-11-17 18:15 ` [RFC PATCH 12/27] KVM: arm64: Introduce a Hyp buddy page allocator Quentin Perret
2020-11-17 18:15 ` [RFC PATCH 13/27] KVM: arm64: Enable access to sanitized CPU features at EL2 Quentin Perret
2020-11-23 10:55   ` Fuad Tabba
2020-11-23 13:51     ` Quentin Perret
2020-11-23 13:22   ` David Brazdil
2020-11-23 14:39     ` Quentin Perret
2020-11-17 18:15 ` [RFC PATCH 14/27] KVM: arm64: Factor out vector address calculation Quentin Perret
2020-11-17 18:15 ` [RFC PATCH 15/27] of/fdt: Introduce early_init_dt_add_memory_hyp() Quentin Perret
2020-11-17 19:44   ` Rob Herring
2020-11-18  9:25     ` Quentin Perret
2020-11-18 14:31       ` Quentin Perret
2020-11-17 18:15 ` [RFC PATCH 16/27] KVM: arm64: Prepare Hyp memory protection Quentin Perret
2020-12-03 12:57   ` Fuad Tabba
2020-12-04 18:01     ` Quentin Perret
2020-12-07 10:20       ` Will Deacon
2020-12-07 11:05         ` Mark Rutland
2020-12-07 11:10           ` Will Deacon
2020-12-07 11:14           ` Fuad Tabba
2020-12-07 11:16       ` Fuad Tabba
2020-12-07 11:58         ` Quentin Perret
2020-12-07 13:54           ` Marc Zyngier
2020-12-07 14:17             ` Quentin Perret
2020-12-07 13:40   ` Will Deacon
2020-12-07 14:11     ` Quentin Perret
2020-12-08  9:40       ` Will Deacon
2020-11-17 18:15 ` Quentin Perret [this message]
2020-11-17 18:15 ` [RFC PATCH 18/27] KVM: arm64: Use kvm_arch for stage 2 pgtable Quentin Perret
2020-11-17 18:15 ` [RFC PATCH 19/27] KVM: arm64: Use kvm_arch in kvm_s2_mmu Quentin Perret
2020-11-17 18:16 ` [RFC PATCH 20/27] KVM: arm64: Set host stage 2 using kvm_nvhe_init_params Quentin Perret
2020-11-17 18:16 ` [RFC PATCH 21/27] KVM: arm64: Refactor kvm_arm_setup_stage2() Quentin Perret
2020-11-17 18:16 ` [RFC PATCH 22/27] KVM: arm64: Refactor __load_guest_stage2() Quentin Perret
2020-11-17 18:16 ` [RFC PATCH 23/27] KVM: arm64: Refactor __populate_fault_info() Quentin Perret
2020-11-17 18:16 ` [RFC PATCH 24/27] KVM: arm64: Make memcache anonymous in pgtable allocator Quentin Perret
2020-11-17 18:16 ` [RFC PATCH 25/27] KVM: arm64: Reserve memory for host stage 2 Quentin Perret
2020-11-17 18:16 ` [RFC PATCH 26/27] KVM: arm64: Sort the memblock regions list Quentin Perret
2020-11-17 18:16 ` [RFC PATCH 27/27] KVM: arm64: Wrap the host with a stage 2 Quentin Perret

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201117181607.1761516-18-qperret@google.com \
    --to=qperret@google.com \
    --cc=android-kvm@google.com \
    --cc=catalin.marinas@arm.com \
    --cc=devicetree@vger.kernel.org \
    --cc=frowand.list@gmail.com \
    --cc=james.morse@arm.com \
    --cc=julien.thierry.kdev@gmail.com \
    --cc=kernel-team@android.com \
    --cc=kvmarm@lists.cs.columbia.edu \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maz@kernel.org \
    --cc=robh+dt@kernel.org \
    --cc=suzuki.poulose@arm.com \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).