एवीएफ़ आर्किटेक्चर

Android, Android वर्चुअलाइज़ेशन फ़्रेमवर्क को लागू करने के लिए ज़रूरी सभी कॉम्पोनेंट का रेफ़रंस लागू करता है. फ़िलहाल, यह सुविधा सिर्फ़ ARM64 के लिए उपलब्ध है. इस पेज पर, फ़्रेमवर्क के आर्किटेक्चर के बारे में बताया गया है.

बैकग्राउंड

आर्म आर्किटेक्चर में चार एक्सेप्शन लेवल होते हैं. इनमें एक्सेप्शन लेवल 0 (EL0) सबसे कम और एक्सेप्शन लेवल 3 (EL3) सबसे ज़्यादा विशेषाधिकार वाला होता है. Android के कोडबेस का सबसे बड़ा हिस्सा (सभी यूज़रस्पेस कॉम्पोनेंट) EL0 पर चलता है. "Android" के बाकी हिस्से को Linux कर्नेल कहा जाता है. यह EL1 पर चलता है.

EL2 लेयर, हाइपरवाइज़र को शुरू करने की अनुमति देती है. इससे EL1/EL0 पर, मेमोरी और डिवाइसों को अलग-अलग pVM में बांटा जा सकता है. साथ ही, यह गोपनीयता और इंटिग्रिटी की गारंटी देता है.

हाइपरवाइज़र

सुरक्षित कर्नल पर आधारित वर्चुअल मशीन (पीकेवीएम) को Linux KVM हाइपरवाइज़र पर बनाया गया है. इसे इस तरह से बनाया गया है कि यह उन पेलोड के ऐक्सेस को सीमित कर सकता है जो गेस्ट वर्चुअल मशीनों में चल रहे हैं. इन मशीनों को बनाते समय ‘सुरक्षित’ के तौर पर मार्क किया गया था.

KVM/arm64, सीपीयू की कुछ सुविधाओं की उपलब्धता के आधार पर अलग-अलग एक्ज़ीक्यूशन मोड के साथ काम करता है. जैसे, वर्चुअलाइज़ेशन होस्ट एक्सटेंशन (वीएचई) (ARMv8.1 और उसके बाद के वर्शन). इन मोड में से एक को आम तौर पर नॉन-वीएचई मोड के तौर पर जाना जाता है. इस मोड में, बूट के दौरान हाइपरवाइज़र कोड को कर्नल इमेज से अलग कर दिया जाता है और इसे EL2 पर इंस्टॉल किया जाता है. वहीं, कर्नल खुद EL1 पर चलता है. KVM का EL2 कॉम्पोनेंट, Linux कोडबेस का हिस्सा है. हालांकि, यह एक छोटा कॉम्पोनेंट है. यह कई EL1 के बीच स्विच करने के लिए ज़िम्मेदार होता है. हाइपरवाइज़र कॉम्पोनेंट को Linux के साथ कंपाइल किया जाता है. हालांकि, यह vmlinux इमेज के अलग और खास मेमोरी सेक्शन में मौजूद होता है. pKVM इस डिज़ाइन का इस्तेमाल करता है. इसके लिए, वह हाइपरवाइज़र कोड को नई सुविधाओं के साथ बढ़ाता है. इससे, Android होस्ट कर्नल और उपयोगकर्ता स्पेस पर पाबंदियां लगाई जा सकती हैं. साथ ही, होस्ट के ऐक्सेस को गेस्ट मेमोरी और हाइपरवाइज़र तक सीमित किया जा सकता है.

pKVM वेंडर मॉड्यूल

pKVM वेंडर मॉड्यूल, हार्डवेयर के हिसाब से बनाया गया मॉड्यूल होता है. इसमें डिवाइस के हिसाब से काम करने वाली सुविधाएं होती हैं. जैसे, इनपुट-आउटपुट मेमोरी मैनेजमेंट यूनिट (आईओएमएमयू) ड्राइवर. इन मॉड्यूल की मदद से, सुरक्षा से जुड़ी उन सुविधाओं को pKVM पर पोर्ट किया जा सकता है जिनके लिए, एक्सेप्शन लेवल 2 (EL2) का ऐक्सेस ज़रूरी होता है.

pKVM वेंडर मॉड्यूल को लागू करने और लोड करने का तरीका जानने के लिए, pKVM वेंडर मॉड्यूल लागू करना लेख पढ़ें.

बूट करने की प्रोसेस

इस इमेज में, pKVM बूट करने की प्रोसेस दिखाई गई है:

pKVM बूट करने की प्रक्रिया

पहली इमेज. pKVM बूट करने की प्रोसेस

  1. बूटलोडर, EL2 पर सामान्य कर्नल में प्रवेश करता है.
  2. जेनेरिक कर्नल को पता चलता है कि यह EL2 पर चल रहा है. इसलिए, यह खुद को EL1 पर ले जाता है. वहीं, pKVM और इसके मॉड्यूल EL2 पर चलते रहते हैं. इसके अलावा, pKVM वेंडर मॉड्यूल भी इसी समय लोड किए जाते हैं.
  3. जेनेरिक कर्नल सामान्य तौर पर बूट होता है. यह उपयोगकर्ता स्पेस तक पहुंचने से पहले, डिवाइस के सभी ज़रूरी ड्राइवर लोड करता है. इस समय, pKVM चालू हो जाता है और स्टेज-2 की पेज टेबल को मैनेज करता है.

बूट करने की प्रोसेस, बूटलोडर पर भरोसा करती है कि वह शुरुआती बूट के दौरान कर्नल इमेज की अखंडता को बनाए रखेगा. जब कर्नल को कम विशेषाधिकार दिए जाते हैं, तो हाइपरवाइज़र उसे भरोसेमंद नहीं मानता. इसके बाद, कर्नल के साथ समझौता होने पर भी, हाइपरवाइज़र खुद को सुरक्षित रखने के लिए ज़िम्मेदार होता है.

