[Feature][ZXW-65]merged P49 base code
Change-Id: I3e09c0c3d47483bc645f02310380ecb7fc6f4041
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);
}