Avi Kivity wrote:
Matteo Frigo wrote:
Matteo Frigo <athena@xxxxxxxx> writes:
Avi Kivity <avi@xxxxxxxxxx> writes:
Can you run the slightly modified gs.c (attached) and rerun on AMD?
The is to see if the runtime somehow restores gs.
Crashes as follows:
w2k3-64:~$ ./a.exe gs: 2b
gs:0x30: 7efdb000
Segmentation fault (core dumped)
A little bit more information:
w2k3-64:~$ gdb a.exe
GNU gdb 6.8.0.20080328-cvs (cygwin-special)
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show
copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-cygwin"...
(no debugging symbols found)
(gdb) r
Starting program: /home/athena/a.exe [New thread 1620.0x6dc]
Error: dll starting at 0x77d40000 not found.
Error: dll starting at 0x77d40000 not found.
Error: dll starting at 0x77c20000 not found.
Error while mapping shared library sections:
/cygdrive/c/WINDOWS/SysWOW64/ntdll32.dll: No such file or directory.
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
[New thread 1620.0x74c]
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
Program received signal SIGSEGV, Segmentation fault.
0x0040109d in main ()
(gdb) x/i $pc
0x40109d <main+77>: mov %gs:0x30,%esi
(gdb) p/x $gs
$1 = 0x2b
(gdb)
Okay, at least this makes some little bit of sense. On both Intel and
AMD, 'mov gs' clobbers gs.base as expected. On AMD, something further
down the line (some syscall likely) restores gs.base, but on Intel it
doesn't. When we avoid the syscall, we get a crash on AMD as well.
The attached patch fixes it for me. Without this, rdmsr(KERNEL_GS_BASE)
reads a stale value, which presumably Windows later writes back.
--
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.
diff --git a/kernel/x86/vmx.c b/kernel/x86/vmx.c
index 7507ce2..048460d 100644
--- a/kernel/x86/vmx.c
+++ b/kernel/x86/vmx.c
@@ -910,6 +910,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
data = vmcs_readl(GUEST_SYSENTER_ESP);
break;
default:
+ vmx_load_host_state(vcpu);
msr = find_msr_entry(to_vmx(vcpu), msr_index);
if (msr) {
data = msr->data;