Android कर्नल और हाइपरवाइज़र को एक ही बाइनरी इमेज में रखने से, उनके बीच बहुत कम समय में डेटा ट्रांसफ़र हो पाता है. इन दोनों कॉम्पोनेंट को एक साथ अपडेट करने की सुविधा मिलती है. इससे, दोनों के बीच इंटरफ़ेस को स्थिर रखने की ज़रूरत नहीं पड़ती. साथ ही, लंबे समय तक रखरखाव में कोई समस्या नहीं आती. इन दोनों कॉम्पोनेंट के बीच मज़बूत कनेक्शन होने की वजह से, परफ़ॉर्मेंस को ऑप्टिमाइज़ किया जा सकता है. ऐसा तब होता है, जब दोनों कॉम्पोनेंट हाइपरवाइज़र की सुरक्षा से जुड़ी गारंटी पर असर डाले बिना एक-दूसरे के साथ काम कर सकते हैं.

इसके अलावा, Android इकोसिस्टम में जीकेआई को अपनाने से, pKVM हाइपरवाइज़र को Android डिवाइसों पर अपने-आप डिप्लॉय किया जा सकता है. यह कर्नेल के साथ एक ही बाइनरी में होता है.

सीपीयू की मेमोरी को ऐक्सेस करने से जुड़ी सुरक्षा

आर्म आर्किटेक्चर में, मेमोरी मैनेजमेंट यूनिट (एमएमयू) को दो अलग-अलग चरणों में बांटा गया है. इन दोनों चरणों का इस्तेमाल, पते के अनुवाद और मेमोरी के अलग-अलग हिस्सों को ऐक्सेस करने के लिए किया जा सकता है. पहले चरण के एमएमयू को EL1 कंट्रोल करता है. इससे पते का अनुवाद पहली बार किया जा सकता है. पहले चरण के एमएमयू का इस्तेमाल Linux करता है. इससे वह हर यूज़रस्पेस प्रोसेस और अपने वर्चुअल पता स्पेस को मैनेज कर पाता है.

दूसरे चरण के एमएमयू को EL2 कंट्रोल करता है. यह पहले चरण के एमएमयू के आउटपुट पते पर दूसरे पते के अनुवाद को लागू करता है. इससे फ़िज़िकल पता (पीए) मिलता है. दूसरे चरण के अनुवाद का इस्तेमाल हाइपरवाइज़र, इन कामों के लिए कर सकते हैं: सभी गेस्ट वीएम से मेमोरी ऐक्सेस को कंट्रोल करना और उनका अनुवाद करना. दूसरी इमेज में दिखाया गया है कि अनुवाद के दोनों चरणों के चालू होने पर, पहले चरण के आउटपुट पते को इंटरमीडिएट फ़िज़िकल पता (आईपीए) कहा जाता है. ध्यान दें: वर्चुअल पते (वीए) का अनुवाद पहले आईपीए में किया जाता है. इसके बाद, इसे पीए में बदला जाता है.

सीपीयू की मेमोरी को ऐक्सेस करने से जुड़ी सुरक्षा

दूसरी इमेज. सीपीयू की मेमोरी को सुरक्षित तरीके से ऐक्सेस करने की सुविधा

पहले, KVM गेस्ट ऑपरेटिंग सिस्टम चलाते समय स्टेज 2 ट्रांसलेशन को चालू रखता था. वहीं, होस्ट Linux कर्नल चलाते समय इसे बंद रखता था. इस आर्किटेक्चर की मदद से, होस्ट के स्टेज 1 एमएमयू से मेमोरी ऐक्सेस, स्टेज 2 एमएमयू से होकर गुज़रता है. इसलिए, होस्ट को गेस्ट मेमोरी पेजों का पूरा ऐक्सेस मिलता है. दूसरी ओर, pKVM होस्ट कॉन्टेक्स्ट में भी दूसरे चरण की सुरक्षा को चालू करता है. साथ ही, हाइपरवाइज़र को होस्ट के बजाय गेस्ट मेमोरी पेजों की सुरक्षा करने की ज़िम्मेदारी देता है.

KVM, दूसरे चरण में पता अनुवाद का पूरा इस्तेमाल करता है, ताकि मेहमानों के लिए जटिल आईपीए/पीए मैपिंग लागू की जा सके. इससे मेहमानों के लिए, फ़िज़िकल फ़्रैगमेंटेशन के बावजूद लगातार मेमोरी का भ्रम पैदा होता है. हालांकि, होस्ट के लिए स्टेज 2 के एमएमयू का इस्तेमाल, सिर्फ़ ऐक्सेस कंट्रोल तक सीमित है. होस्ट स्टेज 2 को आइडेंटिटी-मैप किया जाता है. इससे यह पक्का होता है कि होस्ट के आईपीए स्पेस में लगातार मौजूद मेमोरी, पीए स्पेस में भी लगातार मौजूद हो. इस आर्किटेक्चर की मदद से, पेज टेबल में बड़े मैपिंग का इस्तेमाल किया जा सकता है. इससे ट्रांसलेशन लुकसाइड बफ़र (टीएलबी) पर दबाव कम होता है. आइडेंटिटी मैपिंग को पीए इंडेक्स कर सकता है. इसलिए, होस्ट स्टेज 2 का इस्तेमाल पेज के मालिकाना हक को सीधे तौर पर पेज टेबल में ट्रैक करने के लिए भी किया जाता है.

डायरेक्ट मेमोरी ऐक्सेस (डीएमए) से सुरक्षा

जैसा कि पहले बताया गया है, सीपीयू पेज टेबल में Linux होस्ट से गेस्ट पेज को अनमैप करना, गेस्ट मेमोरी को सुरक्षित रखने के लिए ज़रूरी है. हालांकि, यह काफ़ी नहीं है. pKVM को होस्ट कर्नल के कंट्रोल में मौजूद, डीएमए की सुविधा वाले डिवाइसों के मेमोरी ऐक्सेस से भी सुरक्षा करनी होती है. साथ ही, उसे किसी दुर्भावनापूर्ण होस्ट की ओर से शुरू किए गए डीएमए हमले से भी सुरक्षा करनी होती है. ऐसे डिवाइस को गेस्ट मेमोरी ऐक्सेस करने से रोकने के लिए, pKVM को सिस्टम में DMA की सुविधा वाले हर डिवाइस के लिए, इनपुट-आउटपुट मेमोरी मैनेजमेंट यूनिट (IOMMU) हार्डवेयर की ज़रूरत होती है. इसे इमेज 3 में दिखाया गया है.

डीएमए मेमोरी ऐक्सेस सुरक्षा

तीसरी इमेज. डीएमए मेमोरी ऐक्सेस सुरक्षा

