Download raw body.
[EXT] Re: SEV-ES: vmm(4): vmentry/vmexit for SEV-ES guests
Hi,
On Tue, May 20, 2025 at 02:34:07AM -0700, Mike Larkin wrote:
> On Tue, May 20, 2025 at 11:28:16AM +0200, Hans-Jörg Höxer wrote:
> > Hi,
> >
> > this diff prepares the entry/exit path for SEV-ES enabled guests:
> >
> > With SEV-ES the full vCPU state is automatically loaded from or
> > saved to the encrypted VMSA. However, host state is not fully saved
> > and restored. Therefore, we need a seperate entry/exit path for
> > SEV-ES enabled guests.
> >
> > svm_seves_enter_guest() accomplishes this. Maybe we can streamline
> > svm_enter_guest() and svm_seves_enter_guest() to share code.
> >
> > Take care,
> > HJ.
>
> was this the same diff I ok'ed yesterday? It looks fine regardless.
oh, you're right! I already sent that diff.
> ok mlarkin
thanks!
Take care,
HJ.
>
> > ---------------------------------------------------------------------------
> > commit 1d876e9aa856bac3d580470133c6936c094164d6
> > Author: Hans-Joerg Hoexer <hshoexer@genua.de>
> > Date: Mon Jul 29 15:25:31 2024 +0200
> >
> > vmm(4): vmentry/vmexit for SEV-ES guests
> >
> > With SEV-ES the full vCPU state is automatically loaded from or
> > saved to the encrypted VMSA. However, host state is not fully saved
> > and restored. Therefore, we need a seperate entry/exit path for
> > SEV-ES enabled guests.
> >
> > svm_seves_enter_guest() accomplishes this. Maybe we can streamline
> > svm_enter_guest() and svm_seves_enter_guest() to share code.
> >
> > diff --git a/sys/arch/amd64/amd64/vmm_machdep.c b/sys/arch/amd64/amd64/vmm_machdep.c
> > index 7351221b3a5..9470222c351 100644
> > --- a/sys/arch/amd64/amd64/vmm_machdep.c
> > +++ b/sys/arch/amd64/amd64/vmm_machdep.c
> > @@ -6399,8 +6399,13 @@ vcpu_run_svm(struct vcpu *vcpu, struct vm_run_params *vrp)
> > KASSERT(vmcb->v_intercept1 & SVM_INTERCEPT_INTR);
> > wrmsr(MSR_AMD_VM_HSAVE_PA, vcpu->vc_svm_hsa_pa);
> >
> > - ret = svm_enter_guest(vcpu->vc_control_pa,
> > - &vcpu->vc_gueststate, &gdt);
> > + if (vcpu->vc_seves) {
> > + ret = svm_seves_enter_guest(vcpu->vc_control_pa,
> > + vcpu->vc_svm_hsa_va + SVM_HSA_OFFSET, &gdt);
> > + } else {
> > + ret = svm_enter_guest(vcpu->vc_control_pa,
> > + &vcpu->vc_gueststate, &gdt);
> > + }
> >
> > /* Restore host PKRU state. */
> > if (vmm_softc->sc_md.pkru_enabled) {
> > diff --git a/sys/arch/amd64/amd64/vmm_support.S b/sys/arch/amd64/amd64/vmm_support.S
> > index 30c1b75834f..f9f663cff62 100644
> > --- a/sys/arch/amd64/amd64/vmm_support.S
> > +++ b/sys/arch/amd64/amd64/vmm_support.S
> > @@ -42,6 +42,7 @@
> > .global vmx_enter_guest
> > .global vmm_dispatch_intr
> > .global svm_enter_guest
> > + .global svm_seves_enter_guest
> >
> > .text
> > .code64
> > @@ -662,3 +663,163 @@ restore_host_svm:
> > ret
> > lfence
> > END(svm_enter_guest)
> > +
> > +/*
> > + * When using SEV-ES we have to save some of the host registers to
> > + * the host state save area (HSA). According to the AMD Programmer's
> > + * Manual Volume 2 Appendix B the HSA has the same layout as the guest
> > + * save area (VMSA) except that it starts at offset 0x400 in the HSA
> > + * page.
> > + */
> > +ENTRY(svm_seves_enter_guest)
> > + RETGUARD_SETUP(svm_seves_enter_guest, r11)
> > + clgi
> > + movq %rdi, %r8
> > + pushfq
> > +
> > + pushq %rdx /* gdt pointer */
> > +
> > + /*
> > + * Save (possibly) lazy-switched selectors
> > + */
> > + strw %ax
> > + pushw %ax
> > + movw %es, %ax
> > + pushw %ax
> > + movw %ds, %ax
> > + pushw %ax
> > + movw %ss, %ax
> > + pushw %ax
> > +
> > + movq $MSR_FSBASE, %rcx
> > + rdmsr
> > + pushq %rax
> > + pushq %rdx
> > + pushw %fs
> > + movq $MSR_GSBASE, %rcx
> > + rdmsr
> > + pushq %rax
> > + pushq %rdx
> > + pushw %gs
> > + movq $MSR_KERNELGSBASE, %rcx
> > + rdmsr
> > + pushq %rax
> > + pushq %rdx
> > +
> > + /*
> > + * Save various MSRs
> > + */
> > + movq $MSR_STAR, %rcx
> > + rdmsr
> > + pushq %rax
> > + pushq %rdx
> > +
> > + movq $MSR_LSTAR, %rcx
> > + rdmsr
> > + pushq %rax
> > + pushq %rdx
> > +
> > + movq $MSR_SFMASK, %rcx
> > + rdmsr
> > + pushq %rax
> > + pushq %rdx
> > +
> > + RETGUARD_PUSH(r11)
> > +
> > + /*
> > + * Preserve callee-preserved registers as per AMD64 ABI in
> > + * HSA. Although all registers will be restored from HSA
> > + * on vmexit, these will not be saved on vmrun.
> > + */
> > + movq %r15, 0x378(%rsi)
> > + movq %r14, 0x370(%rsi)
> > + movq %r13, 0x368(%rsi)
> > + movq %r12, 0x360(%rsi)
> > + movq %rbp, 0x328(%rsi)
> > + movq %rbx, 0x318(%rsi)
> > +
> > + movq %r8, %rax /* rax = vmcb pa */
> > +
> > + vmrun %rax
> > +
> > + /* %rdi = 0 means we took an exit */
> > + xorq %rdi, %rdi
> > +
> > + RETGUARD_POP(r11)
> > +
> > + /*
> > + * Restore saved MSRs
> > + */
> > + popq %rdx
> > + popq %rax
> > + movq $MSR_SFMASK, %rcx
> > + wrmsr
> > +
> > + /* make sure guest doesn't bleed into host */
> > + xorl %edx, %edx
> > + xorl %eax, %eax
> > + movq $MSR_CSTAR, %rcx
> > + wrmsr
> > +
> > + popq %rdx
> > + popq %rax
> > + movq $MSR_LSTAR, %rcx
> > + wrmsr
> > +
> > + popq %rdx
> > + popq %rax
> > + movq $MSR_STAR, %rcx
> > + wrmsr
> > +
> > + /*
> > + * popw %gs will reset gsbase to 0, so preserve it
> > + * first. This is to accommodate possibly lazy-switched
> > + * selectors from above
> > + */
> > + cli
> > + popq %rdx
> > + popq %rax
> > + movq $MSR_KERNELGSBASE, %rcx
> > + wrmsr
> > +
> > + popw %gs
> > + popq %rdx
> > + popq %rax
> > + movq $MSR_GSBASE, %rcx
> > + wrmsr
> > +
> > + popw %fs
> > + popq %rdx
> > + popq %rax
> > + movq $MSR_FSBASE, %rcx
> > + wrmsr
> > +
> > + popw %ax
> > + movw %ax, %ss
> > + popw %ax
> > + movw %ax, %ds
> > + popw %ax
> > + movw %ax, %es
> > +
> > + xorq %rax, %rax
> > + lldtw %ax /* Host LDT is always 0 */
> > +
> > + popw %ax /* ax = saved TR */
> > +
> > + popq %rdx
> > + addq $0x2, %rdx
> > + movq (%rdx), %rdx
> > +
> > + /* rdx = GDTR base addr */
> > + andb $0xF9, 5(%rdx, %rax)
> > +
> > + ltrw %ax
> > +
> > + popfq
> > +
> > + movq %rdi, %rax
> > +
> > + RETGUARD_CHECK(svm_seves_enter_guest, r11)
> > + ret
> > + lfence
> > +END(svm_seves_enter_guest)
> > diff --git a/sys/arch/amd64/include/vmmvar.h b/sys/arch/amd64/include/vmmvar.h
> > index 8714fd1aace..03d86639476 100644
> > --- a/sys/arch/amd64/include/vmmvar.h
> > +++ b/sys/arch/amd64/include/vmmvar.h
> > @@ -852,6 +852,13 @@ struct vmsa {
> > uint64_t v_ic_ibs_xtd_ct;/* 7C0h */
> > };
> >
> > +/*
> > + * With SEV-ES the host save are (HSA) has the same layout as the
> > + * VMSA. However, it has the offset 0x400 into the HSA page.
> > + * See AMD APM Vol 2, Appendix B.
> > + */
> > +#define SVM_HSA_OFFSET 0x400
> > +
> > struct vmcs {
> > uint32_t vmcs_revision;
> > };
> > @@ -1028,6 +1035,7 @@ int invept(uint64_t, struct vmx_invept_descriptor *);
> > int vmx_enter_guest(paddr_t *, struct vcpu_gueststate *, int, uint8_t);
> > int svm_enter_guest(uint64_t, struct vcpu_gueststate *,
> > struct region_descriptor *);
> > +int svm_seves_enter_guest(uint64_t, vaddr_t, struct region_descriptor *);
> > void start_vmm_on_cpu(struct cpu_info *);
> > void stop_vmm_on_cpu(struct cpu_info *);
> > void vmclear_on_cpu(struct cpu_info *);
>
>
--
Dr. Hans-Jörg Höxer Hans-Joerg_Hoexer@genua.de
Senior Expert Kryptographie
eXtreme Kernel and Crypto Development
genua GmbH
Domagkstrasse 7, 85551 Kirchheim bei München
tel +49 89 991950-0, fax -999, www.genua.eu
Geschäftsführer: Matthias Ochs, Marc Tesch
Amtsgericht München HRB 98238
genua ist ein Unternehmen der Bundesdruckerei-Gruppe.
[EXT] Re: SEV-ES: vmm(4): vmentry/vmexit for SEV-ES guests