Skip to content

Commit 8238bc6

Browse files
committed
Merge: Enable Arm FFA driver
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/3622 JIRA: https://issues.redhat.com/browse/RHEL-16037 Depends: !3498 This enables Arm's FFA (Firmware Framework for A-profile processors) driver which provides interfaces that standardize communication between various software images. This includes communication between images in the Secure world and Normal world. It also leverages the virtualization extension to isolate software images provided by an ecosystem of vendors from each other. There are a number of optee patches (drivers/tee/optee) included even though optee is not enabled. Including them avoided a lot of conflicts in the FFA patches. Tested using an Nvidia diagnostic tool. Details in the Jira ticket. Signed-off-by: Mark Salter <msalter@redhat.com> Approved-by: Mark Langsdorf <mlangsdo@redhat.com> Approved-by: Charles Mirabile <cmirabil@redhat.com> Merged-by: Scott Weaver <scweaver@redhat.com>
2 parents 5d10683 + 4a8833f commit 8238bc6

File tree

30 files changed

+2955
-911
lines changed

30 files changed

+2955
-911
lines changed

drivers/char/hw_random/optee-rng.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,10 @@ static int optee_rng_init(struct hwrng *rng)
145145
struct optee_rng_private *pvt_data = to_optee_rng_private(rng);
146146
struct tee_shm *entropy_shm_pool = NULL;
147147

148-
entropy_shm_pool = tee_shm_alloc(pvt_data->ctx, MAX_ENTROPY_REQ_SZ,
149-
TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
148+
entropy_shm_pool = tee_shm_alloc_kernel_buf(pvt_data->ctx,
149+
MAX_ENTROPY_REQ_SZ);
150150
if (IS_ERR(entropy_shm_pool)) {
151-
dev_err(pvt_data->dev, "tee_shm_alloc failed\n");
151+
dev_err(pvt_data->dev, "tee_shm_alloc_kernel_buf failed\n");
152152
return PTR_ERR(entropy_shm_pool);
153153
}
154154

drivers/firmware/arm_ffa/bus.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
#include "common.h"
1717

18+
static DEFINE_IDA(ffa_bus_id);
19+
1820
static int ffa_device_match(struct device *dev, struct device_driver *drv)
1921
{
2022
const struct ffa_device_id *id_table;
@@ -53,7 +55,8 @@ static void ffa_device_remove(struct device *dev)
5355
{
5456
struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver);
5557

56-
ffa_drv->remove(to_ffa_dev(dev));
58+
if (ffa_drv->remove)
59+
ffa_drv->remove(to_ffa_dev(dev));
5760
}
5861

5962
static int ffa_device_uevent(const struct device *dev, struct kobj_uevent_env *env)
@@ -130,6 +133,7 @@ static void ffa_release_device(struct device *dev)
130133
{
131134
struct ffa_device *ffa_dev = to_ffa_dev(dev);
132135

136+
ida_free(&ffa_bus_id, ffa_dev->id);
133137
kfree(ffa_dev);
134138
}
135139

@@ -167,22 +171,31 @@ bool ffa_device_is_valid(struct ffa_device *ffa_dev)
167171
return valid;
168172
}
169173

170-
struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id)
174+
struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
175+
const struct ffa_ops *ops)
171176
{
172-
int ret;
177+
int id, ret;
173178
struct device *dev;
174179
struct ffa_device *ffa_dev;
175180

181+
id = ida_alloc_min(&ffa_bus_id, 1, GFP_KERNEL);
182+
if (id < 0)
183+
return NULL;
184+
176185
ffa_dev = kzalloc(sizeof(*ffa_dev), GFP_KERNEL);
177-
if (!ffa_dev)
186+
if (!ffa_dev) {
187+
ida_free(&ffa_bus_id, id);
178188
return NULL;
189+
}
179190

180191
dev = &ffa_dev->dev;
181192
dev->bus = &ffa_bus_type;
182193
dev->release = ffa_release_device;
183-
dev_set_name(&ffa_dev->dev, "arm-ffa-%04x", vm_id);
194+
dev_set_name(&ffa_dev->dev, "arm-ffa-%d", id);
184195

196+
ffa_dev->id = id;
185197
ffa_dev->vm_id = vm_id;
198+
ffa_dev->ops = ops;
186199
uuid_copy(&ffa_dev->uuid, uuid);
187200

188201
ret = device_register(&ffa_dev->dev);
@@ -215,4 +228,5 @@ void arm_ffa_bus_exit(void)
215228
{
216229
ffa_devices_unregister();
217230
bus_unregister(&ffa_bus_type);
231+
ida_destroy(&ffa_bus_id);
218232
}

drivers/firmware/arm_ffa/driver.c

Lines changed: 117 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ struct ffa_drv_info {
8282
struct mutex tx_lock; /* lock to protect Tx buffer */
8383
void *rx_buffer;
8484
void *tx_buffer;
85+
bool mem_ops_native;
8586
};
8687

8788
static struct ffa_drv_info *drv_info;
@@ -182,18 +183,25 @@ static int ffa_rxtx_unmap(u16 vm_id)
182183
return 0;
183184
}
184185

