RDMSR of register 0x345 (IA32_PERF_CAPABILITIES) fails in guest

Bug #1208540 reported by Jari Ruusu on 2013-08-05
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
QEMU
Undecided
Unassigned

Bug Description

I have a problem with qemu when I attempt to configure qemu in a way that
AES-NI op-codes are enabled in quest. To do that, I have to configure qemu
to emulate a recent CPU. But that causes a problem, because with recent
CPUs, guest linux kernel code assumes that RDMSR of register 0x345 works.
Qemu does not handle that correctly. Qemu does not crash. Guests running
newer linux kernels always crash on boot with 'general protection fault' on
RDMSR op-code that attempts to read IA32_PERF_CAPABILITIES. That "crashing"
linux code works OK on bare metal.

- Host processor is Intel i7-3610QM (Ivy Bridge, AES-NI op-codes)
  http://ark.intel.com/products/64899/Intel-Core-i7-3610QM-Processor-6M-Cache-up-to-3_30-GHz
- Host linux kernel version: 3.10.5, x86-64,
  CONFIG_KVM=y CONFIG_KVM_INTEL=y kernel config options enabled.
- Qemu versions 1.5.2 and 1.6.0-rc1, 'kvm' accel method. Westmere,
  SandyBridge, Haswell and 'host' emulated cpu all fail.
- Guest linux kernel version: 3.10.5, x86-64
- Guest linux kernel config required to trigger: CONFIG_GENERIC_CPU=y
- Problem does not occour if qemu is configured to use slow 'tcg' accel
  method.
- Problem does not occour if qemu is configured to emulate older processor
  model. Nehalem works, but does not provide AES-NI op-codes.
- Problem does not occour if guest linux kernel is so old that it does not
  attempt to read IA32_PERF_CAPABILITIES MSR register.
- Problem does not occour if using qemu-kvm-1.0 version, and 'host' emulated
  cpu type, where guest sees i7-3610QM cpu and AES-NI op-codes.

Command line that I used to compile qemu, using host gcc version 4.6.3:

./configure --prefix=/opt/qemu --interp-prefix=/opt/qemu/gnemul \
 --target-list="i386-softmmu x86_64-softmmu ppc-softmmu" --disable-debug-info \
 --audio-drv-list=oss --disable-xen --enable-kvm --disable-guest-agent \
 --disable-seccomp --disable-glusterfs
make -j 8
make install

Command line that I used to start qemu:

/opt/qemu/bin/qemu-system-x86_64 -L /j/qemu/roms -boot menu=on -nographic \
 -enable-kvm -alt-grab -machine pc-1.0 -cpu SandyBridge -m 2048 \
 -drive if=ide,index=0,serial=QQQIDE0,media=disk,format=raw,cache=writeback,file=ide0.raw,cyls=13770,heads=16,secs=56,trans=none \
 -drive if=ide,index=1,serial=QQQIDE1,media=disk,format=raw,cache=writeback,file=ide1.raw,cyls=13770,heads=16,secs=56,trans=none \
 -drive if=ide,index=2,serial=QQQIDE2,media=cdrom,format=raw \
 -drive if=ide,index=3,serial=QQQIDE3,media=disk,format=raw,cache=writeback,file=ide3.raw,cyls=2295,heads=16,secs=56,trans=none \
 -net nic,vlan=0,model=e1000,macaddr=52:54:00:12:34:06 \
 -net tap,vlan=0,script=/j/qemu/scripts/qemu-ifup-br0.sh,downscript=/j/qemu/scripts/qemu-ifdown-br0.sh

Bare metal host /proc/cpuinfo data, last one of 8 processors:

processor : 7
vendor_id : GenuineIntel
cpu family : 6
model : 58
model name : Intel(R) Core(TM) i7-3610QM CPU @ 2.30GHz
stepping : 9
microcode : 0x10
cpu MHz : 1200.000
cache size : 6144 KB
physical id : 0
siblings : 8
core id : 3
cpu cores : 4
apicid : 7
initial apicid : 7
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm ida arat epb xsaveopt pln pts dtherm tpr_shadow vnmi flexpriority ept vpid fsgsbase smep erms
bogomips : 4589.75
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:

Working qemu-kvm-1.0 (cpu type 'host') guest /proc/cpuinfo data, only one processor:

processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 58
model name : Intel(R) Core(TM) i7-3610QM CPU @ 2.30GHz
stepping : 9
microcode : 0x1
cpu MHz : 2294.887
cache size : 4096 KB
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx rdtscp lm constant_tsc rep_good nopl eagerfpu pni pclmulqdq ssse3 cx16 pcid sse4_1 sse4_2 x2apic popcnt aes xsave avx f16c rdrand hypervisor lahf_lm xsaveopt fsgsbase tsc_adjust smep erms
bogomips : 4589.77
clflush size : 64
cache_alignment : 64
address sizes : 40 bits physical, 48 bits virtual
power management:

Working qemu-kvm-1.0 (cpu type 'host') guest linux kernel boot message line
that does not result in 'general protection fault':

[ 0.035221] Performance Events: unsupported p6 CPU model 58 no PMU driver, software events only.

The difference appears to be that qemu-kvm-1.0 (cpu type 'host') drops that
'arch_perfmon' flag, so guest linux kernel code skips that problematic RDMSR
op-code.

Attachment file rdmsr-info.txt contains more info:
- Guest linux kernel boot messages
- Disassembly of failing guest linux kernel function
- C-language source of failing guest linux kernel function

Jari Ruusu (jariruusu) wrote :

Looks like the problem is in host linux kernel kvm code, not in qemu.
Until kvm code is fixed, this works as temporary workaround:

echo 1 >/sys/module/kvm/parameters/ignore_msrs

Changed in qemu:
status: New → Fix Released
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers