Since RPAL involves communication between services, and services require certain preparations (e.g., registering senders/receivers) before communication, the kernel needs to sense whether a service is ready to perform RPAL call-related operations. This patch adds two interfaces: rpal_enable_service() and rpal_disable_service(). rpal_enable_service() passes necessary information to the kernel and marks the service as enabled. RPAL only permits communication between services in the enabled state. rpal_disable_service() clears the service's enabled state, thereby prohibiting communication between the service and others via RPAL. Signed-off-by: Bo Li <libo.gcs85@xxxxxxxxxxxxx> --- arch/x86/rpal/internal.h | 2 ++ arch/x86/rpal/proc.c | 6 +++++ arch/x86/rpal/service.c | 50 ++++++++++++++++++++++++++++++++++++++++ include/linux/rpal.h | 18 +++++++++++++++ 4 files changed, 76 insertions(+) diff --git a/arch/x86/rpal/internal.h b/arch/x86/rpal/internal.h index 65f2cf4baf8f..769d3bbe5a6b 100644 --- a/arch/x86/rpal/internal.h +++ b/arch/x86/rpal/internal.h @@ -17,6 +17,8 @@ extern bool rpal_inited; /* service.c */ int __init rpal_service_init(void); void __init rpal_service_exit(void); +int rpal_enable_service(unsigned long arg); +int rpal_disable_service(void); /* mm.c */ static inline struct rpal_shared_page * diff --git a/arch/x86/rpal/proc.c b/arch/x86/rpal/proc.c index 8a1e4a8a2271..acd814f31649 100644 --- a/arch/x86/rpal/proc.c +++ b/arch/x86/rpal/proc.c @@ -63,6 +63,12 @@ static long rpal_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case RPAL_IOCTL_UNREGISTER_RECEIVER: ret = rpal_unregister_receiver(); break; + case RPAL_IOCTL_ENABLE_SERVICE: + ret = rpal_enable_service(arg); + break; + case RPAL_IOCTL_DISABLE_SERVICE: + ret = rpal_disable_service(); + break; default: return -EINVAL; } diff --git a/arch/x86/rpal/service.c b/arch/x86/rpal/service.c index 42fb719dbb2a..8a7b679bc28b 100644 --- a/arch/x86/rpal/service.c +++ b/arch/x86/rpal/service.c @@ -177,6 +177,7 @@ struct rpal_service *rpal_register_service(void) rs->nr_shared_pages = 0; INIT_LIST_HEAD(&rs->shared_pages); atomic_set(&rs->thread_cnt, 0); + rs->enabled = false; rs->bad_service = false; rs->base = calculate_base_address(rs->id); @@ -228,6 +229,52 @@ void rpal_unregister_service(struct rpal_service *rs) rpal_put_service(rs); } +int rpal_enable_service(unsigned long arg) +{ + struct rpal_service *cur = rpal_current_service(); + struct rpal_service_metadata rsm; + int ret = 0; + + if (cur->bad_service) { + ret = -EINVAL; + goto out; + } + + ret = copy_from_user(&rsm, (void __user *)arg, sizeof(rsm)); + if (ret) { + ret = -EFAULT; + goto out; + } + + mutex_lock(&cur->mutex); + if (!cur->enabled) { + cur->rsm = rsm; + cur->enabled = true; + } + mutex_unlock(&cur->mutex); + +out: + return ret; +} + +int rpal_disable_service(void) +{ + struct rpal_service *cur = rpal_current_service(); + int ret = 0; + + mutex_lock(&cur->mutex); + if (cur->enabled) { + cur->enabled = false; + } else { + ret = -EINVAL; + goto unlock_mutex; + } + +unlock_mutex: + mutex_unlock(&cur->mutex); + return ret; +} + void copy_rpal(struct task_struct *p) { struct rpal_service *cur = rpal_current_service(); @@ -244,6 +291,9 @@ void exit_rpal(bool group_dead) exit_rpal_thread(); + if (group_dead) + rpal_disable_service(); + current->rpal_rs = NULL; rpal_put_service(rs); diff --git a/include/linux/rpal.h b/include/linux/rpal.h index c33425e896af..2e5010602177 100644 --- a/include/linux/rpal.h +++ b/include/linux/rpal.h @@ -84,6 +84,14 @@ enum rpal_task_flag_bits { RPAL_RECEIVER_BIT, }; +/* + * user_meta will be sent to other service when requested. + */ +struct rpal_service_metadata { + unsigned long version; + void __user *user_meta; +}; + /* * Each RPAL process (a.k.a RPAL service) should have a pointer to * struct rpal_service in all its tasks' task_struct. @@ -125,6 +133,10 @@ struct rpal_service { /* sender/receiver thread count */ atomic_t thread_cnt; + /* service metadata */ + bool enabled; + struct rpal_service_metadata rsm; + /* delayed service put work */ struct delayed_work delayed_put_work; @@ -206,6 +218,8 @@ enum rpal_command_type { RPAL_CMD_UNREGISTER_SENDER, RPAL_CMD_REGISTER_RECEIVER, RPAL_CMD_UNREGISTER_RECEIVER, + RPAL_CMD_ENABLE_SERVICE, + RPAL_CMD_DISABLE_SERVICE, RPAL_NR_CMD, }; @@ -226,6 +240,10 @@ enum rpal_command_type { _IOWR(RPAL_IOCTL_MAGIC, RPAL_CMD_REGISTER_RECEIVER, unsigned long) #define RPAL_IOCTL_UNREGISTER_RECEIVER \ _IO(RPAL_IOCTL_MAGIC, RPAL_CMD_UNREGISTER_RECEIVER) +#define RPAL_IOCTL_ENABLE_SERVICE \ + _IOWR(RPAL_IOCTL_MAGIC, RPAL_CMD_ENABLE_SERVICE, unsigned long) +#define RPAL_IOCTL_DISABLE_SERVICE \ + _IO(RPAL_IOCTL_MAGIC, RPAL_CMD_DISABLE_SERVICE) /** * @brief get new reference to a rpal service, a corresponding -- 2.20.1