From 959ae38d717a714776a822bea7056cfc3d99de94 Mon Sep 17 00:00:00 2001 From: Stacey Son Date: Tue, 4 Jun 2013 08:39:57 -0500 Subject: [PATCH 21/23] bsd-user: add miscellaneous system call shims To: Cc: This change add System V semaphores/messages, uuid, FreeBSD cpu scheduling/affinity management, and other miscellaneous system call shims. A lot of these other system call shims are stubs for maybe future work. Signed-off-by: Stacey Son --- bsd-user/Makefile.objs | 2 +- bsd-user/bsd-misc.c | 209 +++++++++++++++++++++ bsd-user/bsd-misc.h | 339 +++++++++++++++++++++++++++++++++ bsd-user/freebsd/os-misc.h | 442 ++++++++++++++++++++++++++++++++++++++++++++ bsd-user/qemu-bsd.h | 21 ++ bsd-user/syscall.c | 224 ++++++++++++++++++++++ bsd-user/syscall_defs.h | 81 ++++++++ 7 files changed, 1317 insertions(+), 1 deletions(-) create mode 100644 bsd-user/bsd-misc.c create mode 100644 bsd-user/bsd-misc.h create mode 100644 bsd-user/freebsd/os-misc.h diff --git a/bsd-user/Makefile.objs b/bsd-user/Makefile.objs index 3dddc00..5308e29 100644 --- a/bsd-user/Makefile.objs +++ b/bsd-user/Makefile.objs @@ -2,4 +2,4 @@ obj-y = main.o bsdload.o elfload.o ioctl.o mmap.o signal.o strace.o syscall.o \ uaccess.o bsd-mem.o bsd-proc.o $(TARGET_OS)/os-time.o \ $(TARGET_OS)/os-proc.o bsd-socket.o $(TARGET_OS)/os-socket.o \ $(TARGET_OS)/os-stat.o $(TARGET_OS)/os-sys.o \ - $(TARGET_OS)/os-thread.o $(TARGET_OS)/os-extattr.o + $(TARGET_OS)/os-thread.o $(TARGET_OS)/os-extattr.o bsd-misc.o diff --git a/bsd-user/bsd-misc.c b/bsd-user/bsd-misc.c new file mode 100644 index 0000000..bc85473 --- /dev/null +++ b/bsd-user/bsd-misc.c @@ -0,0 +1,209 @@ +/* + * BSD misc system call conversions routines + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include +#include + +#include "qemu.h" +#include "qemu-bsd.h" + +/* + * BSD uuidgen(2) struct uuid conversion + */ +abi_long host_to_target_uuid(abi_ulong target_addr, struct uuid *host_uuid) +{ + struct target_uuid *target_uuid; + + if (!lock_user_struct(VERIFY_WRITE, target_uuid, target_addr, 0)) { + return -TARGET_EFAULT; + } + __put_user(host_uuid->time_low, &target_uuid->time_low); + __put_user(host_uuid->time_mid, &target_uuid->time_mid); + __put_user(host_uuid->time_hi_and_version, + &target_uuid->time_hi_and_version); + host_uuid->clock_seq_hi_and_reserved = + target_uuid->clock_seq_hi_and_reserved; + host_uuid->clock_seq_low = target_uuid->clock_seq_low; + memcpy(host_uuid->node, target_uuid->node, TARGET_UUID_NODE_LEN); + unlock_user_struct(target_uuid, target_addr, 1); + return 0; +} + +abi_long target_to_host_semarray(int semid, unsigned short **host_array, + abi_ulong target_addr) +{ + abi_long ret; + int nsems, i; + unsigned short *array; + union semun semun; + struct semid_ds semid_ds; + + semun.buf = &semid_ds; + ret = semctl(semid, 0, IPC_STAT, semun); + if (ret == -1) { + return get_errno(ret); + } + nsems = semid_ds.sem_nsems; + *host_array = (unsigned short *)malloc(nsems * sizeof(unsigned short)); + array = lock_user(VERIFY_READ, target_addr, + nsems*sizeof(unsigned short), 1); + if (array == NULL) { + free(*host_array); + return -TARGET_EFAULT; + } + for (i = 0; i < nsems; i++) { + (*host_array)[i] = array[i]; + } + unlock_user(array, target_addr, 0); + + return 0; +} + +abi_long host_to_target_semarray(int semid, abi_ulong target_addr, + unsigned short **host_array) +{ + abi_long ret; + int nsems, i; + unsigned short *array; + union semun semun; + struct semid_ds semid_ds; + + semun.buf = &semid_ds; + + ret = semctl(semid, 0, IPC_STAT, semun); + if (ret == -1) { + free(*host_array); + return get_errno(ret); + } + + nsems = semid_ds.sem_nsems; + array = (unsigned short *)lock_user(VERIFY_WRITE, target_addr, + nsems*sizeof(unsigned short), 0); + if (array == NULL) { + free(*host_array); + return -TARGET_EFAULT; + } + for (i = 0; i < nsems; i++) { + array[i] = (*host_array)[i]; + } + free(*host_array); + unlock_user(array, target_addr, 1); + return 0; +} + +abi_long target_to_host_semid_ds(struct semid_ds *host_sd, + abi_ulong target_addr) +{ + struct target_semid_ds *target_sd; + + if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) { + return -TARGET_EFAULT; + } + if (target_to_host_ipc_perm(&(host_sd->sem_perm), (target_addr + + offsetof(struct target_semid_ds, sem_perm)))) { + return -TARGET_EFAULT; + } + /* sem_base is not used by kernel for IPC_STAT/IPC_SET */ + /* host_sd->sem_base = g2h(target_sd->sem_base); */ + host_sd->sem_nsems = tswap16(target_sd->sem_nsems); + host_sd->sem_otime = tswapal(target_sd->sem_otime); + host_sd->sem_ctime = tswapal(target_sd->sem_ctime); + unlock_user_struct(target_sd, target_addr, 0); + return 0; +} + +abi_long host_to_target_semid_ds(abi_ulong target_addr, + struct semid_ds *host_sd) +{ + struct target_semid_ds *target_sd; + + if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) { + return -TARGET_EFAULT; + } + if (host_to_target_ipc_perm((target_addr + + offsetof(struct target_semid_ds, sem_perm)), + &(host_sd->sem_perm))) { + return -TARGET_EFAULT; + } + /* sem_base is not used by kernel for IPC_STAT/IPC_SET */ + /* target_sd->sem_base = h2g((void *)host_sd->sem_base); */ + target_sd->sem_nsems = tswap16(host_sd->sem_nsems); + target_sd->sem_otime = tswapal(host_sd->sem_otime); + target_sd->sem_ctime = tswapal(host_sd->sem_ctime); + unlock_user_struct(target_sd, target_addr, 1); + + return 0; +} + +abi_long target_to_host_msqid_ds(struct msqid_ds *host_md, + abi_ulong target_addr) +{ + struct target_msqid_ds *target_md; + + if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1)) { + return -TARGET_EFAULT; + } + if (target_to_host_ipc_perm(&(host_md->msg_perm), target_addr)) { + return -TARGET_EFAULT; + } + + /* msg_first and msg_last are not used by IPC_SET/IPC_STAT in kernel. */ + host_md->msg_first = host_md->msg_last = NULL; + host_md->msg_cbytes = tswapal(target_md->msg_cbytes); + host_md->msg_qnum = tswapal(target_md->msg_qnum); + host_md->msg_qbytes = tswapal(target_md->msg_qbytes); + host_md->msg_lspid = tswapal(target_md->msg_lspid); + host_md->msg_lrpid = tswapal(target_md->msg_lrpid); + host_md->msg_stime = tswapal(target_md->msg_stime); + host_md->msg_rtime = tswapal(target_md->msg_rtime); + host_md->msg_ctime = tswapal(target_md->msg_ctime); + unlock_user_struct(target_md, target_addr, 0); + + return 0; +} + +abi_long host_to_target_msqid_ds(abi_ulong target_addr, + struct msqid_ds *host_md) +{ + struct target_msqid_ds *target_md; + + if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0)) { + return -TARGET_EFAULT; + } + if (host_to_target_ipc_perm(target_addr, &(host_md->msg_perm))) { + return -TARGET_EFAULT; + } + + /* msg_first and msg_last are not used by IPC_SET/IPC_STAT in kernel. */ + target_md->msg_cbytes = tswapal(host_md->msg_cbytes); + target_md->msg_qnum = tswapal(host_md->msg_qnum); + target_md->msg_qbytes = tswapal(host_md->msg_qbytes); + target_md->msg_lspid = tswapal(host_md->msg_lspid); + target_md->msg_lrpid = tswapal(host_md->msg_lrpid); + target_md->msg_stime = tswapal(host_md->msg_stime); + target_md->msg_rtime = tswapal(host_md->msg_rtime); + target_md->msg_ctime = tswapal(host_md->msg_ctime); + unlock_user_struct(target_md, target_addr, 1); + + return 0; +} + diff --git a/bsd-user/bsd-misc.h b/bsd-user/bsd-misc.h new file mode 100644 index 0000000..0c34089 --- /dev/null +++ b/bsd-user/bsd-misc.h @@ -0,0 +1,339 @@ +/* + * miscellaneous BSD system call shims + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#ifndef __BSD_MISC_H_ +#define __BSD_MISC_H_ + +#include +#include +#include +#include +#include + +#include "qemu-bsd.h" + +/* quotactl(2) */ +static inline abi_long do_bsd_quotactl(abi_ulong path, abi_long cmd, + abi_ulong target_addr) +{ + + qemu_log("qemu: Unsupported syscall quotactl()\n"); + return -TARGET_ENOSYS; +} + +/* reboot(2) */ +static inline abi_long do_bsd_reboot(abi_long how) +{ + + qemu_log("qemu: Unsupported syscall reboot()\n"); + return -TARGET_ENOSYS; +} + +/* uuidgen(2) */ +static inline abi_long do_bsd_uuidgen(abi_ulong target_addr, int count) +{ + int i; + abi_long ret; + struct uuid *host_uuid; + + if (count < 1 || count > 2048) { + return -TARGET_EINVAL; + } + + host_uuid = (struct uuid *)g_malloc(count * sizeof(struct uuid)); + + if (host_uuid == NULL) { + return -TARGET_ENOMEM; + } + + ret = get_errno(uuidgen(host_uuid, count)); + if (is_error(ret)) { + goto out; + } + for (i = 0; i < count; i++) { + ret = host_to_target_uuid(target_addr + + (abi_ulong)(sizeof(struct target_uuid) * i), &host_uuid[i]); + if (is_error(ret)) { + goto out; + } + } + +out: + g_free(host_uuid); + return ret; +} + + +/* + * System V Semaphores + */ + +/* semget(2) */ +static inline abi_long do_bsd_semget(abi_long key, int nsems, + int target_flags) +{ + + return get_errno(semget(key, nsems, + target_to_host_bitmask(target_flags, ipc_flags_tbl))); +} + +/* semop(2) */ +static inline abi_long do_bsd_semop(int semid, abi_long ptr, unsigned nsops) +{ + struct sembuf sops[nsops]; + struct target_sembuf *target_sembuf; + int i; + + target_sembuf = lock_user(VERIFY_READ, ptr, + nsops * sizeof(struct target_sembuf), 1); + if (target_sembuf == NULL) { + return -TARGET_EFAULT; + } + for (i = 0; i < nsops; i++) { + __get_user(sops[i].sem_num, &target_sembuf[i].sem_num); + __get_user(sops[i].sem_op, &target_sembuf[i].sem_op); + __get_user(sops[i].sem_flg, &target_sembuf[i].sem_flg); + } + unlock_user(target_sembuf, ptr, 0); + + return semop(semid, sops, nsops); +} + +/* __semctl(2) */ +static inline abi_long do_bsd___semctl(int semid, int semnum, int target_cmd, + union target_semun target_su) +{ + union semun arg; + struct semid_ds dsarg; + unsigned short *array = NULL; + int host_cmd; + abi_long ret = 0; + abi_long err; + abi_ulong target_addr; + + switch (target_cmd) { + case TARGET_GETVAL: + host_cmd = GETVAL; + break; + + case TARGET_SETVAL: + host_cmd = SETVAL; + break; + + case TARGET_GETALL: + host_cmd = GETALL; + break; + + case TARGET_SETALL: + host_cmd = SETALL; + break; + + case TARGET_IPC_STAT: + host_cmd = IPC_STAT; + break; + + case TARGET_IPC_SET: + host_cmd = IPC_SET; + break; + + case TARGET_IPC_RMID: + host_cmd = IPC_RMID; + break; + + case TARGET_GETPID: + host_cmd = GETPID; + break; + + case TARGET_GETNCNT: + host_cmd = GETNCNT; + break; + + case TARGET_GETZCNT: + host_cmd = GETZCNT; + break; + + default: + return -TARGET_EINVAL; + } + + switch (host_cmd) { + case GETVAL: + case SETVAL: + arg.val = tswap32(target_su.val); + ret = get_errno(semctl(semid, semnum, host_cmd, arg)); + target_su.val = tswap32(arg.val); + break; + + case GETALL: + case SETALL: + if (get_user_ual(target_addr, (abi_ulong)target_su.array)) { + return -TARGET_EFAULT; + } + err = target_to_host_semarray(semid, &array, target_addr); + if (is_error(err)) { + return err; + } + arg.array = array; + ret = get_errno(semctl(semid, semnum, host_cmd, arg)); + err = host_to_target_semarray(semid, target_addr, &array); + if (is_error(err)) { + return err; + } + break; + + case IPC_STAT: + case IPC_SET: + if (get_user_ual(target_addr, (abi_ulong)target_su.buf)) { + return -TARGET_EFAULT; + } + err = target_to_host_semid_ds(&dsarg, target_addr); + if (is_error(err)) { + return err; + } + arg.buf = &dsarg; + ret = get_errno(semctl(semid, semnum, host_cmd, arg)); + err = host_to_target_semid_ds(target_addr, &dsarg); + if (is_error(err)) { + return err; + } + break; + + case IPC_RMID: + case GETPID: + case GETNCNT: + case GETZCNT: + ret = get_errno(semctl(semid, semnum, host_cmd, NULL)); + break; + + default: + ret = -TARGET_EINVAL; + break; + } + return ret; +} + +/* msgctl(2) */ +static inline abi_long do_bsd_msgctl(int msgid, int target_cmd, abi_long ptr) +{ + struct msqid_ds dsarg; + abi_long ret = -TARGET_EINVAL; + int host_cmd; + + switch (target_cmd) { + case TARGET_IPC_STAT: + host_cmd = IPC_STAT; + break; + + case TARGET_IPC_SET: + host_cmd = IPC_SET; + break; + + case TARGET_IPC_RMID: + host_cmd = IPC_RMID; + break; + + default: + return -TARGET_EINVAL; + } + + switch (host_cmd) { + case IPC_STAT: + case IPC_SET: + if (target_to_host_msqid_ds(&dsarg, ptr)) { + return -TARGET_EFAULT; + } + ret = get_errno(msgctl(msgid, host_cmd, &dsarg)); + if (host_to_target_msqid_ds(ptr, &dsarg)) { + return -TARGET_EFAULT; + } + break; + + case IPC_RMID: + ret = get_errno(msgctl(msgid, host_cmd, NULL)); + break; + + default: + ret = -TARGET_EINVAL; + break; + } + return ret; +} + +/* msgsnd(2) */ +static inline abi_long do_bsd_msgsnd(int msqid, abi_long msgp, + unsigned int msgsz, int msgflg) +{ + struct target_msgbuf *target_mb; + struct mymsg *host_mb; + abi_long ret; + + if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0)) { + return -TARGET_EFAULT; + } + host_mb = g_malloc(msgsz+sizeof(long)); + host_mb->mtype = (abi_long) tswapal(target_mb->mtype); + memcpy(host_mb->mtext, target_mb->mtext, msgsz); + ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg)); + g_free(host_mb); + unlock_user_struct(target_mb, msgp, 0); + + return ret; +} + +/* msgrcv(2) */ +static inline abi_long do_bsd_msgrcv(int msqid, abi_long msgp, + unsigned int msgsz, abi_long msgtyp, int msgflg) +{ + struct target_msgbuf *target_mb = NULL; + char *target_mtext; + struct mymsg *host_mb; + abi_long ret = 0; + + if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0)) { + return -TARGET_EFAULT; + } + host_mb = g_malloc(msgsz+sizeof(long)); + ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapal(msgtyp), msgflg)); + if (ret > 0) { + abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong); + target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0); + if (target_mtext == NULL) { + ret = -TARGET_EFAULT; + goto end; + } + memcpy(target_mb->mtext, host_mb->mtext, ret); + unlock_user(target_mtext, target_mtext_addr, ret); + } + target_mb->mtype = tswapal(host_mb->mtype); +end: + if (target_mb != NULL) { + unlock_user_struct(target_mb, msgp, 1); + } + g_free(host_mb); + return ret; +} + +/* getdtablesize(2) */ +static inline abi_long do_bsd_getdtablesize(void) +{ + + return get_errno(getdtablesize()); +} + +#endif /* ! __BSD_MISC_H_ */ diff --git a/bsd-user/freebsd/os-misc.h b/bsd-user/freebsd/os-misc.h new file mode 100644 index 0000000..07e60fe --- /dev/null +++ b/bsd-user/freebsd/os-misc.h @@ -0,0 +1,442 @@ +/* + * miscellaneous FreeBSD system call shims + * + * Copyright (c) 2013 Stacey D. Son + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ +#ifndef __OS_MISC_H_ +#define __OS_MISC_H_ + +#include +#include + +/* sched_setparam(2) */ +static inline abi_long do_freebsd_sched_setparam(pid_t pid, + abi_ulong target_sp_addr) +{ + abi_long ret; + struct sched_param host_sp; + + ret = get_user_s32(host_sp.sched_priority, target_sp_addr); + if (!is_error(ret)) { + ret = get_errno(sched_setparam(pid, &host_sp)); + } + return ret; +} + +/* sched_get_param(2) */ +static inline abi_long do_freebsd_sched_getparam(pid_t pid, + abi_ulong target_sp_addr) +{ + abi_long ret; + struct sched_param host_sp; + + ret = get_errno(sched_getparam(pid, &host_sp)); + if (!is_error(ret)) { + ret = put_user_s32(host_sp.sched_priority, target_sp_addr); + } + return ret; +} + +/* sched_setscheduler(2) */ +static inline abi_long do_freebsd_sched_setscheduler(pid_t pid, int policy, + abi_ulong target_sp_addr) +{ + abi_long ret; + struct sched_param host_sp; + + ret = get_user_s32(host_sp.sched_priority, target_sp_addr); + if (!is_error(ret)) { + ret = get_errno(sched_setscheduler(pid, policy, &host_sp)); + } + return ret; +} + +/* sched_getscheduler(2) */ +static inline abi_long do_freebsd_sched_getscheduler(pid_t pid) +{ + + return get_errno(sched_getscheduler(pid)); +} + +/* sched_getscheduler(2) */ +static inline abi_long do_freebsd_sched_rr_get_interval(pid_t pid, + abi_ulong target_ts_addr) +{ + abi_long ret; + struct timespec host_ts; + + ret = get_errno(sched_rr_get_interval(pid, &host_ts)); + if (!is_error(ret)) { + ret = h2t_freebsd_timespec(target_ts_addr, &host_ts); + } + return ret; +} + +/* cpuset(2) */ +static inline abi_long do_freebsd_cpuset(abi_ulong target_cpuid) +{ + abi_long ret; + cpusetid_t setid; + + ret = get_errno(cpuset(&setid)); + if (is_error(ret)) { + return ret; + } + return put_user_s32(setid, target_cpuid); +} + +#define target_to_host_cpuset_which(hp, t) { \ + (*hp) = t; \ +} while (0) + +#define target_to_host_cpuset_level(hp, t) { \ + (*hp) = t; \ +} while (0) + +/* cpuset_setid(2) */ +static inline abi_long do_freebsd_cpuset_setid(void *cpu_env, abi_long arg1, + abi_ulong arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5) +{ + id_t id; /* 64-bit value */ + cpusetid_t setid; + cpuwhich_t which; + + target_to_host_cpuset_which(&which, arg1); +#if TARGET_ABI_BITS == 32 + /* See if we need to align the register pairs */ + if (regpairs_aligned(cpu_env)) { + id = target_offset64(arg3, arg4); + setid = arg5; + } else { + id = target_offset64(arg2, arg3); + setid = arg4; + } +#else + id = arg2; + setid = arg3; +#endif + return get_errno(cpuset_setid(which, id, setid)); +} + +/* cpuset_getid(2) */ +static inline abi_long do_freebsd_cpuset_getid(abi_long arg1, abi_ulong arg2, + abi_ulong arg3, abi_ulong arg4, abi_ulong arg5) +{ + abi_long ret; + id_t id; /* 64-bit value */ + cpusetid_t setid; + cpuwhich_t which; + cpulevel_t level; + abi_ulong target_setid; + + target_to_host_cpuset_which(&which, arg1); + target_to_host_cpuset_level(&level, arg2); +#if TARGET_ABI_BITS == 32 + id = target_offset64(arg3, arg4); + target_setid = arg5; +#else + id = arg3; + target_setid = arg4; +#endif + ret = get_errno(cpuset_getid(level, which, id, &setid)); + if (is_error(ret)) { + return ret; + } + return put_user_s32(setid, target_setid); +} + +/* cpuset_getaffinity(2) */ +static inline abi_long do_freebsd_cpuset_getaffinity(abi_long arg1, + abi_ulong arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5, + abi_ulong arg6) +{ + + qemu_log("qemu: Unsupported syscall cpuset_getaffinity()\n"); + return -TARGET_ENOSYS; +} + +/* cpuset_setaffinity(2) */ +static inline abi_long do_freebsd_cpuset_setaffinity(abi_long arg1, + abi_ulong arg2, abi_ulong arg3, abi_ulong arg4, abi_ulong arg5, + abi_ulong arg6) +{ + + qemu_log("qemu: Unsupported syscall cpuset_setaffinity()\n"); + return -TARGET_ENOSYS; +} + + +/* modfnext(2) */ +static inline abi_long do_freebsd_modfnext(abi_long modid) +{ + + qemu_log("qemu: Unsupported syscall modfnext()\n"); + return -TARGET_ENOSYS; +} + +/* modfind(2) */ +static inline abi_long do_freebsd_modfind(abi_ulong target_name) +{ + + qemu_log("qemu: Unsupported syscall modfind()\n"); + return -TARGET_ENOSYS; +} + +/* kldload(2) */ +static inline abi_long do_freebsd_kldload(abi_ulong target_name) +{ + + qemu_log("qemu: Unsupported syscall kldload()\n"); + return -TARGET_ENOSYS; +} + +/* kldunload(2) */ +static inline abi_long do_freebsd_kldunload(abi_long fileid) +{ + + qemu_log("qemu: Unsupported syscall kldunload()\n"); + return -TARGET_ENOSYS; +} + +/* kldunloadf(2) */ +static inline abi_long do_freebsd_kldunloadf(abi_long fileid, abi_long flags) +{ + + qemu_log("qemu: Unsupported syscall kldunloadf()\n"); + return -TARGET_ENOSYS; +} + +/* kldfind(2) */ +static inline abi_long do_freebsd_kldfind(abi_ulong target_name) +{ + + qemu_log("qemu: Unsupported syscall kldfind()\n"); + return -TARGET_ENOSYS; +} + +/* kldnext(2) */ +static inline abi_long do_freebsd_kldnext(abi_long fileid) +{ + + qemu_log("qemu: Unsupported syscall kldnext()\n"); + return -TARGET_ENOSYS; +} + + +/* kldstat(2) */ +static inline abi_long do_freebsd_kldstat(abi_long fileid, + abi_ulong target_stat) +{ + + qemu_log("qemu: Unsupported syscall kldstat()\n"); + return -TARGET_ENOSYS; +} + +/* kldfirstmod(2) */ +static inline abi_long do_freebsd_kldfirstmod(abi_long fileid) +{ + + qemu_log("qemu: Unsupported syscall kldfirstmod()\n"); + return -TARGET_ENOSYS; +} + +/* kldsym(2) */ +static inline abi_long do_freebsd_kldsym(abi_long fileid, abi_long cmd, + abi_ulong target_data) +{ + + qemu_log("qemu: Unsupported syscall kldsym()\n"); + return -TARGET_ENOSYS; +} + +/* + * Resource limits (undocumented except for rctl(8) and rctl.conf(5) ) + */ +/* rctl_get_racct() */ +static inline abi_long do_freebsd_rctl_get_racct(abi_ulong target_inbufp, + abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen) +{ + + qemu_log("qemu: Unsupported syscall rctl_get_racct()\n"); + return -TARGET_ENOSYS; +} + +/* rctl_get_rules() */ +static inline abi_long do_freebsd_rctl_get_rules(abi_ulong target_inbufp, + abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen) +{ + + qemu_log("qemu: Unsupported syscall rctl_get_rules()\n"); + return -TARGET_ENOSYS; +} + +/* rctl_add_rule() */ +static inline abi_long do_freebsd_rctl_add_rule(abi_ulong target_inbufp, + abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen) +{ + + qemu_log("qemu: Unsupported syscall rctl_add_rule()\n"); + return -TARGET_ENOSYS; +} + +/* rctl_remove_rule() */ +static inline abi_long do_freebsd_rctl_remove_rule(abi_ulong target_inbufp, + abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen) +{ + + qemu_log("qemu: Unsupported syscall rctl_remove_rule()\n"); + return -TARGET_ENOSYS; +} + +/* rctl_get_limits() */ +static inline abi_long do_freebsd_rctl_get_limits(abi_ulong target_inbufp, + abi_ulong inbuflen, abi_ulong target_outbufp, abi_ulong outbuflen) +{ + + qemu_log("qemu: Unsupported syscall rctl_get_limits()\n"); + return -TARGET_ENOSYS; +} + +/* + * Kernel environment + */ + +/* kenv(2) */ +static inline abi_long do_freebsd_kenv(abi_long what, abi_ulong target_name, + abi_ulong target_value, abi_long len) +{ + + qemu_log("qemu: Unsupported syscall kenv()\n"); + return -TARGET_ENOSYS; +} + + +/* + * Mandatory Access Control + */ + +/* __mac_get_proc */ +static inline abi_long do_freebsd___mac_get_proc(abi_ulong target_mac) +{ + + qemu_log("qemu: Unsupported syscall mac_get_proc()\n"); + return -TARGET_ENOSYS; +} + +/* __mac_set_proc */ +static inline abi_long do_freebsd___mac_set_proc(abi_ulong target_mac) +{ + + qemu_log("qemu: Unsupported syscall mac_set_proc()\n"); + return -TARGET_ENOSYS; +} + + +/* __mac_get_fd */ +static inline abi_long do_freebsd___mac_get_fd(abi_long fd, + abi_ulong target_mac) +{ + + qemu_log("qemu: Unsupported syscall mac_get_fd()\n"); + return -TARGET_ENOSYS; +} + +/* __mac_set_fd */ +static inline abi_long do_freebsd___mac_set_fd(abi_long fd, + abi_ulong target_mac) +{ + + qemu_log("qemu: Unsupported syscall mac_set_fd()\n"); + return -TARGET_ENOSYS; +} + +/* __mac_get_file */ +static inline abi_long do_freebsd___mac_get_file(abi_ulong target_path, + abi_ulong target_mac) +{ + + qemu_log("qemu: Unsupported syscall mac_get_file()\n"); + return -TARGET_ENOSYS; +} + +/* __mac_set_file */ +static inline abi_long do_freebsd___mac_set_file(abi_ulong target_path, + abi_ulong target_mac) +{ + + qemu_log("qemu: Unsupported syscall mac_set_file()\n"); + return -TARGET_ENOSYS; +} + +/* __mac_get_link */ +static inline abi_long do_freebsd___mac_get_link(abi_ulong target_path, + abi_ulong target_mac) +{ + + qemu_log("qemu: Unsupported syscall mac_get_link()\n"); + return -TARGET_ENOSYS; +} + +/* __mac_set_link */ +static inline abi_long do_freebsd___mac_set_link(abi_ulong target_path, + abi_ulong target_mac) +{ + + qemu_log("qemu: Unsupported syscall mac_set_link()\n"); + return -TARGET_ENOSYS; +} + +/* mac_syscall */ +static inline abi_long do_freebsd_mac_syscall(abi_ulong target_policy, + abi_long call, abi_ulong target_arg) +{ + + qemu_log("qemu: Unsupported syscall mac_syscall()\n"); + return -TARGET_ENOSYS; +} + + +/* + * New posix calls + */ +/* posix_fallocate(2) */ +static inline abi_long do_freebsd_posix_fallocate(abi_long fd, abi_ulong offset, + abi_ulong len) +{ + + qemu_log("qemu: Unsupported syscall posix_fallocate()\n"); + return -TARGET_ENOSYS; +} + +/* posix_openpt(2) */ +static inline abi_long do_freebsd_posix_openpt(abi_long flags) +{ + + qemu_log("qemu: Unsupported syscall posix_openpt()\n"); + return -TARGET_ENOSYS; +} + +/* posix_fadvise(2) */ +static inline abi_long do_freebsd_posix_fadvise(abi_long fd, abi_ulong offset, + abi_ulong len, abi_long advise) +{ + + qemu_log("qemu: Unsupported syscall posix_fadvise()\n"); + return -TARGET_ENOSYS; +} + + +#endif /* ! __OS_MISC_H_ */ diff --git a/bsd-user/qemu-bsd.h b/bsd-user/qemu-bsd.h index c7c39c6..771245d 100644 --- a/bsd-user/qemu-bsd.h +++ b/bsd-user/qemu-bsd.h @@ -22,10 +22,13 @@ #include #include +#include #include +#include #include #include #include +#include #include #include @@ -55,4 +58,22 @@ abi_long host_to_target_sockaddr(abi_ulong target_addr, struct sockaddr *addr, abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn, abi_ulong target_addr, socklen_t len); +/* bsd-misc.c */ +abi_long host_to_target_uuid(abi_ulong target_addr, struct uuid *host_uuid); + +abi_long target_to_host_semarray(int semid, unsigned short **host_array, + abi_ulong target_addr); +abi_long host_to_target_semarray(int semid, abi_ulong target_addr, + unsigned short **host_array); + +abi_long target_to_host_semid_ds(struct semid_ds *host_sd, + abi_ulong target_addr); +abi_long host_to_target_semid_ds(abi_ulong target_addr, + struct semid_ds *host_sd); + +abi_long target_to_host_msqid_ds(struct msqid_ds *host_md, + abi_ulong target_addr); +abi_long host_to_target_msqid_ds(abi_ulong target_addr, + struct msqid_ds *host_md); + #endif /* !_QEMU_BSD_H_ */ diff --git a/bsd-user/syscall.c b/bsd-user/syscall.c index 014706c..0e639fe 100644 --- a/bsd-user/syscall.c +++ b/bsd-user/syscall.c @@ -37,6 +37,7 @@ static int host_to_target_errno(int err); /* BSD independent syscall shims */ #include "bsd-file.h" #include "bsd-mem.h" +#include "bsd-misc.h" #include "bsd-proc.h" #include "bsd-signal.h" #include "bsd-socket.h" @@ -44,6 +45,7 @@ static int host_to_target_errno(int err); /* *BSD dependent syscall shims */ #include "os-extattr.h" #include "os-time.h" +#include "os-misc.h" #include "os-proc.h" #include "os-signal.h" #include "os-socket.h" @@ -1292,6 +1294,228 @@ abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1, ret = do_freebsd__acl_set_link(arg1, arg2, arg3); break; + /* + * SysV Semaphores + */ + case TARGET_FREEBSD_NR_semget: /* semget(2) */ + ret = do_bsd_semget(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_semop: /* semop(2) */ + ret = do_bsd_semop(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR___semctl: /* __semctl() undocumented */ + ret = do_bsd___semctl(arg1, arg2, arg3, + (union target_semun)(abi_ulong)arg4); + break; + + /* + * SysV Messages + */ + case TARGET_FREEBSD_NR_msgctl: /* msgctl(2) */ + ret = do_bsd_msgctl(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_msgsnd: /* msgsnd(2) */ + ret = do_bsd_msgsnd(arg1, arg2, arg3, arg4); + break; + + case TARGET_FREEBSD_NR_msgrcv: /* msgrcv(2) */ + ret = do_bsd_msgrcv(arg1, arg2, arg3, arg4, arg5); + break; + + /* + * FreeBSD scheduler control + */ + case TARGET_FREEBSD_NR_sched_setparam: /* sched_setparam(2) */ + ret = do_freebsd_sched_setparam(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_sched_getparam: /* sched_getparam(2) */ + ret = do_freebsd_sched_getparam(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_sched_setscheduler: /* sched_setscheduler(2) */ + ret = do_freebsd_sched_setscheduler(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_sched_getscheduler: /* sched_getscheduler(2) */ + ret = do_freebsd_sched_getscheduler(arg1); + break; + + case TARGET_FREEBSD_NR_sched_rr_get_interval: /* sched_rr_get_interval(2) */ + ret = do_freebsd_sched_rr_get_interval(arg1, arg2); + break; + + /* + * FreeBSD CPU affinity sets management + */ + case TARGET_FREEBSD_NR_cpuset: /* cpuset(2) */ + ret = do_freebsd_cpuset(arg1); + break; + + case TARGET_FREEBSD_NR_cpuset_setid: /* cpuset_setid(2) */ + ret = do_freebsd_cpuset_setid(cpu_env, arg1, arg2, arg3, arg4, arg5); + break; + + case TARGET_FREEBSD_NR_cpuset_getid: /* cpuset_getid(2) */ + ret = do_freebsd_cpuset_getid(arg1, arg2, arg3, arg4, arg5); + break; + + case TARGET_FREEBSD_NR_cpuset_getaffinity: /* cpuset_getaffinity(2) */ + ret = do_freebsd_cpuset_getaffinity(arg1, arg2, arg3, arg4, arg5, arg6); + break; + + case TARGET_FREEBSD_NR_cpuset_setaffinity: /* cpuset_setaffinity(2) */ + ret = do_freebsd_cpuset_setaffinity(arg1, arg2, arg3, arg4, arg5, arg6); + break; + + + /* + * FreeBSD kernel module + */ + case TARGET_FREEBSD_NR_modfnext: /* modfnext(2) */ + ret = do_freebsd_modfnext(arg1); + break; + + case TARGET_FREEBSD_NR_modfind: /* modfind(2) */ + ret = do_freebsd_modfind(arg1); + break; + + case TARGET_FREEBSD_NR_kldload: /* kldload(2) */ + ret = do_freebsd_kldload(arg1); + break; + + case TARGET_FREEBSD_NR_kldunload: /* kldunload(2) */ + ret = do_freebsd_kldunload(arg1); + break; + + case TARGET_FREEBSD_NR_kldunloadf: /* kldunloadf(2) */ + ret = do_freebsd_kldunloadf(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_kldfind: /* kldfind(2) */ + ret = do_freebsd_kldfind(arg1); + break; + + case TARGET_FREEBSD_NR_kldnext: /* kldnext(2) */ + ret = do_freebsd_kldnext(arg1); + break; + + case TARGET_FREEBSD_NR_kldstat: /* kldstat(2) */ + ret = do_freebsd_kldstat(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_kldfirstmod: /* kldfirstmod(2) */ + ret = do_freebsd_kldfirstmod(arg1); + break; + + case TARGET_FREEBSD_NR_kldsym: /* kldsym(2) */ + ret = do_freebsd_kldsym(arg1, arg2, arg3); + break; + + /* + * FreeBSD resource controls (undocumented except for rctl(8) + * and rctl.conf(5) ) + */ + case TARGET_FREEBSD_NR_rctl_get_racct: /* rctl_get_racct() */ + ret = do_freebsd_rctl_get_racct(arg1, arg2, arg3, arg4); + break; + + case TARGET_FREEBSD_NR_rctl_get_rules: /* rctl_get_rules() */ + ret = do_freebsd_rctl_get_rules(arg1, arg2, arg3, arg4); + break; + + case TARGET_FREEBSD_NR_rctl_add_rule: /* rctl_add_rule() */ + ret = do_freebsd_rctl_add_rule(arg1, arg2, arg3, arg4); + break; + + case TARGET_FREEBSD_NR_rctl_remove_rule: /* rctl_remove_rule() */ + ret = do_freebsd_rctl_remove_rule(arg1, arg2, arg3, arg4); + break; + + case TARGET_FREEBSD_NR_rctl_get_limits: /* rctl_get_limits() */ + ret = do_freebsd_rctl_get_limits(arg1, arg2, arg3, arg4); + break; + + /* + * FreeBSD Mandatory Access Control + */ + case TARGET_FREEBSD_NR___mac_get_proc: /* __mac_get_proc() */ + ret = do_freebsd___mac_get_proc(arg1); + break; + + case TARGET_FREEBSD_NR___mac_set_proc: /* __mac_set_proc() */ + ret = do_freebsd___mac_set_proc(arg1); + break; + + case TARGET_FREEBSD_NR___mac_get_fd: /* __mac_get_fd() */ + ret = do_freebsd___mac_get_fd(arg1, arg2); + break; + + case TARGET_FREEBSD_NR___mac_set_fd: /* __mac_set_fd() */ + ret = do_freebsd___mac_set_fd(arg1, arg2); + break; + + case TARGET_FREEBSD_NR___mac_get_file: /* __mac_get_file() */ + ret = do_freebsd___mac_get_proc(arg1); + break; + + case TARGET_FREEBSD_NR___mac_set_file: /* __mac_set_file() */ + ret = do_freebsd___mac_set_file(arg1, arg2); + break; + + case TARGET_FREEBSD_NR___mac_get_link: /* __mac_get_link() */ + ret = do_freebsd___mac_get_link(arg1, arg2); + break; + + case TARGET_FREEBSD_NR___mac_set_link: /* __mac_set_link() */ + ret = do_freebsd___mac_set_link(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_mac_syscall: /* mac_syscall() */ + ret = do_freebsd_mac_syscall(arg1, arg2, arg3); + break; + + /* + * FreeBSD additional posix support + */ + case TARGET_FREEBSD_NR_posix_fallocate: /* posix_fallocate(2) */ + ret = do_freebsd_posix_fallocate(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_posix_openpt: /* posix_fallocate(2) */ + ret = do_freebsd_posix_openpt(arg1); + break; + + case TARGET_FREEBSD_NR_posix_fadvise: /* posix_fadvise(2) */ + ret = do_freebsd_posix_fadvise(arg1, arg2, arg3, arg4); + break; + + /* + * Misc + */ + case TARGET_FREEBSD_NR_quotactl: /* quotactl(2) */ + ret = do_bsd_quotactl(arg1, arg2, arg3); + break; + + case TARGET_FREEBSD_NR_reboot: /* reboot(2) */ + ret = do_bsd_reboot(arg1); + break; + + case TARGET_FREEBSD_NR_uuidgen: /* uuidgen(2) */ + ret = do_bsd_uuidgen(arg1, arg2); + break; + + case TARGET_FREEBSD_NR_getdtablesize: /* getdtablesize(2) */ + ret = do_bsd_getdtablesize(); + break; + + case TARGET_FREEBSD_NR_kenv: /* kenv(2) */ + ret = do_freebsd_kenv(arg1, arg2, arg2, arg4); + break; + case TARGET_FREEBSD_NR_break: ret = do_obreak(arg1); diff --git a/bsd-user/syscall_defs.h b/bsd-user/syscall_defs.h index ff329f7..76cbcd6 100644 --- a/bsd-user/syscall_defs.h +++ b/bsd-user/syscall_defs.h @@ -25,6 +25,43 @@ struct target_ipc_perm { abi_long key; /* user specified msg/sem/shm key */ }; +#define TARGET_IPC_RMID 0 /* remove identifier */ +#define TARGET_IPC_SET 1 /* set options */ +#define TARGET_IPC_STAT 2 /* get options */ + +/* + * sys/sem.h + */ +#define TARGET_GETNCNT 3 /* Return the value of semncnt {READ} */ +#define TARGET_GETPID 4 /* Return the value of sempid {READ} */ +#define TARGET_GETVAL 5 /* Return the value of semval {READ} */ +#define TARGET_GETALL 6 /* Return semvals into arg.array {READ} */ +#define TARGET_GETZCNT 7 /* Return the value of semzcnt {READ} */ +#define TARGET_SETVAL 8 /* Set the value of semval to arg.val {ALTER} */ +#define TARGET_SETALL 9 /* Set semvals from arg.array {ALTER} */ +#define TARGET_SEM_STAT 10 /* Like IPC_STAT but treats semid as sema-index */ +#define TARGET_SEM_INFO 11 /* Like IPC_INFO but treats semid as sema-index */ + +struct target_sembuf { + unsigned short sem_num; /* semaphore # */ + short sem_op; /* semaphore operation */ + short sem_flg; /* operation flags */ +}; + +union target_semun { + int val; /* value for SETVAL */ + abi_ulong buf; /* buffer for IPC_STAT & IPC_SET */ + abi_ulong array; /* array for GETALL & SETALL */ +}; + +struct target_semid_ds { + struct target_ipc_perm sem_perm; /* operation permission struct */ + abi_ulong sem_base; /* pointer to first semaphore in set */ + uint16_t sem_nsems; /* number of sems in set */ + abi_ulong sem_otime; /* last operation time */ + abi_ulong sem_ctime; /* times measured in secs */ +}; + /* * sys/shm.h */ @@ -46,6 +83,35 @@ struct bsd_shm_regions { }; /* + * sys/msg.h + */ +struct target_msqid_ds { + struct target_ipc_perm msg_perm; /* msg queue permission bits */ + abi_ulong msg_first; /* first message in the queue */ + abi_ulong msg_last; /* last message in the queue */ + abi_ulong msg_cbytes; /* # of bytes in use on the queue */ + abi_ulong msg_qnum; /* number of msgs in the queue */ + abi_ulong msg_qbytes; /* max # of bytes on the queue */ + int32_t msg_lspid; /* pid of last msgsnd() */ + int32_t msg_lrpid; /* pid of last msgrcv() */ + abi_ulong msg_stime; /* time of last msgsnd() */ + abi_ulong msg_rtime; /* time of last msgrcv() */ + abi_ulong msg_ctime; /* time of last msgctl() */ +}; + +struct target_msgbuf { + abi_long mtype; /* message type */ + char mtext[1]; /* body of message */ +}; + +/* + * sched.h + */ +struct target_sched_param { + int32_t sched_priority; +}; + +/* * sys/mman.h */ #define TARGET_FREEBSD_MAP_RESERVED0080 0x0080 /* previously misimplemented @@ -616,4 +682,19 @@ struct target_freebsd_acl { struct target_freebsd_acl_entry acl_entry[TARGET_FREEBSD_ACL_MAX_ENTRIES]; }; +/* + * sys/uuid.h + */ + +#define TARGET_UUID_NODE_LEN 6 + +struct target_uuid { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint8_t clock_seq_hi_and_reserved; + uint8_t clock_seq_low; + uint8_t node[TARGET_UUID_NODE_LEN]; +}; + #endif /* ! _SYSCALL_DEFS_H_ */ -- 1.7.8