186+
#define PARTITION_INFO_GET_RETURN_COUNT_ONLY BIT(0)
187+
185188
/* buffer must be sizeof(struct ffa_partition_info) * num_partitions */
186189
static int
187190
__ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
188191
struct ffa_partition_info *buffer, int num_partitions)
189192
{
190-
int count;
193+
int idx, count, flags = 0, sz, buf_sz;
191194
ffa_value_t partition_info;
192195

196+
if (drv_info->version > FFA_VERSION_1_0 &&
197+
(!buffer || !num_partitions)) /* Just get the count for now */
198+
flags = PARTITION_INFO_GET_RETURN_COUNT_ONLY;
199+
193200
mutex_lock(&drv_info->rx_lock);
194201
invoke_ffa_fn((ffa_value_t){
195202
.a0 = FFA_PARTITION_INFO_GET,
196203
.a1 = uuid0, .a2 = uuid1, .a3 = uuid2, .a4 = uuid3,
204+
.a5 = flags,
197205
}, &partition_info);
198206

199207
if (partition_info.a0 == FFA_ERROR) {
@@ -203,8 +211,19 @@ __ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
203211

204212
count = partition_info.a2;
205213

214+
if (drv_info->version > FFA_VERSION_1_0) {
215+
buf_sz = sz = partition_info.a3;
216+
if (sz > sizeof(*buffer))
217+
buf_sz = sizeof(*buffer);
218+
} else {
219+
/* FFA_VERSION_1_0 lacks size in the response */
220+
buf_sz = sz = 8;
221+
}
222+
206223
if (buffer && count <= num_partitions)
207-
memcpy(buffer, drv_info->rx_buffer, sizeof(*buffer) * count);
224+
for (idx = 0; idx < count; idx++)
225+
memcpy(buffer + idx, drv_info->rx_buffer + idx * sz,
226+
buf_sz);
208227

209228
ffa_rx_release();
210229

@@ -378,6 +397,19 @@ static u32 ffa_get_num_pages_sg(struct scatterlist *sg)
378397
return num_pages;
379398
}
380399

400+
static u8 ffa_memory_attributes_get(u32 func_id)
401+
{
402+
/*
403+
* For the memory lend or donate operation, if the receiver is a PE or
404+
* a proxy endpoint, the owner/sender must not specify the attributes
405+
*/
406+
if (func_id == FFA_FN_NATIVE(MEM_LEND) ||
407+
func_id == FFA_MEM_LEND)
408+
return 0;
409+
410+
return FFA_MEM_NORMAL | FFA_MEM_WRITE_BACK | FFA_MEM_INNER_SHAREABLE;
411+
}
412+
381413
static int
382414
ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
383415
struct ffa_mem_ops_args *args)
@@ -394,20 +426,25 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
394426
mem_region->tag = args->tag;
395427
mem_region->flags = args->flags;
396428
mem_region->sender_id = drv_info->vm_id;
397-
mem_region->attributes = FFA_MEM_NORMAL | FFA_MEM_WRITE_BACK |
398-
FFA_MEM_INNER_SHAREABLE;
429+
mem_region->attributes = ffa_memory_attributes_get(func_id);
399430
ep_mem_access = &mem_region->ep_mem_access[0];
400431

401432
for (idx = 0; idx < args->nattrs; idx++, ep_mem_access++) {
402433
ep_mem_access->receiver = args->attrs[idx].receiver;
403434
ep_mem_access->attrs = args->attrs[idx].attrs;
404435
ep_mem_access->composite_off = COMPOSITE_OFFSET(args->nattrs);
436+
ep_mem_access->flag = 0;
437+
ep_mem_access->reserved = 0;
405438
}
439+
mem_region->handle = 0;
440+
mem_region->reserved_0 = 0;
441+
mem_region->reserved_1 = 0;
406442
mem_region->ep_count = args->nattrs;
407443

408444
composite = buffer + COMPOSITE_OFFSET(args->nattrs);
409445
composite->total_pg_cnt = ffa_get_num_pages_sg(args->sg);
410446
composite->addr_range_cnt = num_entries;
447+
composite->reserved = 0;
411448

