* [PATCH RFT 00/12] firmware: arm_ffa: Add FF-A v1.1 notifications support
@ 2023-08-03 19:02 Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 01/12] firmware: arm_ffa: Update the FF-A command list with v1.1 additions Sudeep Holla
` (11 more replies)
0 siblings, 12 replies; 18+ messages in thread
From: Sudeep Holla @ 2023-08-03 19:02 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: Sudeep Holla, Jens Wiklander, Lucian Paul-Trifu, Marc Bonnici,
Coboy Chen
The series adds initial support for the notifications added in FF-A v1.1
The notification mechanism enables a requester/sender endpoint to notify
a service provider/receiver endpoint about an event with non-blocking
semantics.
A notification is akin to the doorbell between two endpoints in a
communication protocol that is based upon the doorbell/mailbox mechanism.
The framework is responsible for the delivery of the notification from the
sender to the receiver without blocking the sender. The receiver endpoint
relies on the OS scheduler for allocation of CPU cycles to handle a
notification.
OS is referred as the receiver’s scheduler in the context of notifications.
The framework is responsible for informing the receiver’s scheduler that
the receiver must be run since it has a pending notification.
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
Sudeep Holla (12):
firmware: arm_ffa: Update the FF-A command list with v1.1 additions
firmware: arm_ffa: Implement notification bitmap create and destroy interfaces
firmware: arm_ffa: Implement the notification bind and unbind interface
firmware: arm_ffa: Implement the FFA_RUN interface
firmware: arm_ffa: Implement the FFA_NOTIFICATION_SET interface
firmware: arm_ffa: Implement the FFA_NOTIFICATION_GET interface
firmware: arm_ffa: Implement the NOTIFICATION_INFO_GET interface
firmware: arm_ffa: Initial support for scheduler receiver interrupt
firmware: arm_ffa: Add schedule receiver callback mechanism
firmware: arm_ffa: Add interfaces to request notification callbacks
firmware: arm_ffa: Add interface to send a notification to a given partition
firmware: arm_ffa: Add notification handling mechanism
drivers/firmware/arm_ffa/driver.c | 700 +++++++++++++++++++++++++++++++++++++-
include/linux/arm_ffa.h | 41 +++
2 files changed, 740 insertions(+), 1 deletion(-)
---
base-commit: 5d0c230f1de8c7515b6567d9afba1f196fb4e2f4
change-id: 20230803-ffa_v1-1_notif-e11bc9459962
Best regards,
--
Regards,
Sudeep
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH RFT 01/12] firmware: arm_ffa: Update the FF-A command list with v1.1 additions
2023-08-03 19:02 [PATCH RFT 00/12] firmware: arm_ffa: Add FF-A v1.1 notifications support Sudeep Holla
@ 2023-08-03 19:02 ` Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 02/12] firmware: arm_ffa: Implement notification bitmap create and destroy interfaces Sudeep Holla
` (10 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Sudeep Holla @ 2023-08-03 19:02 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: Sudeep Holla, Jens Wiklander, Lucian Paul-Trifu, Marc Bonnici,
Coboy Chen
Arm Firmware Framework for A-profile(FFA) v1.1 introduces notifications
and indirect messaging based upon notifications support and extends some
of the memory interfaces.
Let us add all the newly supported FF-A function IDs in the spec.
Also update to the error values and associated handling.
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
drivers/firmware/arm_ffa/driver.c | 3 ++-
include/linux/arm_ffa.h | 20 ++++++++++++++++++++
2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 2109cd178ff7..6fc83fa6b81c 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -64,6 +64,7 @@ static const int ffa_linux_errmap[] = {
-EACCES, /* FFA_RET_DENIED */
-EAGAIN, /* FFA_RET_RETRY */
-ECANCELED, /* FFA_RET_ABORTED */
+ -ENODATA, /* FFA_RET_NO_DATA */
};
static inline int ffa_to_linux_errno(int errno)
@@ -336,7 +337,7 @@ static int ffa_mem_first_frag(u32 func_id, phys_addr_t buf, u32 buf_sz,
if (ret.a0 == FFA_ERROR)
return ffa_to_linux_errno((int)ret.a2);
- if (ret.a0 == FFA_SUCCESS) {
+ if (ret.a0 == FFA_SUCCESS || ret.a0 == FFA_FN64_SUCCESS) {
if (handle)
*handle = PACK_HANDLE(ret.a2, ret.a3);
} else if (ret.a0 == FFA_MEM_FRAG_RX) {
diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
index cc060da51bec..2ea1717a0825 100644
--- a/include/linux/arm_ffa.h
+++ b/include/linux/arm_ffa.h
@@ -20,6 +20,7 @@
#define FFA_ERROR FFA_SMC_32(0x60)
#define FFA_SUCCESS FFA_SMC_32(0x61)
+#define FFA_FN64_SUCCESS FFA_SMC_64(0x61)
#define FFA_INTERRUPT FFA_SMC_32(0x62)
#define FFA_VERSION FFA_SMC_32(0x63)
#define FFA_FEATURES FFA_SMC_32(0x64)
@@ -54,6 +55,23 @@
#define FFA_MEM_FRAG_RX FFA_SMC_32(0x7A)
#define FFA_MEM_FRAG_TX FFA_SMC_32(0x7B)
#define FFA_NORMAL_WORLD_RESUME FFA_SMC_32(0x7C)
+#define FFA_NOTIFICATION_BITMAP_CREATE FFA_SMC_32(0x7D)
+#define FFA_NOTIFICATION_BITMAP_DESTROY FFA_SMC_32(0x7E)
+#define FFA_NOTIFICATION_BIND FFA_SMC_32(0x7F)
+#define FFA_NOTIFICATION_UNBIND FFA_SMC_32(0x80)
+#define FFA_NOTIFICATION_SET FFA_SMC_32(0x81)
+#define FFA_NOTIFICATION_GET FFA_SMC_32(0x82)
+#define FFA_NOTIFICATION_INFO_GET FFA_SMC_32(0x83)
+#define FFA_FN64_NOTIFICATION_INFO_GET FFA_SMC_64(0x83)
+#define FFA_RX_ACQUIRE FFA_SMC_32(0x84)
+#define FFA_SPM_ID_GET FFA_SMC_32(0x85)
+#define FFA_MSG_SEND2 FFA_SMC_32(0x86)
+#define FFA_SECONDARY_EP_REGISTER FFA_SMC_32(0x87)
+#define FFA_FN64_SECONDARY_EP_REGISTER FFA_SMC_64(0x87)
+#define FFA_MEM_PERM_GET FFA_SMC_32(0x88)
+#define FFA_FN64_MEM_PERM_GET FFA_SMC_64(0x88)
+#define FFA_MEM_PERM_SET FFA_SMC_32(0x89)
+#define FFA_FN64_MEM_PERM_SET FFA_SMC_64(0x89)
/*
* For some calls it is necessary to use SMC64 to pass or return 64-bit values.
@@ -76,6 +94,7 @@
#define FFA_RET_DENIED (-6)
#define FFA_RET_RETRY (-7)
#define FFA_RET_ABORTED (-8)
+#define FFA_RET_NO_DATA (-9)
/* FFA version encoding */
#define FFA_MAJOR_VERSION_MASK GENMASK(30, 16)
@@ -86,6 +105,7 @@
(FIELD_PREP(FFA_MAJOR_VERSION_MASK, (major)) | \
FIELD_PREP(FFA_MINOR_VERSION_MASK, (minor)))
#define FFA_VERSION_1_0 FFA_PACK_VERSION_INFO(1, 0)
+#define FFA_VERSION_1_1 FFA_PACK_VERSION_INFO(1, 1)
/**
* FF-A specification mentions explicitly about '4K pages'. This should
--
2.41.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH RFT 02/12] firmware: arm_ffa: Implement notification bitmap create and destroy interfaces
2023-08-03 19:02 [PATCH RFT 00/12] firmware: arm_ffa: Add FF-A v1.1 notifications support Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 01/12] firmware: arm_ffa: Update the FF-A command list with v1.1 additions Sudeep Holla
@ 2023-08-03 19:02 ` Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 03/12] firmware: arm_ffa: Implement the notification bind and unbind interface Sudeep Holla
` (9 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Sudeep Holla @ 2023-08-03 19:02 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: Sudeep Holla, Jens Wiklander, Lucian Paul-Trifu, Marc Bonnici,
Coboy Chen
On systems without a hypervisor the responsibility of requesting the
creation of the notification bitmaps in the SPM falls to the FF-A driver.
We use FFA features to determine if the ABI is supported, if it is not
we can assume there is a hypervisor present and will take care of ensure
the relevant notifications bitmaps are created on this partitions behalf.
An endpoint’s notification bitmaps needs to be setup before it configures
its notifications and before other endpoints and partition managers can
start signaling these notifications.
Add interface to create and destroy the notification bitmaps and use the
same to do the necessary setup during the initialisation and cleanup
during the module exit.
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
drivers/firmware/arm_ffa/driver.c | 58 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 57 insertions(+), 1 deletion(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 6fc83fa6b81c..022c893c9e06 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -84,6 +84,7 @@ struct ffa_drv_info {
void *rx_buffer;
void *tx_buffer;
bool mem_ops_native;
+ bool bitmap_created;
};
static struct ffa_drv_info *drv_info;
@@ -543,6 +544,37 @@ static int ffa_features(u32 func_feat_id, u32 input_props,
return 0;
}
+static int ffa_notification_bitmap_create(void)
+{
+ ffa_value_t ret;
+ u16 vcpu_count = nr_cpu_ids;
+
+ invoke_ffa_fn((ffa_value_t){
+ .a0 = FFA_NOTIFICATION_BITMAP_CREATE,
+ .a1 = drv_info->vm_id, .a2 = vcpu_count,
+ }, &ret);
+
+ if (ret.a0 == FFA_ERROR)
+ return ffa_to_linux_errno((int)ret.a2);
+
+ return 0;
+}
+
+static int ffa_notification_bitmap_destroy(void)
+{
+ ffa_value_t ret;
+
+ invoke_ffa_fn((ffa_value_t){
+ .a0 = FFA_NOTIFICATION_BITMAP_DESTROY,
+ .a1 = drv_info->vm_id,
+ }, &ret);
+
+ if (ret.a0 == FFA_ERROR)
+ return ffa_to_linux_errno((int)ret.a2);
+
+ return 0;
+}
+
static void ffa_set_up_mem_ops_native_flag(void)
{
if (!ffa_features(FFA_FN_NATIVE(MEM_LEND), 0, NULL, NULL) ||
@@ -700,6 +732,29 @@ static void ffa_setup_partitions(void)
kfree(pbuf);
}
+static int ffa_notifications_setup(void)
+{
+ int ret;
+
+ ret = ffa_features(FFA_NOTIFICATION_BITMAP_CREATE, 0, NULL, NULL);
+ if (!ret) {
+ ret = ffa_notification_bitmap_create();
+ if (ret) {
+ pr_err("notification_bitmap_create error %d\n", ret);
+ return ret;
+ }
+ }
+ drv_info->bitmap_created = true;
+
+ return 0;
+}
+
+static void ffa_notifications_cleanup(void)
+{
+ if (drv_info->bitmap_created)
+ ffa_notification_bitmap_destroy();
+}
+
static int __init ffa_init(void)
{
int ret;
@@ -755,7 +810,7 @@ static int __init ffa_init(void)
ffa_set_up_mem_ops_native_flag();
- return 0;
+ return ffa_notifications_setup();
free_pages:
if (drv_info->tx_buffer)
free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE);
@@ -770,6 +825,7 @@ subsys_initcall(ffa_init);
static void __exit ffa_exit(void)
{
+ ffa_notifications_cleanup();
ffa_rxtx_unmap(drv_info->vm_id);
free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE);
free_pages_exact(drv_info->rx_buffer, RXTX_BUFFER_SIZE);
--
2.41.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH RFT 03/12] firmware: arm_ffa: Implement the notification bind and unbind interface
2023-08-03 19:02 [PATCH RFT 00/12] firmware: arm_ffa: Add FF-A v1.1 notifications support Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 01/12] firmware: arm_ffa: Update the FF-A command list with v1.1 additions Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 02/12] firmware: arm_ffa: Implement notification bitmap create and destroy interfaces Sudeep Holla
@ 2023-08-03 19:02 ` Sudeep Holla
2023-09-12 13:23 ` Jens Wiklander
2023-08-03 19:02 ` [PATCH RFT 04/12] firmware: arm_ffa: Implement the FFA_RUN interface Sudeep Holla
` (8 subsequent siblings)
11 siblings, 1 reply; 18+ messages in thread
From: Sudeep Holla @ 2023-08-03 19:02 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: Sudeep Holla, Jens Wiklander, Lucian Paul-Trifu, Marc Bonnici,
Coboy Chen
A receiver endpoint must bind a notification to any sender endpoint
before the latter can signal the notification to the former. The receiver
assigns one or more doorbells to a specific sender. Only the sender can
ring these doorbells.
A receiver uses the FFA_NOTIFICATION_BIND interface to bind one or more
notifications to the sender. A receiver un-binds a notification from a
sender endpoint to stop the notification from being signaled. It uses
the FFA_NOTIFICATION_UNBIND interface to do this.
Allow the FF-A driver to be able to bind and unbind a given notification
ID to a specific partition ID. This will be used to register and
unregister notification callbacks from the FF-A client drivers.
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
drivers/firmware/arm_ffa/driver.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 022c893c9e06..a76e5d3a2422 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -575,6 +575,35 @@ static int ffa_notification_bitmap_destroy(void)
return 0;
}
+#define NOTIFICATION_LOW_MASK GENMASK(31, 0)
+#define NOTIFICATION_HIGH_MASK GENMASK(63, 32)
+#define NOTIFICATION_BITMAP_HIGH(x) \
+ ((u32)(FIELD_GET(NOTIFICATION_HIGH_MASK, (x))))
+#define NOTIFICATION_BITMAP_LOW(x) \
+ ((u32)(FIELD_GET(NOTIFICATION_LOW_MASK, (x))))
+
+static int ffa_notification_bind_common(u16 dst_id, u64 bitmap,
+ u32 flags, bool is_bind)
+{
+ ffa_value_t ret;
+ u32 func, src_dst_ids = PACK_TARGET_INFO(dst_id, drv_info->vm_id);
+
+ func = is_bind ? FFA_NOTIFICATION_BIND : FFA_NOTIFICATION_UNBIND;
+
+ invoke_ffa_fn((ffa_value_t){
+ .a0 = func, .a1 = src_dst_ids, .a2 = flags,
+ .a3 = NOTIFICATION_BITMAP_LOW(bitmap),
+ .a4 = NOTIFICATION_BITMAP_HIGH(bitmap),
+ }, &ret);
+
+ if (ret.a0 == FFA_ERROR)
+ return ffa_to_linux_errno((int)ret.a2);
+ else if (ret.a0 != FFA_SUCCESS)
+ return -EINVAL;
+
+ return 0;
+}
+
static void ffa_set_up_mem_ops_native_flag(void)
{
if (!ffa_features(FFA_FN_NATIVE(MEM_LEND), 0, NULL, NULL) ||
--
2.41.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH RFT 04/12] firmware: arm_ffa: Implement the FFA_RUN interface
2023-08-03 19:02 [PATCH RFT 00/12] firmware: arm_ffa: Add FF-A v1.1 notifications support Sudeep Holla
` (2 preceding siblings ...)
2023-08-03 19:02 ` [PATCH RFT 03/12] firmware: arm_ffa: Implement the notification bind and unbind interface Sudeep Holla
@ 2023-08-03 19:02 ` Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 05/12] firmware: arm_ffa: Implement the FFA_NOTIFICATION_SET interface Sudeep Holla
` (7 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Sudeep Holla @ 2023-08-03 19:02 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: Sudeep Holla, Jens Wiklander, Lucian Paul-Trifu, Marc Bonnici,
Coboy Chen
FFA_RUN is used by a scheduler to allocate CPU cycles to a target
endpoint execution context specified in the target information parameter.
If the endpoint execution context is in the waiting/blocked state, it
transitions to the running state.
Expose the ability to call FFA_RUN in order to give any partition in the
system cpu cycles to perform IMPDEF functionality.
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
drivers/firmware/arm_ffa/driver.c | 22 ++++++++++++++++++++++
include/linux/arm_ffa.h | 5 +++++
2 files changed, 27 insertions(+)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index a76e5d3a2422..41171ae7f63a 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -604,6 +604,23 @@ static int ffa_notification_bind_common(u16 dst_id, u64 bitmap,
return 0;
}
+static int ffa_run(struct ffa_device *dev, u16 vcpu)
+{
+ ffa_value_t ret;
+ u32 target = dev->vm_id << 16 | vcpu;
+
+ invoke_ffa_fn((ffa_value_t){ .a0 = FFA_RUN, .a1 = target, }, &ret);
+
+ while (ret.a0 == FFA_INTERRUPT)
+ invoke_ffa_fn((ffa_value_t){ .a0 = FFA_RUN, .a1 = ret.a1, },
+ &ret);
+
+ if (ret.a0 == FFA_ERROR)
+ return ffa_to_linux_errno((int)ret.a2);
+
+ return 0;
+}
+
static void ffa_set_up_mem_ops_native_flag(void)
{
if (!ffa_features(FFA_FN_NATIVE(MEM_LEND), 0, NULL, NULL) ||
@@ -696,10 +713,15 @@ static const struct ffa_mem_ops ffa_drv_mem_ops = {
.memory_lend = ffa_memory_lend,
};
+static const struct ffa_cpu_ops ffa_drv_cpu_ops = {
+ .run = ffa_run,
+};
+
static const struct ffa_ops ffa_drv_ops = {
.info_ops = &ffa_drv_info_ops,
.msg_ops = &ffa_drv_msg_ops,
.mem_ops = &ffa_drv_mem_ops,
+ .cpu_ops = &ffa_drv_cpu_ops,
};
void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid)
diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
index 2ea1717a0825..12fd134bf670 100644
--- a/include/linux/arm_ffa.h
+++ b/include/linux/arm_ffa.h
@@ -387,10 +387,15 @@ struct ffa_mem_ops {
int (*memory_lend)(struct ffa_mem_ops_args *args);
};
+struct ffa_cpu_ops {
+ int (*run)(struct ffa_device *dev, u16 vcpu);
+};
+
struct ffa_ops {
const struct ffa_info_ops *info_ops;
const struct ffa_msg_ops *msg_ops;
const struct ffa_mem_ops *mem_ops;
+ const struct ffa_cpu_ops *cpu_ops;
};
#endif /* _LINUX_ARM_FFA_H */
--
2.41.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH RFT 05/12] firmware: arm_ffa: Implement the FFA_NOTIFICATION_SET interface
2023-08-03 19:02 [PATCH RFT 00/12] firmware: arm_ffa: Add FF-A v1.1 notifications support Sudeep Holla
` (3 preceding siblings ...)
2023-08-03 19:02 ` [PATCH RFT 04/12] firmware: arm_ffa: Implement the FFA_RUN interface Sudeep Holla
@ 2023-08-03 19:02 ` Sudeep Holla
2023-09-12 13:23 ` Jens Wiklander
2023-08-03 19:02 ` [PATCH RFT 06/12] firmware: arm_ffa: Implement the FFA_NOTIFICATION_GET interface Sudeep Holla
` (6 subsequent siblings)
11 siblings, 1 reply; 18+ messages in thread
From: Sudeep Holla @ 2023-08-03 19:02 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: Sudeep Holla, Jens Wiklander, Lucian Paul-Trifu, Marc Bonnici,
Coboy Chen
The framework provides an interface to the sender to specify the
notification to signal to the receiver. A sender signals a notification
by requesting its partition manager to set the corresponding bit in the
notifications bitmap of the receiver invoking FFA_NOTIFICATION_SET.
Implement the FFA_NOTIFICATION_SET to enable the caller(sender) to send
the notifications for any other partitions in the system.
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
drivers/firmware/arm_ffa/driver.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 41171ae7f63a..492f5bfa3751 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -604,6 +604,26 @@ static int ffa_notification_bind_common(u16 dst_id, u64 bitmap,
return 0;
}
+static
+int ffa_notification_set(u16 src_id, u16 dst_id, u32 flags, u64 bitmap)
+{
+ ffa_value_t ret;
+ u32 src_dst_ids = PACK_TARGET_INFO(dst_id, src_id);
+
+ invoke_ffa_fn((ffa_value_t) {
+ .a0 = FFA_NOTIFICATION_SET, .a1 = src_dst_ids, .a2 = flags,
+ .a3 = NOTIFICATION_BITMAP_LOW(bitmap),
+ .a4 = NOTIFICATION_BITMAP_HIGH(bitmap),
+ }, &ret);
+
+ if (ret.a0 == FFA_ERROR)
+ return ffa_to_linux_errno((int)ret.a2);
+ else if (ret.a0 != FFA_SUCCESS)
+ return -EINVAL;
+
+ return 0;
+}
+
static int ffa_run(struct ffa_device *dev, u16 vcpu)
{
ffa_value_t ret;
--
2.41.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH RFT 06/12] firmware: arm_ffa: Implement the FFA_NOTIFICATION_GET interface
2023-08-03 19:02 [PATCH RFT 00/12] firmware: arm_ffa: Add FF-A v1.1 notifications support Sudeep Holla
` (4 preceding siblings ...)
2023-08-03 19:02 ` [PATCH RFT 05/12] firmware: arm_ffa: Implement the FFA_NOTIFICATION_SET interface Sudeep Holla
@ 2023-08-03 19:02 ` Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 07/12] firmware: arm_ffa: Implement the NOTIFICATION_INFO_GET interface Sudeep Holla
` (5 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Sudeep Holla @ 2023-08-03 19:02 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: Sudeep Holla, Jens Wiklander, Lucian Paul-Trifu, Marc Bonnici,
Coboy Chen
The framework provides an interface to the receiver to determine the
identity of the notification. A receiver endpoint must use the
FFA_NOTIFICATION_GET interface to retrieve its pending notifications
and handle them.
Add the support for FFA_NOTIFICATION_GET to allow the caller(receiver)
to fetch its pending notifications from other partitions in the system.
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
drivers/firmware/arm_ffa/driver.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 492f5bfa3751..6cad91ee57eb 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -581,6 +581,14 @@ static int ffa_notification_bitmap_destroy(void)
((u32)(FIELD_GET(NOTIFICATION_HIGH_MASK, (x))))
#define NOTIFICATION_BITMAP_LOW(x) \
((u32)(FIELD_GET(NOTIFICATION_LOW_MASK, (x))))
+#define PACK_NOTIFICATION_BITMAP(low, high) \
+ (FIELD_PREP(NOTIFICATION_LOW_MASK, (low)) | \
+ FIELD_PREP(NOTIFICATION_HIGH_MASK, (high)))
+
+#define RECEIVER_VCPU_MASK GENMASK(31, 16)
+#define PACK_NOTIFICATION_GET_RECEIVER_INFO(vcpu_r, r) \
+ (FIELD_PREP(RECEIVER_VCPU_MASK, (vcpu_r)) | \
+ FIELD_PREP(RECEIVER_ID_MASK, (r)))
static int ffa_notification_bind_common(u16 dst_id, u64 bitmap,
u32 flags, bool is_bind)
@@ -624,6 +632,35 @@ int ffa_notification_set(u16 src_id, u16 dst_id, u32 flags, u64 bitmap)
return 0;
}
+struct ffa_notify_bitmaps {
+ u64 sp_map;
+ u64 vm_map;
+ u64 arch_map;
+};
+
+static int ffa_notification_get(u32 flags, struct ffa_notify_bitmaps *notify)
+{
+ ffa_value_t ret;
+ u16 src_id = drv_info->vm_id;
+ u16 cpu_id = smp_processor_id();
+ u32 rec_vcpu_ids = PACK_NOTIFICATION_GET_RECEIVER_INFO(cpu_id, src_id);
+
+ invoke_ffa_fn((ffa_value_t){
+ .a0 = FFA_NOTIFICATION_GET, .a1 = rec_vcpu_ids, .a2 = flags,
+ }, &ret);
+
+ if (ret.a0 == FFA_ERROR)
+ return ffa_to_linux_errno((int)ret.a2);
+ else if (ret.a0 != FFA_SUCCESS)
+ return -EINVAL; /* Something else went wrong. */
+
+ notify->sp_map = PACK_NOTIFICATION_BITMAP(ret.a2, ret.a3);
+ notify->vm_map = PACK_NOTIFICATION_BITMAP(ret.a4, ret.a5);
+ notify->arch_map = PACK_NOTIFICATION_BITMAP(ret.a6, ret.a7);
+
+ return 0;
+}
+
static int ffa_run(struct ffa_device *dev, u16 vcpu)
{
ffa_value_t ret;
--
2.41.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH RFT 07/12] firmware: arm_ffa: Implement the NOTIFICATION_INFO_GET interface
2023-08-03 19:02 [PATCH RFT 00/12] firmware: arm_ffa: Add FF-A v1.1 notifications support Sudeep Holla
` (5 preceding siblings ...)
2023-08-03 19:02 ` [PATCH RFT 06/12] firmware: arm_ffa: Implement the FFA_NOTIFICATION_GET interface Sudeep Holla
@ 2023-08-03 19:02 ` Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 08/12] firmware: arm_ffa: Initial support for scheduler receiver interrupt Sudeep Holla
` (4 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Sudeep Holla @ 2023-08-03 19:02 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: Sudeep Holla, Jens Wiklander, Lucian Paul-Trifu, Marc Bonnici,
Coboy Chen
The receiver’s scheduler uses the FFA_NOTIFICATION_INFO_GET interface
to retrieve the list of endpoints that have pending notifications and
must be run. A notification could be signaled by a sender in the secure
world to a VM. The Hypervisor needs to determine which VM and vCPU
(in case a per-vCPU notification is signaled) has a pending notification
in this scenario. It must obtain this information through an invocation
of the FFA_NOTIFICATION_INFO_GET.
Add the implementation of the NOTIFICATION_INFO_GET interface
and prepare to use this to handle the schedule receiver interrupt.
Implementation of handling notifications will be added later.
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
drivers/firmware/arm_ffa/driver.c | 70 +++++++++++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 6cad91ee57eb..77ca9753e3f0 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -590,6 +590,13 @@ static int ffa_notification_bitmap_destroy(void)
(FIELD_PREP(RECEIVER_VCPU_MASK, (vcpu_r)) | \
FIELD_PREP(RECEIVER_ID_MASK, (r)))
+#define NOTIFICATION_INFO_GET_MORE_PEND_MASK BIT(0)
+#define NOTIFICATION_INFO_GET_ID_COUNT GENMASK(11, 7)
+#define ID_LIST_MASK_64 GENMASK(51, 12)
+#define ID_LIST_MASK_32 GENMASK(31, 12)
+#define MAX_IDS_64 20
+#define MAX_IDS_32 10
+
static int ffa_notification_bind_common(u16 dst_id, u64 bitmap,
u32 flags, bool is_bind)
{
@@ -661,6 +668,69 @@ static int ffa_notification_get(u32 flags, struct ffa_notify_bitmaps *notify)
return 0;
}
+static void __do_sched_recv_cb(u16 partition_id, u16 vcpu, bool is_per_vcpu)
+{
+ pr_err("Callback for partition 0x%x failed.\n", partition_id);
+}
+
+static void ffa_notification_info_get(bool is_64b)
+{
+ int idx, list, max_ids, lists_cnt, ids_processed, ids_count[MAX_IDS_64];
+ ffa_value_t ret;
+ u64 id_list;
+
+ do {
+ invoke_ffa_fn((ffa_value_t){
+ .a0 = FFA_FN_NATIVE(NOTIFICATION_INFO_GET),
+ }, &ret);
+
+ if (ret.a0 != FFA_FN_NATIVE(SUCCESS)) {
+ if (ret.a2 != FFA_RET_NO_DATA)
+ pr_err("Notification Info fetch failed: 0x%lx (0x%lx)",
+ ret.a0, ret.a2);
+ return;
+ }
+
+ ids_processed = 0;
+ lists_cnt = FIELD_GET(NOTIFICATION_INFO_GET_ID_COUNT, ret.a2);
+ if (is_64b) {
+ max_ids = MAX_IDS_64;
+ id_list = FIELD_GET(ID_LIST_MASK_64, ret.a2);
+ } else {
+ max_ids = MAX_IDS_32;
+ id_list = FIELD_GET(ID_LIST_MASK_32, ret.a2);
+ }
+
+ for (idx = 0; idx < lists_cnt; idx++, id_list >>= 2)
+ ids_count[idx] = (id_list & 0x3) + 1;
+
+ /* Process IDs */
+ for (list = 0; list < lists_cnt; list++) {
+ u16 vcpu_id, part_id, *packed_id_list = (u16 *)&ret.a3;
+
+ if (ids_processed >= max_ids - 1)
+ break;
+
+ part_id = packed_id_list[++ids_processed];
+
+ if (!ids_count[list]) { /* Global Notification */
+ __do_sched_recv_cb(part_id, 0, false);
+ continue;
+ }
+
+ /* Per vCPU Notification */
+ for (idx = 0; idx < ids_count[list]; idx++) {
+ if (ids_processed >= max_ids - 1)
+ break;
+
+ vcpu_id = packed_id_list[++ids_processed];
+
+ __do_sched_recv_cb(part_id, vcpu_id, true);
+ }
+ }
+ } while (ret.a2 & NOTIFICATION_INFO_GET_MORE_PEND_MASK);
+}
+
static int ffa_run(struct ffa_device *dev, u16 vcpu)
{
ffa_value_t ret;
--
2.41.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH RFT 08/12] firmware: arm_ffa: Initial support for scheduler receiver interrupt
2023-08-03 19:02 [PATCH RFT 00/12] firmware: arm_ffa: Add FF-A v1.1 notifications support Sudeep Holla
` (6 preceding siblings ...)
2023-08-03 19:02 ` [PATCH RFT 07/12] firmware: arm_ffa: Implement the NOTIFICATION_INFO_GET interface Sudeep Holla
@ 2023-08-03 19:02 ` Sudeep Holla
2023-09-12 13:41 ` Jens Wiklander
2023-08-03 19:02 ` [PATCH RFT 09/12] firmware: arm_ffa: Add schedule receiver callback mechanism Sudeep Holla
` (3 subsequent siblings)
11 siblings, 1 reply; 18+ messages in thread
From: Sudeep Holla @ 2023-08-03 19:02 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: Sudeep Holla, Jens Wiklander, Lucian Paul-Trifu, Marc Bonnici,
Coboy Chen
The Framework uses the schedule receiver interrupt to inform the
receiver’s scheduler that the receiver must be run to handle a pending
notification. A receiver’s scheduler can obtain the description of the
schedule receiver interrupt by invoking the FFA_FEATURES interface.
The delivery of the physical schedule receiver interrupt from the secure
state to the non-secure state depends upon the state of the interrupt
controller as configured by the hypervisor.
The schedule seceiver interrupt is assumed to be a PPI. The Arm GIC
specification defines 16 SGIs. It recommends that they are equally
divided between the non-secure and secure states. OS like Linux kernel
in the non-secure state typically do not have SGIs to spare. The usage
of SGIs in the secure state is however limited. It is more likely that
software in the Secure world does not use all the SGIs allocated to it.
It is recommended that the secure world software donates an unused SGI
to the normal world for use as the schedule receiver interrupt. This
implies that secure world software must configure the SGI in the GIC
as a non-secure interrupt before presenting it to the normal world.
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
drivers/firmware/arm_ffa/driver.c | 183 ++++++++++++++++++++++++++++++++++++--
1 file changed, 175 insertions(+), 8 deletions(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 77ca9753e3f0..84c934a0ec14 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -22,15 +22,20 @@
#define DRIVER_NAME "ARM FF-A"
#define pr_fmt(fmt) DRIVER_NAME ": " fmt
+#include <linux/acpi.h>
#include <linux/arm_ffa.h>
#include <linux/bitfield.h>
+#include <linux/cpuhotplug.h>
#include <linux/device.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mm.h>
+#include <linux/of_irq.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
+#include <linux/smp.h>
#include <linux/uuid.h>
#include "common.h"
@@ -76,6 +81,10 @@ static inline int ffa_to_linux_errno(int errno)
return -EINVAL;
}
+struct ffa_pcpu_irq {
+ struct ffa_drv_info *info;
+};
+
struct ffa_drv_info {
u32 version;
u16 vm_id;
@@ -85,6 +94,12 @@ struct ffa_drv_info {
void *tx_buffer;
bool mem_ops_native;
bool bitmap_created;
+ unsigned int sched_recv_irq;
+ unsigned int cpuhp_state;
+ struct ffa_pcpu_irq __percpu *irq_pcpu;
+ struct workqueue_struct *notif_pcpu_wq;
+ struct work_struct irq_work;
+ bool info_get_64b;
};
static struct ffa_drv_info *drv_info;
@@ -910,9 +925,147 @@ static void ffa_setup_partitions(void)
kfree(pbuf);
}
+/* FFA FEATURE IDs */
+#define FFA_FEAT_NOTIFICATION_PENDING_INT (1)
+#define FFA_FEAT_SCHEDULE_RECEIVER_INT (2)
+#define FFA_FEAT_MANAGED_EXIT_INT (3)
+
+static irqreturn_t irq_handler(int irq, void *irq_data)
+{
+ struct ffa_pcpu_irq *pcpu = irq_data;
+ struct ffa_drv_info *info = pcpu->info;
+
+ queue_work(info->notif_pcpu_wq, &info->irq_work);
+
+ return IRQ_HANDLED;
+}
+
+static void ffa_sched_recv_irq_work_fn(struct work_struct *work)
+{
+ struct ffa_drv_info *info = container_of(work, struct ffa_drv_info,
+ irq_work);
+
+ ffa_notification_info_get(info->info_get_64b);
+}
+
+static int ffa_sched_recv_irq_map(void)
+{
+ int ret, irq, sr_intid;
+
+ ret = ffa_features(FFA_FEAT_SCHEDULE_RECEIVER_INT, 0, &sr_intid, NULL);
+ if (ret < 0) {
+ if (ret != -EOPNOTSUPP)
+ pr_err("Failed to retrieve scheduler Rx interrupt\n");
+ return ret;
+ }
+
+ if (acpi_disabled) {
+ struct of_phandle_args oirq = {};
+ struct device_node *gic;
+
+ gic = of_find_compatible_node(NULL, NULL, "arm,gic-v3");
+ if (!gic)
+ return -ENXIO;
+
+ oirq.np = gic;
+ oirq.args_count = 1;
+ oirq.args[0] = sr_intid;
+ irq = irq_create_of_mapping(&oirq);
+ of_node_put(gic);
+ } else {
+ irq = acpi_register_gsi(NULL, sr_intid, ACPI_EDGE_SENSITIVE,
+ ACPI_ACTIVE_HIGH);
+ }
+
+ if (irq <= 0) {
+ pr_err("Failed to create IRQ mapping!\n");
+ return -ENODATA;
+ }
+
+ return irq;
+}
+
+static void ffa_sched_recv_irq_unmap(void)
+{
+ if (drv_info->sched_recv_irq)
+ irq_dispose_mapping(drv_info->sched_recv_irq);
+}
+
+static int ffa_cpuhp_pcpu_irq_enable(unsigned int cpu)
+{
+ enable_percpu_irq(drv_info->sched_recv_irq, IRQ_TYPE_NONE);
+ return 0;
+}
+
+static int ffa_cpuhp_pcpu_irq_disable(unsigned int cpu)
+{
+ disable_percpu_irq(drv_info->sched_recv_irq);
+ return 0;
+}
+
+static void ffa_uninit_pcpu_irq(void)
+{
+ if (drv_info->cpuhp_state)
+ cpuhp_remove_state(drv_info->cpuhp_state);
+
+ if (drv_info->notif_pcpu_wq)
+ destroy_workqueue(drv_info->notif_pcpu_wq);
+
+ if (drv_info->sched_recv_irq)
+ free_percpu_irq(drv_info->sched_recv_irq, drv_info->irq_pcpu);
+
+ if (drv_info->irq_pcpu)
+ free_percpu(drv_info->irq_pcpu);
+}
+
+static int ffa_init_pcpu_irq(unsigned int irq)
+{
+ struct ffa_pcpu_irq __percpu *irq_pcpu;
+ int ret, cpu;
+
+ irq_pcpu = alloc_percpu(struct ffa_pcpu_irq);
+ if (!irq_pcpu)
+ return -ENOMEM;
+
+ for_each_present_cpu(cpu)
+ per_cpu_ptr(irq_pcpu, cpu)->info = drv_info;
+
+ drv_info->irq_pcpu = irq_pcpu;
+
+ ret = request_percpu_irq(irq, irq_handler, "ARM-FFA", irq_pcpu);
+ if (ret) {
+ pr_err("Error registering notification IRQ %d: %d\n", irq, ret);
+ return ret;
+ }
+
+ INIT_WORK(&drv_info->irq_work, ffa_sched_recv_irq_work_fn);
+ drv_info->notif_pcpu_wq = create_workqueue("ffa_pcpu_irq_notification");
+ if (!drv_info->notif_pcpu_wq)
+ return -EINVAL;
+
+ ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ffa/pcpu-irq:starting",
+ ffa_cpuhp_pcpu_irq_enable,
+ ffa_cpuhp_pcpu_irq_disable);
+
+ if (ret < 0)
+ return ret;
+
+ drv_info->cpuhp_state = ret;
+ return 0;
+}
+
+static void ffa_notifications_cleanup(void)
+{
+ ffa_uninit_pcpu_irq();
+ ffa_sched_recv_irq_unmap();
+
+ if (drv_info->bitmap_created)
+ ffa_notification_bitmap_destroy();
+}
+
static int ffa_notifications_setup(void)
{
- int ret;
+ int ret, irq;
ret = ffa_features(FFA_NOTIFICATION_BITMAP_CREATE, 0, NULL, NULL);
if (!ret) {
@@ -924,13 +1077,23 @@ static int ffa_notifications_setup(void)
}
drv_info->bitmap_created = true;
- return 0;
-}
+ irq = ffa_sched_recv_irq_map();
+ if (irq <= 0)
+ goto cleanup;
-static void ffa_notifications_cleanup(void)
-{
- if (drv_info->bitmap_created)
- ffa_notification_bitmap_destroy();
+ if (FFA_FN_NATIVE(NOTIFICATION_INFO_GET) ==
+ FFA_FN64_NOTIFICATION_INFO_GET)
+ drv_info->info_get_64b = true;
+
+ ret = ffa_init_pcpu_irq(irq);
+ if (ret)
+ goto cleanup;
+
+ drv_info->sched_recv_irq = irq;
+ return 0;
+cleanup:
+ ffa_notifications_cleanup();
+ return ret;
}
static int __init ffa_init(void)
@@ -988,7 +1151,11 @@ static int __init ffa_init(void)
ffa_set_up_mem_ops_native_flag();
- return ffa_notifications_setup();
+ ret = ffa_notifications_setup();
+ if (ret)
+ goto free_pages;
+
+ return 0;
free_pages:
if (drv_info->tx_buffer)
free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE);
--
2.41.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH RFT 09/12] firmware: arm_ffa: Add schedule receiver callback mechanism
2023-08-03 19:02 [PATCH RFT 00/12] firmware: arm_ffa: Add FF-A v1.1 notifications support Sudeep Holla
` (7 preceding siblings ...)
2023-08-03 19:02 ` [PATCH RFT 08/12] firmware: arm_ffa: Initial support for scheduler receiver interrupt Sudeep Holla
@ 2023-08-03 19:02 ` Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 10/12] firmware: arm_ffa: Add interfaces to request notification callbacks Sudeep Holla
` (2 subsequent siblings)
11 siblings, 0 replies; 18+ messages in thread
From: Sudeep Holla @ 2023-08-03 19:02 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: Sudeep Holla, Jens Wiklander, Lucian Paul-Trifu, Marc Bonnici,
Coboy Chen
Enable client drivers to register a callback function that will be
called when one or more notifications are pending for a target partition.
as part of schedule receiver interrupt handling.
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
drivers/firmware/arm_ffa/driver.c | 102 ++++++++++++++++++++++++++++++++++++--
include/linux/arm_ffa.h | 9 ++++
2 files changed, 108 insertions(+), 3 deletions(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 84c934a0ec14..54fca776e5d8 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -37,6 +37,7 @@
#include <linux/slab.h>
#include <linux/smp.h>
#include <linux/uuid.h>
+#include <linux/xarray.h>
#include "common.h"
@@ -100,6 +101,8 @@ struct ffa_drv_info {
struct workqueue_struct *notif_pcpu_wq;
struct work_struct irq_work;
bool info_get_64b;
+ struct xarray partition_info;
+ unsigned int partition_count;
};
static struct ffa_drv_info *drv_info;
@@ -683,9 +686,25 @@ static int ffa_notification_get(u32 flags, struct ffa_notify_bitmaps *notify)
return 0;
}
-static void __do_sched_recv_cb(u16 partition_id, u16 vcpu, bool is_per_vcpu)
+struct ffa_dev_part_info {
+ ffa_sched_recv_cb callback;
+ void *cb_data;
+ rwlock_t rw_lock;
+};
+
+static void __do_sched_recv_cb(u16 part_id, u16 vcpu, bool is_per_vcpu)
{
- pr_err("Callback for partition 0x%x failed.\n", partition_id);
+ struct ffa_dev_part_info *partition;
+ ffa_sched_recv_cb callback;
+ void *cb_data;
+
+ partition = xa_load(&drv_info->partition_info, part_id);
+ read_lock(&partition->rw_lock);
+ callback = partition->callback;
+ cb_data = partition->cb_data;
+ read_unlock(&partition->rw_lock);
+
+ callback(part_id, vcpu, is_per_vcpu, cb_data);
}
static void ffa_notification_info_get(bool is_64b)
@@ -839,6 +858,39 @@ static int ffa_memory_lend(struct ffa_mem_ops_args *args)
return ffa_memory_ops(FFA_MEM_LEND, args);
}
+static int ffa_sched_recv_cb_update(u16 part_id, ffa_sched_recv_cb callback,
+ void *cb_data, bool is_registration)
+{
+ struct ffa_dev_part_info *partition;
+ bool cb_valid;
+
+ partition = xa_load(&drv_info->partition_info, part_id);
+ write_lock(&partition->rw_lock);
+
+ cb_valid = !!partition->callback;
+ if (!(is_registration ^ cb_valid)) {
+ write_unlock(&partition->rw_lock);
+ return -EINVAL;
+ }
+
+ partition->callback = callback;
+ partition->cb_data = cb_data;
+
+ write_unlock(&partition->rw_lock);
+ return 0;
+}
+
+static int ffa_sched_recv_cb_register(struct ffa_device *dev,
+ ffa_sched_recv_cb cb, void *cb_data)
+{
+ return ffa_sched_recv_cb_update(dev->vm_id, cb, cb_data, true);
+}
+
+static int ffa_sched_recv_cb_unregister(struct ffa_device *dev)
+{
+ return ffa_sched_recv_cb_update(dev->vm_id, NULL, NULL, false);
+}
+
static const struct ffa_info_ops ffa_drv_info_ops = {
.api_version_get = ffa_api_version_get,
.partition_info_get = ffa_partition_info_get,
@@ -859,11 +911,17 @@ static const struct ffa_cpu_ops ffa_drv_cpu_ops = {
.run = ffa_run,
};
+static const struct ffa_notifier_ops ffa_drv_notifier_ops = {
+ .sched_recv_cb_register = ffa_sched_recv_cb_register,
+ .sched_recv_cb_unregister = ffa_sched_recv_cb_unregister,
+};
+
static const struct ffa_ops ffa_drv_ops = {
.info_ops = &ffa_drv_info_ops,
.msg_ops = &ffa_drv_msg_ops,
.mem_ops = &ffa_drv_mem_ops,
.cpu_ops = &ffa_drv_cpu_ops,
+ .notifier_ops = &ffa_drv_notifier_ops,
};
void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid)
@@ -894,6 +952,7 @@ static void ffa_setup_partitions(void)
int count, idx;
uuid_t uuid;
struct ffa_device *ffa_dev;
+ struct ffa_dev_part_info *info;
struct ffa_partition_info *pbuf, *tpbuf;
count = ffa_partition_probe(&uuid_null, &pbuf);
@@ -902,6 +961,7 @@ static void ffa_setup_partitions(void)
return;
}
+ xa_init(&drv_info->partition_info);
for (idx = 0, tpbuf = pbuf; idx < count; idx++, tpbuf++) {
import_uuid(&uuid, (u8 *)tpbuf->uuid);
@@ -921,10 +981,42 @@ static void ffa_setup_partitions(void)
if (drv_info->version > FFA_VERSION_1_0 &&
!(tpbuf->properties & FFA_PARTITION_AARCH64_EXEC))
_ffa_mode_32bit_set(ffa_dev);
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+ ffa_device_unregister(ffa_dev);
+ continue;
+ }
+ xa_store(&drv_info->partition_info, tpbuf->id, info, GFP_KERNEL);
}
+ drv_info->partition_count = count;
+
kfree(pbuf);
}
+static void ffa_partitions_cleanup(void)
+{
+ struct ffa_dev_part_info **info;
+ int idx, count = drv_info->partition_count;
+
+ if (!count)
+ return;
+
+ info = kcalloc(count, sizeof(**info), GFP_KERNEL);
+ if (!info)
+ return;
+
+ xa_extract(&drv_info->partition_info, (void **)info, 0, VM_ID_MASK,
+ count, XA_PRESENT);
+
+ for (idx = 0; idx < count; idx++)
+ kfree(info[idx]);
+ kfree(info);
+
+ drv_info->partition_count = 0;
+ xa_destroy(&drv_info->partition_info);
+}
+
/* FFA FEATURE IDs */
#define FFA_FEAT_NOTIFICATION_PENDING_INT (1)
#define FFA_FEAT_SCHEDULE_RECEIVER_INT (2)
@@ -1153,9 +1245,11 @@ static int __init ffa_init(void)
ret = ffa_notifications_setup();
if (ret)
- goto free_pages;
+ goto partitions_cleanup;
return 0;
+partitions_cleanup:
+ ffa_partitions_cleanup();
free_pages:
if (drv_info->tx_buffer)
free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE);
@@ -1171,9 +1265,11 @@ subsys_initcall(ffa_init);
static void __exit ffa_exit(void)
{
ffa_notifications_cleanup();
+ ffa_partitions_cleanup();
ffa_rxtx_unmap(drv_info->vm_id);
free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE);
free_pages_exact(drv_info->rx_buffer, RXTX_BUFFER_SIZE);
+ xa_destroy(&drv_info->partition_info);
kfree(drv_info);
arm_ffa_bus_exit();
}
diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
index 12fd134bf670..63f2e1f5fdc4 100644
--- a/include/linux/arm_ffa.h
+++ b/include/linux/arm_ffa.h
@@ -391,11 +391,20 @@ struct ffa_cpu_ops {
int (*run)(struct ffa_device *dev, u16 vcpu);
};
+typedef void(*ffa_sched_recv_cb)(u16 partition_id, u16 vcpu, bool is_per_vcpu,
+ void *cb_data);
+struct ffa_notifier_ops {
+ int (*sched_recv_cb_register)(struct ffa_device *dev,
+ ffa_sched_recv_cb cb, void *cb_data);
+ int (*sched_recv_cb_unregister)(struct ffa_device *dev);
+};
+
struct ffa_ops {
const struct ffa_info_ops *info_ops;
const struct ffa_msg_ops *msg_ops;
const struct ffa_mem_ops *mem_ops;
const struct ffa_cpu_ops *cpu_ops;
+ const struct ffa_notifier_ops *notifier_ops;
};
#endif /* _LINUX_ARM_FFA_H */
--
2.41.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH RFT 10/12] firmware: arm_ffa: Add interfaces to request notification callbacks
2023-08-03 19:02 [PATCH RFT 00/12] firmware: arm_ffa: Add FF-A v1.1 notifications support Sudeep Holla
` (8 preceding siblings ...)
2023-08-03 19:02 ` [PATCH RFT 09/12] firmware: arm_ffa: Add schedule receiver callback mechanism Sudeep Holla
@ 2023-08-03 19:02 ` Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 11/12] firmware: arm_ffa: Add interface to send a notification to a given partition Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 12/12] firmware: arm_ffa: Add notification handling mechanism Sudeep Holla
11 siblings, 0 replies; 18+ messages in thread
From: Sudeep Holla @ 2023-08-03 19:02 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: Sudeep Holla, Jens Wiklander, Lucian Paul-Trifu, Marc Bonnici,
Coboy Chen
Add interface to the FFA driver to allow for client drivers to request
and relinquish a notification as well as provide a callback for the
notification.
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
drivers/firmware/arm_ffa/driver.c | 130 ++++++++++++++++++++++++++++++++++++++
include/linux/arm_ffa.h | 5 ++
2 files changed, 135 insertions(+)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 54fca776e5d8..29f69f7010c9 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -27,11 +27,13 @@
#include <linux/bitfield.h>
#include <linux/cpuhotplug.h>
#include <linux/device.h>
+#include <linux/hashtable.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mm.h>
+#include <linux/mutex.h>
#include <linux/of_irq.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
@@ -57,6 +59,8 @@
*/
#define RXTX_BUFFER_SIZE SZ_4K
+#define FFA_MAX_NOTIFICATIONS 64
+
static ffa_fn *invoke_ffa_fn;
static const int ffa_linux_errmap[] = {
@@ -103,6 +107,8 @@ struct ffa_drv_info {
bool info_get_64b;
struct xarray partition_info;
unsigned int partition_count;
+ DECLARE_HASHTABLE(notifier_hash, ilog2(FFA_MAX_NOTIFICATIONS));
+ struct mutex notify_lock; /* lock to protect notifier hashtable */
};
static struct ffa_drv_info *drv_info;
@@ -615,6 +621,9 @@ static int ffa_notification_bitmap_destroy(void)
#define MAX_IDS_64 20
#define MAX_IDS_32 10
+#define PER_VCPU_NOTIFICATION_FLAG BIT(0)
+#define ALL_NOTIFICATION_BITMAPS_FLAGS (0xF)
+
static int ffa_notification_bind_common(u16 dst_id, u64 bitmap,
u32 flags, bool is_bind)
{
@@ -858,6 +867,13 @@ static int ffa_memory_lend(struct ffa_mem_ops_args *args)
return ffa_memory_ops(FFA_MEM_LEND, args);
}
+struct notifier_cb_info {
+ struct hlist_node hnode;
+ ffa_notifier_cb cb;
+ void *cb_data;
+ u16 vm_id;
+};
+
static int ffa_sched_recv_cb_update(u16 part_id, ffa_sched_recv_cb callback,
void *cb_data, bool is_registration)
{
@@ -891,6 +907,114 @@ static int ffa_sched_recv_cb_unregister(struct ffa_device *dev)
return ffa_sched_recv_cb_update(dev->vm_id, NULL, NULL, false);
}
+static int ffa_notification_bind(u16 dst_id, u64 bitmap, u32 flags)
+{
+ return ffa_notification_bind_common(dst_id, bitmap, flags, true);
+}
+
+static int ffa_notification_unbind(u16 dst_id, u64 bitmap)
+{
+ return ffa_notification_bind_common(dst_id, bitmap, 0, false);
+}
+
+/* Should be called while the notify_lock is taken */
+static struct notifier_cb_info *
+notifier_hash_node_get(u16 part_id, u16 notify_id)
+{
+ struct notifier_cb_info *node;
+
+ hash_for_each_possible(drv_info->notifier_hash, node, hnode, notify_id)
+ if (part_id == node->vm_id)
+ return node;
+
+ return NULL;
+}
+
+static int
+update_notifier_cb(u16 part_id, int notify_id, ffa_notifier_cb cb,
+ void *cb_data, bool is_registration)
+{
+ struct notifier_cb_info *cb_info = NULL;
+ bool cb_found;
+
+ cb_info = notifier_hash_node_get(part_id, notify_id);
+ cb_found = !!cb_info;
+
+ if (!(is_registration ^ cb_found))
+ return -EINVAL;
+
+ if (is_registration) {
+ cb_info = kzalloc(sizeof(*cb_info), GFP_KERNEL);
+ if (!cb_info)
+ return -ENOMEM;
+
+ cb_info->vm_id = part_id;
+ cb_info->cb = cb;
+ cb_info->cb_data = cb_data;
+
+ hash_add(drv_info->notifier_hash, &cb_info->hnode, notify_id);
+ } else {
+ hash_del(&cb_info->hnode);
+ }
+
+ return 0;
+}
+
+static int ffa_notify_relinquish(struct ffa_device *dev, int notify_id)
+{
+ int rc;
+
+ if (notify_id >= FFA_MAX_NOTIFICATIONS)
+ return -EINVAL;
+
+ mutex_lock(&drv_info->notify_lock);
+
+ rc = update_notifier_cb(dev->vm_id, notify_id, NULL, NULL, false);
+ if (rc) {
+ pr_err("Could not unregister notifcation callback\n");
+ mutex_unlock(&drv_info->notify_lock);
+ return rc;
+ }
+
+ rc = ffa_notification_unbind(dev->vm_id, BIT(notify_id));
+
+ mutex_unlock(&drv_info->notify_lock);
+
+ return rc;
+}
+
+static int ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu,
+ ffa_notifier_cb cb, void *cb_data, int notify_id)
+{
+ int rc;
+ u32 flags = 0;
+
+ if (notify_id >= FFA_MAX_NOTIFICATIONS)
+ return -EINVAL;
+
+ mutex_lock(&drv_info->notify_lock);
+
+ if (is_per_vcpu)
+ flags = PER_VCPU_NOTIFICATION_FLAG;
+
+ rc = ffa_notification_bind(dev->vm_id, BIT(notify_id), flags);
+ if (rc) {
+ mutex_unlock(&drv_info->notify_lock);
+ return rc;
+ }
+
+ rc = update_notifier_cb(dev->vm_id, notify_id, cb, cb_data, true);
+ if (rc) {
+ pr_err("Failed to register callback for %d - %d\n",
+ notify_id, rc);
+ ffa_notification_unbind(dev->vm_id, BIT(notify_id));
+ return rc;
+ }
+ mutex_unlock(&drv_info->notify_lock);
+
+ return rc;
+}
+
static const struct ffa_info_ops ffa_drv_info_ops = {
.api_version_get = ffa_api_version_get,
.partition_info_get = ffa_partition_info_get,
@@ -914,6 +1038,8 @@ static const struct ffa_cpu_ops ffa_drv_cpu_ops = {
static const struct ffa_notifier_ops ffa_drv_notifier_ops = {
.sched_recv_cb_register = ffa_sched_recv_cb_register,
.sched_recv_cb_unregister = ffa_sched_recv_cb_unregister,
+ .notify_request = ffa_notify_request,
+ .notify_relinquish = ffa_notify_relinquish,
};
static const struct ffa_ops ffa_drv_ops = {
@@ -1182,6 +1308,10 @@ static int ffa_notifications_setup(void)
goto cleanup;
drv_info->sched_recv_irq = irq;
+
+ hash_init(drv_info->notifier_hash);
+ mutex_init(&drv_info->notify_lock);
+
return 0;
cleanup:
ffa_notifications_cleanup();
diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
index 63f2e1f5fdc4..99440129b733 100644
--- a/include/linux/arm_ffa.h
+++ b/include/linux/arm_ffa.h
@@ -393,10 +393,15 @@ struct ffa_cpu_ops {
typedef void(*ffa_sched_recv_cb)(u16 partition_id, u16 vcpu, bool is_per_vcpu,
void *cb_data);
+typedef void (*ffa_notifier_cb)(u16 part_id, int notify_id, void *cb_data);
+
struct ffa_notifier_ops {
int (*sched_recv_cb_register)(struct ffa_device *dev,
ffa_sched_recv_cb cb, void *cb_data);
int (*sched_recv_cb_unregister)(struct ffa_device *dev);
+ int (*notify_request)(struct ffa_device *dev, bool per_vcpu,
+ ffa_notifier_cb cb, void *cb_data, int notify_id);
+ int (*notify_relinquish)(struct ffa_device *dev, int notify_id);
};
struct ffa_ops {
--
2.41.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH RFT 11/12] firmware: arm_ffa: Add interface to send a notification to a given partition
2023-08-03 19:02 [PATCH RFT 00/12] firmware: arm_ffa: Add FF-A v1.1 notifications support Sudeep Holla
` (9 preceding siblings ...)
2023-08-03 19:02 ` [PATCH RFT 10/12] firmware: arm_ffa: Add interfaces to request notification callbacks Sudeep Holla
@ 2023-08-03 19:02 ` Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 12/12] firmware: arm_ffa: Add notification handling mechanism Sudeep Holla
11 siblings, 0 replies; 18+ messages in thread
From: Sudeep Holla @ 2023-08-03 19:02 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: Sudeep Holla, Jens Wiklander, Lucian Paul-Trifu, Marc Bonnici,
Coboy Chen
The framework provides an interface to the sender endpoint to specify
the notification to signal to the receiver endpoint. A sender signals
a notification by requesting its partition manager to set the
corresponding bit in the notifications bitmap of the receiver.
Expose the ability to send a notification to another partition.
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
drivers/firmware/arm_ffa/driver.c | 13 +++++++++++++
include/linux/arm_ffa.h | 2 ++
2 files changed, 15 insertions(+)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 29f69f7010c9..d98d0fbe5605 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -1015,6 +1015,18 @@ static int ffa_notify_request(struct ffa_device *dev, bool is_per_vcpu,
return rc;
}
+static int ffa_notify_send(struct ffa_device *dev, int notify_id,
+ bool is_per_vcpu, u16 vcpu)
+{
+ u32 flags = 0;
+
+ if (is_per_vcpu)
+ flags |= (PER_VCPU_NOTIFICATION_FLAG | vcpu << 16);
+
+ return ffa_notification_set(dev->vm_id, drv_info->vm_id, flags,
+ BIT(notify_id));
+}
+
static const struct ffa_info_ops ffa_drv_info_ops = {
.api_version_get = ffa_api_version_get,
.partition_info_get = ffa_partition_info_get,
@@ -1040,6 +1052,7 @@ static const struct ffa_notifier_ops ffa_drv_notifier_ops = {
.sched_recv_cb_unregister = ffa_sched_recv_cb_unregister,
.notify_request = ffa_notify_request,
.notify_relinquish = ffa_notify_relinquish,
+ .notify_send = ffa_notify_send,
};
static const struct ffa_ops ffa_drv_ops = {
diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
index 99440129b733..3bba5f999e4f 100644
--- a/include/linux/arm_ffa.h
+++ b/include/linux/arm_ffa.h
@@ -402,6 +402,8 @@ struct ffa_notifier_ops {
int (*notify_request)(struct ffa_device *dev, bool per_vcpu,
ffa_notifier_cb cb, void *cb_data, int notify_id);
int (*notify_relinquish)(struct ffa_device *dev, int notify_id);
+ int (*notify_send)(struct ffa_device *dev, int notify_id, bool per_vcpu,
+ u16 vcpu);
};
struct ffa_ops {
--
2.41.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH RFT 12/12] firmware: arm_ffa: Add notification handling mechanism
2023-08-03 19:02 [PATCH RFT 00/12] firmware: arm_ffa: Add FF-A v1.1 notifications support Sudeep Holla
` (10 preceding siblings ...)
2023-08-03 19:02 ` [PATCH RFT 11/12] firmware: arm_ffa: Add interface to send a notification to a given partition Sudeep Holla
@ 2023-08-03 19:02 ` Sudeep Holla
11 siblings, 0 replies; 18+ messages in thread
From: Sudeep Holla @ 2023-08-03 19:02 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel
Cc: Sudeep Holla, Jens Wiklander, Lucian Paul-Trifu, Marc Bonnici,
Coboy Chen
With all the necessary plumbing in place, let us add handling the
notifications as part of schedule receiver interrupt handler. In order
to do so, we need to just register scheduling callback on behalf of the
driver partition.
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
---
drivers/firmware/arm_ffa/driver.c | 61 +++++++++++++++++++++++++++++++++++++--
1 file changed, 59 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index d98d0fbe5605..63daef95b048 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -103,6 +103,7 @@ struct ffa_drv_info {
unsigned int cpuhp_state;
struct ffa_pcpu_irq __percpu *irq_pcpu;
struct workqueue_struct *notif_pcpu_wq;
+ struct work_struct notif_pcpu_work;
struct work_struct irq_work;
bool info_get_64b;
struct xarray partition_info;
@@ -1027,6 +1028,54 @@ static int ffa_notify_send(struct ffa_device *dev, int notify_id,
BIT(notify_id));
}
+static void handle_notif_callbacks(u64 bitmap, u16 part_id)
+{
+ int i = 0;
+ struct notifier_cb_info *cb_info = NULL;
+
+ while (bitmap) {
+ if (bitmap & 1) {
+ mutex_lock(&drv_info->notify_lock);
+ cb_info = notifier_hash_node_get(part_id, i);
+ mutex_unlock(&drv_info->notify_lock);
+ if (cb_info->cb)
+ cb_info->cb(part_id, i, cb_info->cb_data);
+ }
+ i++;
+ bitmap >>= 1;
+ }
+}
+
+static void notif_pcpu_irq_work_fn(struct work_struct *work)
+{
+ int rc;
+ struct ffa_notify_bitmaps bitmaps;
+ struct ffa_drv_info *info = container_of(work, struct ffa_drv_info,
+ notif_pcpu_work);
+
+ rc = ffa_notification_get(ALL_NOTIFICATION_BITMAPS_FLAGS, &bitmaps);
+ if (rc) {
+ pr_err("Failed to retrieve notifications with %d!\n", rc);
+ return;
+ }
+
+ handle_notif_callbacks(bitmaps.vm_map, info->vm_id);
+ handle_notif_callbacks(bitmaps.sp_map, info->vm_id);
+ handle_notif_callbacks(bitmaps.arch_map, info->vm_id);
+}
+
+static void
+ffa_self_notif_handle(u16 part_id, u16 vcpu, bool is_per_vcpu, void *cb_data)
+{
+ struct ffa_drv_info *info = cb_data;
+
+ if (!is_per_vcpu)
+ notif_pcpu_irq_work_fn(&info->notif_pcpu_work);
+ else
+ queue_work_on(vcpu, info->notif_pcpu_wq,
+ &info->notif_pcpu_work);
+}
+
static const struct ffa_info_ops ffa_drv_info_ops = {
.api_version_get = ffa_api_version_get,
.partition_info_get = ffa_partition_info_get,
@@ -1128,7 +1177,12 @@ static void ffa_setup_partitions(void)
}
xa_store(&drv_info->partition_info, tpbuf->id, info, GFP_KERNEL);
}
- drv_info->partition_count = count;
+ /* Allocate for the host */
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return;
+ xa_store(&drv_info->partition_info, drv_info->vm_id, info, GFP_KERNEL);
+ drv_info->partition_count = count + 1;
kfree(pbuf);
}
@@ -1270,6 +1324,7 @@ static int ffa_init_pcpu_irq(unsigned int irq)
}
INIT_WORK(&drv_info->irq_work, ffa_sched_recv_irq_work_fn);
+ INIT_WORK(&drv_info->notif_pcpu_work, notif_pcpu_irq_work_fn);
drv_info->notif_pcpu_wq = create_workqueue("ffa_pcpu_irq_notification");
if (!drv_info->notif_pcpu_wq)
return -EINVAL;
@@ -1325,7 +1380,9 @@ static int ffa_notifications_setup(void)
hash_init(drv_info->notifier_hash);
mutex_init(&drv_info->notify_lock);
- return 0;
+ /* Register internal scheduling callback */
+ return ffa_sched_recv_cb_update(drv_info->vm_id,
+ ffa_self_notif_handle, drv_info, true);
cleanup:
ffa_notifications_cleanup();
return ret;
--
2.41.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH RFT 05/12] firmware: arm_ffa: Implement the FFA_NOTIFICATION_SET interface
2023-08-03 19:02 ` [PATCH RFT 05/12] firmware: arm_ffa: Implement the FFA_NOTIFICATION_SET interface Sudeep Holla
@ 2023-09-12 13:23 ` Jens Wiklander
0 siblings, 0 replies; 18+ messages in thread
From: Jens Wiklander @ 2023-09-12 13:23 UTC (permalink / raw)
To: Sudeep Holla
Cc: linux-arm-kernel, linux-kernel, Lucian Paul-Trifu, Marc Bonnici,
Coboy Chen
On Thu, Aug 03, 2023 at 08:02:09PM +0100, Sudeep Holla wrote:
> The framework provides an interface to the sender to specify the
> notification to signal to the receiver. A sender signals a notification
> by requesting its partition manager to set the corresponding bit in the
> notifications bitmap of the receiver invoking FFA_NOTIFICATION_SET.
>
> Implement the FFA_NOTIFICATION_SET to enable the caller(sender) to send
> the notifications for any other partitions in the system.
>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> ---
> drivers/firmware/arm_ffa/driver.c | 20 ++++++++++++++++++++
> 1 file changed, 20 insertions(+)
>
> diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
> index 41171ae7f63a..492f5bfa3751 100644
> --- a/drivers/firmware/arm_ffa/driver.c
> +++ b/drivers/firmware/arm_ffa/driver.c
> @@ -604,6 +604,26 @@ static int ffa_notification_bind_common(u16 dst_id, u64 bitmap,
> return 0;
> }
>
> +static
> +int ffa_notification_set(u16 src_id, u16 dst_id, u32 flags, u64 bitmap)
> +{
> + ffa_value_t ret;
> + u32 src_dst_ids = PACK_TARGET_INFO(dst_id, src_id);
dst_id and src_id should be swapped in the argument to PACK_TARGET_INFO().
Thanks,
Jens
> +
> + invoke_ffa_fn((ffa_value_t) {
> + .a0 = FFA_NOTIFICATION_SET, .a1 = src_dst_ids, .a2 = flags,
> + .a3 = NOTIFICATION_BITMAP_LOW(bitmap),
> + .a4 = NOTIFICATION_BITMAP_HIGH(bitmap),
> + }, &ret);
> +
> + if (ret.a0 == FFA_ERROR)
> + return ffa_to_linux_errno((int)ret.a2);
> + else if (ret.a0 != FFA_SUCCESS)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> static int ffa_run(struct ffa_device *dev, u16 vcpu)
> {
> ffa_value_t ret;
>
> --
> 2.41.0
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH RFT 03/12] firmware: arm_ffa: Implement the notification bind and unbind interface
2023-08-03 19:02 ` [PATCH RFT 03/12] firmware: arm_ffa: Implement the notification bind and unbind interface Sudeep Holla
@ 2023-09-12 13:23 ` Jens Wiklander
2023-09-12 16:08 ` Sudeep Holla
0 siblings, 1 reply; 18+ messages in thread
From: Jens Wiklander @ 2023-09-12 13:23 UTC (permalink / raw)
To: Sudeep Holla
Cc: linux-arm-kernel, linux-kernel, Lucian Paul-Trifu, Marc Bonnici,
Coboy Chen
On Thu, Aug 03, 2023 at 08:02:07PM +0100, Sudeep Holla wrote:
> A receiver endpoint must bind a notification to any sender endpoint
> before the latter can signal the notification to the former. The receiver
> assigns one or more doorbells to a specific sender. Only the sender can
> ring these doorbells.
>
> A receiver uses the FFA_NOTIFICATION_BIND interface to bind one or more
> notifications to the sender. A receiver un-binds a notification from a
> sender endpoint to stop the notification from being signaled. It uses
> the FFA_NOTIFICATION_UNBIND interface to do this.
>
> Allow the FF-A driver to be able to bind and unbind a given notification
> ID to a specific partition ID. This will be used to register and
> unregister notification callbacks from the FF-A client drivers.
>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> ---
> drivers/firmware/arm_ffa/driver.c | 29 +++++++++++++++++++++++++++++
> 1 file changed, 29 insertions(+)
>
> diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
> index 022c893c9e06..a76e5d3a2422 100644
> --- a/drivers/firmware/arm_ffa/driver.c
> +++ b/drivers/firmware/arm_ffa/driver.c
> @@ -575,6 +575,35 @@ static int ffa_notification_bitmap_destroy(void)
> return 0;
> }
>
> +#define NOTIFICATION_LOW_MASK GENMASK(31, 0)
> +#define NOTIFICATION_HIGH_MASK GENMASK(63, 32)
> +#define NOTIFICATION_BITMAP_HIGH(x) \
> + ((u32)(FIELD_GET(NOTIFICATION_HIGH_MASK, (x))))
> +#define NOTIFICATION_BITMAP_LOW(x) \
> + ((u32)(FIELD_GET(NOTIFICATION_LOW_MASK, (x))))
> +
> +static int ffa_notification_bind_common(u16 dst_id, u64 bitmap,
> + u32 flags, bool is_bind)
> +{
> + ffa_value_t ret;
> + u32 func, src_dst_ids = PACK_TARGET_INFO(dst_id, drv_info->vm_id);
dst_id and drv_info->vm_id should be swapped in the argument to
PACK_TARGET_INFO().
Thanks,
Jens
> +
> + func = is_bind ? FFA_NOTIFICATION_BIND : FFA_NOTIFICATION_UNBIND;
> +
> + invoke_ffa_fn((ffa_value_t){
> + .a0 = func, .a1 = src_dst_ids, .a2 = flags,
> + .a3 = NOTIFICATION_BITMAP_LOW(bitmap),
> + .a4 = NOTIFICATION_BITMAP_HIGH(bitmap),
> + }, &ret);
> +
> + if (ret.a0 == FFA_ERROR)
> + return ffa_to_linux_errno((int)ret.a2);
> + else if (ret.a0 != FFA_SUCCESS)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> static void ffa_set_up_mem_ops_native_flag(void)
> {
> if (!ffa_features(FFA_FN_NATIVE(MEM_LEND), 0, NULL, NULL) ||
>
> --
> 2.41.0
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH RFT 08/12] firmware: arm_ffa: Initial support for scheduler receiver interrupt
2023-08-03 19:02 ` [PATCH RFT 08/12] firmware: arm_ffa: Initial support for scheduler receiver interrupt Sudeep Holla
@ 2023-09-12 13:41 ` Jens Wiklander
2023-09-12 16:06 ` Sudeep Holla
0 siblings, 1 reply; 18+ messages in thread
From: Jens Wiklander @ 2023-09-12 13:41 UTC (permalink / raw)
To: Sudeep Holla
Cc: linux-arm-kernel, linux-kernel, Lucian Paul-Trifu, Marc Bonnici,
Coboy Chen
Hi Sudeep,
On Thu, Aug 03, 2023 at 08:02:12PM +0100, Sudeep Holla wrote:
> The Framework uses the schedule receiver interrupt to inform the
> receiver’s scheduler that the receiver must be run to handle a pending
> notification. A receiver’s scheduler can obtain the description of the
> schedule receiver interrupt by invoking the FFA_FEATURES interface.
>
> The delivery of the physical schedule receiver interrupt from the secure
> state to the non-secure state depends upon the state of the interrupt
> controller as configured by the hypervisor.
>
> The schedule seceiver interrupt is assumed to be a PPI. The Arm GIC
> specification defines 16 SGIs. It recommends that they are equally
> divided between the non-secure and secure states. OS like Linux kernel
> in the non-secure state typically do not have SGIs to spare. The usage
> of SGIs in the secure state is however limited. It is more likely that
> software in the Secure world does not use all the SGIs allocated to it.
>
> It is recommended that the secure world software donates an unused SGI
> to the normal world for use as the schedule receiver interrupt. This
> implies that secure world software must configure the SGI in the GIC
> as a non-secure interrupt before presenting it to the normal world.
>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> ---
> drivers/firmware/arm_ffa/driver.c | 183 ++++++++++++++++++++++++++++++++++++--
> 1 file changed, 175 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
> index 77ca9753e3f0..84c934a0ec14 100644
> --- a/drivers/firmware/arm_ffa/driver.c
> +++ b/drivers/firmware/arm_ffa/driver.c
> @@ -22,15 +22,20 @@
> #define DRIVER_NAME "ARM FF-A"
> #define pr_fmt(fmt) DRIVER_NAME ": " fmt
>
> +#include <linux/acpi.h>
> #include <linux/arm_ffa.h>
> #include <linux/bitfield.h>
> +#include <linux/cpuhotplug.h>
> #include <linux/device.h>
> +#include <linux/interrupt.h>
> #include <linux/io.h>
> #include <linux/kernel.h>
> #include <linux/module.h>
> #include <linux/mm.h>
> +#include <linux/of_irq.h>
> #include <linux/scatterlist.h>
> #include <linux/slab.h>
> +#include <linux/smp.h>
> #include <linux/uuid.h>
>
> #include "common.h"
> @@ -76,6 +81,10 @@ static inline int ffa_to_linux_errno(int errno)
> return -EINVAL;
> }
>
> +struct ffa_pcpu_irq {
> + struct ffa_drv_info *info;
> +};
> +
> struct ffa_drv_info {
> u32 version;
> u16 vm_id;
> @@ -85,6 +94,12 @@ struct ffa_drv_info {
> void *tx_buffer;
> bool mem_ops_native;
> bool bitmap_created;
> + unsigned int sched_recv_irq;
> + unsigned int cpuhp_state;
> + struct ffa_pcpu_irq __percpu *irq_pcpu;
> + struct workqueue_struct *notif_pcpu_wq;
> + struct work_struct irq_work;
> + bool info_get_64b;
> };
>
> static struct ffa_drv_info *drv_info;
> @@ -910,9 +925,147 @@ static void ffa_setup_partitions(void)
> kfree(pbuf);
> }
>
> +/* FFA FEATURE IDs */
> +#define FFA_FEAT_NOTIFICATION_PENDING_INT (1)
> +#define FFA_FEAT_SCHEDULE_RECEIVER_INT (2)
> +#define FFA_FEAT_MANAGED_EXIT_INT (3)
> +
> +static irqreturn_t irq_handler(int irq, void *irq_data)
> +{
> + struct ffa_pcpu_irq *pcpu = irq_data;
> + struct ffa_drv_info *info = pcpu->info;
> +
> + queue_work(info->notif_pcpu_wq, &info->irq_work);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static void ffa_sched_recv_irq_work_fn(struct work_struct *work)
> +{
> + struct ffa_drv_info *info = container_of(work, struct ffa_drv_info,
> + irq_work);
> +
> + ffa_notification_info_get(info->info_get_64b);
> +}
> +
> +static int ffa_sched_recv_irq_map(void)
> +{
> + int ret, irq, sr_intid;
> +
> + ret = ffa_features(FFA_FEAT_SCHEDULE_RECEIVER_INT, 0, &sr_intid, NULL);
> + if (ret < 0) {
> + if (ret != -EOPNOTSUPP)
> + pr_err("Failed to retrieve scheduler Rx interrupt\n");
> + return ret;
> + }
> +
> + if (acpi_disabled) {
> + struct of_phandle_args oirq = {};
> + struct device_node *gic;
> +
> + gic = of_find_compatible_node(NULL, NULL, "arm,gic-v3");
"arm,gic-v3" might be good enough for now, but eventually we may need more scalable probing.
> + if (!gic)
> + return -ENXIO;
> +
> + oirq.np = gic;
> + oirq.args_count = 1;
> + oirq.args[0] = sr_intid;
> + irq = irq_create_of_mapping(&oirq);
You mention (or try to ;-)) in the commit message that SGIs only are
assumed for now. A comment here stating that fact wouldn't hurt.
I'm trying to test this on QEMU, but I can't seem to recieve the SGI in
the kernel. I've donated the previously secure SGI-8 at boot (simple
patch in TF-A) before the kernel starts. I've verified with GDB that
QEMU has accepted the write to ICC_ASGI1R_EL1 while in secure world, but
it seems it never triggers when switching back to normal world. I'm
starting to suspect that irq_create_of_mapping() might not update SGI-8
properly. Perhaps something more is needed when donating SGI-8 on the
kernel side.
Did you have this working in your tests?
Cheers,
Jens
> + of_node_put(gic);
> + } else {
> + irq = acpi_register_gsi(NULL, sr_intid, ACPI_EDGE_SENSITIVE,
> + ACPI_ACTIVE_HIGH);
> + }
> +
> + if (irq <= 0) {
> + pr_err("Failed to create IRQ mapping!\n");
> + return -ENODATA;
> + }
> +
> + return irq;
> +}
> +
> +static void ffa_sched_recv_irq_unmap(void)
> +{
> + if (drv_info->sched_recv_irq)
> + irq_dispose_mapping(drv_info->sched_recv_irq);
> +}
> +
> +static int ffa_cpuhp_pcpu_irq_enable(unsigned int cpu)
> +{
> + enable_percpu_irq(drv_info->sched_recv_irq, IRQ_TYPE_NONE);
> + return 0;
> +}
> +
> +static int ffa_cpuhp_pcpu_irq_disable(unsigned int cpu)
> +{
> + disable_percpu_irq(drv_info->sched_recv_irq);
> + return 0;
> +}
> +
> +static void ffa_uninit_pcpu_irq(void)
> +{
> + if (drv_info->cpuhp_state)
> + cpuhp_remove_state(drv_info->cpuhp_state);
> +
> + if (drv_info->notif_pcpu_wq)
> + destroy_workqueue(drv_info->notif_pcpu_wq);
> +
> + if (drv_info->sched_recv_irq)
> + free_percpu_irq(drv_info->sched_recv_irq, drv_info->irq_pcpu);
> +
> + if (drv_info->irq_pcpu)
> + free_percpu(drv_info->irq_pcpu);
> +}
> +
> +static int ffa_init_pcpu_irq(unsigned int irq)
> +{
> + struct ffa_pcpu_irq __percpu *irq_pcpu;
> + int ret, cpu;
> +
> + irq_pcpu = alloc_percpu(struct ffa_pcpu_irq);
> + if (!irq_pcpu)
> + return -ENOMEM;
> +
> + for_each_present_cpu(cpu)
> + per_cpu_ptr(irq_pcpu, cpu)->info = drv_info;
> +
> + drv_info->irq_pcpu = irq_pcpu;
> +
> + ret = request_percpu_irq(irq, irq_handler, "ARM-FFA", irq_pcpu);
> + if (ret) {
> + pr_err("Error registering notification IRQ %d: %d\n", irq, ret);
> + return ret;
> + }
> +
> + INIT_WORK(&drv_info->irq_work, ffa_sched_recv_irq_work_fn);
> + drv_info->notif_pcpu_wq = create_workqueue("ffa_pcpu_irq_notification");
> + if (!drv_info->notif_pcpu_wq)
> + return -EINVAL;
> +
> + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ffa/pcpu-irq:starting",
> + ffa_cpuhp_pcpu_irq_enable,
> + ffa_cpuhp_pcpu_irq_disable);
> +
> + if (ret < 0)
> + return ret;
> +
> + drv_info->cpuhp_state = ret;
> + return 0;
> +}
> +
> +static void ffa_notifications_cleanup(void)
> +{
> + ffa_uninit_pcpu_irq();
> + ffa_sched_recv_irq_unmap();
> +
> + if (drv_info->bitmap_created)
> + ffa_notification_bitmap_destroy();
> +}
> +
> static int ffa_notifications_setup(void)
> {
> - int ret;
> + int ret, irq;
>
> ret = ffa_features(FFA_NOTIFICATION_BITMAP_CREATE, 0, NULL, NULL);
> if (!ret) {
> @@ -924,13 +1077,23 @@ static int ffa_notifications_setup(void)
> }
> drv_info->bitmap_created = true;
>
> - return 0;
> -}
> + irq = ffa_sched_recv_irq_map();
> + if (irq <= 0)
> + goto cleanup;
>
> -static void ffa_notifications_cleanup(void)
> -{
> - if (drv_info->bitmap_created)
> - ffa_notification_bitmap_destroy();
> + if (FFA_FN_NATIVE(NOTIFICATION_INFO_GET) ==
> + FFA_FN64_NOTIFICATION_INFO_GET)
> + drv_info->info_get_64b = true;
> +
> + ret = ffa_init_pcpu_irq(irq);
> + if (ret)
> + goto cleanup;
> +
> + drv_info->sched_recv_irq = irq;
> + return 0;
> +cleanup:
> + ffa_notifications_cleanup();
> + return ret;
> }
>
> static int __init ffa_init(void)
> @@ -988,7 +1151,11 @@ static int __init ffa_init(void)
>
> ffa_set_up_mem_ops_native_flag();
>
> - return ffa_notifications_setup();
> + ret = ffa_notifications_setup();
> + if (ret)
> + goto free_pages;
> +
> + return 0;
> free_pages:
> if (drv_info->tx_buffer)
> free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE);
>
> --
> 2.41.0
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH RFT 08/12] firmware: arm_ffa: Initial support for scheduler receiver interrupt
2023-09-12 13:41 ` Jens Wiklander
@ 2023-09-12 16:06 ` Sudeep Holla
0 siblings, 0 replies; 18+ messages in thread
From: Sudeep Holla @ 2023-09-12 16:06 UTC (permalink / raw)
To: Jens Wiklander
Cc: linux-arm-kernel, linux-kernel, Lucian Paul-Trifu, Marc Bonnici,
Coboy Chen
On Tue, Sep 12, 2023 at 03:41:04PM +0200, Jens Wiklander wrote:
> Hi Sudeep,
>
> On Thu, Aug 03, 2023 at 08:02:12PM +0100, Sudeep Holla wrote:
> > The Framework uses the schedule receiver interrupt to inform the
> > receiver’s scheduler that the receiver must be run to handle a pending
> > notification. A receiver’s scheduler can obtain the description of the
> > schedule receiver interrupt by invoking the FFA_FEATURES interface.
> >
> > The delivery of the physical schedule receiver interrupt from the secure
> > state to the non-secure state depends upon the state of the interrupt
> > controller as configured by the hypervisor.
> >
> > The schedule seceiver interrupt is assumed to be a PPI. The Arm GIC
> > specification defines 16 SGIs. It recommends that they are equally
> > divided between the non-secure and secure states. OS like Linux kernel
> > in the non-secure state typically do not have SGIs to spare. The usage
> > of SGIs in the secure state is however limited. It is more likely that
> > software in the Secure world does not use all the SGIs allocated to it.
> >
> > It is recommended that the secure world software donates an unused SGI
> > to the normal world for use as the schedule receiver interrupt. This
> > implies that secure world software must configure the SGI in the GIC
> > as a non-secure interrupt before presenting it to the normal world.
> >
> > Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> > ---
> > drivers/firmware/arm_ffa/driver.c | 183 ++++++++++++++++++++++++++++++++++++--
> > 1 file changed, 175 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
> > index 77ca9753e3f0..84c934a0ec14 100644
> > --- a/drivers/firmware/arm_ffa/driver.c
> > +++ b/drivers/firmware/arm_ffa/driver.c
> > @@ -22,15 +22,20 @@
> > #define DRIVER_NAME "ARM FF-A"
> > #define pr_fmt(fmt) DRIVER_NAME ": " fmt
> >
> > +#include <linux/acpi.h>
> > #include <linux/arm_ffa.h>
> > #include <linux/bitfield.h>
> > +#include <linux/cpuhotplug.h>
> > #include <linux/device.h>
> > +#include <linux/interrupt.h>
> > #include <linux/io.h>
> > #include <linux/kernel.h>
> > #include <linux/module.h>
> > #include <linux/mm.h>
> > +#include <linux/of_irq.h>
> > #include <linux/scatterlist.h>
> > #include <linux/slab.h>
> > +#include <linux/smp.h>
> > #include <linux/uuid.h>
> >
> > #include "common.h"
> > @@ -76,6 +81,10 @@ static inline int ffa_to_linux_errno(int errno)
> > return -EINVAL;
> > }
> >
> > +struct ffa_pcpu_irq {
> > + struct ffa_drv_info *info;
> > +};
> > +
> > struct ffa_drv_info {
> > u32 version;
> > u16 vm_id;
> > @@ -85,6 +94,12 @@ struct ffa_drv_info {
> > void *tx_buffer;
> > bool mem_ops_native;
> > bool bitmap_created;
> > + unsigned int sched_recv_irq;
> > + unsigned int cpuhp_state;
> > + struct ffa_pcpu_irq __percpu *irq_pcpu;
> > + struct workqueue_struct *notif_pcpu_wq;
> > + struct work_struct irq_work;
> > + bool info_get_64b;
> > };
> >
> > static struct ffa_drv_info *drv_info;
> > @@ -910,9 +925,147 @@ static void ffa_setup_partitions(void)
> > kfree(pbuf);
> > }
> >
> > +/* FFA FEATURE IDs */
> > +#define FFA_FEAT_NOTIFICATION_PENDING_INT (1)
> > +#define FFA_FEAT_SCHEDULE_RECEIVER_INT (2)
> > +#define FFA_FEAT_MANAGED_EXIT_INT (3)
> > +
> > +static irqreturn_t irq_handler(int irq, void *irq_data)
> > +{
> > + struct ffa_pcpu_irq *pcpu = irq_data;
> > + struct ffa_drv_info *info = pcpu->info;
> > +
> > + queue_work(info->notif_pcpu_wq, &info->irq_work);
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static void ffa_sched_recv_irq_work_fn(struct work_struct *work)
> > +{
> > + struct ffa_drv_info *info = container_of(work, struct ffa_drv_info,
> > + irq_work);
> > +
> > + ffa_notification_info_get(info->info_get_64b);
> > +}
> > +
> > +static int ffa_sched_recv_irq_map(void)
> > +{
> > + int ret, irq, sr_intid;
> > +
> > + ret = ffa_features(FFA_FEAT_SCHEDULE_RECEIVER_INT, 0, &sr_intid, NULL);
> > + if (ret < 0) {
> > + if (ret != -EOPNOTSUPP)
> > + pr_err("Failed to retrieve scheduler Rx interrupt\n");
> > + return ret;
> > + }
> > +
> > + if (acpi_disabled) {
> > + struct of_phandle_args oirq = {};
> > + struct device_node *gic;
> > +
> > + gic = of_find_compatible_node(NULL, NULL, "arm,gic-v3");
>
> "arm,gic-v3" might be good enough for now, but eventually we may need more scalable probing.
>
> > + if (!gic)
> > + return -ENXIO;
> > +
> > + oirq.np = gic;
> > + oirq.args_count = 1;
> > + oirq.args[0] = sr_intid;
> > + irq = irq_create_of_mapping(&oirq);
>
> You mention (or try to ;-)) in the commit message that SGIs only are
> assumed for now. A comment here stating that fact wouldn't hurt.
>
Fair enough, I will add.
> I'm trying to test this on QEMU, but I can't seem to recieve the SGI in
> the kernel. I've donated the previously secure SGI-8 at boot (simple
> patch in TF-A) before the kernel starts. I've verified with GDB that
> QEMU has accepted the write to ICC_ASGI1R_EL1 while in secure world, but
> it seems it never triggers when switching back to normal world. I'm
> starting to suspect that irq_create_of_mapping() might not update SGI-8
> properly. Perhaps something more is needed when donating SGI-8 on the
> kernel side.
>
> Did you have this working in your tests?
Nope, I haven't been able to get a working end-to-end stack and hence RFT.
However I had tried to test just the SGI part but did have some hacks which
I have lost. I wanted to check if those changes were just for my testing or
is indeed needed in the kernel. I will try to dig more details.
--
Regards,
Sudeep
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH RFT 03/12] firmware: arm_ffa: Implement the notification bind and unbind interface
2023-09-12 13:23 ` Jens Wiklander
@ 2023-09-12 16:08 ` Sudeep Holla
0 siblings, 0 replies; 18+ messages in thread
From: Sudeep Holla @ 2023-09-12 16:08 UTC (permalink / raw)
To: Jens Wiklander
Cc: linux-arm-kernel, linux-kernel, Lucian Paul-Trifu, Marc Bonnici,
Coboy Chen
On Tue, Sep 12, 2023 at 03:23:53PM +0200, Jens Wiklander wrote:
> On Thu, Aug 03, 2023 at 08:02:07PM +0100, Sudeep Holla wrote:
> > A receiver endpoint must bind a notification to any sender endpoint
> > before the latter can signal the notification to the former. The receiver
> > assigns one or more doorbells to a specific sender. Only the sender can
> > ring these doorbells.
> >
> > A receiver uses the FFA_NOTIFICATION_BIND interface to bind one or more
> > notifications to the sender. A receiver un-binds a notification from a
> > sender endpoint to stop the notification from being signaled. It uses
> > the FFA_NOTIFICATION_UNBIND interface to do this.
> >
> > Allow the FF-A driver to be able to bind and unbind a given notification
> > ID to a specific partition ID. This will be used to register and
> > unregister notification callbacks from the FF-A client drivers.
> >
> > Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> > ---
> > drivers/firmware/arm_ffa/driver.c | 29 +++++++++++++++++++++++++++++
> > 1 file changed, 29 insertions(+)
> >
> > diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
> > index 022c893c9e06..a76e5d3a2422 100644
> > --- a/drivers/firmware/arm_ffa/driver.c
> > +++ b/drivers/firmware/arm_ffa/driver.c
> > @@ -575,6 +575,35 @@ static int ffa_notification_bitmap_destroy(void)
> > return 0;
> > }
> >
> > +#define NOTIFICATION_LOW_MASK GENMASK(31, 0)
> > +#define NOTIFICATION_HIGH_MASK GENMASK(63, 32)
> > +#define NOTIFICATION_BITMAP_HIGH(x) \
> > + ((u32)(FIELD_GET(NOTIFICATION_HIGH_MASK, (x))))
> > +#define NOTIFICATION_BITMAP_LOW(x) \
> > + ((u32)(FIELD_GET(NOTIFICATION_LOW_MASK, (x))))
> > +
> > +static int ffa_notification_bind_common(u16 dst_id, u64 bitmap,
> > + u32 flags, bool is_bind)
> > +{
> > + ffa_value_t ret;
> > + u32 func, src_dst_ids = PACK_TARGET_INFO(dst_id, drv_info->vm_id);
> dst_id and drv_info->vm_id should be swapped in the argument to
> PACK_TARGET_INFO().
>
Thanks a lot for having a look at the series. I see Olivier or someone
have already pointed this in private and I seem to have it fixed locally
already.
--
Regards,
Sudeep
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2023-09-12 16:08 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-03 19:02 [PATCH RFT 00/12] firmware: arm_ffa: Add FF-A v1.1 notifications support Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 01/12] firmware: arm_ffa: Update the FF-A command list with v1.1 additions Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 02/12] firmware: arm_ffa: Implement notification bitmap create and destroy interfaces Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 03/12] firmware: arm_ffa: Implement the notification bind and unbind interface Sudeep Holla
2023-09-12 13:23 ` Jens Wiklander
2023-09-12 16:08 ` Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 04/12] firmware: arm_ffa: Implement the FFA_RUN interface Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 05/12] firmware: arm_ffa: Implement the FFA_NOTIFICATION_SET interface Sudeep Holla
2023-09-12 13:23 ` Jens Wiklander
2023-08-03 19:02 ` [PATCH RFT 06/12] firmware: arm_ffa: Implement the FFA_NOTIFICATION_GET interface Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 07/12] firmware: arm_ffa: Implement the NOTIFICATION_INFO_GET interface Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 08/12] firmware: arm_ffa: Initial support for scheduler receiver interrupt Sudeep Holla
2023-09-12 13:41 ` Jens Wiklander
2023-09-12 16:06 ` Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 09/12] firmware: arm_ffa: Add schedule receiver callback mechanism Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 10/12] firmware: arm_ffa: Add interfaces to request notification callbacks Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 11/12] firmware: arm_ffa: Add interface to send a notification to a given partition Sudeep Holla
2023-08-03 19:02 ` [PATCH RFT 12/12] firmware: arm_ffa: Add notification handling mechanism Sudeep Holla
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).