Commit 5cd4393b14b68a4e80a3ffa74c04efff2b9590a5

Authored by bellard
1 parent 7ed601b7

first vm86 support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@60 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 162 additions and 33 deletions
linux-user/syscall.c
@@ -103,10 +103,10 @@ extern int personality(int); @@ -103,10 +103,10 @@ extern int personality(int);
103 extern int flock(int, int); 103 extern int flock(int, int);
104 extern int setfsuid(int); 104 extern int setfsuid(int);
105 extern int setfsgid(int); 105 extern int setfsgid(int);
106 -extern int setresuid(int,int,int);  
107 -extern int getresuid(int *,int *,int *);  
108 -extern int setresgid(int,int,int);  
109 -extern int getresgid(int *,int *,int *); 106 +extern int setresuid(uid_t, uid_t, uid_t);
  107 +extern int getresuid(uid_t *, uid_t *, uid_t *);
  108 +extern int setresgid(gid_t, gid_t, gid_t);
  109 +extern int getresgid(gid_t *, gid_t *, gid_t *);
110 110
111 static inline long get_errno(long ret) 111 static inline long get_errno(long ret)
112 { 112 {
@@ -210,14 +210,14 @@ static inline void host_to_target_fds(target_long *target_fds, @@ -210,14 +210,14 @@ static inline void host_to_target_fds(target_long *target_fds,
210 } 210 }
211 211
212 static inline void target_to_host_timeval(struct timeval *tv, 212 static inline void target_to_host_timeval(struct timeval *tv,
213 - struct target_timeval *target_tv) 213 + const struct target_timeval *target_tv)
214 { 214 {
215 tv->tv_sec = tswapl(target_tv->tv_sec); 215 tv->tv_sec = tswapl(target_tv->tv_sec);
216 tv->tv_usec = tswapl(target_tv->tv_usec); 216 tv->tv_usec = tswapl(target_tv->tv_usec);
217 } 217 }
218 218
219 static inline void host_to_target_timeval(struct target_timeval *target_tv, 219 static inline void host_to_target_timeval(struct target_timeval *target_tv,
220 - struct timeval *tv) 220 + const struct timeval *tv)
221 { 221 {
222 target_tv->tv_sec = tswapl(tv->tv_sec); 222 target_tv->tv_sec = tswapl(tv->tv_sec);
223 target_tv->tv_usec = tswapl(tv->tv_usec); 223 target_tv->tv_usec = tswapl(tv->tv_usec);
@@ -238,8 +238,7 @@ static long do_select(long n, @@ -238,8 +238,7 @@ static long do_select(long n,
238 efds_ptr = target_to_host_fds(&efds, target_efds, n); 238 efds_ptr = target_to_host_fds(&efds, target_efds, n);
239 239
240 if (target_tv) { 240 if (target_tv) {
241 - tv.tv_sec = tswapl(target_tv->tv_sec);  
242 - tv.tv_usec = tswapl(target_tv->tv_usec); 241 + target_to_host_timeval(&tv, target_tv);
243 tv_ptr = &tv; 242 tv_ptr = &tv;
244 } else { 243 } else {
245 tv_ptr = NULL; 244 tv_ptr = NULL;
@@ -251,8 +250,7 @@ static long do_select(long n, @@ -251,8 +250,7 @@ static long do_select(long n,
251 host_to_target_fds(target_efds, efds_ptr, n); 250 host_to_target_fds(target_efds, efds_ptr, n);
252 251
253 if (target_tv) { 252 if (target_tv) {
254 - target_tv->tv_sec = tswapl(tv.tv_sec);  
255 - target_tv->tv_usec = tswapl(tv.tv_usec); 253 + host_to_target_timeval(target_tv, &tv);
256 } 254 }
257 } 255 }
258 return ret; 256 return ret;
@@ -755,7 +753,7 @@ install: @@ -755,7 +753,7 @@ install:
755 } 753 }
756 754
757 /* specific and weird i386 syscalls */ 755 /* specific and weird i386 syscalls */
758 -int gemu_modify_ldt(CPUX86State *env, int func, void *ptr, unsigned long bytecount) 756 +int do_modify_ldt(CPUX86State *env, int func, void *ptr, unsigned long bytecount)
759 { 757 {
760 int ret = -ENOSYS; 758 int ret = -ENOSYS;
761 759
@@ -773,6 +771,79 @@ int gemu_modify_ldt(CPUX86State *env, int func, void *ptr, unsigned long bytecou @@ -773,6 +771,79 @@ int gemu_modify_ldt(CPUX86State *env, int func, void *ptr, unsigned long bytecou
773 return ret; 771 return ret;
774 } 772 }
775 773
  774 +/* vm86 emulation */
  775 +
  776 +#define SAFE_MASK (0xDD5)
  777 +
  778 +int do_vm86(CPUX86State *env, long subfunction,
  779 + struct target_vm86plus_struct * target_v86)
  780 +{
  781 + TaskState *ts = env->opaque;
  782 + int ret;
  783 +
  784 + switch (subfunction) {
  785 + case TARGET_VM86_REQUEST_IRQ:
  786 + case TARGET_VM86_FREE_IRQ:
  787 + case TARGET_VM86_GET_IRQ_BITS:
  788 + case TARGET_VM86_GET_AND_RESET_IRQ:
  789 + gemu_log("qemu: unsupported vm86 subfunction (%ld)\n", subfunction);
  790 + ret = -EINVAL;
  791 + goto out;
  792 + case TARGET_VM86_PLUS_INSTALL_CHECK:
  793 + /* NOTE: on old vm86 stuff this will return the error
  794 + from verify_area(), because the subfunction is
  795 + interpreted as (invalid) address to vm86_struct.
  796 + So the installation check works.
  797 + */
  798 + ret = 0;
  799 + goto out;
  800 + }
  801 +
  802 + ts->target_v86 = target_v86;
  803 +
  804 + /* save current CPU regs */
  805 + ts->vm86_saved_regs.eax = 0; /* default vm86 syscall return code */
  806 + ts->vm86_saved_regs.ebx = env->regs[R_EBX];
  807 + ts->vm86_saved_regs.ecx = env->regs[R_ECX];
  808 + ts->vm86_saved_regs.edx = env->regs[R_EDX];
  809 + ts->vm86_saved_regs.esi = env->regs[R_ESI];
  810 + ts->vm86_saved_regs.edi = env->regs[R_EDI];
  811 + ts->vm86_saved_regs.ebp = env->regs[R_EBP];
  812 + ts->vm86_saved_regs.esp = env->regs[R_ESP];
  813 + ts->vm86_saved_regs.eflags = env->eflags;
  814 + ts->vm86_saved_regs.eip = env->eip;
  815 + ts->vm86_saved_regs.cs = env->segs[R_CS];
  816 + ts->vm86_saved_regs.ss = env->segs[R_SS];
  817 + ts->vm86_saved_regs.ds = env->segs[R_DS];
  818 + ts->vm86_saved_regs.es = env->segs[R_ES];
  819 + ts->vm86_saved_regs.fs = env->segs[R_FS];
  820 + ts->vm86_saved_regs.gs = env->segs[R_GS];
  821 +
  822 + /* build vm86 CPU state */
  823 + env->eflags = (env->eflags & ~SAFE_MASK) |
  824 + (tswap32(target_v86->regs.eflags) & SAFE_MASK) | VM_MASK;
  825 +
  826 + env->regs[R_EBX] = tswap32(target_v86->regs.ebx);
  827 + env->regs[R_ECX] = tswap32(target_v86->regs.ecx);
  828 + env->regs[R_EDX] = tswap32(target_v86->regs.edx);
  829 + env->regs[R_ESI] = tswap32(target_v86->regs.esi);
  830 + env->regs[R_EDI] = tswap32(target_v86->regs.edi);
  831 + env->regs[R_EBP] = tswap32(target_v86->regs.ebp);
  832 + env->regs[R_ESP] = tswap32(target_v86->regs.esp);
  833 + env->eip = tswap32(target_v86->regs.eip);
  834 + cpu_x86_load_seg(env, R_CS, tswap16(target_v86->regs.cs));
  835 + cpu_x86_load_seg(env, R_SS, tswap16(target_v86->regs.ss));
  836 + cpu_x86_load_seg(env, R_DS, tswap16(target_v86->regs.ds));
  837 + cpu_x86_load_seg(env, R_ES, tswap16(target_v86->regs.es));
  838 + cpu_x86_load_seg(env, R_FS, tswap16(target_v86->regs.fs));
  839 + cpu_x86_load_seg(env, R_GS, tswap16(target_v86->regs.gs));
  840 + ret = tswap32(target_v86->regs.eax); /* eax will be restored at
  841 + the end of the syscall */
  842 + /* now the virtual CPU is ready for vm86 execution ! */
  843 + out:
  844 + return ret;
  845 +}
  846 +
776 /* this stack is the equivalent of the kernel stack associated with a 847 /* this stack is the equivalent of the kernel stack associated with a
777 thread/process */ 848 thread/process */
778 #define NEW_STACK_SIZE 8192 849 #define NEW_STACK_SIZE 8192
@@ -788,19 +859,26 @@ static int clone_func(void *arg) @@ -788,19 +859,26 @@ static int clone_func(void *arg)
788 int do_fork(CPUX86State *env, unsigned int flags, unsigned long newsp) 859 int do_fork(CPUX86State *env, unsigned int flags, unsigned long newsp)
789 { 860 {
790 int ret; 861 int ret;
  862 + TaskState *ts;
791 uint8_t *new_stack; 863 uint8_t *new_stack;
792 CPUX86State *new_env; 864 CPUX86State *new_env;
793 865
794 if (flags & CLONE_VM) { 866 if (flags & CLONE_VM) {
795 if (!newsp) 867 if (!newsp)
796 newsp = env->regs[R_ESP]; 868 newsp = env->regs[R_ESP];
797 - new_stack = malloc(NEW_STACK_SIZE);  
798 - 869 + ts = malloc(sizeof(TaskState) + NEW_STACK_SIZE);
  870 + memset(ts, 0, sizeof(TaskState));
  871 + new_stack = ts->stack;
  872 + ts->used = 1;
  873 + /* add in task state list */
  874 + ts->next = first_task_state;
  875 + first_task_state = ts;
799 /* we create a new CPU instance. */ 876 /* we create a new CPU instance. */
800 new_env = cpu_x86_init(); 877 new_env = cpu_x86_init();
801 memcpy(new_env, env, sizeof(CPUX86State)); 878 memcpy(new_env, env, sizeof(CPUX86State));
802 new_env->regs[R_ESP] = newsp; 879 new_env->regs[R_ESP] = newsp;
803 new_env->regs[R_EAX] = 0; 880 new_env->regs[R_EAX] = 0;
  881 + new_env->opaque = ts;
804 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env); 882 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
805 } else { 883 } else {
806 /* if no CLONE_VM, we consider it is a fork */ 884 /* if no CLONE_VM, we consider it is a fork */
@@ -1281,8 +1359,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1281,8 +1359,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1281 struct timeval tv; 1359 struct timeval tv;
1282 ret = get_errno(gettimeofday(&tv, NULL)); 1360 ret = get_errno(gettimeofday(&tv, NULL));
1283 if (!is_error(ret)) { 1361 if (!is_error(ret)) {
1284 - target_tv->tv_sec = tswapl(tv.tv_sec);  
1285 - target_tv->tv_usec = tswapl(tv.tv_usec); 1362 + host_to_target_timeval(target_tv, &tv);
1286 } 1363 }
1287 } 1364 }
1288 break; 1365 break;
@@ -1290,8 +1367,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1290,8 +1367,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1290 { 1367 {
1291 struct target_timeval *target_tv = (void *)arg1; 1368 struct target_timeval *target_tv = (void *)arg1;
1292 struct timeval tv; 1369 struct timeval tv;
1293 - tv.tv_sec = tswapl(target_tv->tv_sec);  
1294 - tv.tv_usec = tswapl(target_tv->tv_usec); 1370 + target_to_host_timeval(&tv, target_tv);
1295 ret = get_errno(settimeofday(&tv, NULL)); 1371 ret = get_errno(settimeofday(&tv, NULL));
1296 } 1372 }
1297 break; 1373 break;
@@ -1487,8 +1563,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1487,8 +1563,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1487 break; 1563 break;
1488 case TARGET_NR_idle: 1564 case TARGET_NR_idle:
1489 goto unimplemented; 1565 goto unimplemented;
1490 - case TARGET_NR_vm86old:  
1491 - goto unimplemented;  
1492 case TARGET_NR_wait4: 1566 case TARGET_NR_wait4:
1493 { 1567 {
1494 int status; 1568 int status;
@@ -1548,7 +1622,12 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1548,7 +1622,12 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1548 break; 1622 break;
1549 #ifdef TARGET_I386 1623 #ifdef TARGET_I386
1550 case TARGET_NR_modify_ldt: 1624 case TARGET_NR_modify_ldt:
1551 - ret = get_errno(gemu_modify_ldt(cpu_env, arg1, (void *)arg2, arg3)); 1625 + ret = get_errno(do_modify_ldt(cpu_env, arg1, (void *)arg2, arg3));
  1626 + break;
  1627 + case TARGET_NR_vm86old:
  1628 + goto unimplemented;
  1629 + case TARGET_NR_vm86:
  1630 + ret = do_vm86(cpu_env, arg1, (void *)arg2);
1552 break; 1631 break;
1553 #endif 1632 #endif
1554 case TARGET_NR_adjtimex: 1633 case TARGET_NR_adjtimex:
@@ -1652,13 +1731,13 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1652,13 +1731,13 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1652 1731
1653 pfd = alloca(sizeof(struct pollfd) * nfds); 1732 pfd = alloca(sizeof(struct pollfd) * nfds);
1654 for(i = 0; i < nfds; i++) { 1733 for(i = 0; i < nfds; i++) {
1655 - pfd->fd = tswap32(target_pfd->fd);  
1656 - pfd->events = tswap16(target_pfd->events); 1734 + pfd[i].fd = tswap32(target_pfd[i].fd);
  1735 + pfd[i].events = tswap16(target_pfd[i].events);
1657 } 1736 }
1658 ret = get_errno(poll(pfd, nfds, timeout)); 1737 ret = get_errno(poll(pfd, nfds, timeout));
1659 if (!is_error(ret)) { 1738 if (!is_error(ret)) {
1660 for(i = 0; i < nfds; i++) { 1739 for(i = 0; i < nfds; i++) {
1661 - target_pfd->revents = tswap16(pfd->revents); 1740 + target_pfd[i].revents = tswap16(pfd[i].revents);
1662 } 1741 }
1663 } 1742 }
1664 } 1743 }
@@ -1702,25 +1781,59 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1702,25 +1781,59 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1702 ret = get_errno(getsid(arg1)); 1781 ret = get_errno(getsid(arg1));
1703 break; 1782 break;
1704 case TARGET_NR_fdatasync: 1783 case TARGET_NR_fdatasync:
1705 - goto unimplemented; 1784 + ret = get_errno(fdatasync(arg1));
  1785 + break;
1706 case TARGET_NR__sysctl: 1786 case TARGET_NR__sysctl:
1707 goto unimplemented; 1787 goto unimplemented;
1708 case TARGET_NR_sched_setparam: 1788 case TARGET_NR_sched_setparam:
1709 - goto unimplemented; 1789 + {
  1790 + struct sched_param *target_schp = (void *)arg2;
  1791 + struct sched_param schp;
  1792 + schp.sched_priority = tswap32(target_schp->sched_priority);
  1793 + ret = get_errno(sched_setparam(arg1, &schp));
  1794 + }
  1795 + break;
1710 case TARGET_NR_sched_getparam: 1796 case TARGET_NR_sched_getparam:
1711 - goto unimplemented; 1797 + {
  1798 + struct sched_param *target_schp = (void *)arg2;
  1799 + struct sched_param schp;
  1800 + ret = get_errno(sched_getparam(arg1, &schp));
  1801 + if (!is_error(ret)) {
  1802 + target_schp->sched_priority = tswap32(schp.sched_priority);
  1803 + }
  1804 + }
  1805 + break;
1712 case TARGET_NR_sched_setscheduler: 1806 case TARGET_NR_sched_setscheduler:
1713 - goto unimplemented; 1807 + {
  1808 + struct sched_param *target_schp = (void *)arg3;
  1809 + struct sched_param schp;
  1810 + schp.sched_priority = tswap32(target_schp->sched_priority);
  1811 + ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
  1812 + }
  1813 + break;
1714 case TARGET_NR_sched_getscheduler: 1814 case TARGET_NR_sched_getscheduler:
1715 - goto unimplemented; 1815 + ret = get_errno(sched_getscheduler(arg1));
  1816 + break;
1716 case TARGET_NR_sched_yield: 1817 case TARGET_NR_sched_yield:
1717 ret = get_errno(sched_yield()); 1818 ret = get_errno(sched_yield());
1718 break; 1819 break;
1719 case TARGET_NR_sched_get_priority_max: 1820 case TARGET_NR_sched_get_priority_max:
  1821 + ret = get_errno(sched_get_priority_max(arg1));
  1822 + break;
1720 case TARGET_NR_sched_get_priority_min: 1823 case TARGET_NR_sched_get_priority_min:
  1824 + ret = get_errno(sched_get_priority_min(arg1));
  1825 + break;
1721 case TARGET_NR_sched_rr_get_interval: 1826 case TARGET_NR_sched_rr_get_interval:
1722 - goto unimplemented;  
1723 - 1827 + {
  1828 + struct target_timespec *target_ts = (void *)arg2;
  1829 + struct timespec ts;
  1830 + ret = get_errno(sched_rr_get_interval(arg1, &ts));
  1831 + if (!is_error(ret)) {
  1832 + target_ts->tv_sec = tswapl(ts.tv_sec);
  1833 + target_ts->tv_nsec = tswapl(ts.tv_nsec);
  1834 + }
  1835 + }
  1836 + break;
1724 case TARGET_NR_nanosleep: 1837 case TARGET_NR_nanosleep:
1725 { 1838 {
1726 struct target_timespec *target_req = (void *)arg1; 1839 struct target_timespec *target_req = (void *)arg1;
@@ -1767,11 +1880,14 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1767,11 +1880,14 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1767 } 1880 }
1768 } 1881 }
1769 break; 1882 break;
1770 - case TARGET_NR_vm86:  
1771 case TARGET_NR_query_module: 1883 case TARGET_NR_query_module:
  1884 + goto unimplemented;
1772 case TARGET_NR_nfsservctl: 1885 case TARGET_NR_nfsservctl:
  1886 + goto unimplemented;
1773 case TARGET_NR_prctl: 1887 case TARGET_NR_prctl:
  1888 + goto unimplemented;
1774 case TARGET_NR_pread: 1889 case TARGET_NR_pread:
  1890 + goto unimplemented;
1775 case TARGET_NR_pwrite: 1891 case TARGET_NR_pwrite:
1776 goto unimplemented; 1892 goto unimplemented;
1777 case TARGET_NR_chown: 1893 case TARGET_NR_chown:
@@ -1781,16 +1897,24 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1781,16 +1897,24 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1781 ret = get_errno(sys_getcwd1((char *)arg1, arg2)); 1897 ret = get_errno(sys_getcwd1((char *)arg1, arg2));
1782 break; 1898 break;
1783 case TARGET_NR_capget: 1899 case TARGET_NR_capget:
  1900 + goto unimplemented;
1784 case TARGET_NR_capset: 1901 case TARGET_NR_capset:
  1902 + goto unimplemented;
1785 case TARGET_NR_sigaltstack: 1903 case TARGET_NR_sigaltstack:
  1904 + goto unimplemented;
1786 case TARGET_NR_sendfile: 1905 case TARGET_NR_sendfile:
  1906 + goto unimplemented;
1787 case TARGET_NR_getpmsg: 1907 case TARGET_NR_getpmsg:
  1908 + goto unimplemented;
1788 case TARGET_NR_putpmsg: 1909 case TARGET_NR_putpmsg:
  1910 + goto unimplemented;
1789 case TARGET_NR_vfork: 1911 case TARGET_NR_vfork:
1790 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0)); 1912 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0));
1791 break; 1913 break;
1792 case TARGET_NR_ugetrlimit: 1914 case TARGET_NR_ugetrlimit:
  1915 + goto unimplemented;
1793 case TARGET_NR_truncate64: 1916 case TARGET_NR_truncate64:
  1917 + goto unimplemented;
1794 case TARGET_NR_ftruncate64: 1918 case TARGET_NR_ftruncate64:
1795 goto unimplemented; 1919 goto unimplemented;
1796 case TARGET_NR_stat64: 1920 case TARGET_NR_stat64:
@@ -1919,6 +2043,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1919,6 +2043,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1919 ret = get_errno(gettid()); 2043 ret = get_errno(gettid());
1920 break; 2044 break;
1921 case TARGET_NR_readahead: 2045 case TARGET_NR_readahead:
  2046 + goto unimplemented;
1922 case TARGET_NR_setxattr: 2047 case TARGET_NR_setxattr:
1923 case TARGET_NR_lsetxattr: 2048 case TARGET_NR_lsetxattr:
1924 case TARGET_NR_fsetxattr: 2049 case TARGET_NR_fsetxattr:
@@ -1931,10 +2056,14 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, @@ -1931,10 +2056,14 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1931 case TARGET_NR_removexattr: 2056 case TARGET_NR_removexattr:
1932 case TARGET_NR_lremovexattr: 2057 case TARGET_NR_lremovexattr:
1933 case TARGET_NR_fremovexattr: 2058 case TARGET_NR_fremovexattr:
1934 - goto unimplemented; 2059 + goto unimplemented_nowarn;
  2060 + case TARGET_NR_set_thread_area:
  2061 + case TARGET_NR_get_thread_area:
  2062 + goto unimplemented_nowarn;
1935 default: 2063 default:
1936 unimplemented: 2064 unimplemented:
1937 - gemu_log("gemu: Unsupported syscall: %d\n", num); 2065 + gemu_log("qemu: Unsupported syscall: %d\n", num);
  2066 + unimplemented_nowarn:
1938 ret = -ENOSYS; 2067 ret = -ENOSYS;
1939 break; 2068 break;
1940 } 2069 }