[Feature][ZXW-65]merged P49 base code
Change-Id: I3e09c0c3d47483bc645f02310380ecb7fc6f4041
diff --git a/ap/os/linux/linux-3.4.x/ipc/Makefile b/ap/os/linux/linux-3.4.x/ipc/Makefile
index 9075e17..bb1c60c 100644
--- a/ap/os/linux/linux-3.4.x/ipc/Makefile
+++ b/ap/os/linux/linux-3.4.x/ipc/Makefile
@@ -9,4 +9,5 @@
obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y)
obj-$(CONFIG_IPC_NS) += namespace.o
obj-$(CONFIG_POSIX_MQUEUE_SYSCTL) += mq_sysctl.o
-
+obj-$(CONFIG_SYSVIPC_CROSSMSG) += cross_msg.o
+obj-$(CONFIG_SYSVIPC_CROSS_SHM) += shm_ctrl.o
diff --git a/ap/os/linux/linux-3.4.x/ipc/cross_msg.c b/ap/os/linux/linux-3.4.x/ipc/cross_msg.c
new file mode 100755
index 0000000..c5491bc
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/ipc/cross_msg.c
@@ -0,0 +1,142 @@
+/*
+ * linux/ipc/cross_msg.c
+ * Copyright (C) 2023 Sanechips Technology Co., Ltd.
+ */
+#include <linux/kthread.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+
+#include "cross_msg.h"
+
+extern int msg_chn_ready;
+extern struct mutex cross_msg_mutex;
+
+extern int sys_msgget(key_t key, int msgflg);
+extern long do_kmsgsnd(int msqid, struct msgbuf* msgp, size_t msgsz, int msgflg);
+
+static void msg_ap_icp_init(void)
+{
+ mutex_init(&cross_msg_mutex);
+
+ if (zDrvRpMsg_CreateChannel_Cap(CROSS_MSG_ACT, CROSS_MSG_CHN, CROSS_CHN_SIZE)) {
+ panic(CROSS_PRINT "Failed create ap->cap msg channel id %d!\n", CROSS_MSG_CHN);
+ } else {
+ printk(KERN_INFO CROSS_PRINT "create ap->cap msg channel success!\n");
+ msg_chn_ready = 1;
+ }
+
+ if (zDrvRpMsg_CreateChannel_Cap(CROSS_MSG_ACT, CROSS_MSG_CHN_CAP, CROSS_CHN_SIZE)) {
+ panic(CROSS_PRINT "Failed create cap->ap msg channel id %d\n", CROSS_MSG_CHN_CAP);
+ } else {
+ printk(KERN_INFO CROSS_PRINT "create cap->ap msg channel success!\n");
+ }
+}
+
+void cross_msg_recv()
+{
+ T_sc_msg_header *msgheader = NULL;
+ long *typeheader = NULL;
+ char *textheader = NULL;
+ T_ZDrvRpMsg_Msg Icp_Msg;
+ int ret;
+ int msqid, alen;
+
+ msgheader = (T_sc_msg_header *)kmalloc(CROSS_MSG_SIZE, GFP_KERNEL);
+ if (!msgheader) {
+ panic(CROSS_PRINT "Failed malloc send msgheader!\n");
+ }
+
+ while (1)
+ {
+ memset(msgheader, 0, sizeof(T_sc_msg_header));
+ Icp_Msg.actorID = CROSS_MSG_ACT;
+ Icp_Msg.chID = CROSS_MSG_CHN_CAP;
+ Icp_Msg.buf = msgheader;
+ Icp_Msg.len = CROSS_MSG_SIZE;
+ Icp_Msg.flag = 0;
+ ret = zDrvRpMsg_Read_Cap(&Icp_Msg);
+#if CROSS_DEBUG
+ printk(KERN_INFO CROSS_PRINT "cross message rpmsg recv header %x ops %x\n", msgheader->head, msgheader->ops);
+#endif
+ if(ret < 0) {
+ printk(KERN_ERR CROSS_PRINT "read rmpsg from cap error:(%d)\n", ret);
+ continue;
+ }
+ if (msgheader->head != CROSS_MSG_HEAD)
+ {
+ printk(KERN_ERR CROSS_PRINT "read rmpsg content error\n");
+ continue;
+ }
+ switch (msgheader->ops) {
+ case MSGGET_F: {
+ break;
+ }
+ case MSGCTL_F: {
+ break;
+ }
+ case MSGSND_F: {
+ typeheader = (long *)(msgheader + 1);
+ textheader = (char *)(typeheader + 1);
+#if CROSS_DEBUG
+ printk(KERN_INFO CROSS_PRINT "cross message msgget key:(%d) flag:(%d)\n", msgheader->sndp.getp.key, msgheader->sndp.getp.msgflg);
+#endif
+ msqid = sys_msgget(msgheader->sndp.getp.key, msgheader->sndp.getp.msgflg);
+ if (msqid < 0) {
+ printk(KERN_ERR CROSS_PRINT "msgget error:(%d)\n", msqid);
+ ret = msqid;
+ goto ack;
+ }
+#if CROSS_DEBUG
+ printk(KERN_INFO CROSS_PRINT "cross message msgsnd text:(%s) msgtyp:(%d)\n", textheader, *typeheader);
+ printk(KERN_INFO CROSS_PRINT "cross message msgsnd msgflg: %x, msgsz:(%d)\n", msgheader->sndp.msgflg, msgheader->sndp.msgsz);
+#endif
+ ret = do_kmsgsnd(msqid, typeheader, msgheader->sndp.msgsz, msgheader->sndp.msgflg);
+ if (ret < 0) {
+ printk(KERN_ERR CROSS_PRINT "msgsnd error:(%d)\n", ret);
+ goto ack;
+ }
+#if CROSS_DEBUG
+ printk(KERN_INFO CROSS_PRINT "cross message msgsnd ret:(%d)\n", ret);
+#endif
+ack:
+ msgheader->head = CROSS_MSG_HEAD;
+ msgheader->ret = ret;
+ Icp_Msg.actorID = CROSS_MSG_ACT;
+ Icp_Msg.chID = CROSS_MSG_CHN_CAP;
+ Icp_Msg.flag = RPMSG_WRITE_INT;
+ Icp_Msg.buf = msgheader;
+ Icp_Msg.len = sizeof(T_sc_msg_header);
+ ret = zDrvRpMsg_Write_Cap(&Icp_Msg);
+ if (ret < 0)
+ printk(KERN_INFO CROSS_PRINT "write rpmsg to cap error:(%d)\n", ret);
+ break;
+ }
+ case MSGRCV_F: {
+ break;
+ }
+ default: {
+ printk(KERN_INFO CROSS_PRINT "cross message msg options unknow:(%d)\n", ret);
+ break;
+ }
+ }
+ }
+
+}
+
+void __init cross_msg_init(void)
+{
+ struct task_struct *recv_msg_thread;
+ msg_ap_icp_init();
+
+ printk(KERN_INFO CROSS_PRINT "cross message init");
+ recv_msg_thread = kthread_run(cross_msg_recv, NULL, "cross_msg_recv");
+ if (IS_ERR(recv_msg_thread)) {
+ panic("create recv_msg_thread err");
+ }
+ else {
+ wake_up_process(recv_msg_thread);
+ }
+}
+late_initcall(cross_msg_init);
+
diff --git a/ap/os/linux/linux-3.4.x/ipc/cross_msg.h b/ap/os/linux/linux-3.4.x/ipc/cross_msg.h
new file mode 100755
index 0000000..eedcd6f
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/ipc/cross_msg.h
@@ -0,0 +1,62 @@
+/*
+ * linux/ipc/cross_msg.h
+ * Copyright (C) 2023 Sanechips Technology Co., Ltd.
+ */
+#ifndef _CROSS_MSG_H
+#define _CROSS_MSG_H
+
+#ifdef CONFIG_SYSVIPC_CROSSMSG
+#include <linux/soc/zte/rpm/rpmsg.h>
+
+#define CROSS_MSG_ACT CAP_ID
+#define CROSS_MSG_CHN 13
+#define CROSS_MSG_CHN_CAP 14
+#define CROSS_MSG_SIZE ((size_t)0x1000)
+#define CROSS_MSG_NUM (4)
+#define CROSS_CHN_SIZE ((size_t)CROSS_MSG_SIZE * CROSS_MSG_NUM)
+#define CROSS_PRINT "[MESSAGE QUEUE] "
+#define CROSS_DEBUG 0
+
+#define CROSS_MSG_HEAD 0xABBA
+#define CROSS_MSG_MASK 0xFFFF0000
+#define CROSS_REMOTE_MASK 0x80000000
+
+enum msg_function {
+ MSGGET_F = 0xAA,
+ MSGCTL_F = 0xBB,
+ MSGSND_F = 0xCC,
+ MSGRCV_F = 0xDD
+};
+
+struct msgget_para {
+ key_t key;
+ int msgflg;
+};
+
+struct msgctl_para {
+ struct msgget_para getp;
+ int cmd;
+};
+
+struct msgsnd_para {
+ struct msgget_para getp;
+ int msgflg;
+ size_t msgsz;
+};
+
+typedef struct msg_para {
+ unsigned short head;
+ unsigned short ops;
+ union {
+ struct msgctl_para ctlp;
+ struct msgsnd_para sndp;
+ struct {
+ int ret;
+ int merrno;
+ };
+ };
+} T_sc_msg_header;
+
+#endif
+#endif // _CROSS_MSG_H
+
diff --git a/ap/os/linux/linux-3.4.x/ipc/msg.c b/ap/os/linux/linux-3.4.x/ipc/msg.c
index a1cf543..038d954 100755
--- a/ap/os/linux/linux-3.4.x/ipc/msg.c
+++ b/ap/os/linux/linux-3.4.x/ipc/msg.c
@@ -40,6 +40,11 @@
#include <asm/current.h>
#include <asm/uaccess.h>
+#ifdef CONFIG_SYSVIPC_CROSSMSG
+#include <linux/soc/zte/rpm/rpmsg.h>
+#include "cross_msg.h"
+#endif
+
#include "util.h"
/*
@@ -62,6 +67,12 @@
struct task_struct *tsk;
};
+#ifdef CONFIG_SYSVIPC_CROSSMSG
+int msg_chn_ready;
+struct mutex cross_msg_mutex;
+T_sc_msg_header *msgheader = NULL;
+#endif
+
#define SEARCH_ANY 1
#define SEARCH_EQUAL 2
#define SEARCH_NOTEQUAL 3
@@ -136,7 +147,7 @@
init_ipc_ns.msg_ctlmni);
if (IS_ENABLED(CONFIG_PROC_STRIPPED))
- return 0;
+ return;
ipc_init_proc_interface("sysvipc/msg",
" key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n",
@@ -336,10 +347,63 @@
msg_params.key = key;
msg_params.flg = msgflg;
+#ifdef CONFIG_SYSVIPC_CROSSMSG
+ if ((key & CROSS_MSG_MASK) == CROSS_MSG_MASK)
+ msg_params.flg |= IPC_CREAT;
+#endif
return ipcget(ns, &msg_ids(ns), &msg_ops, &msg_params);
}
+#ifdef CONFIG_SYSVIPC_CROSSMSG
+static inline unsigned long
+copy_msqid_by_version(void *buf, struct msqid64_ds *in, int version)
+{
+ switch(version) {
+ case IPC_64:
+ memcpy(buf, in, sizeof(*in));
+ return 0;
+ case IPC_OLD:
+ {
+ struct msqid_ds out;
+
+ memset(&out, 0, sizeof(out));
+
+ ipc64_perm_to_ipc_perm(&in->msg_perm, &out.msg_perm);
+
+ out.msg_stime = in->msg_stime;
+ out.msg_rtime = in->msg_rtime;
+ out.msg_ctime = in->msg_ctime;
+
+ if (in->msg_cbytes > USHRT_MAX)
+ out.msg_cbytes = USHRT_MAX;
+ else
+ out.msg_cbytes = in->msg_cbytes;
+ out.msg_lcbytes = in->msg_cbytes;
+
+ if (in->msg_qnum > USHRT_MAX)
+ out.msg_qnum = USHRT_MAX;
+ else
+ out.msg_qnum = in->msg_qnum;
+
+ if (in->msg_qbytes > USHRT_MAX)
+ out.msg_qbytes = USHRT_MAX;
+ else
+ out.msg_qbytes = in->msg_qbytes;
+ out.msg_lqbytes = in->msg_qbytes;
+
+ out.msg_lspid = in->msg_lspid;
+ out.msg_lrpid = in->msg_lrpid;
+
+ memcpy(buf, &out, sizeof(out));
+ return 0;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+#endif
+
static inline unsigned long
copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version)
{
@@ -479,6 +543,67 @@
return err;
}
+#ifdef CONFIG_SYSVIPC_CROSSMSG
+static int get_msgstat(int msqid, int cmd, struct msqid_ds * buf)
+{
+ struct msg_queue *msq;
+ int err, version;
+ struct ipc_namespace *ns;
+
+ if (msqid < 0 || cmd < 0)
+ return -EINVAL;
+
+ version = ipc_parse_version(&cmd);
+ ns = current->nsproxy->ipc_ns;
+
+ switch (cmd) {
+ case IPC_STAT:
+ {
+ struct msqid64_ds tbuf;
+ int success_return;
+
+ if (!buf)
+ return -EFAULT;
+
+
+ msq = msg_lock_check(ns, msqid);
+ if (IS_ERR(msq))
+ return PTR_ERR(msq);
+ success_return = 0;
+
+ err = -EACCES;
+ if (ipcperms(ns, &msq->q_perm, S_IRUGO))
+ goto out_unlock;
+
+ err = security_msg_queue_msgctl(msq, cmd);
+ if (err)
+ goto out_unlock;
+
+ memset(&tbuf, 0, sizeof(tbuf));
+
+ kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm);
+ tbuf.msg_stime = msq->q_stime;
+ tbuf.msg_rtime = msq->q_rtime;
+ tbuf.msg_ctime = msq->q_ctime;
+ tbuf.msg_cbytes = msq->q_cbytes;
+ tbuf.msg_qnum = msq->q_qnum;
+ tbuf.msg_qbytes = msq->q_qbytes;
+ tbuf.msg_lspid = msq->q_lspid;
+ tbuf.msg_lrpid = msq->q_lrpid;
+ msg_unlock(msq);
+ copy_msqid_by_version(buf, &tbuf, version);
+ return success_return;
+ }
+ default:
+ return -EINVAL;
+ }
+
+out_unlock:
+ msg_unlock(msq);
+ return err;
+}
+#endif
+
SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
{
struct msg_queue *msq;
@@ -744,6 +869,104 @@
return err;
}
+#ifdef CONFIG_SYSVIPC_CROSSMSG
+long do_kmsgsnd(int msqid, struct msgbuf* msgp, size_t msgsz, int msgflg)
+{
+ struct msg_queue *msq;
+ struct msg_msg *msg;
+ int err;
+ struct ipc_namespace *ns;
+ long mtype;
+ char *mtext;
+
+ ns = current->nsproxy->ipc_ns;
+
+ mtype = msgp->mtype;
+ mtext = msgp->mtext;
+
+ if (msgsz > ns->msg_ctlmax || (long) msgsz < 0 || msqid < 0)
+ return -EINVAL;
+ if (mtype < 1)
+ return -EINVAL;
+
+ msg = load_kmsg(mtext, msgsz);
+ if (IS_ERR(msg))
+ return PTR_ERR(msg);
+
+ msg->m_type = mtype;
+ msg->m_ts = msgsz;
+
+ msq = msg_lock_check(ns, msqid);
+ if (IS_ERR(msq)) {
+ err = PTR_ERR(msq);
+ goto out_free;
+ }
+
+ for (;;) {
+ struct msg_sender s;
+
+ err = -EACCES;
+ if (ipcperms(ns, &msq->q_perm, S_IWUGO))
+ goto out_unlock_free;
+
+ err = security_msg_queue_msgsnd(msq, msg, msgflg);
+ if (err)
+ goto out_unlock_free;
+
+ if (msgsz + msq->q_cbytes <= msq->q_qbytes &&
+ 1 + msq->q_qnum <= msq->q_qbytes) {
+ break;
+ }
+
+ /* queue full, wait: */
+ if (msgflg & IPC_NOWAIT) {
+ err = -EAGAIN;
+ goto out_unlock_free;
+ }
+ ss_add(msq, &s);
+ ipc_rcu_getref(msq);
+ msg_unlock(msq);
+ schedule();
+
+ ipc_lock_by_ptr(&msq->q_perm);
+ ipc_rcu_putref(msq);
+ if (msq->q_perm.deleted) {
+ err = -EIDRM;
+ goto out_unlock_free;
+ }
+ ss_del(&s);
+
+ if (signal_pending(current)) {
+ err = -ERESTARTNOHAND;
+ goto out_unlock_free;
+ }
+ }
+
+ msq->q_lspid = task_tgid_vnr(current);
+ msq->q_stime = get_seconds();
+
+ if (!pipelined_send(msq, msg)) {
+ /* no one is waiting for this message, enqueue it */
+ list_add_tail(&msg->m_list, &msq->q_messages);
+ msq->q_cbytes += msgsz;
+ msq->q_qnum++;
+ atomic_add(msgsz, &ns->msg_bytes);
+ atomic_inc(&ns->msg_hdrs);
+ }
+
+ err = 0;
+ msg = NULL;
+
+out_unlock_free:
+ msg_unlock(msq);
+out_free:
+ if (msg != NULL)
+ free_msg(msg);
+ return err;
+
+}
+#endif
+
SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
int, msgflg)
{
@@ -751,6 +974,99 @@
if (get_user(mtype, &msgp->mtype))
return -EFAULT;
+
+#ifdef CONFIG_SYSVIPC_CROSSMSG
+ struct msqid_ds msgque;
+ struct ipc_perm *ipcp = &msgque.msg_perm;
+ T_ZDrvRpMsg_Msg Icp_Msg;
+ T_sc_msg_header *msgrcvheader = NULL;
+ long *typeheader = NULL;
+ char *textheader = NULL;
+ int ret, key;
+ size_t alen;
+
+ ret = get_msgstat(msqid, IPC_STAT, &msgque);
+ if (ret < 0) {
+ return ret;
+ }
+ key = ipcp->key;
+ //跨核处理
+ if (msg_chn_ready && ((key & CROSS_MSG_MASK) == CROSS_MSG_MASK)) {
+#if CROSS_DEBUG
+ printk(KERN_INFO CROSS_PRINT "msg key beyond (%x)\n", key);
+#endif
+ mutex_lock(&cross_msg_mutex);
+ alen = sizeof(T_sc_msg_header) + sizeof(long) + msgsz;
+ if (alen > CROSS_MSG_SIZE) {
+ mutex_unlock(&cross_msg_mutex);
+ return -EINVAL;
+ }
+ if (!msgheader)
+ msgheader = (T_sc_msg_header *)kmalloc(CROSS_MSG_SIZE, GFP_KERNEL);
+ if (!msgheader) {
+ panic(CROSS_PRINT "Failed malloc send msgheader!\n");
+ }
+ memset(msgheader, 0, sizeof(T_sc_msg_header));
+ msgheader->head = CROSS_MSG_HEAD;
+ msgheader->ops = MSGSND_F;
+ msgheader->sndp.getp.key = key;
+ msgheader->sndp.getp.msgflg = ipcp->mode | IPC_CREAT;
+ msgheader->sndp.msgflg = msgflg;
+ msgheader->sndp.msgsz = msgsz;
+ typeheader = (long *)(msgheader + 1);
+ *typeheader = mtype;
+ textheader = (char *)(typeheader + 1);
+ ret = copy_from_user(textheader, msgp->mtext, alen - sizeof(T_sc_msg_header) - sizeof(long));
+ if (ret < 0) {
+ mutex_unlock(&cross_msg_mutex);
+ return -EFAULT;
+ }
+#if CROSS_DEBUG
+ printk(KERN_INFO CROSS_PRINT "msg send text:(%s) msgtyp:(%d) msgsize:(%d)\n", textheader, *typeheader, msgsz);
+#endif
+ Icp_Msg.actorID = CROSS_MSG_ACT;
+ Icp_Msg.chID = CROSS_MSG_CHN;
+ Icp_Msg.flag = RPMSG_WRITE_INT; /* 1- means send an icp interrupt> */
+ Icp_Msg.buf = msgheader;
+ Icp_Msg.len = alen;
+
+ ret = zDrvRpMsg_Write_Cap(&Icp_Msg);
+ if(ret < 0) {
+ printk(KERN_ERR CROSS_PRINT "write rpmsg error:(%d)\n", ret);
+ mutex_unlock(&cross_msg_mutex);
+ return ret;
+ }
+ else {
+#if CROSS_DEBUG
+ printk(KERN_INFO CROSS_PRINT "write rpmsg ok:(%d)\n", ret);
+#endif
+ }
+ Icp_Msg.actorID = CROSS_MSG_ACT;
+ Icp_Msg.chID = CROSS_MSG_CHN;
+ Icp_Msg.flag = 0;
+ Icp_Msg.buf = msgheader;
+ Icp_Msg.len = CROSS_MSG_SIZE;
+
+ ret = zDrvRpMsg_Read_Cap(&Icp_Msg);
+ mutex_unlock(&cross_msg_mutex);
+ if(ret < 0) {
+ printk(KERN_ERR CROSS_PRINT "read rpmsg error:(%d)\n", ret);
+ return ret;
+ }
+ else {
+#if CROSS_DEBUG
+ printk(KERN_INFO CROSS_PRINT "read rpmsg ok:(%d)\n", ret);
+#endif
+ }
+ msgrcvheader = (T_sc_msg_header *)Icp_Msg.buf;
+ ret = msgrcvheader->ret;
+#if CROSS_DEBUG
+ printk(KERN_INFO CROSS_PRINT "msgsnd return number:(%x)\n", ret);
+#endif
+ return ret;
+ }
+#endif
+
return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
}
diff --git a/ap/os/linux/linux-3.4.x/ipc/msgutil.c b/ap/os/linux/linux-3.4.x/ipc/msgutil.c
old mode 100644
new mode 100755
index 52be05a..e384793
--- a/ap/os/linux/linux-3.4.x/ipc/msgutil.c
+++ b/ap/os/linux/linux-3.4.x/ipc/msgutil.c
@@ -42,6 +42,61 @@
#define DATALEN_MSG ((size_t)PAGE_SIZE-sizeof(struct msg_msg))
#define DATALEN_SEG ((size_t)PAGE_SIZE-sizeof(struct msg_msgseg))
+#ifdef CONFIG_SYSVIPC_CROSSMSG
+struct msg_msg *load_kmsg(const void *src, size_t len)
+{
+ struct msg_msg *msg;
+ struct msg_msgseg **pseg;
+ int err;
+ size_t alen;
+
+ alen = len;
+ if (alen > DATALEN_MSG)
+ alen = DATALEN_MSG;
+
+ msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL);
+ if (msg == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ msg->next = NULL;
+ msg->security = NULL;
+
+ memcpy(msg + 1, src, alen);
+
+ len -= alen;
+ src = ((char *)src) + alen;
+ pseg = &msg->next;
+ while (len > 0) {
+ struct msg_msgseg *seg;
+ alen = len;
+ if (alen > DATALEN_SEG)
+ alen = DATALEN_SEG;
+ seg = kmalloc(sizeof(*seg) + alen,
+ GFP_KERNEL);
+ if (seg == NULL) {
+ err = -ENOMEM;
+ goto out_err;
+ }
+ *pseg = seg;
+ seg->next = NULL;
+ memcpy(seg + 1, src, alen);
+ pseg = &seg->next;
+ len -= alen;
+ src = ((char *)src) + alen;
+ }
+
+ err = security_msg_msg_alloc(msg);
+ if (err)
+ goto out_err;
+
+ return msg;
+
+out_err:
+ free_msg(msg);
+ return ERR_PTR(err);
+}
+#endif
+
struct msg_msg *load_msg(const void __user *src, size_t len)
{
struct msg_msg *msg;
diff --git a/ap/os/linux/linux-3.4.x/ipc/shm.c b/ap/os/linux/linux-3.4.x/ipc/shm.c
index 054c4e0..47d3255 100755
--- a/ap/os/linux/linux-3.4.x/ipc/shm.c
+++ b/ap/os/linux/linux-3.4.x/ipc/shm.c
@@ -43,6 +43,9 @@
#include <asm/uaccess.h>
#include "util.h"
+#ifdef CONFIG_SYSVIPC_CROSS_SHM
+#include "shm_ctrl.h"
+#endif
struct shm_file_data {
int id;
@@ -69,6 +72,11 @@
static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
#endif
+#ifdef CONFIG_SYSVIPC_CROSS_SHM
+extern int shm_remote_free_pages(struct vm_area_struct *unmap_vma);
+extern int shm_do_remote_map_vma(struct vm_area_struct *vma, key_t key);
+#endif
+
void shm_init_ns(struct ipc_namespace *ns)
{
ns->shm_ctlmax = SHMMAX;
@@ -141,6 +149,24 @@
return container_of(ipcp, struct shmid_kernel, shm_perm);
}
+#ifdef CONFIG_SYSVIPC_CROSS_SHM
+void shm_mmap_pagetable(struct vm_area_struct *vma, struct file *file)
+{
+ int ret = 0;
+ struct shm_file_data *sfd;
+ struct shmid_kernel *shp;
+
+ sfd = shm_file_data(file);
+ shp = shm_lock(sfd->ns, sfd->id);
+
+ ret = shm_do_remote_map_vma(vma, shp->shm_perm.key);
+ if (ret < 0)
+ printk("shm_mmap_pagetable Error");
+
+ shm_unlock(shp);
+}
+#endif
+
static inline void shm_lock_by_ptr(struct shmid_kernel *ipcp)
{
rcu_read_lock();
@@ -240,6 +266,10 @@
shp->shm_lprid = task_tgid_vnr(current);
shp->shm_dtim = get_seconds();
shp->shm_nattch--;
+#ifdef CONFIG_SYSVIPC_CROSS_SHM
+ if (shp->shm_perm.rpmflag == TRUE)
+ shm_remote_free_pages(shp->shm_perm.key);
+#endif
if (shm_may_destroy(ns, shp))
shm_destroy(ns, shp);
else
@@ -517,6 +547,12 @@
shp->shm_nattch = 0;
shp->shm_file = file;
shp->shm_creator = current;
+#ifdef CONFIG_SYSVIPC_CROSS_SHM
+ if((key & SHM_REMOTE_ATTR_MASK) == SHM_REMOTE_ATTR_MASK)
+ shp->shm_perm.rpmflag = TRUE;
+ else
+ shp->shm_perm.rpmflag = FALSE;
+#endif
/*
* shmid gets reported as "inode#" in /proc/pid/maps.
* proc-ps tools use this. Changing this will break them.
@@ -1049,7 +1085,10 @@
sfd->ns = get_ipc_ns(ns);
sfd->file = shp->shm_file;
sfd->vm_ops = NULL;
-
+#ifdef CONFIG_SYSVIPC_CROSS_SHM
+ if(shp->shm_perm.rpmflag == TRUE)
+ file->f_flags = SHM_REMOTE_ATTR_YES;
+#endif
down_write(¤t->mm->mmap_sem);
if (addr && !(shmflg & SHM_REMAP)) {
err = -EINVAL;
diff --git a/ap/os/linux/linux-3.4.x/ipc/shm_ctrl.c b/ap/os/linux/linux-3.4.x/ipc/shm_ctrl.c
new file mode 100755
index 0000000..598cb28
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/ipc/shm_ctrl.c
@@ -0,0 +1,504 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * linux/ipc/shm_ctrl.c
+ * Copyright (C) 1992, 1993 Krishna Balasubramanian
+ * Replaced `struct shm_desc' by `struct vm_area_struct', July 1994.
+ * Fixed the shm swap deallocation (shm_unuse()), August 1998 Andrea Arcangeli.
+ *
+ * /proc/sysvipc/shm support (c) 1999 Dragos Acostachioaie <dragos@iname.com>
+ * Make shmmax, shmall, shmmni sysctl'able, Christoph Rohland <cr@sap.com>
+ * Move the mm functionality over to mm/shmem.c, Christoph Rohland <cr@sap.com>
+ *
+ * Better ipc lock (kern_ipc_perm.lock) handling
+ * Davidlohr Bueso <davidlohr.bueso@hp.com>, June 2013.
+ */
+#include <linux/mm.h>
+#include <asm/pgtable.h>
+#include "shm_ctrl.h"
+#include "../mm/internal.h"
+
+/**
+ * ºê¶¨Òå
+ */
+#define SHM_UNIT_BUFF_ORDER (12)
+#define SHM_KEYS_STATUS_LEN (4*1024)
+#define SHM_REMOTE_BUFF_LEN (128*1024)
+#define SHM_BUFF_BASE_PHY_ADDR (g_shm_phyAddr)
+
+#define SHM_UNIT_BUFF_SIZE (1UL<<SHM_UNIT_BUFF_ORDER) /*4KB*/
+#define SHM_UNIT_INDEX(addr) (((unsigned long)addr - SHM_BUFF_BASE_PHY_ADDR) >> SHM_UNIT_BUFF_ORDER)
+#define SHM_UNIT_PAGE_ADDR(index) ((void *)(SHM_BUFF_BASE_PHY_ADDR + ((unsigned long)index << SHM_UNIT_BUFF_ORDER)))
+#define SHM_UNIT_NUM_BITS (SHM_REMOTE_BUFF_LEN >> SHM_UNIT_BUFF_ORDER)
+#define SHM_CTRL_BITMAP_NUM (SHM_UNIT_NUM_BITS / SHM_CTRL_LONG_32BIT)
+
+struct shm_key_node {
+ key_t key;
+ unsigned int vma_count;
+ DECLARE_BITMAP(shm_inuse_index, SHM_UNIT_NUM_BITS);
+};
+
+struct shm_entity {
+ DECLARE_BITMAP(shm_regions_bitmap, SHM_UNIT_NUM_BITS);/*×ÜÄÚ´æ³Ø¹ÜÀíÐÅÏ¢*/
+ struct shm_key_node keys_info_head[SHM_UNIT_NUM_BITS]; /*ÿ¸öshmµÄkey¹ÜÀíÐÅÏ¢*/
+};
+
+/**
+ * È«¾Ö±äÁ¿¶¨Òå
+ */
+phys_addr_t g_shm_phyAddr = 0;
+void *g_shm_region = NULL;
+
+struct shm_entity *shm_remote_manager;
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö: shm_quary_keyArray
+* ²ÎÊý˵Ã÷:
+* (´«Èë²ÎÊý) void
+* (´«³ö²ÎÊý) void
+* ·µ »Ø Öµ: SHM_CTRL_OK or SHM_CTRL_ERROR
+* ÆäËü˵Ã÷: This function is used for search a special key in array
+*******************************************************************************/
+static int shm_quary_keyArray(const key_t key)
+{
+ unsigned int index = 0;
+ struct shm_key_node *shm_data = NULL;
+
+ shm_data = shm_remote_manager->keys_info_head;
+
+ for (; index < SHM_UNIT_NUM_BITS; index++)
+ {
+ if (shm_data[index].key == key)
+ return index;
+ }
+ return SHM_CTRL_ERROR;
+}
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö: shm_ctrl_pte_range
+* ²ÎÊý˵Ã÷:
+* (´«Èë²ÎÊý) void
+* (´«³ö²ÎÊý) void
+* ·µ »Ø Öµ: SHM_CTRL_OK or SHM_CTRL_ERROR
+* ÆäËü˵Ã÷: This function is used for clear the pagetable pte
+*******************************************************************************/
+unsigned long shm_ctrl_pte_range(struct mm_struct *mm,
+ struct vm_area_struct *vma, pmd_t *pmd,
+ unsigned long addr, unsigned long end)
+{
+ spinlock_t *ptl;
+ pte_t *start_pte;
+ pte_t *pte;
+
+ start_pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+ pte = start_pte;
+ arch_enter_lazy_mmu_mode();
+ do {
+ pte_t ptent = *pte;
+ if (pte_none(ptent)) {
+ continue;
+ }
+
+ if (pte_present(ptent)) {
+
+ ptent = ptep_get_and_clear(mm, addr, pte);
+ }
+ pte_clear_not_present_full(mm, addr, pte, 0);
+ } while (pte++, addr += PAGE_SIZE, addr != end);
+
+ arch_leave_lazy_mmu_mode();
+ pte_unmap_unlock(start_pte, ptl);
+
+ return addr;
+}
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö: shm_ctrl_pmd_range
+* ²ÎÊý˵Ã÷:
+* (´«Èë²ÎÊý) mm: ÈÎÎñµÄÄÚ´æÃèÊö·û
+* (´«Èë²ÎÊý) vma£º¿çºË¹²ÏíÄÚ´æ½ø³ÌµØÖ·¿Õ¼ävma
+* (´«Èë²ÎÊý) pud£ºpudÒ³ÉϲãĿ¼
+* (´«Èë²ÎÊý) addr: ÐéÄâÆðʼµØÖ·
+* (´«Èë²ÎÊý) end: ÐéÄâ½áÊøµØÖ·
+* (´«³ö²ÎÊý) ¿Õ
+* ·µ »Ø Öµ: addr
+* ÆäËü˵Ã÷: This function is used for clear the pagetable pte
+*******************************************************************************/
+static inline unsigned long shm_ctrl_pmd_range(struct mm_struct *mm,
+ struct vm_area_struct *vma, pud_t *pud,
+ unsigned long addr, unsigned long end)
+{
+ pmd_t *pmd;
+ unsigned long next;
+
+ pmd = pmd_offset(pud, addr);
+ do {
+ next = pmd_addr_end(addr, end);
+ /*
+ * Here there can be other concurrent MADV_DONTNEED or
+ * trans huge page faults running, and if the pmd is
+ * none or trans huge it can change under us. This is
+ * because MADV_DONTNEED holds the mmap_sem in read
+ * mode.
+ */
+ if (pmd_none_or_trans_huge_or_clear_bad(pmd))
+ goto next;
+ next = shm_ctrl_pte_range(mm, vma, pmd, addr, next);
+next:
+ cond_resched();
+ } while (pmd++, addr = next, addr != end);
+
+ return addr;
+}
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö: shm_ctrl_pud_range
+* ²ÎÊý˵Ã÷:
+* (´«Èë²ÎÊý) mm: ÈÎÎñµÄÄÚ´æÃèÊö·û
+* (´«Èë²ÎÊý) vma: ¿çºË¹²ÏíÄÚ´æ½ø³ÌµØÖ·¿Õ¼ävma
+* (´«Èë²ÎÊý) pgd: pgdҳĿ¼Ïî
+* (´«Èë²ÎÊý) addr: ÐéÄâÆðʼµØÖ·
+* (´«Èë²ÎÊý) end: ÐéÄâ½áÊøµØÖ·
+* (´«³ö²ÎÊý) ÎÞ
+* ·µ »Ø Öµ: SHM_CTRL_OK or SHM_CTRL_ERROR
+* ÆäËü˵Ã÷: This function is used for find pud
+*******************************************************************************/
+static inline unsigned long shm_ctrl_pud_range(struct mm_struct *mm,
+ struct vm_area_struct *vma, pgd_t *pgd,
+ unsigned long addr, unsigned long end)
+{
+ pud_t *pud;
+ unsigned long next;
+
+ pud = pud_offset(pgd, addr);
+ do {
+ next = pud_addr_end(addr, end);
+ if (pud_none_or_clear_bad(pud))
+ continue;
+ next = shm_ctrl_pmd_range(mm, vma, pud, addr, next);
+ } while (pud++, addr = next, addr != end);
+
+ return addr;
+}
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö: shm_unmap_page_range
+* ²ÎÊý˵Ã÷:
+* (´«Èë²ÎÊý) mm: ÈÎÎñµÄÄÚ´æÃèÊö·û
+* (´«Èë²ÎÊý) vma ¿çºË¹²ÏíÄÚ´æ½ø³ÌµØÖ·¿Õ¼ävma
+* (´«Èë²ÎÊý) addr ÐéÄâÆðʼµØÖ·
+* (´«Èë²ÎÊý) end ÐéÄâ½áÊøµØÖ·
+* (´«³ö²ÎÊý) ¿Õ
+* ·µ »Ø Öµ: void
+* ÆäËü˵Ã÷: This function is used for unmap the shm memory
+*******************************************************************************/
+void shm_unmap_page_range(struct mm_struct *mm, struct vm_area_struct *vma,
+ unsigned long addr, unsigned long end)
+{
+ pgd_t *pgd;
+ unsigned long next;
+
+ BUG_ON(addr >= end);
+ pgd = pgd_offset(vma->vm_mm, addr);
+ do {
+ next = pgd_addr_end(addr, end);
+ if (pgd_none_or_clear_bad(pgd))
+ continue;
+ next = shm_ctrl_pud_range(mm, vma, pgd, addr, next);
+ } while (pgd++, addr = next, addr != end);
+}
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö: shm_vma_write_pagetable
+* ²ÎÊý˵Ã÷:
+* (´«Èë²ÎÊý) void
+* (´«³ö²ÎÊý) void
+* ·µ »Ø Öµ: SHM_CTRL_OK or SHM_CTRL_ERROR
+* ÆäËü˵Ã÷: This function is used for create pagetable for shm mem region
+*******************************************************************************/
+static int shm_vma_write_pagetable(struct vm_area_struct *vma, unsigned long vm_addr,
+ phys_addr_t shmaddr_phy)
+{
+ pte_t *pte;
+ int retval = 0;
+ pte_t pte_val = 0;
+ spinlock_t *ptl;
+
+ if (vm_addr < vma->vm_start || vm_addr >= vma->vm_end)
+ return -EFAULT;
+
+ pte = get_locked_pte(vma->vm_mm, vm_addr, &ptl);
+ if ((!pte) || (!pte_none(*pte)))
+ return -EFAULT;
+
+ pte_val = __pte((phys_addr_t)(shmaddr_phy) | pgprot_val(vma->vm_page_prot));
+
+ set_pte_at(vma->vm_mm, vm_addr, pte, pte_val);
+ pte_unmap_unlock(pte, ptl);
+
+ return retval;
+}
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö: shm_fill_keytable
+* ²ÎÊý˵Ã÷:
+* (´«Èë²ÎÊý) void
+* (´«³ö²ÎÊý) void
+* ·µ »Ø Öµ: SHM_CTRL_OK or SHM_CTRL_ERROR
+* ÆäËü˵Ã÷: This function is used for record the key and index relation
+*******************************************************************************/
+int shm_fill_keytable(struct shm_key_node *keydata)
+{
+ unsigned int key_index = 0;
+
+ if (keydata == NULL)
+ return SHM_CTRL_ERROR;
+
+ for(; key_index < SHM_UNIT_NUM_BITS; key_index++)
+ {
+ if(shm_remote_manager->keys_info_head[key_index].key == 0)
+ {
+ memcpy(&shm_remote_manager->keys_info_head[key_index], keydata, sizeof(struct shm_key_node));
+ return SHM_CTRL_OK;
+ }
+ }
+ return SHM_CTRL_ERROR;
+}
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö: shm_remove_keynode
+* ²ÎÊý˵Ã÷:
+* (´«Èë²ÎÊý) void
+* (´«³ö²ÎÊý) void
+* ·µ »Ø Öµ: SHM_CTRL_OK or SHM_CTRL_ERROR
+* ÆäËü˵Ã÷: This function is used for remove the key and index relation
+*******************************************************************************/
+static void shm_remove_keynode(unsigned int key_index)
+{
+ memset(&shm_remote_manager->keys_info_head[key_index], 0, sizeof(struct shm_key_node));
+}
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö: shm_alloc_new_page
+* ²ÎÊý˵Ã÷:
+* (´«Èë²ÎÊý) void
+* (´«³ö²ÎÊý) void
+* ·µ »Ø Öµ: SHM_CTRL_OK or SHM_CTRL_ERROR
+* ÆäËü˵Ã÷: This function is used for alloc page from shm mem region
+*******************************************************************************/
+int shm_alloc_new_page(struct vm_area_struct *vma, key_t key)
+{
+ unsigned long vm_addr = 0;
+ unsigned int region_index = 0;
+ void *new_page = NULL;
+ struct shm_key_node new_key = {0};
+
+ if((vma == NULL) || (g_shm_region == NULL))
+ {
+ printk("Shm region is not ready\n");
+ return SHM_CTRL_ERROR;
+ }
+
+ vm_addr = vma->vm_start;
+
+ for (; vm_addr < vma->vm_end; vm_addr += PAGE_SIZE)
+ {
+ region_index = find_first_zero_bit(shm_remote_manager->shm_regions_bitmap, SHM_UNIT_NUM_BITS);
+
+ if (region_index < SHM_UNIT_NUM_BITS)
+ {
+ set_bit(region_index, shm_remote_manager->shm_regions_bitmap);
+ new_page = SHM_UNIT_PAGE_ADDR(region_index);
+
+ if (shm_vma_write_pagetable(vma, vm_addr, new_page))
+ {
+ return SHM_CTRL_ERROR;
+ }
+ set_bit(region_index, new_key.shm_inuse_index);
+ }
+ else
+ {
+ return SHM_CTRL_ERROR;
+ }
+ }
+
+ if (!bitmap_empty(new_key.shm_inuse_index, SHM_UNIT_NUM_BITS))
+ {
+ new_key.key = key;
+ new_key.vma_count++;
+ shm_fill_keytable(&new_key);
+ }
+ return SHM_CTRL_OK;
+}
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö: shm_do_remote_map_vma
+* ²ÎÊý˵Ã÷:
+* (´«Èë²ÎÊý) void
+* (´«³ö²ÎÊý) void
+* ·µ »Ø Öµ: SHM_CTRL_OK or SHM_CTRL_ERROR
+* ÆäËü˵Ã÷: This function is used for
+*
+/*²éѯkey,Èç¹ûÒÑ·ÖÅä¹ýʹÓÃkey¶ÔÓ¦µÄbitmap, ·ñÔò´Ó×ÜÄÚ´æ³Ø·ÖÅä
+*******************************************************************************/
+int shm_do_remote_map_vma(struct vm_area_struct *vma, key_t key)
+{
+ int ret = 0;
+ unsigned long vm_addr = 0;
+ unsigned int region_index = 0;
+ int key_index = 0;
+ void *new_page_phy = NULL;
+ struct shm_key_node *key_node = NULL;
+ DECLARE_BITMAP(shm_inuse_tmp, SHM_UNIT_NUM_BITS);
+
+ if((vma == NULL) || (g_shm_region == NULL))
+ {
+ printk("shm_do_remote_map_vma:Shm region is not ready\n");
+ return SHM_CTRL_ERROR;
+ }
+
+ /*Ó³ÉävmaΪ·ÇcacheÊôÐÔ*/
+ pgprot_noncached(vma->vm_page_prot);
+
+ soft_spin_lock(SHM_SFLOCK);
+
+ key_index = shm_quary_keyArray(key);
+
+ if (key_index < 0)
+ {
+ ret = shm_alloc_new_page(vma, key);
+ soft_spin_unlock(SHM_SFLOCK);
+ if (ret < 0)
+ panic("shm_alloc_new_page Fail\n");
+ return ret;
+ }
+
+ vm_addr = vma->vm_start;
+
+ if ((0 <= key_index) && (key_index < SHM_UNIT_NUM_BITS))
+ key_node = &shm_remote_manager->keys_info_head[key_index];
+ else
+ panic("key_index out of range: failed\n");
+
+ memcpy(shm_inuse_tmp, key_node->shm_inuse_index, sizeof(shm_inuse_tmp));
+
+ for (; vm_addr < vma->vm_end; vm_addr += PAGE_SIZE)
+ {
+ region_index = find_first_bit(shm_inuse_tmp, SHM_UNIT_NUM_BITS);
+ if (region_index < SHM_UNIT_NUM_BITS)
+ {
+ new_page_phy = SHM_UNIT_PAGE_ADDR(region_index);
+ if (shm_vma_write_pagetable(vma, vm_addr, new_page_phy))
+ {
+ soft_spin_unlock(SHM_SFLOCK);
+ panic("shm_do_remote_map_vma vm_insert_page failed\n");
+ return SHM_CTRL_ERROR;
+ }
+ clear_bit(region_index, shm_inuse_tmp);
+ }
+ else
+ {
+ return SHM_CTRL_ERROR;
+ }
+ }
+ key_node->vma_count++;
+
+ soft_spin_unlock(SHM_SFLOCK);
+ return SHM_CTRL_OK;
+}
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö: shm_remote_free_pages
+* ²ÎÊý˵Ã÷:
+* (´«Èë²ÎÊý) void
+* (´«³ö²ÎÊý) void
+* ·µ »Ø Öµ: SHM_CTRL_OK or SHM_CTRL_ERROR
+* ÆäËü˵Ã÷: This function is used for
+*******************************************************************************/
+int shm_remote_free_pages(key_t key)
+{
+ int key_index = 0;
+ unsigned int region_index = 0;
+ struct shm_key_node *key_node = NULL;
+
+ if(g_shm_region == NULL)
+ {
+ printk("shm_remote_free_pages: Shm region is not ready\n");
+ return SHM_CTRL_ERROR;
+ }
+
+ soft_spin_lock(SHM_SFLOCK);
+
+ /*²éѯkey*/
+ key_index = shm_quary_keyArray(key);
+ if(key_index < 0 || key_index >= SHM_UNIT_NUM_BITS)
+ {
+ soft_spin_unlock(SHM_SFLOCK);
+ panic("error\n");
+ }
+
+ /*ÊôÓÚ¿çºËµÄ¾ÍÊͷŵ½³Ø×ÓÀï*/
+ key_node = &shm_remote_manager->keys_info_head[key_index];
+
+ key_node->vma_count--;
+
+ if(key_node->vma_count == 0)
+ {
+ for_each_set_bit(region_index, key_node->shm_inuse_index, SHM_UNIT_NUM_BITS)
+ {
+ clear_bit(region_index, shm_remote_manager->shm_regions_bitmap);
+ }
+ shm_remove_keynode(key_index);
+ }
+ soft_spin_unlock(SHM_SFLOCK);
+ return SHM_CTRL_OK;
+}
+
+/*******************************************************************************
+* ¹¦ÄÜÃèÊö: shm_rpcore_init
+* ²ÎÊý˵Ã÷:
+* (´«Èë²ÎÊý) void
+* (´«³ö²ÎÊý) void
+* ·µ »Ø Öµ:
+* ÆäËü˵Ã÷: This function is used for shm ctrl init
+*******************************************************************************/
+static int __init shm_rpcore_init(void)
+{
+ dma_addr_t dma_phys;
+ dma_addr_t shm_keyInfo_phys;
+ struct shm_pool_msg shm_msg = {0};
+
+ g_shm_region = dma_alloc_coherent(NULL,
+ (size_t)SHM_REMOTE_BUFF_LEN,
+ &dma_phys,
+ GFP_KERNEL);
+ if(!g_shm_region)
+ {
+ panic("g_shm_region NOMEM\n");
+ }
+
+ g_shm_phyAddr = dma_phys;
+
+ shm_remote_manager = dma_alloc_coherent(NULL,
+ (size_t)(SHM_KEYS_STATUS_LEN),
+ &shm_keyInfo_phys,
+ GFP_KERNEL);
+ if(!shm_remote_manager)
+ {
+ panic("shm_remote_manager NOMEM\n");
+ }
+
+ memset(shm_remote_manager, 0, sizeof(struct shm_entity));
+ shm_msg.shm_len = SHM_REMOTE_BUFF_LEN;
+ shm_msg.key_manage_len = SHM_KEYS_STATUS_LEN;
+ shm_msg.shm_memory_phy = g_shm_phyAddr;
+ shm_msg.key_manage_phy = shm_keyInfo_phys;
+
+ memcpy((void*)IRAM_BASE_ADDR_SHM_REMOTE_REGION, &shm_msg, sizeof(struct shm_pool_msg));
+
+ return SHM_CTRL_OK;
+
+}
+
+late_initcall(shm_rpcore_init);
+
+
+
diff --git a/ap/os/linux/linux-3.4.x/ipc/shm_ctrl.h b/ap/os/linux/linux-3.4.x/ipc/shm_ctrl.h
new file mode 100755
index 0000000..5a850a1
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/ipc/shm_ctrl.h
@@ -0,0 +1,56 @@
+/*
+ * linux/ipc/shm_ctrl.h
+ * Copyright (C) 2023 Sanechips Technology Co., Ltd.
+ */
+#ifndef _SHM_CTRL_H
+#define _SHM_CTRL_H
+
+#ifdef CONFIG_SYSVIPC_CROSS_SHM
+/**
+ * ºê¶¨Òå
+ */
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/shm.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/file.h>
+#include <linux/list.h>
+#include <linux/mman.h>
+#include <linux/shmem_fs.h>
+#include <linux/audit.h>
+#include <linux/capability.h>
+#include <linux/ptrace.h>
+#include <linux/rwsem.h>
+#include <linux/nsproxy.h>
+#include <linux/ipc_namespace.h>
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <mach/spinlock.h>
+
+/**
+ * Êý¾ÝÀàÐͶ¨Òå
+ */
+#define TRUE 1
+#define FALSE 0
+#define SHM_REMOTE_ATTR_YES (0x594553) /*YES ASCIIÂë*/
+#define SHM_REMOTE_ATTR_MASK (0xFFFFF000)
+#define SHM_CTRL_OK (0)
+#define SHM_CTRL_ERROR (-1)
+#define SHM_CTRL_VMA_LINK_NUM (2)
+#define SHM_CTRL_MEMSYNC_CHANNEL (15)
+#define SHM_CTRL_CHANNEL_SIZE (0x40)
+#define SHM_CTRL_LONG_32BIT (32)
+
+struct shm_pool_msg
+{
+ unsigned int shm_len;
+ unsigned int key_manage_len;
+ phys_addr_t shm_memory_phy;
+ phys_addr_t key_manage_phy;
+};
+
+
+#endif
+#endif // _SHM_CTRL_H
+
diff --git a/ap/os/linux/linux-3.4.x/ipc/util.h b/ap/os/linux/linux-3.4.x/ipc/util.h
old mode 100644
new mode 100755
index 0bfc934..f8c1757
--- a/ap/os/linux/linux-3.4.x/ipc/util.h
+++ b/ap/os/linux/linux-3.4.x/ipc/util.h
@@ -138,6 +138,9 @@
#endif
extern void free_msg(struct msg_msg *msg);
+#ifdef CONFIG_SYSVIPC_CROSSMSG
+extern struct msg_msg *load_kmsg(const void __user *src, size_t len);
+#endif
extern struct msg_msg *load_msg(const void __user *src, size_t len);
extern int store_msg(void __user *dest, struct msg_msg *msg, size_t len);