कम से कम, IOMMU हार्डवेयर, किसी डिवाइस को पेज के हिसाब से फ़िज़िकल मेमोरी के लिए पढ़ने/लिखने का ऐक्सेस देने और रद्द करने का तरीका उपलब्ध कराता है. हालांकि, यह IOMMU हार्डवेयर, pVM में डिवाइसों के इस्तेमाल को सीमित करता है, क्योंकि वे आइडेंटिटी-मैप्ड स्टेज 2 को मानते हैं.

वर्चुअल मशीनों को अलग-अलग रखने के लिए, अलग-अलग इकाइयों की ओर से जनरेट किए गए मेमोरी लेन-देन को आईओएमएमयू से अलग किया जाना चाहिए, ताकि अनुवाद के लिए पेज टेबल के सही सेट का इस्तेमाल किया जा सके.

इसके अलावा, EL2 पर एसओसी के हिसाब से कोड की मात्रा को कम करना, pKVM के भरोसेमंद कंप्यूटिंग बेस (टीसीबी) को कम करने की एक अहम रणनीति है. साथ ही, यह हाइपरवाइज़र में IOMMU ड्राइवर को शामिल करने के ख़िलाफ़ है. इस समस्या को कम करने के लिए, EL1 पर मौजूद होस्ट, IOMMU को मैनेज करने से जुड़े सहायक टास्क के लिए ज़िम्मेदार होता है. जैसे, पावर मैनेजमेंट, शुरू करना, और जहां ज़रूरी हो वहां इंटरप्ट हैंडल करना.

हालांकि, डिवाइस की स्थिति को कंट्रोल करने की सुविधा होस्ट को देने से, IOMMU हार्डवेयर के प्रोग्रामिंग इंटरफ़ेस पर कुछ और ज़रूरी शर्तें लागू हो जाती हैं. इससे यह पक्का किया जा सकता है कि अनुमति की जांच को किसी अन्य तरीके से बायपास न किया जा सके. उदाहरण के लिए, डिवाइस को रीसेट करने के बाद.

आइसोलेशन और डायरेक्ट असाइनमेंट, दोनों को मुमकिन बनाने के लिए, Arm डिवाइसों के लिए एक स्टैंडर्ड और अच्छी तरह से काम करने वाला आईओएमएमयू, Arm सिस्टम मेमोरी मैनेजमेंट यूनिट (एसएमएमयू) आर्किटेक्चर है. इस आर्किटेक्चर को रेफ़रंस के तौर पर इस्तेमाल करने का सुझाव दिया जाता है.

मेमोरी का मालिकाना हक

बूट होने के समय, हाइपरवाइज़र के अलावा अन्य सभी मेमोरी को होस्ट के मालिकाना हक वाली मेमोरी माना जाता है. साथ ही, हाइपरवाइज़र इसे इसी तरह ट्रैक करता है. जब कोई pVM शुरू होता है, तो होस्ट उसे बूट करने के लिए मेमोरी पेज दान करता है. इसके बाद, हाइपरवाइज़र उन पेजों का मालिकाना हक होस्ट से pVM को ट्रांसफ़र कर देता है. इसलिए, हाइपरवाइज़र होस्ट के स्टेज 2 पेज टेबल में ऐक्सेस कंट्रोल से जुड़ी पाबंदियां लगाता है, ताकि वह पेजों को फिर से ऐक्सेस न कर सके. इससे मेहमान को निजता मिलती है.

होस्ट और मेहमानों के बीच बातचीत, मेमोरी को कंट्रोल करके शेयर करने की सुविधा की वजह से हो पाती है. मेहमानों को हाइपरकॉल का इस्तेमाल करके, अपने कुछ पेजों को होस्ट के साथ वापस शेयर करने की अनुमति होती है. इससे हाइपरवाइज़र को होस्ट के स्टेज 2 पेज टेबल में उन पेजों को फिर से मैप करने का निर्देश मिलता है. इसी तरह, होस्ट के TrustZone के साथ कम्यूनिकेशन को मेमोरी शेयर करने और/या उधार लेने की कार्रवाइयों के ज़रिए मुमकिन बनाया जाता है. इन सभी कार्रवाइयों पर pKVM की नज़र रहती है और वह इन्हें कंट्रोल करता है. इसके लिए, वह आर्म के लिए फ़र्मवेयर फ़्रेमवर्क (एफ़एफ़-ए) स्पेसिफ़िकेशन का इस्तेमाल करता है.

समय के साथ-साथ, pVM की मेमोरी की ज़रूरतें बदल सकती हैं. इसलिए, एक हाइपरकॉल उपलब्ध कराया जाता है. इससे, कॉल करने वाले व्यक्ति के पास मौजूद पेजों का मालिकाना हक वापस होस्ट को दिया जा सकता है. इस हाइपरकॉल का इस्तेमाल, virtio balloon प्रोटोकॉल के साथ किया जाता है. इससे वीएमएम, पीवीएम से मेमोरी वापस पाने का अनुरोध कर सकता है. साथ ही, पीवीएम, वीएमएम को छोड़े गए पेजों के बारे में सूचना दे सकता है. यह सब कंट्रोल किए गए तरीके से होता है.

सिस्टम में मौजूद सभी मेमोरी पेजों के मालिकाना हक को ट्रैक करने की ज़िम्मेदारी हाइपरवाइज़र की होती है. साथ ही, यह भी ट्रैक करने की ज़िम्मेदारी हाइपरवाइज़र की होती है कि मेमोरी पेजों को अन्य इकाइयों के साथ शेयर किया जा रहा है या उन्हें उधार दिया जा रहा है. स्टेट ट्रैकिंग का ज़्यादातर काम, होस्ट और मेहमानों की स्टेज 2 पेज टेबल से जुड़े मेटाडेटा का इस्तेमाल करके किया जाता है. इसके लिए, पेज टेबल एंट्री (पीटीई) में रिज़र्व किए गए बिट का इस्तेमाल किया जाता है. जैसा कि इनके नाम से पता चलता है, इन्हें सॉफ़्टवेयर के इस्तेमाल के लिए रिज़र्व किया जाता है.

होस्ट को यह पक्का करना होगा कि वह उन पेजों को ऐक्सेस करने की कोशिश न करे जिन्हें हाइपरवाइज़र ने ऐक्सेस करने से रोक दिया है. होस्ट को गैर-कानूनी तरीके से ऐक्सेस करने पर, हाइपरवाइज़र होस्ट में सिंक्रोनस अपवाद डालता है. इससे, ज़िम्मेदार यूज़रस्पेस टास्क को SEGV सिग्नल मिल सकता है या होस्ट कर्नल क्रैश हो सकता है. अनजाने में होने वाले ऐक्सेस को रोकने के लिए, मेहमानों को दान किए गए पेजों को होस्ट कर्नल स्वैप या मर्ज नहीं कर सकता.

