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 103 extern int flock(int, int);
104 104 extern int setfsuid(int);
105 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 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 210 }
211 211  
212 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 215 tv->tv_sec = tswapl(target_tv->tv_sec);
216 216 tv->tv_usec = tswapl(target_tv->tv_usec);
217 217 }
218 218  
219 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 222 target_tv->tv_sec = tswapl(tv->tv_sec);
223 223 target_tv->tv_usec = tswapl(tv->tv_usec);
... ... @@ -238,8 +238,7 @@ static long do_select(long n,
238 238 efds_ptr = target_to_host_fds(&efds, target_efds, n);
239 239  
240 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 242 tv_ptr = &tv;
244 243 } else {
245 244 tv_ptr = NULL;
... ... @@ -251,8 +250,7 @@ static long do_select(long n,
251 250 host_to_target_fds(target_efds, efds_ptr, n);
252 251  
253 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 256 return ret;
... ... @@ -755,7 +753,7 @@ install:
755 753 }
756 754  
757 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 758 int ret = -ENOSYS;
761 759  
... ... @@ -773,6 +771,79 @@ int gemu_modify_ldt(CPUX86State *env, int func, void *ptr, unsigned long bytecou
773 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 847 /* this stack is the equivalent of the kernel stack associated with a
777 848 thread/process */
778 849 #define NEW_STACK_SIZE 8192
... ... @@ -788,19 +859,26 @@ static int clone_func(void *arg)
788 859 int do_fork(CPUX86State *env, unsigned int flags, unsigned long newsp)
789 860 {
790 861 int ret;
  862 + TaskState *ts;
791 863 uint8_t *new_stack;
792 864 CPUX86State *new_env;
793 865  
794 866 if (flags & CLONE_VM) {
795 867 if (!newsp)
796 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 876 /* we create a new CPU instance. */
800 877 new_env = cpu_x86_init();
801 878 memcpy(new_env, env, sizeof(CPUX86State));
802 879 new_env->regs[R_ESP] = newsp;
803 880 new_env->regs[R_EAX] = 0;
  881 + new_env->opaque = ts;
804 882 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
805 883 } else {
806 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 1359 struct timeval tv;
1282 1360 ret = get_errno(gettimeofday(&tv, NULL));
1283 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 1365 break;
... ... @@ -1290,8 +1367,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1290 1367 {
1291 1368 struct target_timeval *target_tv = (void *)arg1;
1292 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 1371 ret = get_errno(settimeofday(&tv, NULL));
1296 1372 }
1297 1373 break;
... ... @@ -1487,8 +1563,6 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1487 1563 break;
1488 1564 case TARGET_NR_idle:
1489 1565 goto unimplemented;
1490   - case TARGET_NR_vm86old:
1491   - goto unimplemented;
1492 1566 case TARGET_NR_wait4:
1493 1567 {
1494 1568 int status;
... ... @@ -1548,7 +1622,12 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1548 1622 break;
1549 1623 #ifdef TARGET_I386
1550 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 1631 break;
1553 1632 #endif
1554 1633 case TARGET_NR_adjtimex:
... ... @@ -1652,13 +1731,13 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1652 1731  
1653 1732 pfd = alloca(sizeof(struct pollfd) * nfds);
1654 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 1737 ret = get_errno(poll(pfd, nfds, timeout));
1659 1738 if (!is_error(ret)) {
1660 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 1781 ret = get_errno(getsid(arg1));
1703 1782 break;
1704 1783 case TARGET_NR_fdatasync:
1705   - goto unimplemented;
  1784 + ret = get_errno(fdatasync(arg1));
  1785 + break;
1706 1786 case TARGET_NR__sysctl:
1707 1787 goto unimplemented;
1708 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 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 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 1814 case TARGET_NR_sched_getscheduler:
1715   - goto unimplemented;
  1815 + ret = get_errno(sched_getscheduler(arg1));
  1816 + break;
1716 1817 case TARGET_NR_sched_yield:
1717 1818 ret = get_errno(sched_yield());
1718 1819 break;
1719 1820 case TARGET_NR_sched_get_priority_max:
  1821 + ret = get_errno(sched_get_priority_max(arg1));
  1822 + break;
1720 1823 case TARGET_NR_sched_get_priority_min:
  1824 + ret = get_errno(sched_get_priority_min(arg1));
  1825 + break;
1721 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 1837 case TARGET_NR_nanosleep:
1725 1838 {
1726 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 1880 }
1768 1881 }
1769 1882 break;
1770   - case TARGET_NR_vm86:
1771 1883 case TARGET_NR_query_module:
  1884 + goto unimplemented;
1772 1885 case TARGET_NR_nfsservctl:
  1886 + goto unimplemented;
1773 1887 case TARGET_NR_prctl:
  1888 + goto unimplemented;
1774 1889 case TARGET_NR_pread:
  1890 + goto unimplemented;
1775 1891 case TARGET_NR_pwrite:
1776 1892 goto unimplemented;
1777 1893 case TARGET_NR_chown:
... ... @@ -1781,16 +1897,24 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1781 1897 ret = get_errno(sys_getcwd1((char *)arg1, arg2));
1782 1898 break;
1783 1899 case TARGET_NR_capget:
  1900 + goto unimplemented;
1784 1901 case TARGET_NR_capset:
  1902 + goto unimplemented;
1785 1903 case TARGET_NR_sigaltstack:
  1904 + goto unimplemented;
1786 1905 case TARGET_NR_sendfile:
  1906 + goto unimplemented;
1787 1907 case TARGET_NR_getpmsg:
  1908 + goto unimplemented;
1788 1909 case TARGET_NR_putpmsg:
  1910 + goto unimplemented;
1789 1911 case TARGET_NR_vfork:
1790 1912 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, 0));
1791 1913 break;
1792 1914 case TARGET_NR_ugetrlimit:
  1915 + goto unimplemented;
1793 1916 case TARGET_NR_truncate64:
  1917 + goto unimplemented;
1794 1918 case TARGET_NR_ftruncate64:
1795 1919 goto unimplemented;
1796 1920 case TARGET_NR_stat64:
... ... @@ -1919,6 +2043,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1919 2043 ret = get_errno(gettid());
1920 2044 break;
1921 2045 case TARGET_NR_readahead:
  2046 + goto unimplemented;
1922 2047 case TARGET_NR_setxattr:
1923 2048 case TARGET_NR_lsetxattr:
1924 2049 case TARGET_NR_fsetxattr:
... ... @@ -1931,10 +2056,14 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3,
1931 2056 case TARGET_NR_removexattr:
1932 2057 case TARGET_NR_lremovexattr:
1933 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 2063 default:
1936 2064 unimplemented:
1937   - gemu_log("gemu: Unsupported syscall: %d\n", num);
  2065 + gemu_log("qemu: Unsupported syscall: %d\n", num);
  2066 + unimplemented_nowarn:
1938 2067 ret = -ENOSYS;
1939 2068 break;
1940 2069 }
... ...