Bu sayfada, çekirdek tabanlı korumalı bir sanal makine (pKVM) tedarikçi modülünün nasıl uygulanacağı açıklanmaktadır. Bu adımları tamamladığınızda, şuna benzer bir dizin ağacınız olmalıdır:
Makefile
el1.c
hyp/
Makefile
el2.c
EL2 hipervizör kodunu (
el2.c
) ekleyin. Bu kod, en azındanpkvm_module_ops
yapısına referans kabul eden bir init işlevi beyan etmelidir:#include <asm/kvm_pkvm_module.h> int pkvm_driver_hyp_init(const struct pkvm_module_ops *ops) { /* Init the EL2 code */ return 0; }
pKVM tedarikçi modülü API'si, pKVM hipervizörü. Bu yapı, GKI arayüzleriyle aynı ABI kurallarını uygular.
Hipervizör kodunu oluşturmak için
hyp/Makefile
oluşturun:hyp-obj-y := el2.o include $(srctree)/arch/arm64/kvm/hyp/nvhe/Makefile.module
EL1 çekirdek kodunu (
el1.c
) ekleyin. Bu kodun başlangıç bölümü, 1. adımdaki EL2 hipervizör kodunu yüklemek içinpkvm_load_el2 module
çağrısı içermelidir.#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);
Son olarak, EL1 ve EL2 kodunu birbirine bağlamak için kök oluşturma dosyasını oluşturun:
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
pKVM modülü yükleme
GKI tedarikçi modüllerinde olduğu gibi, pKVM tedarikçi modülleri modprobe kullanılarak yüklenebilir.
Ancak, güvenlik nedeniyle, yükleme ayrıcalığı kaldırılmadan önce gerçekleşmelidir.
pKVM modülü yüklemek için modüllerinizin
kök dosya sistemine (initramfs
) aşağıdaki öğeleri de eklemeniz gerekir:
çekirdek komut satırı:
kvm-arm.protected_modules=mod1,mod2,mod3,...
initramfs
içinde depolanan pKVM tedarikçi modülleri, initramfs
imzasını ve korumasını devralır.
pKVM tedarikçi modüllerinden biri yüklenemezse sistemin güvenli olmadığı kabul edilir ve korumalı bir sanal makine başlatılamaz.
EL2'den (çekirdek modülü) bir EL2 (hipervizör) işlevi çağırma
Hipervizör çağrısı (HVC), çekirdeğin hipervizörü çağırmasına olanak tanıyan bir talimattır. pKVM tedarikçi firma modüllerinin kullanıma sunulmasıyla birlikte HVC, EL2'de (hipervizör modülünde) EL1'den (çekirdek modülü) çalıştırılacak bir işlev çağırmak için kullanılabilir:
- EL2 kodunda (
el2.c
) EL2 işleyicisini tanımlayın:
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;
}
EL1 kodunuzda (
el1.c
) EL2 işleyicisini pKVM tedarikçinize kaydedin modül: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);
EL1 kodunuzda (
el1.c
) HVC'yi arayın:pkvm_el2_mod_call(hvc_number);