tinycorelinux / tinyx

GNU General Public License v3.0
231 stars 31 forks source link

questions about Xvesa #10

Open stefan11111 opened 1 week ago

stefan11111 commented 1 week ago

Hi.

Tinyx has the Xfbdev and Xvesa X servers. Xfbdev works flawlessly. Xvesa refuses to start

                        if (!strcmp("x86_64", info.machine)) {
                                ErrorF("Xvesa is not 64-bit compatible.\n");
                                exit(1);
                        }

I am on an x86_64 machine.

I tried patching this out and running the test command:

# Xvesa -listmodes

which fails like so:

# Xvesa -listmodes
Unexpected result code 0xFFFFFFFF from vm86
eax=0x00004F00 ebx=0x00000000 ecx=0x00000000 edx=0x00000000
esi=0x00000000 edi=0x00000000 ebp=0x00000000
eip=0x000017EA esp=0x00000FFA eflags=0x00003200
cs=0xC000      ds=0x0000      es=0x1101      fs=0x0000      gs=0x0000
 9E 58 66 5F 5E 5B C3 ->52 50 BA CA 03 EC FE C0
vm86 failed (errno 1)
Unexpected result code 0xFFFFFFFF from vm86
eax=0x00004F00 ebx=0x00000000 ecx=0x00000000 edx=0x00000000
esi=0x00000000 edi=0x00000000 ebp=0x00000000
eip=0x000017EA esp=0x00000FFA eflags=0x00003200
cs=0xC000      ds=0x0000      es=0x1101      fs=0x0000      gs=0x0000
 9E 58 66 5F 5E 5B C3 ->52 50 BA CA 03 EC FE C0
vm86 failed (errno 1)
0x0013: 320x200x8 (vga compatible) PseudoColor

I then tried to build tinyx as a 32-bit executable, by passing:

CFLAGS="-m32 -O3 -flto -pipe -march=native"
# file /usr/bin/Xvesa
/usr/bin/Xvesa: setuid ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, stripped

However, this also fails like the 64-bit executable:

# Xvesa -listmodes
Unexpected result code 0xFFFFFFFF from vm86
eax=0x00004F00 ebx=0x00000000 ecx=0x00000000 edx=0x00000000
esi=0x00000000 edi=0x00000000 ebp=0x00000000
eip=0x000017EA esp=0x00000FFA eflags=0x00003200
cs=0xC000      ds=0x0000      es=0x1101      fs=0x0000      gs=0x0000
 9E 58 66 5F 5E 5B C3 ->52 50 BA CA 03 EC FE C0
vm86 failed (errno 38)
Unexpected result code 0xFFFFFFFF from vm86
eax=0x00004F00 ebx=0x00000000 ecx=0x00000000 edx=0x00000000
esi=0x00000000 edi=0x00000000 ebp=0x00000000
eip=0x000017EA esp=0x00000FFA eflags=0x00003200
cs=0xC000      ds=0x0000      es=0x1101      fs=0x0000      gs=0x0000
 9E 58 66 5F 5E 5B C3 ->52 50 BA CA 03 EC FE C0
vm86 failed (errno 38)
0x0013: 320x200x8 (vga compatible) PseudoColor

And at this point, I decided to ask here. Why does this happen? Is there a way around this? what do you do to get around this in tinycorelinux? On what platforms does this happen? 64-bit anything, including arm and other arches? just x86_64?

rofl0r commented 1 week ago

isn't vm86 some ancient low-level instruction that shouldn't be used anymore ?

stefan11111 commented 1 week ago

Took a closer look at the code. Here seems to be the holdup:

static int vm86old(struct vm86_struct *vm)
{
        int res = -1;
#ifndef __x86_64__
        asm volatile ("pushl %%ebx\n\t"
                      "movl %2, %%ebx\n\t"
                      "movl %1,%%eax\n\t"
                      "int $0x80\n\t"
                      "popl %%ebx":"=a" (res):"n"(113), "r"(vm));
#endif
        if (res < 0) {
                errno = -res;
                res = -1;
        } else
                errno = 0;
        return res;
}

This looks like an asm wrapper around the vm86old syscall, with number 113. This syscall doesn't exist on x86_64.

Are there some performance reasons why inline assembly is preferred over the syscall() libc function for implementing this wrapper?

Note: edited my comment, because I read the x32 syscall table instead of the 32-bit syscall and table and misunderstood what the above code is doing.

clbr commented 1 week ago
stefan11111 commented 1 week ago

On another note, is there some way to prevent building Xvesa via options passed to ./configure or make?

Since I found no such option in the code, I though to add it. Opened a pr too: https://github.com/tinycorelinux/tinyx/pull/11