रुकावटों को मैनेज करना और टाइमर

इंटरप्ट, मेहमान के डिवाइसों के साथ इंटरैक्ट करने का एक ज़रूरी हिस्सा है. साथ ही, सीपीयू के बीच कम्यूनिकेशन के लिए भी यह ज़रूरी है. इसमें इंटरप्रोसेसर इंटरप्ट (आईपीआई) कम्यूनिकेशन का मुख्य तरीका है. KVM मॉडल में, सभी वर्चुअल इंटरप्ट मैनेजमेंट को EL1 में होस्ट को सौंप दिया जाता है. इस वजह से, यह हाइपरवाइज़र के एक ऐसे हिस्से के तौर पर काम करता है जिस पर भरोसा नहीं किया जा सकता.

pKVM, मौजूदा KVM कोड के आधार पर, पूरी तरह से जेनेरिक इंटरप्ट कंट्रोलर वर्शन 3 (GICv3) इम्यूलेशन उपलब्ध कराता है. टाइमर और आईपीआई को, भरोसेमंद नहीं माने जाने वाले इस इम्यूलेशन कोड के तहत मैनेज किया जाता है.

GICv3 के साथ काम करता है

EL1 और EL2 के बीच इंटरफ़ेस को यह पक्का करना होगा कि इंटरप्ट की पूरी स्थिति EL1 होस्ट को दिखे. इसमें इंटरप्ट से जुड़े हाइपरवाइज़र रजिस्टर की कॉपी भी शामिल हैं. आम तौर पर, यह विज़िबिलिटी शेयर की गई मेमोरी के क्षेत्रों का इस्तेमाल करके हासिल की जाती है. हर वर्चुअल सीपीयू (वीसीपीयू) के लिए एक क्षेत्र होता है.

सिस्टम रजिस्टर रनटाइम सपोर्ट कोड को आसान बनाया जा सकता है, ताकि यह सिर्फ़ सॉफ़्टवेयर जनरेटेड इंटरप्ट रजिस्टर (एसजीआईआर) और डीऐक्टिवेट इंटरप्ट रजिस्टर (डीआईआर) रजिस्टर ट्रैपिंग के साथ काम कर सके. आर्किटेक्चर के मुताबिक, इन रजिस्टर को हमेशा EL2 पर ट्रैप करना होता है. वहीं, अन्य ट्रैप अब तक सिर्फ़ errata को कम करने के लिए फ़ायदेमंद रहे हैं. बाकी सभी काम हार्डवेयर में किए जा रहे हैं.

MMIO की तरफ़ से, EL1 पर हर चीज़ का इम्यूलेशन किया जाता है. साथ ही, KVM में मौजूद सभी मौजूदा इंफ़्रास्ट्रक्चर का फिर से इस्तेमाल किया जाता है. आखिर में, Wait for Interrupt (WFI) को हमेशा EL1 पर भेजा जाता है, क्योंकि यह KVM की बुनियादी शेड्यूलिंग प्रिमिटिव में से एक है.

टाइमर की सुविधा

वर्चुअल टाइमर के लिए तुलना करने वाली वैल्यू को हर ट्रैपिंग WFI पर EL1 को दिखाना होगा, ताकि EL1, vCPU के ब्लॉक होने पर टाइमर इंटरप्ट इंजेक्ट कर सके. फ़िज़िकल टाइमर पूरी तरह से इम्यूलेट किया जाता है और सभी ट्रैप EL1 को भेजे जाते हैं.

MMIO हैंडलिंग

वर्चुअल मशीन मॉनिटर (वीएमएम) से कम्यूनिकेट करने और जीआईसी इम्यूलेशन करने के लिए, एमएमआईओ ट्रैप को EL1 में होस्ट पर वापस भेजना होगा, ताकि आगे की जांच की जा सके. pKVM के लिए, ये ज़रूरी शर्तें पूरी होनी चाहिए:

  • आईपीए और ऐक्सेस का साइज़
  • लिखने के अनुरोध के मामले में डेटा
  • ट्रैपिंग के समय सीपीयू का एंडियननेस

इसके अलावा, सोर्स/डेस्टिनेशन के तौर पर सामान्य मकसद के रजिस्टर (जीपीआर) वाले ट्रैप, ऐब्स्ट्रैक्ट ट्रांसफ़र स्यूडो-रजिस्टर का इस्तेमाल करके रिले किए जाते हैं.

गेस्ट इंटरफ़ेस

कोई मेहमान, सुरक्षित मेहमान से कम्यूनिकेट कर सकता है. इसके लिए, वह हाइपरकॉल और ट्रैप्ड रीज़न के मेमोरी ऐक्सेस का इस्तेमाल करता है. हाइपरकॉल, एसएमसीसीसी स्टैंडर्ड के हिसाब से दिखाए जाते हैं. साथ ही, केवीएम के ज़रिए वेंडर के लिए एक रेंज रिज़र्व की जाती है. नीचे दिए गए हाइपरकॉल, pKVM गेस्ट के लिए खास तौर पर ज़रूरी हैं.

जेनेरिक हाइपरकॉल

  • PSCI, मेहमान को अपने vCPU के लाइफ़साइकल को कंट्रोल करने के लिए एक स्टैंडर्ड मैकेनिज़्म उपलब्ध कराता है. इसमें ऑनलाइन करना, ऑफ़लाइन करना, और सिस्टम बंद करना शामिल है.
  • टीआरएनजी, मेहमान को पीकेवीएम से एंट्रॉपी का अनुरोध करने के लिए एक स्टैंडर्ड तरीका उपलब्ध कराता है. पीकेवीएम, कॉल को EL3 पर रिले करता है. यह तरीका खास तौर पर तब काम आता है, जब होस्ट पर हार्डवेयर रैंडम नंबर जनरेटर (आरएनजी) को वर्चुअलाइज़ करने के लिए भरोसा नहीं किया जा सकता.