412449
length = COMPOSITE_CONSTITUENTS_OFFSET(args->nattrs, num_entries);
413450
frag_len = COMPOSITE_CONSTITUENTS_OFFSET(args->nattrs, 0);
@@ -442,6 +479,7 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize,
442479

443480
constituents->address = sg_phys(args->sg);
444481
constituents->pg_cnt = args->sg->length / FFA_PAGE_SIZE;
482+
constituents->reserved = 0;
445483
constituents++;
446484
frag_len += sizeof(struct ffa_mem_region_addr_range);
447485
} while ((args->sg = sg_next(args->sg)));
@@ -490,6 +528,39 @@ static int ffa_memory_reclaim(u64 g_handle, u32 flags)
490528
return 0;
491529
}
492530

531+
static int ffa_features(u32 func_feat_id, u32 input_props,
532+
u32 *if_props_1, u32 *if_props_2)
533+
{
534+
ffa_value_t id;
535+
536+
if (!ARM_SMCCC_IS_FAST_CALL(func_feat_id) && input_props) {
537+
pr_err("%s: Invalid Parameters: %x, %x", __func__,
538+
func_feat_id, input_props);
539+
return ffa_to_linux_errno(FFA_RET_INVALID_PARAMETERS);
540+
}
541+
542+
invoke_ffa_fn((ffa_value_t){
543+
.a0 = FFA_FEATURES, .a1 = func_feat_id, .a2 = input_props,
544+
}, &id);
545+
546+
if (id.a0 == FFA_ERROR)
547+
return ffa_to_linux_errno((int)id.a2);
548+
549+
if (if_props_1)
550+
*if_props_1 = id.a2;
551+
if (if_props_2)
552+
*if_props_2 = id.a3;
553+
554+
return 0;
555+
}
556+
557+
static void ffa_set_up_mem_ops_native_flag(void)
558+
{
559+
if (!ffa_features(FFA_FN_NATIVE(MEM_LEND), 0, NULL, NULL) ||
560+
!ffa_features(FFA_FN_NATIVE(MEM_SHARE), 0, NULL, NULL))
561+
drv_info->mem_ops_native = true;
562+
}
563+
493564
static u32 ffa_api_version_get(void)
494565
{
495566
return drv_info->version;
@@ -528,17 +599,15 @@ static int ffa_sync_send_receive(struct ffa_device *dev,
528599
dev->mode_32bit, data);
529600
}
530601

531-
static int
532-
ffa_memory_share(struct ffa_device *dev, struct ffa_mem_ops_args *args)
602+
static int ffa_memory_share(struct ffa_mem_ops_args *args)
533603
{
534-
if (dev->mode_32bit)
535-
return ffa_memory_ops(FFA_MEM_SHARE, args);
604+
if (drv_info->mem_ops_native)
605+
return ffa_memory_ops(FFA_FN_NATIVE(MEM_SHARE), args);
536606

537-
return ffa_memory_ops(FFA_FN_NATIVE(MEM_SHARE), args);
607+
return ffa_memory_ops(FFA_MEM_SHARE, args);
538608
}
539609

540-
static int
541-
ffa_memory_lend(struct ffa_device *dev, struct ffa_mem_ops_args *args)
610+
static int ffa_memory_lend(struct ffa_mem_ops_args *args)
542611
{
543612
/* Note that upon a successful MEM_LEND request the caller
544613
* must ensure that the memory region specified is not accessed
@@ -547,36 +616,47 @@ ffa_memory_lend(struct ffa_device *dev, struct ffa_mem_ops_args *args)
547616
* however on systems without a hypervisor the responsibility
548617
* falls to the calling kernel driver to prevent access.
549618
*/
550-
if (dev->mode_32bit)
551-
return ffa_memory_ops(FFA_MEM_LEND, args);
619+
if (drv_info->mem_ops_native)
620+
return ffa_memory_ops(FFA_FN_NATIVE(MEM_LEND), args);
552621

553-
return ffa_memory_ops(FFA_FN_NATIVE(MEM_LEND), args);
622+
return ffa_memory_ops(FFA_MEM_LEND, args);
554623
}
555624

