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

[Xen-devel] HVM x86 deprivileged mode: AMD SVM TR problem

Hi all,

I've hit a blocker on getting this working for AMD's SVM and would appreciate any thoughts. Hopefully I've missed a much simpler way of doing this or I've missed something!

So, AMD and Intel differ in how they handle the TR on a VMEXIT and VMRUM. On a VMEXIT, Intel Save the guest's TR and then restore the host's TR. AMD do not save the guest's TR nor do they restore the host's TR.

So, we need to context switch it out. The only ways that I know of to do this are with the ltr and str instructions. Now, ltr will throw #GP if loaded with a null selector and, when loaded, will immediately fetch from the current GDT the descriptor's data.

After issuing a VMEXIT and moving into deprivileged mode, I need a valid TSS so that we can handle exceptions in ring 3, otherwise, thanks to an invalid TSS selector in the TR causing a system shutdown (AMD manual), the guest could crash the system.

At the moment, I can save the guest's TR, load the host's TR and then happily handle exceptions when we are in ring 3 now so that's fixed the shutdown issue. But, when moving back to the guest, I have no easy way to restore the TR. If the guest's TR is 0, issuing ltr 0 throws #GP (manual) and won't load the register so we can't just ignore the fault and then VMRUN. If it's not 0, and we issue an ltr, it will immediately load from the host's GDT not the guest's GDT so then the guest will use those values.

Now, the ways I can see to fix this are:
We have to copy the guest's GDT entry for the TSS into the host's GDT at the same selector location, issue the ltr and then fix up the host's GDT. I think, given that AMD does store the GDTR and CR3, it will be possible to read the guest's GDT (not 100% on that) as we fetch this data (but that may be slow, as the GDTR holds a linear address so we'd need to traverse the page tables). But, this still doesn't solve the problem of when the guest's TR is 0. I guess we could load in a fake non-zero TR for a fake GDT entry and hope that the guest then sets up it's TR correctly. I think this situation is happening because the guest is causing a VMEXIT before it's setup its own TSS so I _think_ doing this is fine. However, this would leak information to the guest so it could tell it's in an HVM environment - don't know how serious that is.

Or: We have to inject some code into the guest's domain which the VMRUN jumps to. That code then loads in the TR for the guest and then we jump back to where we should have gone. The problem there is where to put that code in the guest's address space and how we do that injection.

Hopefully there is a better fix! Do you have any ideas or suggestions?

Many thanks in advance,

Xen-devel mailing list



Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.