Halaman ini menjelaskan cara menerapkan modul vendor virtual machine berbasis kernel (pKVM) yang dilindungi.
Untuk android16-6.12 dan yang lebih baru, setelah menyelesaikan langkah-langkah ini, Anda akan memiliki pohon direktori yang mirip dengan:
BUILD.bazel
el1.c
hyp/
BUILD.bazel
el2.c
Untuk contoh lengkapnya, lihat Membangun modul pKVM dengan DDK .
Untuk android15-6.6 dan yang lebih lama:
Makefile
el1.c
hyp/
Makefile
el2.c
Tambahkan kode hypervisor EL2 (
el2.c
). Minimal, kode ini harus mendeklarasikan fungsi init yang menerima referensi ke structpkvm_module_ops
:#include <asm/kvm_pkvm_module.h> int pkvm_driver_hyp_init(const struct pkvm_module_ops *ops) { /* Init the EL2 code */ return 0; }
API modul vendor pKVM adalah struct yang merangkum callback ke hypervisor pKVM. Struktur ini mengikuti aturan ABI yang sama dengan antarmuka GKI.
Buat
hyp/Makefile
untuk membangun kode hypervisor:hyp-obj-y := el2.o include $(srctree)/arch/arm64/kvm/hyp/nvhe/Makefile.module
Tambahkan kode kernel EL1 (
el1.c
). Bagian init kode ini harus berisi panggilan kepkvm_load_el2 module
untuk memuat kode hypervisor EL2 dari langkah 1.#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <asm/kvm_pkvm_module.h> int __kvm_nvhe_pkvm_driver_hyp_init(const struct pkvm_module_ops *ops); static int __init pkvm_driver_init(void) { unsigned long token; return pkvm_load_el2_module(__kvm_nvhe_pkvm_driver_hyp_init, &token); } module_init(pkvm_driver_init);
Terakhir, buat aturan build.
Untuk android16-6.12 dan yang lebih baru, lihat Membangun modul pKVM dengan DDK untuk membuat
ddk_library()
untuk EL2 danddk_module()
untuk EL1.Untuk android15-6.6 dan yang lebih lama, buat file makefile root untuk mengikat kode EL1 dan EL2:
ifneq ($(KERNELRELEASE),) clean-files := hyp/hyp.lds hyp/hyp-reloc.S obj-m := pkvm_module.o pkvm_module-y := el1.o hyp/kvm_nvhe.o $(PWD)/hyp/kvm_nvhe.o: FORCE $(Q)$(MAKE) $(build)=$(obj)/hyp $(obj)/hyp/kvm_nvhe.o else all: make -C $(KDIR) M=$(PWD) modules clean: make -C $(KDIR) M=$(PWD) clean endif
Memuat modul pKVM
Seperti modul vendor GKI, modul vendor pKVM dapat dimuat menggunakan modprobe.
Namun, karena alasan keamanan, pemuatan harus terjadi sebelum penghapusan hak istimewa.
Untuk memuat modul pKVM, Anda harus memastikan modul disertakan dalam
sistem file root (initramfs
) dan Anda harus menambahkan kode berikut ke
command line kernel:
kvm-arm.protected_modules=mod1,mod2,mod3,...
Modul vendor pKVM yang disimpan di initramfs
mewarisi tanda tangan dan perlindungan initramfs
.
Jika salah satu modul vendor pKVM gagal dimuat, sistem dianggap tidak aman dan mesin virtual yang dilindungi tidak dapat dimulai.
Memanggil fungsi EL2 (hypervisor) dari EL1 (modul kernel)
Panggilan hypervisor (HVC) adalah instruksi yang memungkinkan kernel memanggil hypervisor. Dengan diperkenalkannya modul vendor pKVM, HVC dapat digunakan untuk memanggil fungsi agar berjalan di EL2 (dalam modul hypervisor) dari EL1 (modul kernel):
- Dalam kode EL2 (
el2.c
), deklarasikan pengendali EL2:
Android-14
void pkvm_driver_hyp_hvc(struct kvm_cpu_context *ctx)
{
/* Handle the call */
cpu_reg(ctx, 1) = 0;
}
Android-15
void pkvm_driver_hyp_hvc(struct user_pt_regs *regs)
{
/* Handle the call */
regs->regs[0] = SMCCC_RET_SUCCESS;
regs->regs[1] = 0;
}
Dalam kode EL1 Anda (
el1.c
), daftarkan handler EL2 di modul vendor pKVM Anda:int __kvm_nvhe_pkvm_driver_hyp_init(const struct pkvm_module_ops *ops); void __kvm_nvhe_pkvm_driver_hyp_hvc(struct kvm_cpu_context *ctx); // Android14 void __kvm_nvhe_pkvm_driver_hyp_hvc(struct user_pt_regs *regs); // Android15 static int hvc_number; static int __init pkvm_driver_init(void) { long token; int ret; ret = pkvm_load_el2_module(__kvm_nvhe_pkvm_driver_hyp_init,token); if (ret) return ret; ret = pkvm_register_el2_mod_call(__kvm_nvhe_pkvm_driver_hyp_hvc, token) if (ret < 0) return ret; hvc_number = ret; return 0; } module_init(pkvm_driver_init);
Dalam kode EL1 (
el1.c
), panggil HVC:pkvm_el2_mod_call(hvc_number);