}
#endif
+#ifdef TARGET_NR_ipc
#define N_SHM_REGIONS 32
static struct shm_region {
abi_ulong start;
abi_ulong size;
} shm_regions[N_SHM_REGIONS];
+#endif
struct target_ipc_perm
{
return ret;
}
-struct target_shmid_ds
-{
- struct target_ipc_perm shm_perm;
- abi_ulong shm_segsz;
- abi_ulong shm_atime;
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused1;
-#endif
- abi_ulong shm_dtime;
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused2;
-#endif
- abi_ulong shm_ctime;
-#if TARGET_ABI_BITS == 32
- abi_ulong __unused3;
-#endif
- int shm_cpid;
- int shm_lpid;
- abi_ulong shm_nattch;
- unsigned long int __unused4;
- unsigned long int __unused5;
-};
-
-static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
- abi_ulong target_addr)
-{
- struct target_shmid_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->shm_perm), target_addr))
- return -TARGET_EFAULT;
- __put_user(target_sd->shm_segsz, &host_sd->shm_segsz);
- __put_user(target_sd->shm_atime, &host_sd->shm_atime);
- __put_user(target_sd->shm_dtime, &host_sd->shm_dtime);
- __put_user(target_sd->shm_ctime, &host_sd->shm_ctime);
- __put_user(target_sd->shm_cpid, &host_sd->shm_cpid);
- __put_user(target_sd->shm_lpid, &host_sd->shm_lpid);
- __put_user(target_sd->shm_nattch, &host_sd->shm_nattch);
- unlock_user_struct(target_sd, target_addr, 0);
- return 0;
-}
-
-static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
- struct shmid_ds *host_sd)
-{
- struct target_shmid_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, &(host_sd->shm_perm)))
- return -TARGET_EFAULT;
- __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
- __put_user(host_sd->shm_atime, &target_sd->shm_atime);
- __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
- __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
- __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
- __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
- __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
- unlock_user_struct(target_sd, target_addr, 1);
- return 0;
-}
-
-struct target_shminfo {
- abi_ulong shmmax;
- abi_ulong shmmin;
- abi_ulong shmmni;
- abi_ulong shmseg;
- abi_ulong shmall;
-};
-
-static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
- struct shminfo *host_shminfo)
-{
- struct target_shminfo *target_shminfo;
- if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
- return -TARGET_EFAULT;
- __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
- __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
- __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
- __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
- __put_user(host_shminfo->shmall, &target_shminfo->shmall);
- unlock_user_struct(target_shminfo, target_addr, 1);
- return 0;
-}
-
-struct target_shm_info {
- int used_ids;
- abi_ulong shm_tot;
- abi_ulong shm_rss;
- abi_ulong shm_swp;
- abi_ulong swap_attempts;
- abi_ulong swap_successes;
-};
-
-static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
- struct shm_info *host_shm_info)
-{
- struct target_shm_info *target_shm_info;
- if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
- return -TARGET_EFAULT;
- __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
- __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
- __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
- __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
- __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
- __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
- unlock_user_struct(target_shm_info, target_addr, 1);
- return 0;
-}
-
-static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
-{
- struct shmid_ds dsarg;
- struct shminfo shminfo;
- struct shm_info shm_info;
- abi_long ret = -TARGET_EINVAL;
-
- cmd &= 0xff;
-
- switch(cmd) {
- case IPC_STAT:
- case IPC_SET:
- case SHM_STAT:
- if (target_to_host_shmid_ds(&dsarg, buf))
- return -TARGET_EFAULT;
- ret = get_errno(shmctl(shmid, cmd, &dsarg));
- if (host_to_target_shmid_ds(buf, &dsarg))
- return -TARGET_EFAULT;
- break;
- case IPC_INFO:
- ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
- if (host_to_target_shminfo(buf, &shminfo))
- return -TARGET_EFAULT;
- break;
- case SHM_INFO:
- ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
- if (host_to_target_shm_info(buf, &shm_info))
- return -TARGET_EFAULT;
- break;
- case IPC_RMID:
- case SHM_LOCK:
- case SHM_UNLOCK:
- ret = get_errno(shmctl(shmid, cmd, NULL));
- break;
- }
-
- return ret;
-}
-
-static inline abi_long do_shmat(int shmid, abi_ulong shmaddr, int shmflg,
- unsigned long *raddr)
-{
- abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size);
- abi_long ret;
- struct shmid_ds shm_info;
- int i;
-
- /* find out the length of the shared memory segment */
- ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
- if (is_error(ret)) {
- /* can't get length, bail out */
- return get_errno(ret);
- }
-
- mmap_lock();
-
- if (shmaddr)
- *raddr = (unsigned long) shmat(shmid, g2h(shmaddr), shmflg);
- else {
- abi_ulong mmap_start;
-
- mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
-
- if (mmap_start == -1) {
- errno = ENOMEM;
- *raddr = -1;
- } else
- *raddr = (unsigned long) shmat(shmid, g2h(mmap_start),
- shmflg | SHM_REMAP);
- }
-
- if (*raddr == -1) {
- mmap_unlock();
- return get_errno(*raddr);
- }
-
- page_set_flags(h2g(*raddr), h2g(*raddr) + shm_info.shm_segsz,
- PAGE_VALID | PAGE_READ |
- ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
-
- for (i = 0; i < N_SHM_REGIONS; i++) {
- if (shm_regions[i].start == 0) {
- shm_regions[i].start = h2g(*raddr);
- shm_regions[i].size = shm_info.shm_segsz;
- break;
- }
- }
-
- mmap_unlock();
- return 0;
-}
-
-static inline abi_long do_shmdt(abi_ulong shmaddr)
-{
- int i;
-
- for (i = 0; i < N_SHM_REGIONS; ++i) {
- if (shm_regions[i].start == shmaddr) {
- shm_regions[i].start = 0;
- page_set_flags(shmaddr, shm_regions[i].size, 0);
- break;
- }
- }
-
- return get_errno(shmdt(g2h(shmaddr)));
-}
-
#ifdef TARGET_NR_ipc
/* ??? This only works with linear mappings. */
/* do_ipc() must return target values and target errnos. */
{
int version;
abi_long ret = 0;
+ struct shmid_ds shm_info;
+ int i;
version = call >> 16;
call &= 0xffff;
break;
case IPCOP_shmat:
- switch (version) {
- default:
- {
- unsigned long raddr;
-
- ret = do_shmat(first, ptr, second, &raddr);
- if (ret)
- break;
-
- ret = put_user_ual(raddr, third);
+ {
+ abi_ulong raddr;
+ void *host_addr;
+ /* SHM_* flags are the same on all linux platforms */
+ host_addr = shmat(first, (void *)g2h(ptr), second);
+ if (host_addr == (void *)-1) {
+ ret = get_errno((long)host_addr);
break;
}
- case 1:
- ret = -TARGET_EINVAL;
- break;
+ raddr = h2g((unsigned long)host_addr);
+ /* find out the length of the shared memory segment */
+
+ ret = get_errno(shmctl(first, IPC_STAT, &shm_info));
+ if (is_error(ret)) {
+ /* can't get length, bail out */
+ shmdt(host_addr);
+ break;
+ }
+ page_set_flags(raddr, raddr + shm_info.shm_segsz,
+ PAGE_VALID | PAGE_READ |
+ ((second & SHM_RDONLY)? 0: PAGE_WRITE));
+ for (i = 0; i < N_SHM_REGIONS; ++i) {
+ if (shm_regions[i].start == 0) {
+ shm_regions[i].start = raddr;
+ shm_regions[i].size = shm_info.shm_segsz;
+ break;
+ }
+ }
+ if (put_user_ual(raddr, third))
+ return -TARGET_EFAULT;
+ ret = 0;
}
- break;
-
+ break;
case IPCOP_shmdt:
- ret = do_shmdt(ptr);
- break;
+ for (i = 0; i < N_SHM_REGIONS; ++i) {
+ if (shm_regions[i].start == ptr) {
+ shm_regions[i].start = 0;
+ page_set_flags(ptr, shm_regions[i].size, 0);
+ break;
+ }
+ }
+ ret = get_errno(shmdt((void *)g2h(ptr)));
+ break;
case IPCOP_shmget:
- ret = get_errno(shmget(first, second, third));
- break;
+ /* IPC_* flag values are the same on all linux platforms */
+ ret = get_errno(shmget(first, second, third));
+ break;
+ /* IPC_* and SHM_* command values are the same on all linux platforms */
case IPCOP_shmctl:
- ret = do_shmctl(first, second, third);
+ switch(second) {
+ case IPC_RMID:
+ case SHM_LOCK:
+ case SHM_UNLOCK:
+ ret = get_errno(shmctl(first, second, NULL));
+ break;
+ default:
+ goto unimplemented;
+ }
break;
-
default:
- gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
- ret = -TARGET_ENOSYS;
- break;
+ unimplemented:
+ gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
+ ret = -TARGET_ENOSYS;
+ break;
}
return ret;
}