एक pKVM विक्रेता मॉड्यूल लागू करें

यह पृष्ठ बताता है कि संरक्षित कर्नेल-आधारित वर्चुअल मशीन (पीकेवीएम) विक्रेता मॉड्यूल को कैसे कार्यान्वित किया जाए। जब आप ये चरण पूरा कर लें, तो आपके पास निम्न जैसा एक निर्देशिका वृक्ष होना चाहिए:

Makefile
el1.c
hyp/
    Makefile
    el2.c
  1. EL2 हाइपरवाइज़र कोड ( el2.c ) जोड़ें। कम से कम, इस कोड को pkvm_module_ops संरचना के संदर्भ को स्वीकार करते हुए एक init फ़ंक्शन घोषित करना होगा:

    #include <asm/kvm_pkvm_module.h>
    
    int pkvm_driver_hyp_init(const struct pkvm_module_ops *ops)
    {
      /* Init the EL2 code */
    
      return 0;
    }
    

    पीकेवीएम विक्रेता मॉड्यूल एपीआई पीकेवीएम हाइपरवाइजर के लिए कॉलबैक को समाहित करने वाली एक संरचना है। यह संरचना जीकेआई इंटरफेस के समान एबीआई नियमों का पालन करती है।

  2. हाइपरवाइज़र कोड बनाने के लिए hyp/Makefile बनाएं:

    hyp-obj-y := el2.o
    include $(srctree)/arch/arm64/kvm/hyp/nvhe/Makefile.module
    
  3. EL1 कर्नेल कोड ( el1.c ) जोड़ें। इस कोड के init अनुभाग में चरण 1 से EL2 हाइपरवाइजर कोड को लोड करने के लिए pkvm_load_el2 module पर कॉल होनी चाहिए।

    #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);
    
  4. अंत में, EL1 और 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
    

एक pKVM मॉड्यूल लोड करें

GKI विक्रेता मॉड्यूल की तरह, pKVM विक्रेता मॉड्यूल को modprobe का उपयोग करके लोड किया जा सकता है। हालाँकि, सुरक्षा कारणों से, वंचित करने से पहले लोडिंग होनी चाहिए। पीकेवीएम मॉड्यूल को लोड करने के लिए, आपको यह सुनिश्चित करना होगा कि आपके मॉड्यूल रूट फाइल सिस्टम ( initramfs ) में शामिल हैं और आपको निम्नलिखित को अपने कर्नेल कमांड-लाइन में जोड़ना होगा:

kvm-arm.protected_modules= mod1 , mod2 , mod3 , ...

initramfs में संग्रहीत pKVM विक्रेता मॉड्यूल initramfs के हस्ताक्षर और सुरक्षा प्राप्त करते हैं।

यदि पीकेवीएम विक्रेता मॉड्यूल में से एक लोड करने में विफल रहता है, तो सिस्टम को असुरक्षित माना जाता है और संरक्षित वर्चुअल मशीन शुरू करना संभव नहीं होगा।

EL2 (कर्नेल मॉड्यूल) से EL2 (हाइपरवाइजर) फ़ंक्शन को कॉल करें

हाइपरवाइज़र कॉल (HVC) एक निर्देश है जो कर्नेल को हाइपरवाइज़र को कॉल करने देता है। पीकेवीएम विक्रेता मॉड्यूल की शुरूआत के साथ, एक एचवीसी का उपयोग ईएल1 (कर्नेल मॉड्यूल) से ईएल2 (हाइपरवाइजर मॉड्यूल में) चलाने के लिए फ़ंक्शन को कॉल करने के लिए किया जा सकता है:

  1. EL2 कोड ( el2.c ) में, EL2 हैंडलर घोषित करें:

    void pkvm_driver_hyp_hvc(struct kvm_cpu_context *ctx)
    {
      /* Handle the call */
    
      cpu_reg(ctx, 1) = 0;
    }
    
  2. अपने EL1 कोड ( el1.c ) में, EL2 हैंडलर को अपने pKVM विक्रेता मॉड्यूल में पंजीकृत करें:

    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);
    
    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);
    
  3. अपने EL1 कोड ( el1.c ) में, HVC को कॉल करें:

    pkvm_el2_mod_call(hvc_number);