Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

questions about Xvesa #10

Open
stefan11111 opened this issue Nov 7, 2024 · 5 comments
Open

questions about Xvesa #10

stefan11111 opened this issue Nov 7, 2024 · 5 comments

Comments

@stefan11111
Copy link
Contributor

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
Copy link

rofl0r commented Nov 7, 2024

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

@stefan11111
Copy link
Contributor Author

stefan11111 commented Nov 8, 2024

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
Copy link
Collaborator

clbr commented Nov 8, 2024

  • vesa only exists on x86, so trying to use it on arm would be pointless (vesa bios - arm has no bios)
  • on TC we only ship Xvesa on 32-bit x86
  • it uses those bios calls, which only work on x86. The xf86-video-vesa driver works around this with a vm86 emulator IIRC. That has never been adapted to Xvesa, and we haven't bothered either, since x86_64 usually wants accelerated drivers, or at least the full LCD resolution which Xfbdev gives. The vesa modes may not even include 1920x1080, and a selection of lower modes is not very useful on a LCD

@stefan11111
Copy link
Contributor Author

stefan11111 commented Nov 8, 2024

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: #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
Copy link
Contributor Author

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants