@@ -105,6 +105,13 @@ struct gh_rsc_mgr {
static struct gh_rsc_mgr *__rsc_mgr;
SRCU_NOTIFIER_HEAD_STATIC(gh_rm_notifier);
+/* Needs to be out of the gh_rsc_mgr struct as platform_ops might probe before
+ * rsc mgr probes. We can't defer the platform_ops because it might be that
+ * Linux is not a Gunyah guest.
+ */
+static struct gunyah_rm_platform_ops *rm_platform_ops;
+static DECLARE_RWSEM(rm_platform_ops_lock);
+
static struct gh_rm_connection *gh_rm_alloc_connection(u32 msg_id, u8 type)
{
struct gh_rm_connection *connection;
@@ -498,6 +505,51 @@ int gh_rm_call(u32 message_id, void *req_buff, size_t req_buff_size,
return ret;
}
+int gh_rm_platform_pre_mem_share(struct gh_rm_mem_parcel *mem_parcel)
+{
+ int ret = 0;
+
+ down_read(&rm_platform_ops_lock);
+ if (rm_platform_ops && rm_platform_ops->pre_mem_share)
+ ret = rm_platform_ops->pre_mem_share(mem_parcel);
+ up_read(&rm_platform_ops_lock);
+ return ret;
+}
+
+int gh_rm_platform_post_mem_reclaim(struct gh_rm_mem_parcel *mem_parcel)
+{
+ int ret = 0;
+
+ down_read(&rm_platform_ops_lock);
+ if (rm_platform_ops && rm_platform_ops->post_mem_reclaim)
+ ret = rm_platform_ops->post_mem_reclaim(mem_parcel);
+ up_read(&rm_platform_ops_lock);
+ return ret;
+}
+
+int gh_rm_register_platform_ops(struct gunyah_rm_platform_ops *platform_ops)
+{
+ int ret = 0;
+
+ down_write(&rm_platform_ops_lock);
+ if (!rm_platform_ops)
+ rm_platform_ops = platform_ops;
+ else
+ ret = -EEXIST;
+ up_write(&rm_platform_ops_lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(gh_rm_register_platform_ops);
+
+void gh_rm_unregister_platform_ops(struct gunyah_rm_platform_ops *platform_ops)
+{
+ down_write(&rm_platform_ops_lock);
+ if (rm_platform_ops == platform_ops)
+ rm_platform_ops = NULL;
+ up_write(&rm_platform_ops_lock);
+}
+EXPORT_SYMBOL_GPL(gh_rm_unregister_platform_ops);
+
int gh_rm_register_notifier(struct notifier_block *nb)
{
return srcu_notifier_chain_register(&gh_rm_notifier, nb);
@@ -130,6 +130,9 @@ struct gh_vm_set_boot_context_req {
int gh_rm_call(u32 message_id, void *req_buff, size_t req_buff_size,
void **resp_buf, size_t *resp_buff_size);
+int gh_rm_platform_pre_mem_share(struct gh_rm_mem_parcel *mem_parcel);
+int gh_rm_platform_post_mem_reclaim(struct gh_rm_mem_parcel *mem_parcel);
+
struct gh_rm_device {
struct device dev;
const char *name;
@@ -120,6 +120,10 @@ static int gh_rm_mem_lend_common(u32 message_id, struct gh_rm_mem_parcel *p)
if (initial_n_mem_entries > GH_RM_MAX_MEM_ENTRIES)
initial_n_mem_entries = GH_RM_MAX_MEM_ENTRIES;
+ ret = gh_rm_platform_pre_mem_share(p);
+ if (ret)
+ return ret;
+
/* The format of the message goes:
* request header
* ACL entries (which VMs get what kind of access to this memory parcel)
@@ -163,6 +167,7 @@ static int gh_rm_mem_lend_common(u32 message_id, struct gh_rm_mem_parcel *p)
if (resp_size != sizeof(u32)) {
ret = -EIO;
+ gh_rm_platform_post_mem_reclaim(p);
goto out;
}
@@ -234,6 +239,8 @@ int gh_rm_mem_reclaim(struct gh_rm_mem_parcel *parcel)
if (resp_size)
pr_warn("Received unexpected payload for MEM_RECLAIM: %lu\n", resp_size);
+ ret = gh_rm_platform_post_mem_reclaim(parcel);
+
return ret;
}
EXPORT_SYMBOL_GPL(gh_rm_mem_reclaim);
@@ -119,7 +119,6 @@ struct gh_rm_hyp_resource {
} __packed;
ssize_t gh_rm_get_hyp_resources(u16 vmid, struct gh_rm_hyp_resource **resources);
-int gh_rm_get_vmid(u16 *vmid);
#define GH_RM_BOOT_CONTEXT_REG_SET_REGISTERS 0
#define GH_RM_BOOT_CONTEXT_REG_SET_PC 1
@@ -143,4 +142,15 @@ void gh_rm_driver_unregister(struct gh_rm_driver *ghrm_drv);
#define module_gh_rm_driver(ghrm_drv) \
module_driver(ghrm_drv, gh_rm_driver_register, gh_rm_driver_unregister)
+#if IS_ENABLED(CONFIG_GUNYAH)
+int gh_rm_register_platform_ops(struct gunyah_rm_platform_ops *platform_ops);
+void gh_rm_unregister_platform_ops(struct gunyah_rm_platform_ops *platform_ops);
+int gh_rm_get_vmid(u16 *vmid);
+#else
+static inline int gh_rm_register_platform_ops(struct gunyah_rm_platform_ops *platform_ops)
+ { return 0; }
+static inline void gh_rm_unregister_platform_ops(struct gunyah_rm_platform_ops *platform_ops) { }
+static inline int gh_rm_get_vmid(u16 *vmid) { return -ENODEV; }
+#endif
+
#endif