Distribution: Debian etchnhalf Hardware Environment: Cyrix 6x86 processor Software Environment: Linux 2.6.24 as provided by debian Problem Description: The debian provided 2.6.24 kernel crashes on 6x86 during boot with an invalid opcode exception. The cause is that CONFIG_PARAVIRT is enabled, which causes the kernel to patch itself as soon as it detects it runs on bare hardware. The kernel patch function text_poke runs sync_core() after patching, which contains a CPUID instruction, as that is serializing. The 6x86 processor does not support this instruction unless explicitly enabled, so an invalid opcode exception is reported. Steps to reproduce: Compile a kernel with paravirt support and run it on a system with a non-CPUID-capable processor. Suggested fix: As sync_core is only used after microcode update or code patching, performance of sync_core doesn't seem critical, so add a test whether CPUID is supported to sync_core (or alternative.c instead). CPUs that might need this strong kind of serialization should all support CPUID.
Patching it with a lock addl $0, (%esp) ought to do the trick for the 6x86 and other older processors.
Actually, the IA32 manual, volume 3A, section 7.1.3 implies that replacing it with a forward JMP (EB 00) might be better; that is also consistent with what the early boot code does. In fact, I don't see why we can't use the forward jump unconditionally -- it is known to work on all processors including the new ones. Neither the JMP nor CPUID will synchronize other cores, so it should be equivalent in that way. The problem with the current code is that sync_core() does two things which have separate rules in x86: text synchronization, and pipeline serialization (the latter appears to only be due to an erratum in the microcode patching code.) I'm thinking of splitting this into two functions, sync_text() and serialize().
Created attachment 19092 [details] Proposed patch Could you please try this patch?
I backported the fix to 2.6.24 (for debian etchnhalf), and it works fine. I also backported it to 2.6.26 (debian lenny) and started to upgrade the machine, but the hard drive died, so no results yet, but should work there too.
A new HDD has been installed into that 6x86 system. The backport of your patch does not make 2.6.26 (with debian default config) boot, because there is a new unprotected cpuid in kvm_para_available in include/asm-x86/kvm_para.h which is called by the kvm clock source driver during early setup.
Kvm finally fixed in 3.4
A patch referencing this bug report has been merged in Linux v3.4: commit c3709e6734daa4d9b37fe31592ebb0eb57bae1bb Author: Alan Cox <alan@linux.intel.com> Date: Mon May 14 18:41:09 2012 +0100 x86, kvm: KVM paravirt kernels don't check for CPUID being unavailable