pKVM हाइपरकॉल

  • होस्ट के साथ यादें शेयर करना. शुरुआत में, मेहमान के पास मौजूद मेमोरी को होस्ट ऐक्सेस नहीं कर सकता. हालांकि, शेयर की गई मेमोरी से कम्यूनिकेट करने और शेयर किए गए बफ़र पर निर्भर रहने वाले पैरावर्चुअलाइज़्ड डिवाइसों के लिए, होस्ट का ऐक्सेस ज़रूरी है. होस्ट के साथ पेजों को शेयर और अनशेयर करने के लिए हाइपरकॉल की सुविधा उपलब्ध है. इससे मेहमान को यह तय करने की अनुमति मिलती है कि मेमोरी के किन हिस्सों को Android के बाकी हिस्सों के लिए उपलब्ध कराया जाए. इसके लिए, हैंडशेक की ज़रूरत नहीं होती.
  • होस्ट को मेमोरी वापस देना. आम तौर पर, मेहमान के तौर पर इस्तेमाल किए जा रहे डिवाइस की मेमोरी, मेहमान के पास ही रहती है. ऐसा तब तक होता है, जब तक उसे मिटा न दिया जाए. यह स्थिति, लंबे समय तक चलने वाले उन वीएम के लिए सही नहीं हो सकती जिनकी मेमोरी की ज़रूरतें समय के साथ बदलती रहती हैं. relinquish हाइपरकॉल की मदद से, मेहमान के पास पेजों का मालिकाना हक वापस होस्ट को ट्रांसफ़र करने का विकल्प होता है. इसके लिए, मेहमान को मीटिंग से हटाने की ज़रूरत नहीं होती.
  • मेमोरी ऐक्सेस ट्रैपिंग को होस्ट करें. आम तौर पर, अगर KVM गेस्ट किसी ऐसे पते को ऐक्सेस करता है जो मान्य मेमोरी क्षेत्र से मेल नहीं खाता है, तो vCPU थ्रेड होस्ट से बाहर निकल जाता है. साथ ही, ऐक्सेस का इस्तेमाल आम तौर पर MMIO के लिए किया जाता है. इसे उपयोगकर्ता स्पेस में VMM से इम्यूलेट किया जाता है. इस प्रोसेस को आसान बनाने के लिए, pKVM को गड़बड़ी वाले निर्देश की जानकारी देनी होती है. जैसे, उसका पता, रजिस्टर पैरामीटर, और संभावित तौर पर उनके कॉन्टेंट को वापस होस्ट पर भेजना होता है. अगर ट्रैप का अनुमान नहीं लगाया गया था, तो इससे सुरक्षित गेस्ट से संवेदनशील डेटा अनजाने में ज़ाहिर हो सकता है. pKVM इस समस्या को हल करता है. इसके लिए, वह इन गड़बड़ियों को गंभीर गड़बड़ियों के तौर पर मानता है. हालांकि, ऐसा तब तक होता है, जब तक गेस्ट ने पहले से ही गड़बड़ी वाली आईपीए रेंज की पहचान करने के लिए हाइपरकॉल जारी न किया हो. इस रेंज के लिए, होस्ट को वापस ट्रैप करने की अनुमति दी जाती है. इस समाधान को एमएमआईओ गार्ड कहा जाता है.

वर्चुअल I/O डिवाइस (virtio)

Virtio, पैरावर्चुअलाइज़्ड डिवाइसों को लागू करने और उनके साथ इंटरैक्ट करने के लिए एक लोकप्रिय, पोर्टेबल, और मैच्योर स्टैंडर्ड है. सुरक्षित मेहमानों के लिए उपलब्ध कराए गए ज़्यादातर डिवाइसों में virtio का इस्तेमाल किया जाता है. Virtio, vsock को भी सपोर्ट करता है. इसका इस्तेमाल, सुरक्षित गेस्ट और Android के बाकी हिस्सों के बीच कम्यूनिकेशन के लिए किया जाता है.

आम तौर पर, Virtio डिवाइसों को होस्ट के उपयोगकर्ता स्पेस में VMM लागू करता है. यह Virtio डिवाइस के MMIO इंटरफ़ेस से मेहमान के ट्रैप्ड मेमोरी ऐक्सेस को इंटरसेप्ट करता है और अनुमानित व्यवहार का पालन करता है. MMIO ऐक्सेस करना महंगा होता है, क्योंकि डिवाइस को हर बार ऐक्सेस करने के लिए, VMM को राउंड-ट्रिप करने की ज़रूरत होती है. इसलिए, डिवाइस और मेहमान के बीच ज़्यादातर डेटा ट्रांसफ़र, मेमोरी में मौजूद virtqueues के सेट का इस्तेमाल करके होता है. virtio की मुख्य मान्यता यह है कि होस्ट, मेहमान की मेमोरी को अपनी मर्ज़ी से ऐक्सेस कर सकता है. यह अनुमान, virtqueue के डिज़ाइन में दिखता है. इसमें मेहमान के बफ़र के पॉइंटर शामिल हो सकते हैं. डिवाइस इम्यूलेशन को सीधे तौर पर इन बफ़र को ऐक्सेस करना होता है.

हालांकि, पहले बताए गए मेमोरी शेयरिंग हाइपरकॉल का इस्तेमाल, मेहमान से होस्ट तक virtio डेटा बफ़र शेयर करने के लिए किया जा सकता है. हालांकि, यह शेयरिंग पेज के हिसाब से की जाती है. अगर बफ़र का साइज़, पेज के साइज़ से कम है, तो इससे ज़रूरत से ज़्यादा डेटा का पता चल सकता है. इसके बजाय, गेस्ट को शेयर की गई मेमोरी की तय की गई विंडो से, दोनों वर्टक्वी और उनके डेटा बफ़र को असाइन करने के लिए कॉन्फ़िगर किया जाता है. साथ ही, ज़रूरत के मुताबिक डेटा को विंडो में कॉपी (बाउंस) किया जाता है.

आभासी उपकरण

चौथी इमेज. Virtio डिवाइस

TrustZone के साथ इंटरैक्शन

