linux-surface / surface-pro-x

Tracking and meta repository for Surface Pro X support.
76 stars 6 forks source link

KVM Support #34

Open qzed opened 2 years ago

qzed commented 2 years ago

Quoting @jhaxhiaj from #7:

By default Linux boots in Exception Level 1 (Supervisor Level). In order to enable KVM, Linux must execute in Exception Level 2 (Hypervisor Level). My guess is that the UEFI Firmware is configured to boot every image (Windows Bootloader, USB Media, etc) in exception level 1. However Windows for ARM includes a functional Hyper-V (which requires execution in EL2). There must be a channel to unlock instruction execution in EL2.

The boot procedure on Surface Pro X looks similar to x86_64. UEFI FIRWMARE -> bootmgrfw.efi -> winload.efi​ -> hvloader.dll ... _xeroxz describes it here https://git.back.engineering/_xeroxz/Voyager

There is a lot of assumption below: The first method to execute arbitrary code in EL2 would to via a synchronous exception call to EL2 (HVC). Instruction address can be passed via general purpose register. This require a specific exception handler at EL2 which branches to the instruction address.

The second method is similar to the first but via the secure monitor in EL3 (hvc)

I see a lot of hvc and smc calls from hvloader.dll in Ghidra however Windows does not provide public symbols for hvloader.dll, which complicate its reverse engineering . UEFI firmware

Edit: A good starting point would be to dump the content of the exception tables in EL3 and EL2. However this can not be done from EL1 because VBAR_EL2,3 can't be accessed from EL1. I will see if this can be extracted from a UEFI firmware update and analyze them offline

qzed commented 2 years ago

I've found this on the topic:

For the Windows on Arm64 stack (on currently shipped SoCs), a mechanism, Secure Launch, is provided to escalate from EL1 to EL2. bootmgfw issues a SMC call, the function is the same as the one used to initialise Intel ACM or AMD SKINIT. QHEE intercepts it, does some sanity and integrity checks then remaps memory to load the TCB launcher and jumps to the entry point. This means that if you run Linux on those, you don't have EL2.

Source: https://news.ycombinator.com/item?id=30322404

As far as I understand, TCB is some sort of shim that is signed, verified, and gets launched in EL2 (whereas the call to launch it is made from EL1). Not sure whether it can be unsigned with secureboot disabled (likely not...). If not, this would probably require some exploit. Or we would have to re-use whatever blob Windows uses... if we can.

See also: https://argonsys.com/microsoft-cloud/library/force-firmware-code-to-be-measured-and-attested-by-secure-launch-on-windows-10/

gus33000 commented 2 years ago

Yes, it is my understanding Secure Launch is being used to take over the Qualcomm Hypervisor, but you also have a Secure Kernel extension in windows, QcSkExt8180.exe, which is loaded by the Hyper-V kernel to reimplement some now missing scm traps used for PIL. IOMMU support is also switched away from the qcsmmu driver to hyperv, and there's a shim driver, qciommu used to forward requests to the windows native api instead so existing drivers work. (Qualcomm drivers make use of a QC defined DDI/IOCTL set, smmu/iommu driver selection is decided depending on if hyper-v is enabled or not).