summaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-03-22 15:23:14 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-03-22 15:23:14 +0000
commitdab2ed991a49678fbd4d45ff1b328340a77057df (patch)
tree0c587c5ef62faa0c3bf9b39a7ce9281c0a63e2b2 /linux-user
parente591824733ec698d92d1f09c2ffb9b86b799d6da (diff)
downloadqemu-dab2ed991a49678fbd4d45ff1b328340a77057df.tar.gz
better 16 bit code support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@38 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/main.c8
-rw-r--r--linux-user/syscall.c37
-rw-r--r--linux-user/syscall_defs.h16
3 files changed, 48 insertions, 13 deletions
diff --git a/linux-user/main.c b/linux-user/main.c
index 45e81b207c..3222629b27 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -179,7 +179,7 @@ int main(int argc, char **argv)
env->regs[R_EDI] = regs->edi;
env->regs[R_EBP] = regs->ebp;
env->regs[R_ESP] = regs->esp;
- env->pc = regs->eip;
+ env->eip = regs->eip;
/* linux segment setup */
env->gdt.base = (void *)gdt_table;
@@ -198,12 +198,12 @@ int main(int argc, char **argv)
uint8_t *pc;
err = cpu_x86_exec(env);
+ pc = env->seg_cache[R_CS].base + env->eip;
switch(err) {
case EXCP0D_GPF:
- pc = (uint8_t *)env->pc;
if (pc[0] == 0xcd && pc[1] == 0x80) {
/* syscall */
- env->pc += 2;
+ env->eip += 2;
env->regs[R_EAX] = do_syscall(env,
env->regs[R_EAX],
env->regs[R_EBX],
@@ -219,7 +219,7 @@ int main(int argc, char **argv)
default:
trap_error:
fprintf(stderr, "0x%08lx: Unknown exception %d, aborting\n",
- (long)env->pc, err);
+ (long)pc, err);
abort();
}
}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index c0bee47f76..afdf189676 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -53,6 +53,7 @@
#include <linux/cdrom.h>
#include <linux/hdreg.h>
#include <linux/soundcard.h>
+#include <linux/dirent.h>
#include "gemu.h"
@@ -63,13 +64,6 @@
#define PAGE_MASK ~(PAGE_SIZE - 1)
#endif
-struct dirent {
- long d_ino;
- long d_off;
- unsigned short d_reclen;
- char d_name[256]; /* We must not include limits.h! */
-};
-
//#include <linux/msdos_fs.h>
#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2])
@@ -86,6 +80,7 @@ struct dirent {
#define __NR_sys_statfs __NR_statfs
#define __NR_sys_fstatfs __NR_fstatfs
#define __NR_sys_getdents __NR_getdents
+#define __NR_sys_getdents64 __NR_getdents64
#ifdef __NR_gettid
_syscall0(int, gettid)
@@ -97,6 +92,7 @@ static int gettid(void) {
_syscall1(int,sys_uname,struct new_utsname *,buf)
_syscall2(int,sys_getcwd1,char *,buf,size_t,size)
_syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count);
+_syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count);
_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
loff_t *, res, uint, wh);
_syscall2(int,sys_statfs,const char *,path,struct kernel_statfs *,buf)
@@ -1005,7 +1001,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
ret = get_errno(setsid());
break;
case TARGET_NR_sigaction:
-#if 0
+#if 1
{
ret = 0;
}
@@ -1336,6 +1332,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
{
struct dirent *dirp = (void *)arg2;
long count = arg3;
+
ret = get_errno(sys_getdents(arg1, dirp, count));
if (!is_error(ret)) {
struct dirent *de;
@@ -1355,6 +1352,29 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
}
}
break;
+ case TARGET_NR_getdents64:
+ {
+ struct dirent64 *dirp = (void *)arg2;
+ long count = arg3;
+ ret = get_errno(sys_getdents64(arg1, dirp, count));
+ if (!is_error(ret)) {
+ struct dirent64 *de;
+ int len = ret;
+ int reclen;
+ de = dirp;
+ while (len > 0) {
+ reclen = tswap16(de->d_reclen);
+ if (reclen > len)
+ break;
+ de->d_reclen = reclen;
+ tswap64s(&de->d_ino);
+ tswap64s(&de->d_off);
+ de = (struct dirent64 *)((char *)de + reclen);
+ len -= reclen;
+ }
+ }
+ }
+ break;
case TARGET_NR__newselect:
ret = do_select(arg1, (void *)arg2, (void *)arg3, (void *)arg4,
(void *)arg5);
@@ -1519,7 +1539,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
case TARGET_NR_pivot_root:
case TARGET_NR_mincore:
case TARGET_NR_madvise:
- case TARGET_NR_getdents64:
goto unimplemented;
#if TARGET_LONG_BITS == 32
case TARGET_NR_fcntl64:
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index dc44272dbb..8b2d6bd756 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -75,6 +75,22 @@ struct kernel_statfs {
int f_spare[6];
};
+struct target_dirent {
+ target_long d_ino;
+ target_long d_off;
+ unsigned short d_reclen;
+ char d_name[256]; /* We must not include limits.h! */
+};
+
+struct target_dirent64 {
+ uint64_t d_ino;
+ int64_t d_off;
+ unsigned short d_reclen;
+ unsigned char d_type;
+ char d_name[256];
+};
+
+
/* mostly generic signal stuff */
#define TARGET_SIG_DFL ((target_long)0) /* default signal handling */
#define TARGET_SIG_IGN ((target_long)1) /* ignore signal */