मेहमान सीधे तौर पर TrustZone से इंटरैक्ट नहीं कर सकते. हालांकि, होस्ट को अब भी सुरक्षित दुनिया में SMC कॉल जारी करने की सुविधा मिलनी चाहिए. ये कॉल, मेमोरी बफ़र के लिए फ़िज़िकल पते तय कर सकते हैं. हालांकि, होस्ट के पास इन पतों का ऐक्सेस नहीं होता. आम तौर पर, सुरक्षित सॉफ़्टवेयर को बफ़र की ऐक्सेसिबिलिटी के बारे में पता नहीं होता. इसलिए, कोई दुर्भावनापूर्ण होस्ट इस बफ़र का इस्तेमाल, कंफ्यूज़्ड डेप्युटी अटैक (डीएमए अटैक के जैसा) करने के लिए कर सकता है. ऐसे हमलों को रोकने के लिए, pKVM, होस्ट के सभी SMC कॉल को EL2 पर ट्रैप करता है. साथ ही, EL3 पर होस्ट और सुरक्षित मॉनिटर के बीच प्रॉक्सी के तौर पर काम करता है.

होस्ट से मिले पीएससीआई कॉल, EL3 फ़र्मवेयर को कम से कम बदलावों के साथ फ़ॉरवर्ड किए जाते हैं. खास तौर पर, सीपीयू के ऑनलाइन होने या निलंबित होने के बाद फिर से शुरू होने के एंट्री पॉइंट को फिर से लिखा जाता है, ताकि स्टेज 2 की पेज टेबल को EL2 पर इंस्टॉल किया जा सके. इसके बाद, इसे EL1 पर होस्ट को वापस भेजा जा सके. बूट के दौरान, pKVM इस सुरक्षा को लागू करता है.

यह आर्किटेक्चर, SoC के PSCI के साथ काम करने पर निर्भर करता है. इसके लिए, EL3 फ़र्मवेयर के तौर पर TF-A के अप-टू-डेट वर्शन का इस्तेमाल करना बेहतर होता है.

फ़र्मवेयर फ़्रेमवर्क फ़ॉर आर्म (एफ़एफ़-ए) स्टैंडर्ड, सामान्य और सुरक्षित दुनिया के बीच इंटरैक्शन को स्टैंडर्ड बनाता है. खास तौर पर, सुरक्षित हाइपरवाइज़र की मौजूदगी में. स्पेसिफ़िकेशन का मुख्य हिस्सा, सुरक्षित दुनिया के साथ मेमोरी शेयर करने के तरीके के बारे में बताता है. इसके लिए, सामान्य मैसेज फ़ॉर्मैट और बुनियादी पेजों के लिए अच्छी तरह से तय की गई अनुमतियों के मॉडल, दोनों का इस्तेमाल किया जाता है. pKVM, FF-A मैसेज को प्रॉक्सी करता है, ताकि यह पक्का किया जा सके कि होस्ट, सुरक्षित साइड के साथ ऐसी मेमोरी शेयर करने की कोशिश न कर रहा हो जिसके लिए उसके पास ज़रूरी अनुमतियां न हों.

यह आर्किटेक्चर, Secure World सॉफ़्टवेयर पर निर्भर करता है. यह सॉफ़्टवेयर, मेमोरी ऐक्सेस मॉडल को लागू करता है. इससे यह पक्का किया जाता है कि Secure World में चल रहे भरोसेमंद ऐप्लिकेशन और अन्य सॉफ़्टवेयर, मेमोरी को सिर्फ़ तब ऐक्सेस कर सकते हैं, जब वह Secure World के पास हो या उसे FF-A का इस्तेमाल करके, Secure World के साथ शेयर किया गया हो. S-EL2 वाले सिस्टम पर, मेमोरी ऐक्सेस मॉडल को लागू करने का काम, Secure Partition Manager Core (SPMC) को करना चाहिए. जैसे, Hafnium. यह सुरक्षित दुनिया के लिए, दूसरे चरण की पेज टेबल को बनाए रखता है. S-EL2 के बिना किसी सिस्टम पर, टीईई अपनी पहली स्टेज की पेज टेबल के ज़रिए, मेमोरी ऐक्सेस मॉडल लागू कर सकता है.

अगर EL2 को किया गया SMC कॉल, PSCI कॉल या FF-A के हिसाब से तय किया गया मैसेज नहीं है, तो हैंडल नहीं किए गए SMC को EL3 पर फ़ॉरवर्ड कर दिया जाता है. यह माना जाता है कि (ज़रूरी तौर पर भरोसेमंद) सुरक्षित फ़र्मवेयर, बिना हैंडल किए गए एसएमसी को सुरक्षित तरीके से मैनेज कर सकता है. ऐसा इसलिए, क्योंकि फ़र्मवेयर को pVM आइसोलेशन को बनाए रखने के लिए ज़रूरी सावधानियों के बारे में पता होता है.

वर्चुअल मशीन मॉनिटर

crosvm एक वर्चुअल मशीन मॉनिटर (वीएमएम) है. यह Linux के KVM इंटरफ़ेस के ज़रिए वर्चुअल मशीनें चलाता है. crosvm को खास बनाने वाली बात यह है कि यह सुरक्षा पर फ़ोकस करता है. इसके लिए, Rust प्रोग्रामिंग भाषा का इस्तेमाल किया जाता है. साथ ही, होस्ट कर्नल की सुरक्षा के लिए वर्चुअल डिवाइसों के आस-पास एक सैंडबॉक्स बनाया जाता है. crosvm के बारे में ज़्यादा जानने के लिए, इसका आधिकारिक दस्तावेज़ यहां देखें.

फ़ाइल डिस्क्रिप्टर और ioctl

KVM, /dev/kvm कैरेक्टर डिवाइस को userspace के लिए उपलब्ध कराता है. इसमें ioctl होते हैं, जो KVM API बनाते हैं. ioctls इन कैटगरी में आते हैं:

  • सिस्टम ioctls क्वेरी करता है और ऐसे ग्लोबल एट्रिब्यूट सेट करता है जो पूरे KVM सबसिस्टम पर असर डालते हैं. साथ ही, pVM बनाता है.
  • VM ioctl, वर्चुअल सीपीयू (वीसीपीयू) और डिवाइस बनाने वाले एट्रिब्यूट को क्वेरी और सेट करते हैं. साथ ही, ये पूरे pVM पर असर डालते हैं. जैसे, मेमोरी लेआउट और वर्चुअल सीपीयू (वीसीपीयू) और डिवाइसों की संख्या.
  • vCPU ioctls, ऐसे एट्रिब्यूट के बारे में क्वेरी करते हैं और उन्हें सेट करते हैं जो किसी एक वर्चुअल सीपीयू के ऑपरेशन को कंट्रोल करते हैं.
  • डिवाइस ioctls, ऐसे एट्रिब्यूट के बारे में क्वेरी करते हैं और उन्हें सेट करते हैं जो किसी एक वर्चुअल डिवाइस के ऑपरेशन को कंट्रोल करते हैं.