556-
static const struct ffa_dev_ops ffa_ops = {
625+
static const struct ffa_info_ops ffa_drv_info_ops = {
557626
.api_version_get = ffa_api_version_get,
558627
.partition_info_get = ffa_partition_info_get,
628+
};
629+
630+
static const struct ffa_msg_ops ffa_drv_msg_ops = {
559631
.mode_32bit_set = ffa_mode_32bit_set,
560632
.sync_send_receive = ffa_sync_send_receive,
633+
};
634+
635+
static const struct ffa_mem_ops ffa_drv_mem_ops = {
561636
.memory_reclaim = ffa_memory_reclaim,
562637
.memory_share = ffa_memory_share,
563638
.memory_lend = ffa_memory_lend,
564639
};
565640

566-
const struct ffa_dev_ops *ffa_dev_ops_get(struct ffa_device *dev)
567-
{
568-
if (ffa_device_is_valid(dev))
569-
return &ffa_ops;
570-
571-
return NULL;
572-
}
573-
EXPORT_SYMBOL_GPL(ffa_dev_ops_get);
641+
static const struct ffa_ops ffa_drv_ops = {
642+
.info_ops = &ffa_drv_info_ops,
643+
.msg_ops = &ffa_drv_msg_ops,
644+
.mem_ops = &ffa_drv_mem_ops,
645+
};
574646

575647
void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid)
576648
{
577649
int count, idx;
578650
struct ffa_partition_info *pbuf, *tpbuf;
579651

652+
/*
653+
* FF-A v1.1 provides UUID for each partition as part of the discovery
654+
* API, the discovered UUID must be populated in the device's UUID and
655+
* there is no need to copy the same from the driver table.
656+
*/
657+
if (drv_info->version > FFA_VERSION_1_0)
658+
return;
659+
580660
count = ffa_partition_probe(uuid, &pbuf);
581661
if (count <= 0)
582662
return;
@@ -590,6 +670,7 @@ void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid)
590670
static void ffa_setup_partitions(void)
591671
{
592672
int count, idx;
673+
uuid_t uuid;
593674
struct ffa_device *ffa_dev;
594675
struct ffa_partition_info *pbuf, *tpbuf;
595676

@@ -600,19 +681,24 @@ static void ffa_setup_partitions(void)
600681
}
601682

602683
for (idx = 0, tpbuf = pbuf; idx < count; idx++, tpbuf++) {
603-
/* Note that the &uuid_null parameter will require
684+
import_uuid(&uuid, (u8 *)tpbuf->uuid);
685+
686+
/* Note that if the UUID will be uuid_null, that will require
604687
* ffa_device_match() to find the UUID of this partition id
605-
* with help of ffa_device_match_uuid(). Once the FF-A spec
606-
* is updated to provide correct UUID here for each partition
607-
* as part of the discovery API, we need to pass the
608-
* discovered UUID here instead.
688+
* with help of ffa_device_match_uuid(). FF-A v1.1 and above
689+
* provides UUID here for each partition as part of the
690+
* discovery API and the same is passed.
609691
*/
610-
ffa_dev = ffa_device_register(&uuid_null, tpbuf->id);
692+
ffa_dev = ffa_device_register(&uuid, tpbuf->id, &ffa_drv_ops);
611693
if (!ffa_dev) {
612694
pr_err("%s: failed to register partition ID 0x%x\n",
613695
__func__, tpbuf->id);
614696
continue;
615697
}
698+
699+
if (drv_info->version > FFA_VERSION_1_0 &&
700+
!(tpbuf->properties & FFA_PARTITION_AARCH64_EXEC))
701+
ffa_mode_32bit_set(ffa_dev);
616702
}
617703
kfree(pbuf);
618704
}
@@ -670,6 +756,8 @@ static int __init ffa_init(void)
670756

671757
ffa_setup_partitions();
672758

759+
ffa_set_up_mem_ops_native_flag();
760+
673761
return 0;
674762
free_pages:
675763
if (drv_info->tx_buffer)

drivers/tee/Kconfig

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22
# Generic Trusted Execution Environment Configuration
3-
config TEE
3+
menuconfig TEE
44
tristate "Trusted Execution Environment support"
55
depends on HAVE_ARM_SMCCC || COMPILE_TEST || CPU_SUP_AMD
66
select CRYPTO
@@ -13,10 +13,7 @@ config TEE
1313

1414
if TEE
1515

16-
menu "TEE drivers"
17-
1816
source "drivers/tee/optee/Kconfig"
1917
source "drivers/tee/amdtee/Kconfig"
20-
endmenu
2118

2219
endif

drivers/tee/amdtee/call.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ static int amd_params_to_tee_params(struct tee_param *tee, u32 count,
122122
}
123123

124124
static DEFINE_MUTEX(ta_refcount_mutex);
125-
static struct list_head ta_list = LIST_HEAD_INIT(ta_list);
125+
static LIST_HEAD(ta_list);
126126

127127
static u32 get_ta_refcount(u32 ta_handle)
128128
{

0 commit comments

Comments
 (0)