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:
@@ -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[];
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user