ANDROID: KVM: arm64: Support multiple FF-A partition buffers

Store the ffa rx/tx pair of buffers in the hypervisor VM structure
and introduce a helper to return the address of this buffers.
Move the definition of the kvm_ffa_buffers to the common pkvm
header.
No functional change is intended to the existing host ff-a
proxy.

Bug: 269285339
Bug: 278749606
Change-Id: Id56675a050783bb846c2f9b21e147e564aaf411f
Signed-off-by: Sebastian Ene <sebastianene@google.com>
This commit is contained in:
Sebastian Ene
2023-02-14 17:29:14 +00:00
parent f282cf2ef0
commit 4ec99b4414
2 changed files with 44 additions and 18 deletions
+8
View File
@@ -41,6 +41,12 @@ struct pkvm_hyp_vcpu {
int power_state;
};
/* Holds the hyp address of the mapped RX/TX buffers inside the hypervisor */
struct kvm_ffa_buffers {
void *tx;
void *rx;
};
/*
* Holds the relevant data for running a protected vm.
*/
@@ -70,6 +76,8 @@ struct pkvm_hyp_vm {
*/
bool is_dying;
struct kvm_ffa_buffers ffa_buf;
/* Array of the hyp vCPU structures for this VM. */
struct pkvm_hyp_vcpu *vcpus[];
};
+36 -18
View File
@@ -33,6 +33,7 @@
#include <nvhe/ffa.h>
#include <nvhe/mem_protect.h>
#include <nvhe/memory.h>
#include <nvhe/pkvm.h>
#include <nvhe/trap_handler.h>
#include <nvhe/spinlock.h>
@@ -54,11 +55,6 @@ struct kvm_ffa_descriptor_buffer {
static struct kvm_ffa_descriptor_buffer ffa_desc_buf;
struct kvm_ffa_buffers {
void *tx;
void *rx;
};
/*
* Note that we don't currently lock these buffers explicitly, instead
* relying on the locking of the hyp FFA buffers.
@@ -71,6 +67,14 @@ static bool has_version_negotiated;
static DEFINE_HYP_SPINLOCK(version_lock);
static DEFINE_HYP_SPINLOCK(kvm_ffa_hyp_lock);
static struct kvm_ffa_buffers *ffa_get_buffers(struct pkvm_hyp_vcpu *hyp_vcpu)
{
if (!hyp_vcpu)
return &host_buffers;
return &pkvm_hyp_vcpu_to_hyp_vm(hyp_vcpu)->ffa_buf;
}
static void ffa_to_smccc_error(struct arm_smccc_res *res, u64 ffa_errno)
{
*res = (struct arm_smccc_res) {
@@ -197,6 +201,7 @@ static void do_ffa_rxtx_map(struct arm_smccc_res *res,
DECLARE_REG(u32, npages, ctxt, 3);
int ret = 0;
void *rx_virt, *tx_virt;
struct kvm_ffa_buffers *ffa_buf;
if (npages != (KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) / FFA_PAGE_SIZE) {
ret = FFA_RET_INVALID_PARAMETERS;
@@ -209,7 +214,8 @@ static void do_ffa_rxtx_map(struct arm_smccc_res *res,
}
hyp_spin_lock(&kvm_ffa_hyp_lock);
if (host_buffers.tx) {
ffa_buf = ffa_get_buffers(hyp_vcpu);
if (ffa_buf->tx) {
ret = FFA_RET_DENIED;
goto out_unlock;
}
@@ -248,8 +254,8 @@ static void do_ffa_rxtx_map(struct arm_smccc_res *res,
goto err_unpin_tx;
}
host_buffers.tx = tx_virt;
host_buffers.rx = rx_virt;
ffa_buf->tx = tx_virt;
ffa_buf->rx = rx_virt;
out_unlock:
hyp_spin_unlock(&kvm_ffa_hyp_lock);
@@ -274,6 +280,7 @@ static void do_ffa_rxtx_unmap(struct arm_smccc_res *res,
{
DECLARE_REG(u32, id, ctxt, 1);
int ret = 0;
struct kvm_ffa_buffers *ffa_buf;
if (id != HOST_FFA_ID) {
ret = FFA_RET_INVALID_PARAMETERS;
@@ -281,14 +288,19 @@ static void do_ffa_rxtx_unmap(struct arm_smccc_res *res,
}
hyp_spin_lock(&kvm_ffa_hyp_lock);
if (!host_buffers.tx) {
ffa_buf = ffa_get_buffers(hyp_vcpu);
if (!ffa_buf->tx) {
ret = FFA_RET_INVALID_PARAMETERS;
goto out_unlock;
}
hyp_unpin_shared_mem(host_buffers.tx, host_buffers.tx + 1);
WARN_ON(__pkvm_host_unshare_hyp(hyp_virt_to_pfn(host_buffers.tx)));
host_buffers.tx = NULL;
hyp_unpin_shared_mem(ffa_buf->tx, ffa_buf->tx + 1);
WARN_ON(__pkvm_host_unshare_hyp(hyp_virt_to_pfn(ffa_buf->tx)));
ffa_buf->tx = NULL;
hyp_unpin_shared_mem(ffa_buf->rx, ffa_buf->rx + 1);
WARN_ON(__pkvm_host_unshare_hyp(hyp_virt_to_pfn(ffa_buf->rx)));
ffa_buf->rx = NULL;
hyp_unpin_shared_mem(host_buffers.rx, host_buffers.rx + 1);
WARN_ON(__pkvm_host_unshare_hyp(hyp_virt_to_pfn(host_buffers.rx)));
@@ -381,6 +393,7 @@ static void do_ffa_mem_frag_tx(struct arm_smccc_res *res,
struct ffa_mem_region_addr_range *buf;
int ret = FFA_RET_INVALID_PARAMETERS;
u32 nr_ranges;
struct kvm_ffa_buffers *ffa_buf;
if (fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE)
goto out;
@@ -389,11 +402,12 @@ static void do_ffa_mem_frag_tx(struct arm_smccc_res *res,
goto out;
hyp_spin_lock(&kvm_ffa_hyp_lock);
if (!host_buffers.tx)
ffa_buf = ffa_get_buffers(hyp_vcpu);
if (!ffa_buf->tx)
goto out_unlock;
buf = hyp_buffers.tx;
memcpy(buf, host_buffers.tx, fraglen);
memcpy(buf, ffa_buf->tx, fraglen);
nr_ranges = fraglen / sizeof(*buf);
ret = ffa_host_share_ranges(buf, nr_ranges);
@@ -441,6 +455,7 @@ static void __do_ffa_mem_xfer(const u64 func_id,
struct ffa_mem_region_attributes *ep_mem_access;
struct ffa_composite_mem_region *reg;
struct ffa_mem_region *buf;
struct kvm_ffa_buffers *ffa_buf;
u32 offset, nr_ranges;
int ret = 0;
@@ -457,7 +472,8 @@ static void __do_ffa_mem_xfer(const u64 func_id,
}
hyp_spin_lock(&kvm_ffa_hyp_lock);
if (!host_buffers.tx) {
ffa_buf = ffa_get_buffers(hyp_vcpu);
if (!ffa_buf->tx) {
ret = FFA_RET_INVALID_PARAMETERS;
goto out_unlock;
}
@@ -468,7 +484,7 @@ static void __do_ffa_mem_xfer(const u64 func_id,
}
buf = hyp_buffers.tx;
memcpy(buf, host_buffers.tx, fraglen);
memcpy(buf, ffa_buf->tx, fraglen);
ep_mem_access = (void *)buf +
ffa_mem_desc_offset(buf, 0, hyp_ffa_version);
@@ -755,9 +771,11 @@ static void do_ffa_part_get(struct arm_smccc_res *res,
DECLARE_REG(u32, uuid3, ctxt, 4);
DECLARE_REG(u32, flags, ctxt, 5);
u32 count, partition_sz, copy_sz;
struct kvm_ffa_buffers *ffa_buf;
hyp_spin_lock(&kvm_ffa_hyp_lock);
if (!host_buffers.rx) {
ffa_buf = ffa_get_buffers(hyp_vcpu);
if (!ffa_buf->rx) {
ffa_to_smccc_res(res, FFA_RET_BUSY);
goto out_unlock;
}
@@ -790,7 +808,7 @@ static void do_ffa_part_get(struct arm_smccc_res *res,
goto out_unlock;
}
memcpy(host_buffers.rx, hyp_buffers.rx, copy_sz);
memcpy(ffa_buf->rx, hyp_buffers.rx, copy_sz);
out_unlock:
hyp_spin_unlock(&kvm_ffa_hyp_lock);
}