ANDROID: pkvm: x86: Implement secure startup of secondary vCPUs
Current way of starting secondary vCPUs of a pVM, based on INIT/SIPI
emulated by the host's KVM vLAPIC for the guest, is not secure, since
the host controls when to start running a secondary vCPU (so it may
start running when the pVM has not been verified by pvmfw on the primary
vCPU yet, so the pVM code is not trusted yet) and at what address (so it
may start running an arbitrary code).
So add support for letting pVMs start their vCPUs securely. Since LAPIC
is still emulated by the host, implement a new guest hypercall
PKVM_GHC_START_CPU to let pVM ask the pKVM hypervisor to start a CPU at
the given address (similarly to AMD SEV's approach), instead of relying
on INIT/SIPI.
To keep things simple, keep the semantics and the implementation quite
similar to the traditional emulated INIT/SIPI flow. The new flow is:
1. The guest, instead of issuing INIT and SIPI to the CPU's APIC, issues
the hypercall to pKVM asking it to start the vCPU (identified by its
APIC ID) at the given physical start address, at reset state in
16-bit real mode as usual.
2. pKVM marks the vCPU as runnable (i.e. allowed to be run by the host)
and remembers the start address provided by the guest (more
precisely, the sipi_vector calculated from it), and then forwards the
hypercall to the host to finish its handling (most importantly, to
let the host wake up the vcpu thread).
3. The host KVM "asserts" both INIT and SIPI signals of the vCPU's
vLAPIC and kicks the vCPU thread, to let it handle INIT and SIPI
as usual, i.e. reset the vCPU and start running it.
4. Before running the vCPU, pKVM detects that it is running for the
first time, checks that it has been allowed to run, and enforces
resetting it and starting it at the start address provided by the
guest.
This means that kvm_vcpu_reset() + kvm_vcpu_deliver_sipi_vector() done
by the host is almost redundant, since the same is done later by pKVM
anyway (except kvm_lapic_reset() which needs to be done by the host).
On the other hand, it allows to keep the changes simple and
non-intrusive.
Bug: 374338925
Test: run various VMs, check if SMP works
Upstream-Task: 402758258
Change-Id: I38274df30b19f08ec7ae514eed01f29479945636
Signed-off-by:
Dmytro Maluka <dmaluka@google.com>
Loading