• Paolo Bonzini's avatar
    KVM: MMU: fix ept=0/pte.u=1/pte.w=0/CR0.WP=0/CR4.SMEP=1/EFER.NX=0 combo · eac52550
    Paolo Bonzini authored
    [ Upstream commit 844a5fe2 ]
    
    Yes, all of these are needed. :) This is admittedly a bit odd, but
    kvm-unit-tests access.flat tests this if you run it with "-cpu host"
    and of course ept=0.
    
    KVM runs the guest with CR0.WP=1, so it must handle supervisor writes
    specially when pte.u=1/pte.w=0/CR0.WP=0.  Such writes cause a fault
    when U=1 and W=0 in the SPTE, but they must succeed because CR0.WP=0.
    When KVM gets the fault, it sets U=0 and W=1 in the shadow PTE and
    restarts execution.  This will still cause a user write to fault, while
    supervisor writes will succeed.  User reads will fault spuriously now,
    and KVM will then flip U and W again in the SPTE (U=1, W=0).  User reads
    will be enabled and supervisor writes disabled, going back to the
    originary situation where supervisor writes fault spuriously.
    
    When SMEP is in effect, however, U=0 will enable kernel execution of
    this page.  To avoid this, KVM also sets NX=1 in the shadow PTE together
    with U=0.  If the guest has not enabled NX, the result is a continuous
    stream of page faults due to the NX bit being reserved.
    
    The fix is to force EFER.NX=1 even if the CPU is taking care of the EFER
    switch.  (All machines with SMEP have the CPU_LOAD_IA32_EFER vm-entry
    control, so they do not use user-return notifiers for EFER---if they did,
    EFER.NX would be forced to the same value as the host).
    
    There is another bug in the reserved bit check, which I've split to a
    separate patch for easier application to stable kernels.
    
    Cc: stable@vger.kernel.org
    Cc: Andy Lutomirski <luto@amacapital.net>
    Reviewed-by: default avatarXiao Guangrong <guangrong.xiao@linux.intel.com>
    Fixes: f6577a5fSigned-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
    Signed-off-by: default avatarSasha Levin <sasha.levin@oracle.com>
    eac52550
vmx.c 288 KB