Re: [kvm-unit-tests PATCH v2 07/10] x86: AMD SEV-ES: Handle CPUID #VC

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 2/12/22 10:32 PM, Marc Orr wrote:
> On Wed, Feb 9, 2022 at 8:44 AM Varad Gautam <varad.gautam@xxxxxxxx> wrote:
>>
>> Using Linux's CPUID #VC processing logic.
>>
>> Signed-off-by: Varad Gautam <varad.gautam@xxxxxxxx>
>> ---
>>  lib/x86/amd_sev_vc.c | 98 ++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 98 insertions(+)
>>
>> diff --git a/lib/x86/amd_sev_vc.c b/lib/x86/amd_sev_vc.c
>> index 142f2cd..9ee67c0 100644
>> --- a/lib/x86/amd_sev_vc.c
>> +++ b/lib/x86/amd_sev_vc.c
>> @@ -2,6 +2,7 @@
>>
>>  #include "amd_sev.h"
>>  #include "svm.h"
>> +#include "x86/xsave.h"
>>
>>  extern phys_addr_t ghcb_addr;
>>
>> @@ -52,6 +53,100 @@ static void vc_finish_insn(struct es_em_ctxt *ctxt)
>>         ctxt->regs->rip += ctxt->insn.length;
>>  }
>>
>> +static inline u64 lower_bits(u64 val, unsigned int bits)
>> +{
>> +       u64 mask = (1ULL << bits) - 1;
>> +
>> +       return (val & mask);
>> +}
> 
> This isn't used in this patch. I guess it ends up being used later, in
> path 9: "x86: AMD SEV-ES: Handle IOIO #VC". Let's introduce it there
> if we're going to put it in this file. Though, again, maybe it's worth
> creating a platform agnostic bit library, and put this and
> `_test_bit()` (introduced in a previous patch) there.
> 

Ack, it makes sense to introduce it later (and at a different place).

>> +
>> +static inline void sev_es_wr_ghcb_msr(u64 val)
>> +{
>> +       wrmsr(MSR_AMD64_SEV_ES_GHCB, val);
>> +}
>> +
>> +static enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb,
>> +                                         struct es_em_ctxt *ctxt,
>> +                                         u64 exit_code, u64 exit_info_1,
>> +                                         u64 exit_info_2)
>> +{
>> +       enum es_result ret;
>> +
>> +       /* Fill in protocol and format specifiers */
>> +       ghcb->protocol_version = GHCB_PROTOCOL_MAX;
>> +       ghcb->ghcb_usage       = GHCB_DEFAULT_USAGE;
>> +
>> +       ghcb_set_sw_exit_code(ghcb, exit_code);
>> +       ghcb_set_sw_exit_info_1(ghcb, exit_info_1);
>> +       ghcb_set_sw_exit_info_2(ghcb, exit_info_2);
>> +
>> +       sev_es_wr_ghcb_msr(__pa(ghcb));
>> +       VMGEXIT();
>> +
>> +       if ((ghcb->save.sw_exit_info_1 & 0xffffffff) == 1) {
>> +               u64 info = ghcb->save.sw_exit_info_2;
>> +               unsigned long v;
>> +
>> +               info = ghcb->save.sw_exit_info_2;
> 
> This line seems redundant, since `info` is already initialized to this
> value when it's declared, two lines above. That being said, I see this
> is how the code is in Linux as well. I wonder if it was done like this
> on accident.
> 

Nice catch, it seems so. It's harmless, but I will drop it in v3.

>> +               v = info & SVM_EVTINJ_VEC_MASK;
>> +
>> +               /* Check if exception information from hypervisor is sane. */
>> +               if ((info & SVM_EVTINJ_VALID) &&
>> +                   ((v == GP_VECTOR) || (v == UD_VECTOR)) &&
>> +                   ((info & SVM_EVTINJ_TYPE_MASK) == SVM_EVTINJ_TYPE_EXEPT)) {
>> +                       ctxt->fi.vector = v;
>> +                       if (info & SVM_EVTINJ_VALID_ERR)
>> +                               ctxt->fi.error_code = info >> 32;
>> +                       ret = ES_EXCEPTION;
>> +               } else {
>> +                       ret = ES_VMM_ERROR;
>> +               }
>> +       } else if (ghcb->save.sw_exit_info_1 & 0xffffffff) {
>> +               ret = ES_VMM_ERROR;
>> +       } else {
>> +               ret = ES_OK;
>> +       }
>> +
>> +       return ret;
>> +}
>> +
>> +static enum es_result vc_handle_cpuid(struct ghcb *ghcb,
>> +                                     struct es_em_ctxt *ctxt)
>> +{
>> +       struct ex_regs *regs = ctxt->regs;
>> +       u32 cr4 = read_cr4();
>> +       enum es_result ret;
>> +
>> +       ghcb_set_rax(ghcb, regs->rax);
>> +       ghcb_set_rcx(ghcb, regs->rcx);
>> +
>> +       if (cr4 & X86_CR4_OSXSAVE) {
>> +               /* Safe to read xcr0 */
>> +               u64 xcr0;
>> +               xgetbv_checking(XCR_XFEATURE_ENABLED_MASK, &xcr0);
>> +               ghcb_set_xcr0(ghcb, xcr0);
>> +       } else
>> +               /* xgetbv will cause #GP - use reset value for xcr0 */
>> +               ghcb_set_xcr0(ghcb, 1);
> 
> nit: Consider adding curly braces to the else branch, so that it
> matches the if branch.
> 

Will do.

>> +
>> +       ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_CPUID, 0, 0);
>> +       if (ret != ES_OK)
>> +               return ret;
>> +
>> +       if (!(ghcb_rax_is_valid(ghcb) &&
>> +             ghcb_rbx_is_valid(ghcb) &&
>> +             ghcb_rcx_is_valid(ghcb) &&
>> +             ghcb_rdx_is_valid(ghcb)))
>> +               return ES_VMM_ERROR;
>> +
>> +       regs->rax = ghcb->save.rax;
>> +       regs->rbx = ghcb->save.rbx;
>> +       regs->rcx = ghcb->save.rcx;
>> +       regs->rdx = ghcb->save.rdx;
>> +
>> +       return ES_OK;
>> +}
>> +
>>  static enum es_result vc_handle_exitcode(struct es_em_ctxt *ctxt,
>>                                          struct ghcb *ghcb,
>>                                          unsigned long exit_code)
>> @@ -59,6 +154,9 @@ static enum es_result vc_handle_exitcode(struct es_em_ctxt *ctxt,
>>         enum es_result result;
>>
>>         switch (exit_code) {
>> +       case SVM_EXIT_CPUID:
>> +               result = vc_handle_cpuid(ghcb, ctxt);
>> +               break;
>>         default:
>>                 /*
>>                  * Unexpected #VC exception
>> --
>> 2.32.0
>>
> 




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux