diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c index 4b283a4de5..0026ac9134 100644 --- a/xen/arch/arm/tee/ffa.c +++ b/xen/arch/arm/tee/ffa.c @@ -195,6 +195,14 @@ static void handle_msg_send_direct_req(struct cpu_user_regs *regs, uint32_t fid) goto out; } + /* we do not support direct messages to VMs */ + if ( !FFA_ID_IS_SECURE(src_dst & GENMASK(15,0)) ) + { + resp.a0 = FFA_ERROR; + resp.a2 = FFA_RET_NOT_SUPPORTED; + goto out; + } + arg.a1 = src_dst; arg.a2 = get_user_reg(regs, 2) & mask; arg.a3 = get_user_reg(regs, 3) & mask; @@ -391,11 +399,15 @@ static int ffa_domain_init(struct domain *d) if ( !ffa_fw_version ) return -ENODEV; - /* - * We can't use that last possible domain ID or ffa_get_vm_id() would - * cause an overflow. - */ - if ( d->domain_id >= UINT16_MAX) + /* + * We are using the domain_id + 1 as the FF-A ID for VMs as FF-A ID 0 is + * reserved for the hypervisor and we only support secure endpoints using + * FF-A IDs with BIT 15 set to 1 so make sure those are not used by Xen. + */ + BUILD_BUG_ON(DOMID_FIRST_RESERVED >= UINT16_MAX); + BUILD_BUG_ON((DOMID_MASK & BIT(15, U)) != 0); + + if ( d->domain_id >= DOMID_FIRST_RESERVED ) return -ERANGE; ctx = xzalloc(struct ffa_ctx); diff --git a/xen/arch/arm/tee/ffa_partinfo.c b/xen/arch/arm/tee/ffa_partinfo.c index 75a073d090..74324e1d9d 100644 --- a/xen/arch/arm/tee/ffa_partinfo.c +++ b/xen/arch/arm/tee/ffa_partinfo.c @@ -169,14 +169,23 @@ void ffa_handle_partition_info_get(struct cpu_user_regs *regs) if ( ffa_sp_count > 0 ) { - uint32_t n; + uint32_t n, n_limit = ffa_sp_count; void *src_buf = ffa_rx; /* copy the secure partitions info */ - for ( n = 0; n < ffa_sp_count; n++ ) + for ( n = 0; n < n_limit; n++ ) { - memcpy(dst_buf, src_buf, dst_size); - dst_buf += dst_size; + struct ffa_partition_info_1_1 *fpi = src_buf; + + /* filter out SP not following bit 15 convention if any */ + if ( FFA_ID_IS_SECURE(fpi->id) ) + { + memcpy(dst_buf, src_buf, dst_size); + dst_buf += dst_size; + } + else + ffa_sp_count--; + src_buf += src_size; } } @@ -276,10 +285,25 @@ static bool init_subscribers(uint16_t count, uint32_t fpi_size) { fpi = ffa_rx + n * fpi_size; - if ( fpi->partition_properties & FFA_PART_PROP_NOTIF_CREATED ) - subscr_vm_created_count++; - if ( fpi->partition_properties & FFA_PART_PROP_NOTIF_DESTROYED ) - subscr_vm_destroyed_count++; + /* + * We need to have secure partitions using bit 15 set convention for + * secure partition IDs. + * Inform the user with a log and discard giving created or destroy + * event to those IDs. + */ + if ( !FFA_ID_IS_SECURE(fpi->id) ) + { + printk(XENLOG_ERR "ffa: Firmware is not using bit 15 convention for IDs !!\n" + "ffa: Secure partition with id 0x%04x cannot be used\n", + fpi->id); + } + else + { + if ( fpi->partition_properties & FFA_PART_PROP_NOTIF_CREATED ) + subscr_vm_created_count++; + if ( fpi->partition_properties & FFA_PART_PROP_NOTIF_DESTROYED ) + subscr_vm_destroyed_count++; + } } if ( subscr_vm_created_count ) @@ -299,10 +323,13 @@ static bool init_subscribers(uint16_t count, uint32_t fpi_size) { fpi = ffa_rx + n * fpi_size; - if ( fpi->partition_properties & FFA_PART_PROP_NOTIF_CREATED ) - subscr_vm_created[c_pos++] = fpi->id; - if ( fpi->partition_properties & FFA_PART_PROP_NOTIF_DESTROYED ) - subscr_vm_destroyed[d_pos++] = fpi->id; + if ( FFA_ID_IS_SECURE(fpi->id) ) + { + if ( fpi->partition_properties & FFA_PART_PROP_NOTIF_CREATED ) + subscr_vm_created[c_pos++] = fpi->id; + if ( fpi->partition_properties & FFA_PART_PROP_NOTIF_DESTROYED ) + subscr_vm_destroyed[d_pos++] = fpi->id; + } } return true; diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index e5bc73f903..afe69b43db 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -108,6 +108,13 @@ */ #define FFA_CTX_TEARDOWN_DELAY SECONDS(1) +/* + * We rely on the convention suggested but not mandated by the FF-A + * specification that secure world endpoint identifiers have the bit 15 + * set and normal world have it set to 0. + */ +#define FFA_ID_IS_SECURE(id) ((id) & BIT(15, U)) + /* FF-A-1.1-REL0 section 10.9.2 Memory region handle, page 167 */ #define FFA_HANDLE_HYP_FLAG BIT(63, ULL) #define FFA_HANDLE_INVALID 0xffffffffffffffffULL diff --git a/xen/arch/arm/tee/ffa_shm.c b/xen/arch/arm/tee/ffa_shm.c index efa5b67db8..29675f9ba3 100644 --- a/xen/arch/arm/tee/ffa_shm.c +++ b/xen/arch/arm/tee/ffa_shm.c @@ -469,6 +469,7 @@ void ffa_handle_mem_share(struct cpu_user_regs *regs) int ret = FFA_RET_DENIED; uint32_t range_count; uint32_t region_offs; + uint16_t dst_id; if ( !ffa_fw_supports_fid(FFA_MEM_SHARE_64) ) { @@ -537,6 +538,15 @@ void ffa_handle_mem_share(struct cpu_user_regs *regs) goto out_unlock; mem_access = ctx->tx + trans.mem_access_offs; + + dst_id = ACCESS_ONCE(mem_access->access_perm.endpoint_id); + if ( !FFA_ID_IS_SECURE(dst_id) ) + { + /* we do not support sharing with VMs */ + ret = FFA_RET_NOT_SUPPORTED; + goto out_unlock; + } + if ( ACCESS_ONCE(mem_access->access_perm.perm) != FFA_MEM_ACC_RW ) { ret = FFA_RET_NOT_SUPPORTED; @@ -567,7 +577,7 @@ void ffa_handle_mem_share(struct cpu_user_regs *regs) goto out_unlock; } shm->sender_id = trans.sender_id; - shm->ep_id = ACCESS_ONCE(mem_access->access_perm.endpoint_id); + shm->ep_id = dst_id; /* * Check that the Composite memory region descriptor fits.