हर crosvm प्रोसेस, वर्चुअल मशीन के सिर्फ़ एक इंस्टेंस को चलाती है. इस प्रोसेस में, KVM_CREATE_VM सिस्टम ioctl का इस्तेमाल करके, एक वीएम फ़ाइल डिस्क्रिप्टर बनाया जाता है. इसका इस्तेमाल pVM ioctl जारी करने के लिए किया जा सकता है. किसी वीएम के FD पर KVM_CREATE_VCPU या KVM_CREATE_DEVICE ioctl, एक vCPU/डिवाइस बनाता है और नए संसाधन की ओर इशारा करने वाला फ़ाइल डिस्क्रिप्टर दिखाता है. किसी vCPU या डिवाइस के FD पर ioctl का इस्तेमाल, उस डिवाइस को कंट्रोल करने के लिए किया जा सकता है जिसे वीएम के FD पर ioctl का इस्तेमाल करके बनाया गया था. वीसीपीयू के लिए, इसमें गेस्ट कोड चलाने का अहम टास्क शामिल है.

आंतरिक तौर पर, crosvm, वीएम के फ़ाइल डिस्क्रिप्टर को कर्नल के साथ रजिस्टर करता है. इसके लिए, वह एज-ट्रिगर किए गए epoll इंटरफ़ेस का इस्तेमाल करता है. इसके बाद, कर्नल crosvm को सूचना देता है. ऐसा तब होता है, जब किसी भी फ़ाइल डिस्क्रिप्टर में कोई नया इवेंट लंबित होता है.

pKVM में एक नई सुविधा, KVM_CAP_ARM_PROTECTED_VM जोड़ी गई है. इसका इस्तेमाल, pVM एनवायरमेंट के बारे में जानकारी पाने और VM के लिए सुरक्षित मोड सेट अप करने के लिए किया जा सकता है. अगर --protected-vm फ़्लैग पास किया जाता है, तो crosvm इसका इस्तेमाल pVM बनाने के दौरान करता है. ऐसा pVM फ़र्मवेयर के लिए सही मात्रा में मेमोरी का पता लगाने और उसे रिज़र्व करने के लिए किया जाता है. इसके बाद, सुरक्षित मोड चालू किया जाता है.

मेमोरी का बंटवारा

वीएमएम की मुख्य ज़िम्मेदारियों में से एक, वीएम की मेमोरी को असाइन करना और उसके मेमोरी लेआउट को मैनेज करना है. crosvm, मेमोरी का एक तय लेआउट जनरेट करता है. इसके बारे में यहां दी गई टेबल में बताया गया है.

सामान्य मोड में एफ़डीटी PHYS_MEMORY_END - 0x200000
खाली जगह ...
रैमडिस्क ALIGN_UP(KERNEL_END, 0x1000000)
कर्नेल 0x80080000
बूटलोडर 0x80200000
BIOS मोड में FDT 0x80000000
फ़िज़िकल मेमोरी बेस 0x80000000
pVM फ़र्मवेयर 0x7FE00000
डिवाइस का स्टोरेज 0x10000 - 0x40000000

फ़िजिकल मेमोरी को mmap के साथ असाइन किया जाता है. साथ ही, मेमोरी को वीएम को डोनेट किया जाता है, ताकि वह KVM_SET_USER_MEMORY_REGION ioctl के साथ memslots कहे जाने वाले मेमोरी रीजन को भर सके. इसलिए, मेहमान pVM की पूरी मेमोरी को उस crosvm इंस्टेंस के लिए एट्रिब्यूट किया जाता है जो इसे मैनेज करता है. अगर होस्ट के पास खाली मेमोरी कम होने लगती है, तो इस प्रोसेस को बंद किया जा सकता है. इससे वीएम बंद हो जाता है. किसी वीएम को बंद करने पर, हाइपरवाइज़र मेमोरी को अपने-आप मिटा देता है. साथ ही, इसे होस्ट कर्नल को वापस कर देता है.

सामान्य KVM में, VMM के पास मेहमान के तौर पर इस्तेमाल किए जा रहे सभी डिवाइसों की मेमोरी का ऐक्सेस होता है. pKVM की मदद से, मेहमान ओएस को मेमोरी देने पर, मेहमान ओएस की मेमोरी को होस्ट ओएस के फ़िज़िकल पते के स्पेस से अनमैप कर दिया जाता है. हालांकि, मेहमान की ओर से साफ़ तौर पर शेयर की गई मेमोरी इसका अपवाद है. जैसे, virtio डिवाइसों के लिए.

मेहमान के पते की जगह में मौजूद MMIO क्षेत्रों को मैप नहीं किया जाता. मेहमान के पास इन क्षेत्रों का ऐक्सेस नहीं है. इसलिए, वीएम के FD पर I/O इवेंट होता है. इस मैकेनिज़्म का इस्तेमाल वर्चुअल डिवाइसों को लागू करने के लिए किया जाता है. सुरक्षित मोड में, मेहमान को यह स्वीकार करना होगा कि उसके पते की जगह का इस्तेमाल MMIO के लिए किया जा रहा है. इसके लिए, उसे हाइपरकॉल का इस्तेमाल करना होगा, ताकि गलती से जानकारी लीक होने का जोखिम कम हो सके.

समय-निर्धारण

हर वर्चुअल सीपीयू को POSIX थ्रेड से दिखाया जाता है. इसे होस्ट Linux शेड्यूलर शेड्यूल करता है. थ्रेड, vCPU FD पर KVM_RUN ioctl को कॉल करता है. इससे हाइपरवाइज़र, गेस्ट वीसीपीयू कॉन्टेक्स्ट पर स्विच हो जाता है. होस्ट शेड्यूलर, मेहमान के कॉन्टेक्स्ट में बिताए गए समय को, उससे जुड़े vCPU थ्रेड के इस्तेमाल किए गए समय के तौर पर मानता है. KVM_RUN तब दिखता है, जब कोई ऐसा इवेंट होता है जिसे वीएमएम को हैंडल करना होता है. जैसे, I/O, इंटरप्ट खत्म होना या vCPU रुक जाना. वीएमएम, इवेंट को मैनेज करता है और KVM_RUN को फिर से कॉल करता है.

