Re: [Part2 PATCH v9 38/38] KVM: X86: Restart the guest when insn_len is zero and SEV is enabled

Singh, Brijesh
2019-02-04T19:23:03Z

On 2/1/19 2:21 PM, Jim Mattson wrote:
> On Mon, Dec 4, 2017 at 5:07 PM Brijesh Singh <brijesh.singh@amd.com> wrote:
>>
>> On AMD platforms, under certain conditions insn_len may be zero on #NPF.
>> This can happen if a guest gets a page-fault on data access but the HW
>> table walker is not able to read the instruction page (e.g instruction
>> page is not present in memory).
>>
>> Typically, when insn_len is zero, x86_emulate_instruction() walks the
>> guest page table and fetches the instruction bytes from guest memory.
>> When SEV is enabled, the guest memory is encrypted with guest-specific
>> key hence hypervisor will not able to fetch the instruction bytes.
>> In those cases we simply restart the guest.
>>
>> I have encountered this issue when running kernbench inside the guest.
>>
>> Cc: Thomas Gleixner <tglx@linutronix.de>
>> Cc: Ingo Molnar <mingo@redhat.com>
>> Cc: "H. Peter Anvin" <hpa@zytor.com>
>> Cc: Paolo Bonzini <pbonzini@redhat.com>
>> Cc: "Radim Krčmář" <rkrcmar@redhat.com>
>> Cc: Joerg Roedel <joro@8bytes.org>
>> Cc: Borislav Petkov <bp@suse.de>
>> Cc: Tom Lendacky <thomas.lendacky@amd.com>
>> Cc: x86@kernel.org
>> Cc: kvm@vger.kernel.org
>> Cc: linux-kernel@vger.kernel.org
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>> arch/x86/kvm/mmu.c | 10 ++++++++++
>> arch/x86/kvm/svm.c | 6 ++++--
>> 2 files changed, 14 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
>> index e5e66e5c6640..d5e5dbd0e5ad 100644
>> --- a/arch/x86/kvm/mmu.c
>> +++ b/arch/x86/kvm/mmu.c
>> @@ -4950,6 +4950,16 @@ int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u64 error_code,
>> if (mmio_info_in_cache(vcpu, cr2, direct))
>> emulation_type = 0;
>> emulate:
>> + /*
>> + * On AMD platforms, under certain conditions insn_len may be zero on #NPF.
>> + * This can happen if a guest gets a page-fault on data access but the HW
>> + * table walker is not able to read the instruction page (e.g instruction
>> + * page is not present in memory). In those cases we simply restart the
>> + * guest.
>> + */
>> + if (unlikely(insn && !insn_len))
>> + return 1;
>> +
>
> How does this work, for instance, with MMIO at CPL3 with SMAP enabled?
>

The processor will still attempt to supply correct instruction
bytes in this case (basically it disables SMAP temporarily during
this read). *HOWEVER*, looking through Zen docs, there is an
errata about this on Zen. See errata 1096 in
https://www.amd.com/system/files/TechDocs/55449_Fam_17h_M_00h0Fh_Rev_Guide.pdf

Looking at errata it seems on Zen processors, the CPU will not
supply instruction bytes in this scenario (MMIO at CPL3 with
SMAP=1). I will reach out to HW folks to see if there is any
plans to fix in upcoming CPU cores.

We probably need to workaround for this errata. In non SEV case
we can let the host read the instruction bytes but in SEV case
we can disable SMAP temporarily in CR4, then retry the guest,
and then restore the CR4.SMAP settings. I will work on patch
and post on mailing list.

-Brijesh