Compare commits
No commits in common. "master" and "v0.1" have entirely different histories.
47
README.md
47
README.md
|
@ -3,8 +3,7 @@ only under linux (though BSD support would probably be feasable).
|
||||||
|
|
||||||
### compiling
|
### compiling
|
||||||
|
|
||||||
Configure QEMU for irix/solaris userland emulation and compile (see the original
|
Configure QEMU for irix/solaris userland emulation and compile:
|
||||||
QEMU README for further instructions):
|
|
||||||
|
|
||||||
```
|
```
|
||||||
configure --target-list=irix-linux-user,irixn32-linux-user,irix64-linux-user,solaris-linux-user
|
configure --target-list=irix-linux-user,irixn32-linux-user,irix64-linux-user,solaris-linux-user
|
||||||
|
@ -13,10 +12,31 @@ make && make install
|
||||||
|
|
||||||
### using
|
### using
|
||||||
|
|
||||||
I recommend using binfmt. I have prepared some scripts for this which you can
|
I recommend using binfmt. Prepare some wrapper scripts for each of the qemu
|
||||||
obtain from my qemu-irix-helpers repository at github. Adapt the wrapper scripts
|
binaries for irix/solaris using this template:
|
||||||
to your setup and install them somewhere in your executable path. Activate them
|
|
||||||
with the binfmt install scripts.
|
```
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
ex=$1; shift
|
||||||
|
a0=$1; shift
|
||||||
|
|
||||||
|
export QEMU_RESERVED_VA=1G
|
||||||
|
export QEMU_LD_PREFIX=<target rootfs>
|
||||||
|
export QEMU_SET_ENV=LANG=C
|
||||||
|
|
||||||
|
exec <qemu binary> -0 $a0 $ex "$@"
|
||||||
|
```
|
||||||
|
|
||||||
|
Install the binfmt (replace the QEMU* environment variables by the location of
|
||||||
|
the wrapper scripts):
|
||||||
|
|
||||||
|
```
|
||||||
|
echo :irix:M::'\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00':'\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xef':${QEMUIRIX32}:P > /proc/sys/fs/binfmt_misc/register
|
||||||
|
echo :irixn32:M::'\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20':'\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xef':${QEMUIRIXN32}:P > /proc/sys/fs/binfmt_misc/register
|
||||||
|
echo :irix64:M::'\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08':'\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff':${QEMUIRIX64}:P > /proc/sys/fs/binfmt_misc/register
|
||||||
|
echo :solaris:M::'\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02':'\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff':${QEMUSOLARIS32}:P > /proc/sys/fs/binfmt_misc/register
|
||||||
|
```
|
||||||
|
|
||||||
Now you should be able to directly execute irix/solaris binaries from the shell.
|
Now you should be able to directly execute irix/solaris binaries from the shell.
|
||||||
As a rather simple test, try:
|
As a rather simple test, try:
|
||||||
|
@ -25,19 +45,4 @@ As a rather simple test, try:
|
||||||
<target rootfs>/bin/ls
|
<target rootfs>/bin/ls
|
||||||
```
|
```
|
||||||
|
|
||||||
### notes
|
|
||||||
|
|
||||||
IRIX threading uses a local TLS storage area named PRDA which is privately mapped
|
|
||||||
into each thread at address 0x20000. qemu-irix will emulate this behaviour if
|
|
||||||
QEMU_IRIXPRDA is set in the environment. You most probably need to do so for any
|
|
||||||
IRIX software using multithreading. Be aware that this will noticably harm the
|
|
||||||
performance of the emulation since every memory access is checked for PRDA access
|
|
||||||
(AFAIK it isn't possible to emulate this directly on linux or BSD).
|
|
||||||
|
|
||||||
For conveniance I have also extended the handling of QEMU_LD_PREFIX to allow
|
|
||||||
the specification of multiple paths separated by ':'. That way you can keep the
|
|
||||||
target os root separate from additional software. Moreover, for a noticable
|
|
||||||
speed gain at qemu startup, QEMU_LD_PREFIX is not pre-scanned anymore. Instead,
|
|
||||||
it is now caching any directories accessed by the emulated program.
|
|
||||||
|
|
||||||
send bug reports, fixes etc to Kai-Uwe Bloem (<derkub@gmail.com>)
|
send bug reports, fixes etc to Kai-Uwe Bloem (<derkub@gmail.com>)
|
||||||
|
|
|
@ -6836,7 +6836,6 @@ case "$target_name" in
|
||||||
solaris)
|
solaris)
|
||||||
TARGET_ARCH=sparc
|
TARGET_ARCH=sparc
|
||||||
TARGET_ABI_DIR=solaris
|
TARGET_ABI_DIR=solaris
|
||||||
TARGET_BASE_ARCH=sparc
|
|
||||||
echo "TARGET_ABI_SOLARIS=y" >> $config_target_mak
|
echo "TARGET_ABI_SOLARIS=y" >> $config_target_mak
|
||||||
;;
|
;;
|
||||||
solaris64)
|
solaris64)
|
||||||
|
|
|
@ -2067,8 +2067,6 @@ abi_ulong sgi_map_elf_image(int image_fd, struct elf_phdr *phdr, int phnum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mmap_lock();
|
|
||||||
|
|
||||||
/* The image indicates that it can be loaded anywhere. Find a
|
/* The image indicates that it can be loaded anywhere. Find a
|
||||||
location that can hold the memory space required. If the
|
location that can hold the memory space required. If the
|
||||||
image is pre-linked, LOADDR will be non-zero. Since we do
|
image is pre-linked, LOADDR will be non-zero. Since we do
|
||||||
|
@ -2115,13 +2113,9 @@ abi_ulong sgi_map_elf_image(int image_fd, struct elf_phdr *phdr, int phnum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mmap_unlock();
|
|
||||||
|
|
||||||
return load_bias + phdr[0].p_vaddr;
|
return load_bias + phdr[0].p_vaddr;
|
||||||
|
|
||||||
exit_perror:
|
exit_perror:
|
||||||
mmap_unlock();
|
|
||||||
|
|
||||||
errmsg = strerror(errno);
|
errmsg = strerror(errno);
|
||||||
fprintf(stderr, "error in syssgi elfmap: %s\n", errmsg);
|
fprintf(stderr, "error in syssgi elfmap: %s\n", errmsg);
|
||||||
return -ENOEXEC;
|
return -ENOEXEC;
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
IOCTL(TIOCSETD, IOC_W, MK_PTR(TYPE_INT))
|
IOCTL(TIOCSETD, IOC_W, MK_PTR(TYPE_INT))
|
||||||
IOCTL(TIOCGPTN, IOC_R, MK_PTR(TYPE_INT))
|
IOCTL(TIOCGPTN, IOC_R, MK_PTR(TYPE_INT))
|
||||||
IOCTL(TIOCSPTLCK, IOC_W, MK_PTR(TYPE_INT))
|
IOCTL(TIOCSPTLCK, IOC_W, MK_PTR(TYPE_INT))
|
||||||
#if defined TIOCGPTPEER && defined TARGET_TIOCGPTPEER
|
#ifdef TIOCGPTPEER
|
||||||
IOCTL_SPECIAL(TIOCGPTPEER, 0, do_ioctl_tiocgptpeer, TYPE_INT)
|
IOCTL_SPECIAL(TIOCGPTPEER, 0, do_ioctl_tiocgptpeer, TYPE_INT)
|
||||||
#endif
|
#endif
|
||||||
IOCTL(FIOCLEX, 0, TYPE_NULL)
|
IOCTL(FIOCLEX, 0, TYPE_NULL)
|
||||||
|
|
|
@ -258,7 +258,6 @@
|
||||||
/* SGI specific syssgi calls */
|
/* SGI specific syssgi calls */
|
||||||
#define TARGET_NR_syssgi_sysid (1)
|
#define TARGET_NR_syssgi_sysid (1)
|
||||||
#define TARGET_NR_syssgi_elfmap (68)
|
#define TARGET_NR_syssgi_elfmap (68)
|
||||||
#define TARGET_NR_syssgi_getprocattr (85)
|
|
||||||
#define TARGET_NR_syssgi_rldenv (92)
|
#define TARGET_NR_syssgi_rldenv (92)
|
||||||
#define TARGET_NR_syssgi_tosstsave (108)
|
#define TARGET_NR_syssgi_tosstsave (108)
|
||||||
#define TARGET_NR_syssgi_fdhi (109)
|
#define TARGET_NR_syssgi_fdhi (109)
|
||||||
|
|
|
@ -40,7 +40,6 @@
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/swap.h>
|
#include <sys/swap.h>
|
||||||
#include <linux/capability.h>
|
#include <linux/capability.h>
|
||||||
#include <linux/sockios.h>
|
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <sys/timex.h>
|
#include <sys/timex.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
@ -259,9 +258,15 @@ static inline type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,
|
||||||
#define TARGET_NR__llseek TARGET_NR_llseek
|
#define TARGET_NR__llseek TARGET_NR_llseek
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define __NR_sys_gettid __NR_gettid
|
#ifdef __NR_gettid
|
||||||
_syscall0(int, sys_gettid)
|
_syscall0(int, gettid)
|
||||||
|
#else
|
||||||
|
/* This is a replacement for the host gettid() and must return a host
|
||||||
|
errno. */
|
||||||
|
static int gettid(void) {
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#if defined(TARGET_NR_getdents) && defined(__NR_getdents)
|
#if defined(TARGET_NR_getdents) && defined(__NR_getdents)
|
||||||
_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
|
_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
|
||||||
#endif
|
#endif
|
||||||
|
@ -5782,7 +5787,7 @@ static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined TIOCGPTPEER && defined TARGET_TIOCGPTPEER
|
#ifdef TIOCGPTPEER
|
||||||
static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
|
static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||||
int fd, int cmd, abi_long arg)
|
int fd, int cmd, abi_long arg)
|
||||||
{
|
{
|
||||||
|
@ -6442,7 +6447,7 @@ static void *clone_func(void *arg)
|
||||||
cpu = ENV_GET_CPU(env);
|
cpu = ENV_GET_CPU(env);
|
||||||
thread_cpu = cpu;
|
thread_cpu = cpu;
|
||||||
ts = (TaskState *)cpu->opaque;
|
ts = (TaskState *)cpu->opaque;
|
||||||
info->tid = sys_gettid();
|
info->tid = gettid();
|
||||||
task_settid(ts);
|
task_settid(ts);
|
||||||
#ifdef TARGET_ABI_IRIX
|
#ifdef TARGET_ABI_IRIX
|
||||||
/* TODO: which fields in the PRDA are filled in by the IRIX kernel? */
|
/* TODO: which fields in the PRDA are filled in by the IRIX kernel? */
|
||||||
|
@ -6604,9 +6609,9 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
|
||||||
mapping. We can't repeat the spinlock hack used above because
|
mapping. We can't repeat the spinlock hack used above because
|
||||||
the child process gets its own copy of the lock. */
|
the child process gets its own copy of the lock. */
|
||||||
if (flags & CLONE_CHILD_SETTID)
|
if (flags & CLONE_CHILD_SETTID)
|
||||||
put_user_u32(sys_gettid(), child_tidptr);
|
put_user_u32(gettid(), child_tidptr);
|
||||||
if (flags & CLONE_PARENT_SETTID)
|
if (flags & CLONE_PARENT_SETTID)
|
||||||
put_user_u32(sys_gettid(), parent_tidptr);
|
put_user_u32(gettid(), parent_tidptr);
|
||||||
if (flags & CLONE_SETTLS)
|
if (flags & CLONE_SETTLS)
|
||||||
cpu_set_tls (env, newtls);
|
cpu_set_tls (env, newtls);
|
||||||
if (flags & CLONE_CHILD_CLEARTID)
|
if (flags & CLONE_CHILD_CLEARTID)
|
||||||
|
@ -8861,11 +8866,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||||
#ifdef TARGET_NR_stime /* not on alpha */
|
#ifdef TARGET_NR_stime /* not on alpha */
|
||||||
case TARGET_NR_stime:
|
case TARGET_NR_stime:
|
||||||
{
|
{
|
||||||
struct timespec ts;
|
time_t host_time;
|
||||||
ts.tv_nsec = 0;
|
if (get_user_sal(host_time, arg1))
|
||||||
if (get_user_sal(ts.tv_sec, arg1))
|
|
||||||
goto efault;
|
goto efault;
|
||||||
ret = get_errno(clock_settime(CLOCK_REALTIME, &ts));
|
ret = get_errno(stime(&host_time));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -12584,7 +12588,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||||
#endif
|
#endif
|
||||||
#ifdef TARGET_NR_gettid
|
#ifdef TARGET_NR_gettid
|
||||||
case TARGET_NR_gettid:
|
case TARGET_NR_gettid:
|
||||||
ret = get_errno(sys_gettid());
|
ret = get_errno(gettid());
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef TARGET_NR_readahead
|
#ifdef TARGET_NR_readahead
|
||||||
|
@ -13857,10 +13861,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||||
if (arg4) {
|
if (arg4) {
|
||||||
if (copy_from_user_timeval(&tv[0], arg4) ||
|
if (copy_from_user_timeval(&tv[0], arg4) ||
|
||||||
copy_from_user_timeval(&tv[1],
|
copy_from_user_timeval(&tv[1],
|
||||||
arg4 + sizeof(struct target_timeval))) {
|
arg4 + sizeof(struct target_timeval)))
|
||||||
unlock_user(p, arg3, 0);
|
unlock_user(p, arg3, 0);
|
||||||
goto efault;
|
goto efault;
|
||||||
}
|
|
||||||
tvp = tv;
|
tvp = tv;
|
||||||
} else {
|
} else {
|
||||||
tvp = NULL;
|
tvp = NULL;
|
||||||
|
@ -14603,7 +14606,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
|
||||||
case TARGET_NR_syssgi_rldenv:
|
case TARGET_NR_syssgi_rldenv:
|
||||||
case TARGET_NR_syssgi_tosstsave:
|
case TARGET_NR_syssgi_tosstsave:
|
||||||
case TARGET_NR_syssgi_fpbcopy:
|
case TARGET_NR_syssgi_fpbcopy:
|
||||||
case TARGET_NR_syssgi_getprocattr: /* ? 2nd=string 3rd=result ptr */
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
case TARGET_NR_syssgi_setgroups:
|
case TARGET_NR_syssgi_setgroups:
|
||||||
|
|
|
@ -1622,7 +1622,7 @@ struct target_stat {
|
||||||
abi_long target_st_ctime;
|
abi_long target_st_ctime;
|
||||||
abi_ulong __unused3;
|
abi_ulong __unused3;
|
||||||
abi_int st_blksize;
|
abi_int st_blksize;
|
||||||
abi_llong st_blocks;
|
int64_t st_blocks;
|
||||||
char st_fstype[16];
|
char st_fstype[16];
|
||||||
abi_long __unused4[8];
|
abi_long __unused4[8];
|
||||||
};
|
};
|
||||||
|
@ -1631,14 +1631,14 @@ struct target_stat {
|
||||||
struct target_stat64 {
|
struct target_stat64 {
|
||||||
abi_ulong st_dev;
|
abi_ulong st_dev;
|
||||||
abi_long st_pad1[3];
|
abi_long st_pad1[3];
|
||||||
abi_ullong st_ino;
|
uint64_t st_ino;
|
||||||
abi_uint st_mode;
|
abi_uint st_mode;
|
||||||
abi_uint st_nlink;
|
abi_uint st_nlink;
|
||||||
abi_int st_uid;
|
abi_int st_uid;
|
||||||
abi_int st_gid;
|
abi_int st_gid;
|
||||||
abi_ulong st_rdev;
|
abi_ulong st_rdev;
|
||||||
abi_long st_pad2[2];
|
abi_long st_pad2[2];
|
||||||
abi_llong st_size;
|
int64_t st_size;
|
||||||
abi_long target_st_atime;
|
abi_long target_st_atime;
|
||||||
abi_ulong __unused1;
|
abi_ulong __unused1;
|
||||||
abi_long target_st_mtime;
|
abi_long target_st_mtime;
|
||||||
|
@ -1646,7 +1646,7 @@ struct target_stat64 {
|
||||||
abi_long target_st_ctime;
|
abi_long target_st_ctime;
|
||||||
abi_ulong __unused3;
|
abi_ulong __unused3;
|
||||||
abi_int st_blksize;
|
abi_int st_blksize;
|
||||||
abi_llong st_blocks;
|
int64_t st_blocks;
|
||||||
char st_fstype[16];
|
char st_fstype[16];
|
||||||
abi_long __unused4[8];
|
abi_long __unused4[8];
|
||||||
};
|
};
|
||||||
|
@ -1977,7 +1977,7 @@ struct target_stat {
|
||||||
struct target_stat64 {
|
struct target_stat64 {
|
||||||
uint32_t st_dev;
|
uint32_t st_dev;
|
||||||
abi_long st_pad0[3]; /* Reserved for st_dev expansion */
|
abi_long st_pad0[3]; /* Reserved for st_dev expansion */
|
||||||
abi_ullong st_ino;
|
uint64_t st_ino;
|
||||||
|
|
||||||
uint32_t st_mode;
|
uint32_t st_mode;
|
||||||
uint32_t st_nlink;
|
uint32_t st_nlink;
|
||||||
|
@ -1987,7 +1987,7 @@ struct target_stat64 {
|
||||||
|
|
||||||
uint32_t st_rdev;
|
uint32_t st_rdev;
|
||||||
abi_long st_pad1[2]; /* Reserved for st_rdev expansion */
|
abi_long st_pad1[2]; /* Reserved for st_rdev expansion */
|
||||||
abi_llong st_size;
|
int64_t st_size;
|
||||||
abi_long st_pad2;
|
abi_long st_pad2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2004,7 +2004,7 @@ struct target_stat64 {
|
||||||
abi_long target_st_ctime_nsec;
|
abi_long target_st_ctime_nsec;
|
||||||
|
|
||||||
abi_long st_blksize;
|
abi_long st_blksize;
|
||||||
abi_llong st_blocks;
|
int64_t st_blocks;
|
||||||
char st_fstype[16];
|
char st_fstype[16];
|
||||||
abi_long st_projid;
|
abi_long st_projid;
|
||||||
abi_long st_pad[7];
|
abi_long st_pad[7];
|
||||||
|
|
|
@ -2696,12 +2696,6 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
|
||||||
case INDEX_op_x86_packus_vec:
|
case INDEX_op_x86_packus_vec:
|
||||||
insn = packus_insn[vece];
|
insn = packus_insn[vece];
|
||||||
goto gen_simd;
|
goto gen_simd;
|
||||||
#if TCG_TARGET_REG_BITS == 32
|
|
||||||
case INDEX_op_dup2_vec:
|
|
||||||
/* Constraints have already placed both 32-bit inputs in xmm regs. */
|
|
||||||
insn = OPC_PUNPCKLDQ;
|
|
||||||
goto gen_simd;
|
|
||||||
#endif
|
|
||||||
gen_simd:
|
gen_simd:
|
||||||
tcg_debug_assert(insn != OPC_UD2);
|
tcg_debug_assert(insn != OPC_UD2);
|
||||||
if (type == TCG_TYPE_V256) {
|
if (type == TCG_TYPE_V256) {
|
||||||
|
@ -3051,9 +3045,6 @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
|
||||||
case INDEX_op_x86_vperm2i128_vec:
|
case INDEX_op_x86_vperm2i128_vec:
|
||||||
case INDEX_op_x86_punpckl_vec:
|
case INDEX_op_x86_punpckl_vec:
|
||||||
case INDEX_op_x86_punpckh_vec:
|
case INDEX_op_x86_punpckh_vec:
|
||||||
#if TCG_TARGET_REG_BITS == 32
|
|
||||||
case INDEX_op_dup2_vec:
|
|
||||||
#endif
|
|
||||||
return &x_x_x;
|
return &x_x_x;
|
||||||
case INDEX_op_dup_vec:
|
case INDEX_op_dup_vec:
|
||||||
case INDEX_op_shli_vec:
|
case INDEX_op_shli_vec:
|
||||||
|
|
Loading…
Reference in New Issue