Skip to content

[TDX] Improve instruction emulator by removing unecessary vmcs accesses #484

Closed
@babayet2

Description

@babayet2

Originally reported by @chris-oo, his words are copied below. PR #482

Today, the instruction emulator requires a bunch of state upfront that isn't necessarily needed for every exit. The EmulatorSupport trait is implemented by every arch backend, and taking a look at state() and set_state() on TDX we're forced to do additional VMCS queries via tdcall which require a roundtrip to the kernel:

fn state(&mut self) -> Result<x86emu::CpuState, Self::Error> {
        let cr0 = self.vp.backing.cr0.read(&self.vp.partition.hcl);
        let efer = self.vp.backing.efer;
        let gpr_list = self.vp.runner.tdx_gpr_list().unwrap();

        // TODO TDX: Only supports VTL0
        Ok(x86emu::CpuState {
            gps: gpr_list.gps,
            segs: [
                self.vp
                    .read_segment(Vtl::Vtl0, TdxSegmentReg::Es)
                    .expect("BUGBUG convert error")
                    .into(),
                self.vp
                    .read_segment(Vtl::Vtl0, TdxSegmentReg::Cs)
                    .expect("BUGBUG convert error")
                    .into(),
                self.vp
                    .read_segment(Vtl::Vtl0, TdxSegmentReg::Ss)
                    .expect("BUGBUG convert error")
                    .into(),
                self.vp
                    .read_segment(Vtl::Vtl0, TdxSegmentReg::Ds)
                    .expect("BUGBUG convert error")
                    .into(),
                self.vp
                    .read_segment(Vtl::Vtl0, TdxSegmentReg::Fs)
                    .expect("BUGBUG convert error")
                    .into(),
                self.vp
                    .read_segment(Vtl::Vtl0, TdxSegmentReg::Gs)
                    .expect("BUGBUG convert error")
                    .into(),
            ],
            rip: gpr_list.rip,
            rflags: gpr_list.rflags.into(),
            cr0,
            efer,
        })
    }

It would be preferable to modify the instruction emulator to only query the given state as needed. Most instructions don't need the full set of segment registers and system registers, and instead would only need CS which is returned via registers from the TDX module from VP.ENTER.

This also helps fix the set_state() path where we could return an error if we try to set an immutable field, whereas today we silently drop the state change.

Note that other platforms like MSHV and SNP have a much lower cost to querying batches of state upfront or have the state readily available, whereas on TDX each requires a roundtrip to the kernel via tdcall.

Metadata

Metadata

Assignees

Labels

tdxTDX specific bugs or features

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions