Commit 1a08f492 authored by Oliver Upton's avatar Oliver Upton
Browse files

Merge branch kvm-arm64/ffa-proxy into kvmarm/next



* kvm-arm64/ffa-proxy:
  : pKVM FF-A Proxy, courtesy Will Deacon and Andrew Walbran
  :
  : From the cover letter:
  :
  : pKVM's primary goal is to protect guest pages from a compromised host by
  : enforcing access control restrictions using stage-2 page-tables. Sadly,
  : this cannot prevent TrustZone from accessing non-secure memory, and a
  : compromised host could, for example, perform a 'confused deputy' attack
  : by asking TrustZone to use pages that have been donated to protected
  : guests. This would effectively allow the host to have TrustZone
  : exfiltrate guest secrets on its behalf, hence breaking the isolation
  : that pKVM intends to provide.
  :
  : This series addresses this problem by providing pKVM with the ability to
  : monitor SMCs following the Arm FF-A protocol. FF-A provides (among other
  : things) a set of memory management APIs allowing the Normal World to
  : share, donate or lend pages with Secure. By monitoring these SMCs, pKVM
  : can ensure that the pages that are shared, lent or donated to Secure by
  : the host kernel are only pages that it owns.
  KVM: arm64: pkvm: Add support for fragmented FF-A descriptors
  KVM: arm64: Handle FFA_FEATURES call from the host
  KVM: arm64: Handle FFA_MEM_LEND calls from the host
  KVM: arm64: Handle FFA_MEM_RECLAIM calls from the host
  KVM: arm64: Handle FFA_MEM_SHARE calls from the host
  KVM: arm64: Add FF-A helpers to share/unshare memory with secure world
  KVM: arm64: Handle FFA_RXTX_MAP and FFA_RXTX_UNMAP calls from the host
  KVM: arm64: Allocate pages for hypervisor FF-A mailboxes
  KVM: arm64: Probe FF-A version and host/hyp partition ID during init
  KVM: arm64: Block unsafe FF-A calls from the host

Signed-off-by: default avatarOliver Upton <oliver.upton@linux.dev>
parents 83510396 0a9f15fd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -420,6 +420,7 @@ struct kvm_host_data {
struct kvm_host_psci_config {
	/* PSCI version used by host. */
	u32 version;
	u32 smccc_version;

	/* Function IDs used by host if version is v0.1. */
	struct psci_0_1_function_ids function_ids_0_1;
+21 −0
Original line number Diff line number Diff line
@@ -6,7 +6,9 @@
#ifndef __ARM64_KVM_PKVM_H__
#define __ARM64_KVM_PKVM_H__

#include <linux/arm_ffa.h>
#include <linux/memblock.h>
#include <linux/scatterlist.h>
#include <asm/kvm_pgtable.h>

/* Maximum number of VMs that can co-exist under pKVM. */
@@ -106,4 +108,23 @@ static inline unsigned long host_s2_pgtable_pages(void)
	return res;
}

#define KVM_FFA_MBOX_NR_PAGES	1

static inline unsigned long hyp_ffa_proxy_pages(void)
{
	size_t desc_max;

	/*
	 * The hypervisor FFA proxy needs enough memory to buffer a fragmented
	 * descriptor returned from EL3 in response to a RETRIEVE_REQ call.
	 */
	desc_max = sizeof(struct ffa_mem_region) +
		   sizeof(struct ffa_mem_region_attributes) +
		   sizeof(struct ffa_composite_mem_region) +
		   SG_MAX_SEGMENTS * sizeof(struct ffa_mem_region_addr_range);

	/* Plus a page each for the hypervisor's RX and TX mailboxes. */
	return (2 * KVM_FFA_MBOX_NR_PAGES) + DIV_ROUND_UP(desc_max, PAGE_SIZE);
}

#endif	/* __ARM64_KVM_PKVM_H__ */
+1 −0
Original line number Diff line number Diff line
@@ -1938,6 +1938,7 @@ static bool __init init_psci_relay(void)
	}

	kvm_host_psci_config.version = psci_ops.get_version();
	kvm_host_psci_config.smccc_version = arm_smccc_get_version();

	if (kvm_host_psci_config.version == PSCI_VERSION(0, 1)) {
		kvm_host_psci_config.function_ids_0_1 = get_psci_0_1_function_ids();
+17 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2022 - Google LLC
 * Author: Andrew Walbran <qwandor@google.com>
 */
#ifndef __KVM_HYP_FFA_H
#define __KVM_HYP_FFA_H

#include <asm/kvm_host.h>

#define FFA_MIN_FUNC_NUM 0x60
#define FFA_MAX_FUNC_NUM 0x7F

int hyp_ffa_init(void *pages);
bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt);

#endif /* __KVM_HYP_FFA_H */
+3 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ extern struct host_mmu host_mmu;
enum pkvm_component_id {
	PKVM_ID_HOST,
	PKVM_ID_HYP,
	PKVM_ID_FFA,
};

extern unsigned long hyp_nr_cpus;
@@ -66,6 +67,8 @@ int __pkvm_host_share_hyp(u64 pfn);
int __pkvm_host_unshare_hyp(u64 pfn);
int __pkvm_host_donate_hyp(u64 pfn, u64 nr_pages);
int __pkvm_hyp_donate_host(u64 pfn, u64 nr_pages);
int __pkvm_host_share_ffa(u64 pfn, u64 nr_pages);
int __pkvm_host_unshare_ffa(u64 pfn, u64 nr_pages);

bool addr_is_memory(phys_addr_t phys);
int host_stage2_idmap_locked(phys_addr_t addr, u64 size, enum kvm_pgtable_prot prot);
Loading