A partire dal 27 marzo 2025, ti consigliamo di utilizzare android-latest-release anziché aosp-main per compilare e contribuire ad AOSP. Per ulteriori informazioni, vedi Modifiche ad AOSP.
Aggiungi il codice dell'hypervisor EL2 (el2.c). Come minimo, questo codice deve dichiarare una funzione di inizializzazione che accetti un riferimento alla struttura pkvm_module_ops:
L'API del modulo del fornitore pKVM è una struttura che incapsula i callback all'hypervisor pKVM. Questa struttura segue le stesse regole ABI delle interfacce GKI.
Crea il hyp/Makefile per compilare il codice dell'hypervisor:
Aggiungi il codice del kernel EL1 (el1.c). La sezione di inizializzazione di questo codice deve contenere una chiamata a pkvm_load_el2 module per caricare il codice dell'hypervisor EL2 del passaggio 1.
Come per i moduli del fornitore GKI, i moduli del fornitore pKVM possono essere caricati utilizzando modprobe.
Tuttavia, per motivi di sicurezza, il caricamento deve avvenire prima del ritiro dei privilegi.
Per caricare un modulo pKVM, devi assicurarti che i moduli siano inclusi nel file system principale (initramfs) e devi aggiungere quanto segue alla riga di comando del kernel:
kvm-arm.protected_modules=mod1,mod2,mod3,...
I moduli del fornitore di pKVM archiviati in initramfs ereditano la firma e la protezione di initramfs.
Se non riesce a caricare uno dei moduli del fornitore di pKVM, il sistema è considerato non sicuro e non sarà possibile avviare una macchina virtuale protetta.
Chiama una funzione EL2 (hypervisor) da EL1 (modulo del kernel)
Una chiamata all'hypervisor (HVC) è un'istruzione che consente al kernel di chiamare l'hypervisor. Con l'introduzione dei moduli del fornitore pKVM, un HVC può essere utilizzato per chiamare una funzione da eseguire in EL2 (nel modulo dell'hypervisor) da EL1 (il modulo del kernel):
Nel codice EL2 (el2.c), dichiara l'handler EL2:
Android-14
voidpkvm_driver_hyp_hvc(structkvm_cpu_context*ctx){/* Handle the call */cpu_reg(ctx,1)=0;}
Android-15
voidpkvm_driver_hyp_hvc(structuser_pt_regs*regs){/* Handle the call */regs->regs[0]=SMCCC_RET_SUCCESS;regs->regs[1]=0;}
Nel codice EL1 (el1.c), registra l'handler EL2 nel modulo del fornitore del pKVM:
I campioni di contenuti e codice in questa pagina sono soggetti alle licenze descritte nella Licenza per i contenuti. Java e OpenJDK sono marchi o marchi registrati di Oracle e/o delle sue società consociate.
Ultimo aggiornamento 2025-07-27 UTC.
[[["Facile da capire","easyToUnderstand","thumb-up"],["Il problema è stato risolto","solvedMyProblem","thumb-up"],["Altra","otherUp","thumb-up"]],[["Mancano le informazioni di cui ho bisogno","missingTheInformationINeed","thumb-down"],["Troppo complicato/troppi passaggi","tooComplicatedTooManySteps","thumb-down"],["Obsoleti","outOfDate","thumb-down"],["Problema di traduzione","translationIssue","thumb-down"],["Problema relativo a esempi/codice","samplesCodeIssue","thumb-down"],["Altra","otherDown","thumb-down"]],["Ultimo aggiornamento 2025-07-27 UTC."],[],[],null,["# Implement a pKVM vendor module\n\nThis page explains how to implement a protected kernel-based virtual machine\n(pKVM) vendor module.\n\nFor android16-6.12 and later, when you are done with these\nsteps, you should have a directory tree similar to: \n\n BUILD.bazel\n el1.c\n hyp/\n BUILD.bazel\n el2.c\n\nFor a complete example, see\n[Build a pKVM module with DDK](https://android.googlesource.com/kernel/build/+/refs/heads/main-kernel/kleaf/tests/ddk_examples/pkvm/README.md)\n.\n\nFor android15-6.6 and earlier: \n\n Makefile\n el1.c\n hyp/\n Makefile\n el2.c\n\n1. Add the EL2 hypervisor code (`el2.c`). At a minimum, this code must declare an init function accepting a reference to the `pkvm_module_ops` struct:\n\n #include \u003casm/kvm_pkvm_module.h\u003e\n\n int pkvm_driver_hyp_init(const struct pkvm_module_ops *ops)\n {\n /* Init the EL2 code */\n\n return 0;\n }\n\n The pKVM vendor module API is a struct encapsulating callbacks to the\n pKVM hypervisor. This struct follows the same ABI rules as GKI interfaces.\n | **Note:** Unlike the kernel, no symbol is exported and all calls to the hypervisor must happen through the callbacks in the struct [pkvm_module_ops](https://android.googlesource.com/kernel/common/+/refs/heads/android14-6.1/arch/arm64/include/asm/kvm_pkvm_module.h#19 \"kvm_pkvm_module.h\").\n2. Create the `hyp/Makefile` to build the hypervisor code:\n\n hyp-obj-y := el2.o\n include $(srctree)/arch/arm64/kvm/hyp/nvhe/Makefile.module\n\n3. Add the EL1 kernel code (`el1.c`). This code's init section must contain a call to `pkvm_load_el2 module` to load the EL2 hypervisor code from step 1.\n\n #include \u003clinux/init.h\u003e\n #include \u003clinux/module.h\u003e\n #include \u003clinux/kernel.h\u003e\n #include \u003casm/kvm_pkvm_module.h\u003e\n\n int __kvm_nvhe_pkvm_driver_hyp_init(const struct pkvm_module_ops *ops);\n\n static int __init pkvm_driver_init(void)\n {\n unsigned long token;\n\n return pkvm_load_el2_module(__kvm_nvhe_pkvm_driver_hyp_init, &token);\n }\n module_init(pkvm_driver_init);\n\n | **Note:** `__kvm_nvhe_pkvm_driver_hyp_init` is a pointer to the EL2 init function in the EL2 hypervisor code (step 1).\n4. Finally, create the build rules.\n\n For android16-6.12 and later, refer to\n [Build a pKVM module with DDK](https://android.googlesource.com/kernel/build/+/refs/heads/main-kernel/kleaf/tests/ddk_examples/pkvm/README.md)\n to create `ddk_library()` for EL2 and `ddk_module()` for EL1.\n\n For android15-6.6 and earlier, create the root makefile to tie the EL1 and\n EL2 code together: \n\n ifneq ($(KERNELRELEASE),)\n clean-files := hyp/hyp.lds hyp/hyp-reloc.S\n\n obj-m := pkvm_module.o\n pkvm_module-y := el1.o hyp/kvm_nvhe.o\n\n $(PWD)/hyp/kvm_nvhe.o: FORCE\n $(Q)$(MAKE) $(build)=$(obj)/hyp $(obj)/hyp/kvm_nvhe.o\n else\n all:\n make -C $(KDIR) M=$(PWD) modules\n clean:\n make -C $(KDIR) M=$(PWD) clean\n endif\n\nLoad a pKVM module\n------------------\n\nAs with GKI vendor modules, pKVM vendor modules can be loaded using modprobe.\nHowever, for security reasons, loading must occur before deprivileging.\nTo load a pKVM module, you must ensure your modules are included in\nthe root filesystem (`initramfs`) and you must add the following to your\nkernel command-line:\n\n`kvm-arm.protected_modules=`\u003cvar translate=\"no\"\u003emod1\u003c/var\u003e`,`\u003cvar translate=\"no\"\u003emod2\u003c/var\u003e`,`\u003cvar translate=\"no\"\u003emod3\u003c/var\u003e`,`\u003cvar translate=\"no\"\u003e...\u003c/var\u003e\n\npKVM vendor modules stored in the `initramfs` inherit the signature and protection of `initramfs`.\n\nIf one of the pKVM vendor modules fails to load, the system is considered insecure and it won't be possible to start a protected virtual machine.\n\nCall an EL2 (hypervisor) function from EL1 (kernel module)\n----------------------------------------------------------\n\nAn *hypervisor call (HVC)* is an instruction that lets the kernel to call the hypervisor. With the introduction of pKVM vendor modules, an HVC can be used to call for a function to run at EL2 (in the hypervisor module) from EL1 (the kernel module):\n\n1. In the EL2 code (`el2.c`), declare the EL2 handler:\n\n**Android-14** \n\n void pkvm_driver_hyp_hvc(struct kvm_cpu_context *ctx)\n {\n /* Handle the call */\n\n cpu_reg(ctx, 1) = 0;\n }\n\n**Android-15** \n\n void pkvm_driver_hyp_hvc(struct user_pt_regs *regs)\n {\n /* Handle the call */\n\n regs-\u003eregs[0] = SMCCC_RET_SUCCESS;\n regs-\u003eregs[1] = 0;\n }\n\n| **Note:** EL2 code is non preemptable. This section must therefore be as short as possible.\n\n1. In your EL1 code (`el1.c`), register the EL2 handler in your pKVM vendor\n module:\n\n int __kvm_nvhe_pkvm_driver_hyp_init(const struct pkvm_module_ops *ops);\n void __kvm_nvhe_pkvm_driver_hyp_hvc(struct kvm_cpu_context *ctx); // Android14\n void __kvm_nvhe_pkvm_driver_hyp_hvc(struct user_pt_regs *regs); // Android15\n\n static int hvc_number;\n\n static int __init pkvm_driver_init(void)\n {\n long token;\n int ret;\n\n ret = pkvm_load_el2_module(__kvm_nvhe_pkvm_driver_hyp_init,token);\n if (ret)\n return ret;\n\n ret = pkvm_register_el2_mod_call(__kvm_nvhe_pkvm_driver_hyp_hvc, token)\n if (ret \u003c 0)\n return ret;\n\n hvc_number = ret;\n\n return 0;\n }\n module_init(pkvm_driver_init);\n\n2. In your EL1 code (`el1.c`), call the HVC:\n\n pkvm_el2_mod_call(hvc_number);"]]