Ab dem 27. März 2025 empfehlen wir, android-latest-release anstelle von aosp-main zu verwenden, um AOSP zu erstellen und Beiträge dazu zu leisten. Weitere Informationen finden Sie unter Änderungen am AOSP.
Mit Sammlungen den Überblick behalten
Sie können Inhalte basierend auf Ihren Einstellungen speichern und kategorisieren.
Auf dieser Seite wird beschrieben, wie Sie ein Anbietermodul für eine geschützte kernelbasierte virtuelle Maschine (Protected Kernel-based Virtual Machine, pKVM) implementieren.
Bei Android 16-6.12 und höher sollte nach diesen Schritten eine Verzeichnisstruktur ähnlich der folgenden vorhanden sein:
Fügen Sie den EL2-Hypervisorcode (el2.c) hinzu. Dieser Code muss mindestens eine Init-Funktion deklarieren, die einen Verweis auf das pkvm_module_ops-Struktur akzeptiert:
Die pKVM-Anbietermodul-API ist ein struct, das Callbacks an den pKVM-Hypervisor kapselt. Diese Struktur folgt denselben ABI-Regeln wie GKI-Schnittstellen.
Erstellen Sie die hyp/Makefile, um den Hypervisorcode zu erstellen:
Fügen Sie den EL1-Kernelcode (el1.c) hinzu. Der Init-Abschnitt dieses Codes muss einen Aufruf an pkvm_load_el2 module enthalten, um den EL2-Hypervisorcode aus Schritt 1 zu laden.
Für android16-6.12 und höher finden Sie unter pKVM-Modul mit DDK erstellen Informationen zum Erstellen von ddk_library() für EL2 und ddk_module() für EL1.
Erstellen Sie für android15-6.6 und älter das Root-Makefile, um den EL1- und EL2-Code zu verknüpfen:
Wie bei GKI-Anbietermodulen können auch pKVM-Anbietermodule mit modprobe geladen werden.
Aus Sicherheitsgründen muss das Laden jedoch vor dem Entzug der Berechtigungen erfolgen.
Wenn Sie ein pKVM-Modul laden möchten, müssen Ihre Module im Stammdateisystem (initramfs) enthalten sein. Außerdem müssen Sie der Kernel-Befehlszeile Folgendes hinzufügen:
kvm-arm.protected_modules=mod1,mod2,mod3,...
In der initramfs gespeicherte pKVM-Anbietermodule übernehmen die Signatur und den Schutz von initramfs.
Wenn eines der pKVM-Anbietermodule nicht geladen werden kann, wird das System als unsicher eingestuft und es ist nicht möglich, eine geschützte virtuelle Maschine zu starten.
EL2-Funktion (Hypervisor) von EL1 (Kernelmodul) aufrufen
Ein Hypervisoraufruf (HVC) ist eine Anweisung, mit der der Kernel den Hypervisor aufrufen kann. Mit der Einführung von pKVM-Anbietermodulen kann ein HVC verwendet werden, um eine Funktion von EL1 (dem Kernelmodul) aus auf EL2 (im Hypervisormodul) auszuführen:
Deklarieren Sie im EL2-Code (el2.c) den EL2-Handler:
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;}
Registrieren Sie in Ihrem EL1-Code (el1.c) den EL2-Handler in Ihrem pKVM-Anbietermodul:
Alle Inhalte und Codebeispiele auf dieser Seite unterliegen den Lizenzen wie im Abschnitt Inhaltslizenz beschrieben. Java und OpenJDK sind Marken oder eingetragene Marken von Oracle und/oder seinen Tochtergesellschaften.
Zuletzt aktualisiert: 2025-07-27 (UTC).
[[["Leicht verständlich","easyToUnderstand","thumb-up"],["Mein Problem wurde gelöst","solvedMyProblem","thumb-up"],["Sonstiges","otherUp","thumb-up"]],[["Benötigte Informationen nicht gefunden","missingTheInformationINeed","thumb-down"],["Zu umständlich/zu viele Schritte","tooComplicatedTooManySteps","thumb-down"],["Nicht mehr aktuell","outOfDate","thumb-down"],["Problem mit der Übersetzung","translationIssue","thumb-down"],["Problem mit Beispielen/Code","samplesCodeIssue","thumb-down"],["Sonstiges","otherDown","thumb-down"]],["Zuletzt aktualisiert: 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);"]]