KVM_RUN के दौरान, थ्रेड को होस्ट शेड्यूलर से रोका जा सकता है. हालांकि, EL2 हाइपरवाइज़र कोड के एक्ज़ीक्यूशन को रोका नहीं जा सकता. गेस्ट pVM में, इस व्यवहार को कंट्रोल करने का कोई तरीका नहीं है.

सभी vCPU थ्रेड को किसी अन्य यूज़रस्पेस टास्क की तरह शेड्यूल किया जाता है. इसलिए, वे सभी स्टैंडर्ड QoS मेकेनिज़्म के दायरे में आते हैं. खास तौर पर, हर वीसीपीयू थ्रेड को फ़िज़िकल सीपीयू से जोड़ा जा सकता है, सीपीयूसेट में रखा जा सकता है, और यूटिलाइज़ेशन क्लैंपिंग का इस्तेमाल करके बढ़ाया या सीमित किया जा सकता है. साथ ही, इसकी प्राथमिकता/शेड्यूलिंग नीति को बदला जा सकता है.

वर्चुअल डिवाइस

crosvm कई डिवाइसों के साथ काम करता है. इनमें ये डिवाइस शामिल हैं:

  • कंपोज़िट डिस्क इमेज के लिए virtio-blk, सिर्फ़ पढ़ने या पढ़ने-लिखने के लिए
  • होस्ट के साथ कम्यूनिकेट करने के लिए vhost-vsock
  • virtio-pci को virtio ट्रांसपोर्ट के तौर पर इस्तेमाल करना
  • pl030 रीयल टाइम क्लॉक (आरटीसी)
  • सीरियल कम्यूनिकेशन के लिए 16550a UART

pVM फ़र्मवेयर

pVM फ़र्मवेयर (pvmfw), pVM पर चलने वाला पहला कोड होता है. यह किसी फ़िज़िकल डिवाइस के बूट रोम की तरह होता है. pvmfw का मुख्य काम, सुरक्षित बूट को बूटस्ट्रैप करना और pVM के यूनीक सीक्रेट को पाना है. pvmfw का इस्तेमाल किसी खास ओएस, जैसे कि Microdroid के साथ ही नहीं किया जा सकता. इसका इस्तेमाल किसी भी ऐसे ओएस के साथ किया जा सकता है जो crosvm के साथ काम करता हो और जिसे सही तरीके से साइन किया गया हो.

pvmfw बाइनरी को उसी नाम के फ़्लैश पार्टिशन में सेव किया जाता है. इसे OTA का इस्तेमाल करके अपडेट किया जाता है.

डिवाइस बूट

pKVM की सुविधा वाले डिवाइस के बूट करने की प्रोसेस में, यहाँ दिया गया क्रम जोड़ा जाता है:

  1. Android Bootloader (ABL), pvmfw को अपने पार्टिशन से मेमोरी में लोड करता है और इमेज की पुष्टि करता है.
  2. ABL, Device Identifier Composition Engine (DICE) के सीक्रेट (Compound Device Identifiers (CDI) और DICE सर्टिफ़िकेट चेन) को Root of Trust से हासिल करता है.
  3. ABL, pvmfw के लिए ज़रूरी सीडीआई बनाता है और उन्हें pvmfw बाइनरी में जोड़ता है.
  4. ABL, DT में linux,pkvm-guest-firmware-memory आरक्षित मेमोरी क्षेत्र नोड जोड़ता है. इसमें pvmfw बाइनरी की जगह और साइज़ के बारे में बताया जाता है. साथ ही, पिछले चरण में उससे मिले सीक्रेट के बारे में भी बताया जाता है.
  5. ABL, Linux को कंट्रोल सौंपता है और Linux, pKVM को शुरू करता है.
  6. pKVM, pvmfw मेमोरी क्षेत्र को होस्ट के स्टेज 2 पेज टेबल से अनमैप करता है. साथ ही, डिवाइस के चालू रहने तक इसे होस्ट (और मेहमानों) से सुरक्षित रखता है.

डिवाइस बूट होने के बाद, Microdroid दस्तावेज़ के बूट सीक्वेंस सेक्शन में दिए गए चरणों के मुताबिक Microdroid बूट होता है.

pVM बूट

pVM बनाते समय, crosvm (या कोई अन्य VMM) को एक बड़ा memslot बनाना होगा, ताकि हाइपरवाइज़र pvmfw इमेज को भर सके. वीएमएम को उन रजिस्टर की सूची में भी सीमित किया गया है जिनकी शुरुआती वैल्यू सेट की जा सकती है. प्राइमरी वीसीपीयू के लिए x0-x14 और सेकंडरी वीसीपीयू के लिए कोई नहीं. बाकी रजिस्टर सुरक्षित रखे गए हैं. ये हाइपरवाइज़र-pvmfw ABI का हिस्सा हैं.

pVM के चलने पर, हाइपरवाइज़र सबसे पहले प्राइमरी vCPU का कंट्रोल pvmfw को सौंपता है. फ़र्मवेयर को उम्मीद होती है कि crosvm ने AVB-हस्ताक्षर वाला कर्नल लोड किया है. यह बूटलोडर या कोई अन्य इमेज हो सकती है. साथ ही, फ़र्मवेयर को उम्मीद होती है कि crosvm ने बिना हस्ताक्षर वाला FDT, मेमोरी में लोड किया है. pvmfw, AVB हस्ताक्षर की पुष्टि करता है. पुष्टि होने पर, pvmfw को मिले FDT से भरोसेमंद डिवाइस ट्री जनरेट करता है. इसके बाद, pvmfw मेमोरी से अपने सीक्रेट मिटा देता है और पेलोड के एंट्री पॉइंट पर चला जाता है. अगर पुष्टि करने के किसी चरण में गड़बड़ी होती है, तो फ़र्मवेयर, PSCI SYSTEM_RESET हाइपरकॉल जारी करता है.

बूटिंग के दौरान, pVM इंस्टेंस के बारे में जानकारी को एक पार्टीशन (virtio-blk डिवाइस) में सेव किया जाता है. साथ ही, इसे pvmfw के सीक्रेट से एन्क्रिप्ट (सुरक्षित) किया जाता है. इससे यह पक्का किया जाता है कि रीबूट करने के बाद, सीक्रेट को सही इंस्टेंस में उपलब्ध कराया जा रहा है.