All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sean Christopherson <seanjc@google.com>
To: "H. Peter Anvin" <hpa@zytor.com>
Cc: Elizabeth Figura <zfigura@codeweavers.com>,
	x86@kernel.org,  Linux Kernel <linux-kernel@vger.kernel.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	 Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
	 Dave Hansen <dave.hansen@linux.intel.com>,
	 Ricardo Neri <ricardo.neri-calderon@linux.intel.com>,
	wine-devel@winehq.org
Subject: Re: x86 SGDT emulation for Wine
Date: Tue, 2 Jan 2024 09:12:11 -0800	[thread overview]
Message-ID: <ZZRD66ilLsX53Vj_@google.com> (raw)
In-Reply-To: <868D3980-3323-4E4A-8A7A-B9C26F123A1E@zytor.com>

On Wed, Dec 27, 2023, H. Peter Anvin wrote:
> On December 27, 2023 2:20:37 PM PST, Elizabeth Figura <zfigura@codeweavers.com> wrote:
> >Hello all,
> >
> >There is a Windows 98 program, a game called Nuclear Strike, which wants to do 
> >some amount of direct VGA access. Part of this is port I/O, which naturally 
> >throws SIGILL that we can trivially catch and emulate in Wine. The other part 
> >is direct access to the video memory at 0xa0000, which in general isn't a 
> >problem to catch and virtualize as well.
> >
> >However, this program is a bit creative about how it accesses that memory; 
> >instead of just writing to 0xa0000 directly, it looks up a segment descriptor 
> >whose base is at 0xa0000 and then uses the %es override to write bytes. In 
> >pseudo-C, what it does is:

...

> >Currently we emulate IDT access. On a read fault, we execute sidt ourselves, 
> >check if the read address falls within the IDT, and return some dummy data 
> >from the exception handler if it does [1]. We can easily enough implement GDT 
> >access as well this way, and there is even an out-of-tree patch written some 
> >years ago that does this, and helps the game run.
> >
> >However, there are two problems that I have observed or anticipated:
> >
> >(1) On systems with UMIP, the kernel emulates sgdt instructions and returns a 
> >consistent address which we can guarantee is invalid. However, it also returns 
> >a size of zero. The program doesn't expect this (cf. the way the loop is 
> >written above) and I believe will effectively loop forever in that case, or 
> >until it finds the VGA selector or hits invalid memory.
> >
> >    I see two obvious ways to fix this: either adjust the size of the fake 
> >kernel GDT, or provide a switch to stop emulating and let Wine handle it. The 
> >latter may very well a more sustainable option in the long term (although I'll 
> >admit I can't immediately come up with a reason why, other than "we might need 
> >to raise the size yet again".)
> >
> >    Does anyone have opinions on this particular topic? I can look into 
> >writing a patch but I'm not sure what the best approach is.
> >
> >(2) On 64-bit systems without UMIP, sgdt returns a truncated address when in 
> >32-bit mode. This truncated address in practice might point anywhere in the 
> >address space, including to valid memory.
> >
> >    In order to fix this, we would need the kernel to guarantee that the GDT 
> >base points to an address whose bottom 32 bits we can guarantee are 
> >inaccessible. This is relatively easy to achieve ourselves by simply mapping 
> >those pages as noaccess, but it also means that those pages can't overlap 
> >something we need; we already go to pains to make sure that certain parts of 
> >the address space are free. Broadly anything above the 2G boundary *should* be 
> >okay though. Is this feasible?
> >
> >    We could also just decide we don't care about systems without UMIP, but 
> >that seems a bit unfortunate; it's not that old of a feature. But I also have 
> >no idea how hard it would be to make this kind of a guarantee on the kernel 
> >side.
> >
> >    This is also, theoretically, a problem for the IDT, except that on the 
> >machines I've tested, the IDT is always at 0xfffffe0000000000. That's not 
> >great either (it's certainly caused some weirdness and confusion when 
> >debugging, when we unexpectedly catch an unrelated null pointer access) but it 
> >seems to work in practice.
> >
> >--Zeb
> >
> >[1] https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/krnl386.exe16/
> >instr.c#l702
> >
> >
> 
> A prctl() to set the UMIP-emulated return values or disable it (giving
> SIGILL) would be easy enough.
> 
> For the non-UMIP case, and probably for a lot of other corner cases like
> relying on certain magic selector values and what not, the best option really
> would be to wrap the code in a lightweight KVM container. I do *not* mean
> running the Qemu user space part of KVM; instead have Wine interface with
> /dev/kvm directly.

+1.  Pivoting to KVM would require quite a bit of work up front, but I suspect
the payoff would be worthwhile in the end.

See also https://github.com/dosemu2/dosemu2/tree/devel/src/base/emu-i386.

  reply	other threads:[~2024-01-02 17:12 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-27 22:20 x86 SGDT emulation for Wine Elizabeth Figura
2023-12-27 23:58 ` H. Peter Anvin
2024-01-02 17:12   ` Sean Christopherson [this message]
2024-01-02 19:53   ` Elizabeth Figura
2024-01-03  7:30     ` Stefan Dösinger
2024-01-03 15:19     ` Sean Christopherson
2024-01-03 15:33       ` H. Peter Anvin
2024-01-04  6:35         ` Elizabeth Figura
2024-01-05  1:02           ` H. Peter Anvin
2024-01-05  1:21             ` Sean Christopherson
2024-01-05  2:47             ` Andrew Cooper
2024-01-05  4:03               ` H. Peter Anvin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ZZRD66ilLsX53Vj_@google.com \
    --to=seanjc@google.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=ricardo.neri-calderon@linux.intel.com \
    --cc=tglx@linutronix.de \
    --cc=wine-devel@winehq.org \
    --cc=x86@kernel.org \
    --cc=zfigura@codeweavers.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.