diff --git a/configure.ac b/configure.ac
index 1770fd4..67e60b7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -259,7 +259,9 @@ AC_ARG_ENABLE(xf86bigfont,    AS_HELP_STRING([--disable-xf86bigfont], [Build XF8
 AC_ARG_ENABLE(dpms,           AS_HELP_STRING([--disable-dpms], [Build DPMS extension (default: enabled)]), [DPMSExtension=$enableval], [DPMSExtension=yes])

 dnl kdrive and its subsystems
-AC_ARG_ENABLE(kdrive,         AS_HELP_STRING([--enable-kdrive], [Build kdrive servers (default: yes)]), [KDRIVE=$enableval], [KDRIVE=yes])
+AC_ARG_ENABLE(kdrive,         AS_HELP_STRING([--enable-kdrive],  [Build kdrive servers (default: yes)]), [KDRIVE=$enableval], [KDRIVE=yes])
+AC_ARG_ENABLE(xvesa,          AS_HELP_STRING([--disable-xvesa],  [Build Xvesa server (default: yes)]), [XVESA=$enableval], [XVESA=yes])
+AC_ARG_ENABLE(xfbdev,         AS_HELP_STRING([--disable-xfbdev], [Build Xfbdev server (default: yes)]), [XFBDEV=$enableval], [XFBDEV=yes])

 dnl chown/chmod to be setuid root as part of build
@@ -535,12 +537,16 @@ if test "$KDRIVE" = yes; then

     AC_CHECK_HEADERS([asm/vm86.h sys/io.h])
     if test "$ac_cv_header_asm_vm86_h" = yes; then
-        AC_DEFINE(KDRIVEVESA, 1, [Build VESA-based kdrive servers])
+        if test "x$XVESA" != "xno"; then
+            AC_DEFINE(KDRIVEVESA, 1, [Build VESA-based kdrive servers])
+        fi
     fi

     AC_CHECK_HEADERS([linux/fb.h])
     if test "$ac_cv_header_linux_fb_h" = yes; then
-        AC_DEFINE(KDRIVEFBDEV, 1, [Build fbdev-based kdrive server])
+        if test "x$XFBDEV" != "xno"; then
+            AC_DEFINE(KDRIVEFBDEV, 1, [Build fbdev-based kdrive server])
+        fi
     fi

     # damage shadow extension fb mi
@@ -571,8 +577,15 @@ AC_SUBST(KDRIVE_CFLAGS)
 AC_SUBST(KDRIVE_PURE_LIBS)
 AC_SUBST(KDRIVE_LIBS)
 AM_CONDITIONAL(KDRIVELINUX, [test "x$KDRIVELINUX" = xyes])
-AM_CONDITIONAL(KDRIVEVESA, [test x"$ac_cv_header_asm_vm86_h" = xyes])
+AM_CONDITIONAL(KDRIVEVESA,  [test x"$ac_cv_header_asm_vm86_h" = xyes])
+if test "x$XVESA" = "xno"; then
+    AM_CONDITIONAL(KDRIVEVESA, 0)
+fi
 AM_CONDITIONAL(KDRIVEFBDEV, [test x"$ac_cv_header_linux_fb_h" = xyes])
+if test "x$XFBDEV" = "xno"; then
+    AM_CONDITIONAL(KDRIVEFBDEV, 0)
+fi
+

 dnl and the rest of these are generic, so they're in config.h
 AC_DEFINE(XResExtension, 1, [Build XRes extension])

Edit: just realized I edited my old comment instead of quoting it. Anyway, what was said in there wasn't that important and is probably in your emails too, but I'll try to write it from memory again.

stefan11111 commented 1 week ago

Found a copy of my old message. Posting it again. @clbr I see, so TC doesn't have a solution for this either.

I tried simply faking the success of vm86old, which gave me some output:

# Xvesa -listmodes
Int 10h (0x4F00) failed: 0x4F00 (unknown error)
Int 10h (0x4F00) failed: 0x4F00 (unknown error)
0x0013: 320x200x8 (vga compatible) PseudoColor

And running Xvesa did produce some output, a very small X screen at the top of my monitor, duplicated along the length of my monitor. The X screen was my actual X setup, and I could even open a browser in that tiny window.

I guess Xvesa just used whatever mode the video card was in, and that happened to be it.

This is how I faked the success of vm86old:

diff --git a/kdrive/vesa/vm86.c b/kdrive/vesa/vm86.c
index 26ecd74..4b8817f 100644
--- a/kdrive/vesa/vm86.c
+++ b/kdrive/vesa/vm86.c
@@ -737,13 +737,16 @@ void Vm86ReleaseMemory(Vm86InfoPtr vi, int mark)

 static int vm86old(struct vm86_struct *vm)
 {
-       int res = -1;
+       int res = VM86_INTx | 0xFF00;
 #ifndef __x86_64__
        asm volatile ("pushl %%ebx\n\t"
                      "movl %2, %%ebx\n\t"
                      "movl %1,%%eax\n\t"
                      "int $0x80\n\t"
                      "popl %%ebx":"=a" (res):"n"(113), "r"(vm));
+#if 0
+       res = syscall(113, vm);
+#endif
 #endif
        if (res < 0) {
                errno = -res;
@@ -752,3 +755,4 @@ static int vm86old(struct vm86_struct *vm)
                errno = 0;
        return res;
 }
+

I also found this old project, which claims that it was once able to implement the vm86 syscall on x86_64 linux: https://v86-64.sourceforge.net/

Does anyone know the reason why this syscall wasn't implemented on 64-bit linux?

On another note, is there some way to prevent building Xvesa via options passed to ./configure or make?