lkml.org 
[lkml]   [2009]   [Mar]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 27/57] microblaze_v7: IPC support
    Date
    From: Michal Simek <monstr@monstr.eu>


    Signed-off-by: Michal Simek <monstr@monstr.eu>
    ---
    arch/microblaze/include/asm/ipc.h | 1 +
    arch/microblaze/include/asm/ipcbuf.h | 36 +++++
    arch/microblaze/kernel/sys_microblaze.c | 226 +++++++++++++++++++++++++++++++
    3 files changed, 263 insertions(+), 0 deletions(-)
    create mode 100644 arch/microblaze/include/asm/ipc.h
    create mode 100644 arch/microblaze/include/asm/ipcbuf.h
    create mode 100644 arch/microblaze/kernel/sys_microblaze.c

    diff --git a/arch/microblaze/include/asm/ipc.h b/arch/microblaze/include/asm/ipc.h
    new file mode 100644
    index 0000000..a46e3d9
    --- /dev/null
    +++ b/arch/microblaze/include/asm/ipc.h
    @@ -0,0 +1 @@
    +#include <asm-generic/ipc.h>
    diff --git a/arch/microblaze/include/asm/ipcbuf.h b/arch/microblaze/include/asm/ipcbuf.h
    new file mode 100644
    index 0000000..b056fa4
    --- /dev/null
    +++ b/arch/microblaze/include/asm/ipcbuf.h
    @@ -0,0 +1,36 @@
    +/*
    + * Copyright (C) 2006 Atmark Techno, Inc.
    + *
    + * This file is subject to the terms and conditions of the GNU General Public
    + * License. See the file "COPYING" in the main directory of this archive
    + * for more details.
    + */
    +
    +#ifndef _ASM_MICROBLAZE_IPCBUF_H
    +#define _ASM_MICROBLAZE_IPCBUF_H
    +
    +/*
    + * The user_ipc_perm structure for microblaze architecture.
    + * Note extra padding because this structure is passed back and forth
    + * between kernel and user space.
    + *
    + * Pad space is left for:
    + * - 32-bit mode_t and seq
    + * - 2 miscellaneous 32-bit values
    + */
    +
    +struct ipc64_perm {
    + __kernel_key_t key;
    + __kernel_uid32_t uid;
    + __kernel_gid32_t gid;
    + __kernel_uid32_t cuid;
    + __kernel_gid32_t cgid;
    + __kernel_mode_t mode;
    + unsigned short __pad1;
    + unsigned short seq;
    + unsigned short __pad2;
    + unsigned long __unused1;
    + unsigned long __unused2;
    +};
    +
    +#endif /* _ASM_MICROBLAZE_IPCBUF_H */
    diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c
    new file mode 100644
    index 0000000..831fc31
    --- /dev/null
    +++ b/arch/microblaze/kernel/sys_microblaze.c
    @@ -0,0 +1,226 @@
    +/*
    + * Copyright (C) 2007 PetaLogix
    + * John Williams <john.williams@petalogix.com>
    + * Copyright (C) 2006 Atmark Techno, Inc.
    + * Yasushi SHOJI <yashi@atmark-techno.com>
    + * Tetsuya OHKAWA <tetsuya@atmark-techno.com>
    + *
    + * This file is subject to the terms and conditions of the GNU General Public
    + * License. See the file "COPYING" in the main directory of this archive
    + * for more details.
    + */
    +
    +#include <linux/errno.h>
    +#include <linux/mm.h>
    +#include <linux/smp.h>
    +#include <linux/smp_lock.h>
    +#include <linux/syscalls.h>
    +#include <linux/sem.h>
    +#include <linux/msg.h>
    +#include <linux/shm.h>
    +#include <linux/stat.h>
    +#include <linux/mman.h>
    +#include <linux/sys.h>
    +#include <linux/ipc.h>
    +#include <linux/utsname.h>
    +#include <linux/file.h>
    +#include <linux/module.h>
    +#include <linux/err.h>
    +#include <linux/fs.h>
    +#include <linux/ipc.h>
    +#include <linux/semaphore.h>
    +#include <linux/syscalls.h>
    +#include <linux/uaccess.h>
    +#include <linux/unistd.h>
    +
    +#include <asm/syscalls.h>
    +/*
    + * sys_ipc() is the de-multiplexer for the SysV IPC calls..
    + *
    + * This is really horribly ugly. This will be remove with new toolchain.
    + */
    +asmlinkage int
    +sys_ipc(uint call, int first, int second, int third, void *ptr, long fifth)
    +{
    + int version, ret;
    +
    + version = call >> 16; /* hack for backward compatibility */
    + call &= 0xffff;
    +
    + ret = -EINVAL;
    + switch (call) {
    + case SEMOP:
    + ret = sys_semop(first, (struct sembuf *)ptr, second);
    + break;
    + case SEMGET:
    + ret = sys_semget(first, second, third);
    + break;
    + case SEMCTL:
    + {
    + union semun fourth;
    +
    + if (!ptr)
    + break;
    + if ((ret = access_ok(VERIFY_READ, ptr,
    + sizeof(long)) ? 0 : -EFAULT)
    + || (ret = get_user(fourth.__pad, (void **)ptr)))
    + break;
    + ret = sys_semctl(first, second, third, fourth);
    + break;
    + }
    + case MSGSND:
    + ret = sys_msgsnd(first, (struct msgbuf *) ptr, second, third);
    + break;
    + case MSGRCV:
    + switch (version) {
    + case 0: {
    + struct ipc_kludge tmp;
    +
    + if (!ptr)
    + break;
    + if ((ret = access_ok(VERIFY_READ, ptr,
    + sizeof(tmp)) ? 0 : -EFAULT)
    + || (ret = copy_from_user(&tmp,
    + (struct ipc_kludge *) ptr,
    + sizeof(tmp))))
    + break;
    + ret = sys_msgrcv(first, tmp.msgp, second, tmp.msgtyp,
    + third);
    + break;
    + }
    + default:
    + ret = sys_msgrcv(first, (struct msgbuf *) ptr,
    + second, fifth, third);
    + break;
    + }
    + break;
    + case MSGGET:
    + ret = sys_msgget((key_t) first, second);
    + break;
    + case MSGCTL:
    + ret = sys_msgctl(first, second, (struct msqid_ds *) ptr);
    + break;
    + case SHMAT:
    + switch (version) {
    + default: {
    + ulong raddr;
    +
    + if ((ret = access_ok(VERIFY_WRITE, (ulong *) third,
    + sizeof(ulong)) ? 0 : -EFAULT))
    + break;
    + ret = do_shmat(first, (char *) ptr, second, &raddr);
    + if (ret)
    + break;
    + ret = put_user(raddr, (ulong *) third);
    + break;
    + }
    + case 1: /* iBCS2 emulator entry point */
    + if (!segment_eq(get_fs(), get_ds()))
    + break;
    + ret = do_shmat(first, (char *) ptr, second,
    + (ulong *) third);
    + break;
    + }
    + break;
    + case SHMDT:
    + ret = sys_shmdt((char *)ptr);
    + break;
    + case SHMGET:
    + ret = sys_shmget(first, second, third);
    + break;
    + case SHMCTL:
    + ret = sys_shmctl(first, second, (struct shmid_ds *) ptr);
    + break;
    + }
    + return -EINVAL;
    +}
    +
    +asmlinkage int sys_vfork(struct pt_regs *regs)
    +{
    + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->r1,
    + regs, 0, NULL, NULL);
    +}
    +
    +asmlinkage int sys_clone(int flags, unsigned long stack, struct pt_regs *regs)
    +{
    + if (!stack)
    + stack = regs->r1;
    + return do_fork(flags, stack, regs, 0, NULL, NULL);
    +}
    +
    +asmlinkage int sys_execve(char __user *filenamei, char __user *__user *argv,
    + char __user *__user *envp, struct pt_regs *regs)
    +{
    + int error;
    + char *filename;
    +
    + filename = getname(filenamei);
    + error = PTR_ERR(filename);
    + if (IS_ERR(filename))
    + goto out;
    + error = do_execve(filename, argv, envp, regs);
    + putname(filename);
    +out:
    + return error;
    +}
    +
    +asmlinkage unsigned long
    +sys_mmap2(unsigned long addr, size_t len,
    + unsigned long prot, unsigned long flags,
    + unsigned long fd, unsigned long pgoff)
    +{
    + struct file *file = NULL;
    + int ret = -EBADF;
    +
    + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
    + if (!(flags & MAP_ANONYMOUS)) {
    + file = fget(fd);
    + if (!file) {
    + printk(KERN_INFO "no fd in mmap\r\n");
    + goto out;
    + }
    + }
    +
    + down_write(&current->mm->mmap_sem);
    + ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
    + up_write(&current->mm->mmap_sem);
    + if (file)
    + fput(file);
    +out:
    + return ret;
    +}
    +
    +asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
    + unsigned long prot, unsigned long flags,
    + unsigned long fd, off_t offset)
    +{
    + int err = -EINVAL;
    +
    + if (offset & ~PAGE_MASK) {
    + printk(KERN_INFO "no pagemask in mmap\r\n");
    + goto out;
    + }
    +
    + err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
    +out:
    + return err;
    +}
    +
    +/*
    + * Do a system call from kernel instead of calling sys_execve so we
    + * end up with proper pt_regs.
    + */
    +int kernel_execve(const char *filename, char *const argv[], char *const envp[])
    +{
    + register const char *__a __asm__("r5") = filename;
    + register const void *__b __asm__("r6") = argv;
    + register const void *__c __asm__("r7") = envp;
    + register unsigned long __syscall __asm__("r12") = __NR_execve;
    + register unsigned long __ret __asm__("r3");
    + __asm__ __volatile__ ("brki r14, 0x8"
    + : "=r" (__ret), "=r" (__syscall)
    + : "1" (__syscall), "r" (__a), "r" (__b), "r" (__c)
    + : "r4", "r8", "r9",
    + "r10", "r11", "r14", "cc", "memory");
    + return __ret;
    +}
    --
    1.5.5.1


    \
     
     \ /
      Last update: 2009-03-18 22:57    [W:4.089 / U:0.720 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site