Android, वर्चुअलाइज़ेशन फ़्रेमवर्क को लागू करने के लिए ज़रूरी सभी कॉम्पोनेंट को लागू करने की जानकारी देता है. फ़िलहाल, यह तरीका ARM64 तक ही सीमित है. यह पेज, फ़्रेमवर्क के आर्किटेक्चर के बारे में बताता है.
बैकग्राउंड
आर्म आर्किटेक्चर में ज़्यादा से ज़्यादा चार अपवाद लेवल जोड़े जा सकते हैं. इनमें अपवाद लेवल 0 (EL0) सबसे कम अधिकार और अपवाद लेवल 3 (EL3) सबसे ज़्यादा है. Android कोड बेस का सबसे बड़ा हिस्सा (सभी यूज़रस्पेस कॉम्पोनेंट) EL0 पर चलता है. बाकी के हिस्से को आम तौर पर "Android" कहा जाता है. यह Linux कर्नेल है, जो EL1 पर चलता है.
EL2 लेयर, हायपरवाइज़र का इस्तेमाल करने की अनुमति देती है. यह EL1/EL0 में, मेमोरी और डिवाइसों को अलग-अलग पीवीएम में आइसोलेट करने की सुविधा देती है. इसमें, निजता और सुरक्षा की मज़बूत गारंटी दी जाती है.
हाइपरवाइज़र
सुरक्षित कर्नेल-आधारित वर्चुअल मशीन (pKVM) को Linux KVM Hypervisor पर बनाया गया है. इसे बनाते समय, मेहमान वर्चुअल मशीनों पर चल रहे पेलोड के ऐक्सेस को सीमित करने की सुविधा के साथ-साथ, ऐसी सुविधा भी बढ़ा दी गई है जिसे 'सुरक्षित' के तौर पर मार्क किया गया है.
KVM/arm64, सीपीयू की कुछ सुविधाओं की उपलब्धता के आधार पर अलग-अलग एक्ज़ीक्यूशन मोड के साथ काम करता है.
जैसे, वर्चुअलाइज़ेशन होस्ट एक्सटेंशन (VHE) (ARMv8.1 और उसके बाद के वर्शन). इनमें से एक मोड में, जिसे आम तौर पर गैर-वीएचई मोड कहा जाता है, उसमें हायपरवाइज़र कोड, बूट के दौरान कर्नेल इमेज से अलग हो जाता है और EL2 पर इंस्टॉल हो जाता है. वहीं, कर्नेल खुद EL1 पर चलता है. हालांकि, यह Linux कोड बेस का हिस्सा है, लेकिन KVM का EL2 कॉम्पोनेंट एक छोटा कॉम्पोनेंट है. यह कई EL1 के बीच स्विच करने की ज़िम्मेदारी लेता है. Hypervisor कॉम्पोनेंट को Linux के साथ कंपाइल किया जाता है, लेकिन यह vmlinux
इमेज के एक अलग मेमोरी सेक्शन में मौजूद होता है. pKVM इस डिज़ाइन का इस्तेमाल, Hypervisor कोड को नई सुविधाओं के साथ बढ़ाकर, Android होस्ट कर्नेल और यूज़र स्पेस पर पाबंदियां लगाता है. साथ ही, मेहमान मेमोरी और हाइपरवाइज़र के लिए होस्ट के ऐक्सेस को सीमित करता है.
pKVM वेंडर मॉड्यूल
pKVM वेंडर मॉड्यूल, हार्डवेयर के हिसाब से बनाया गया मॉड्यूल होता है. इसमें डिवाइस के हिसाब से फ़ंक्शन होता है. जैसे, इनपुट-आउटपुट मेमोरी मैनेजमेंट यूनिट (IOMMU) के ड्राइवर. इन मॉड्यूल की मदद से, सुरक्षा से जुड़ी उन सुविधाओं को पोर्ट किया जा सकता है जिन्हें pKVM के अपवाद लेवल 2 (EL2) के ऐक्सेस की ज़रूरत होती है.
pKVM वेंडर मॉड्यूल को लागू और लोड करने का तरीका जानने के लिए, pKVM वेंडर मॉड्यूल लागू करना लेख पढ़ें.
बूट प्रोसेस
नीचे दिए गए डायग्राम में pKVM को चालू करने की प्रोसेस दिखाई गई है:
- बूटलोडर, EL2 पर सामान्य कर्नेल में चला जाता है.
- सामान्य कर्नेल को पता चलता है कि यह EL2 पर चल रहा है और खुद को EL1 पर चला रहा है. हालांकि, pKVM और इसके मॉड्यूल, EL2 पर चलते रहेंगे. इसके अलावा, इस समय pKVM वेंडर मॉड्यूल लोड होते हैं.
- सामान्य कर्नेल, सभी ज़रूरी डिवाइस ड्राइवर को लोड करते हुए, सामान्य रूप से चालू होता है. ऐसा तब तक होता है, जब तक उपयोगकर्ता की जगह पर न पहुंचा जा सके. इस समय, pKVM सही जगह पर है और स्टेज-2 पेज टेबल को हैंडल करता है.
बूट प्रोसेस में बूटलोडर पर भरोसा किया जाता है, ताकि कर्नेल इमेज की सुरक्षा बनी रहे. ऐसा सिर्फ़ शुरुआती बूट के दौरान किया जाता है. जब कर्नेल से कुछ छूट जाता है, तब हाइपरवाइज़र उसे भरोसेमंद नहीं मानता. इसके बाद, कर्नेल के हैक होने की स्थिति में भी उसकी खुद की सुरक्षा की ज़िम्मेदारी होती है.
Android कर्नेल और हायपरवाइज़र एक ही बाइनरी इमेज में होने से, उनके बीच बहुत मज़बूत कम्यूनिकेशन इंटरफ़ेस हो जाता है. इस तरह से सही कपलिंग, दो कॉम्पोनेंट के ऐटॉमिक अपडेट की गारंटी देती है, जिससे इंटरफ़ेस के बीच के इंटरफ़ेस को स्थिर रखने की ज़रूरत नहीं होती. साथ ही, लंबे समय तक रखरखाव से समझौता किए बिना ये सुविधाएं काम करती हैं. टाइट कपलिंग की मदद से परफ़ॉर्मेंस ऑप्टिमाइज़ेशन भी किया जा सकता है. ऐसा तब होता है, जब दोनों कॉम्पोनेंट हायपरवाइज़र से मिलने वाली सुरक्षा गारंटी पर असर डाले बिना, एक-दूसरे के साथ काम कर सकते हैं.
इसके अलावा, Android नेटवर्क में GKI (जीकेआई) को लागू करने से, pKVM हाइपरवाइज़र को Android डिवाइसों पर उसी बाइनरी में अपने-आप डिप्लॉय कर दिया जाता है जिसमें कर्नेल का इस्तेमाल किया जाता है.
सीपीयू की मेमोरी के ऐक्सेस से जुड़ी सुरक्षा
आर्म आर्किटेक्चर की मदद से, मेमोरी मैनेजमेंट यूनिट (एमएमयू) को दो इंडिपेंडेंट स्टेज में बांटा जाता है. इन दोनों स्टेज का इस्तेमाल, पते के अनुवाद को लागू करने और मेमोरी के अलग-अलग हिस्सों को ऐक्सेस कंट्रोल करने के लिए किया जा सकता है. चरण 1 एमएमयू को EL1 से कंट्रोल किया जाता है और पते के अनुवाद के पहले लेवल की अनुमति दी जाती है. पहले चरण के एमएमयू का इस्तेमाल, Linux हर यूज़रस्पेस प्रोसेस को दिए जाने वाले वर्चुअल पता स्पेस को मैनेज करने और अपने वर्चुअल पता स्पेस को मैनेज करने के लिए करता है.
स्टेज 2 एमएमयू को EL2 से कंट्रोल किया जाता है. साथ ही, यह स्टेज 1 एमएमयू के आउटपुट पते पर दूसरे पते का अनुवाद लागू करने की सुविधा देता है. इससे घर या ऑफ़िस का पता (पीए) मिलता है. हाइपरवाइज़र, स्टेज 2 के अनुवाद का इस्तेमाल सभी मेहमान वीएम से मेमोरी ऐक्सेस को कंट्रोल और उसका अनुवाद करने के लिए कर सकते हैं. जैसा कि दूसरी इमेज में दिखाया गया है, अनुवाद के दोनों चरण चालू होने पर, पहले चरण के आउटपुट पते को इंटरमीडिएट फ़िज़िकल पता (आईपीए) कहा जाता है ध्यान दें: वर्चुअल पते (VA) का अनुवाद आईपीए और फिर पीए में किया जाता है.
अब तक, मेहमानों को चलाने के दौरान, केवीएम दूसरे चरण में अनुवाद की सुविधा के साथ काम करता है. साथ ही, होस्ट Linux कर्नेल चलाते समय, दूसरा चरण बंद रहता है. यह आर्किटेक्चर, होस्ट के पहले एमएमयू वाले स्टेज से मेमोरी के ऐक्सेस की अनुमति देता है. इससे वह स्टेज 2 एमएमयू से होकर गुज़रता है. इसलिए, होस्ट से गेस्ट मेमोरी पेजों को बिना पाबंदी वाला ऐक्सेस दिया जाता है. वहीं दूसरी ओर, pKVM, होस्ट के कॉन्टेक्स्ट में भी स्टेज 2 सुरक्षा को चालू करता है. साथ ही, हाइपरवाइज़र को होस्ट के बजाय, मेहमान की मेमोरी वाले पेजों की सुरक्षा करने की ज़िम्मेदारी देता है.
केवीएम, मेहमानों के लिए कॉम्प्लेक्स आईपीए/पीए मैपिंग को लागू करने के लिए, दूसरे चरण में पते के अनुवाद का पूरा इस्तेमाल करता है. इससे मेहमानों के लिए, अलग-अलग तरह की मेमोरी के होने का भ्रम पैदा होता है. हालांकि, होस्ट के लिए स्टेज 2 एमएमयू का इस्तेमाल सिर्फ़ ऐक्सेस कंट्रोल के लिए किया जा सकता है. होस्ट स्टेज 2, आइडेंटिटी मैप करता है. इससे यह पक्का किया जाता है कि होस्ट आईपीए स्पेस में लगातार एक साथ मेमोरी बनी रहे. इस आर्किटेक्चर की मदद से, पेज टेबल में लार्ज मैपिंग का इस्तेमाल किया जा सकता है. इससे, अनुवाद के लुकसाइड बफ़र (टीएलबी) पर दबाव कम हो जाता है. पहचान की मैपिंग को पीए से इंडेक्स किया जा सकता है, इसलिए होस्ट स्टेज 2 का इस्तेमाल, सीधे पेज टेबल में पेज के मालिकाना हक को ट्रैक करने के लिए भी किया जाता है.
डायरेक्ट मेमोरी ऐक्सेस (डीएमए) की सुरक्षा
जैसा कि पहले बताया गया है, मेहमान मेमोरी की सुरक्षा के लिए, Linux होस्ट से सीपीयू पेज की टेबल में मेहमान पेजों को अनमैप करना ज़रूरी है, लेकिन यह काफ़ी नहीं है. pKVM को होस्ट कर्नेल के कंट्रोल के तहत, डीएमए-सुविधा वाले डिवाइसों से किए गए मेमोरी ऐक्सेस से सुरक्षा की भी ज़रूरत होती है. साथ ही, नुकसान पहुंचाने वाले होस्ट के डीएमए हमले की संभावना को भी सुरक्षित रखना होता है. ऐसे डिवाइस को गेस्ट मेमोरी ऐक्सेस करने से रोकने के लिए, pKVM को इनपुट-आउटपुट मेमोरी मैनेजमेंट यूनिट (IOMMU) हार्डवेयर की ज़रूरत होती है. यह हार्डवेयर, सिस्टम में डीएमए की सुविधा वाले हर डिवाइस के लिए ज़रूरी है, जैसा कि तीसरी इमेज में दिखाया गया है.
IOMMU हार्डवेयर कम से कम, किसी डिवाइस को पेज की जानकारी के स्तर पर, फ़िज़िकल मेमोरी के लिए पढ़ने/लिखने का ऐक्सेस देने और वापस लेने का ज़रिया देता है. हालांकि, यह IOMMU हार्डवेयर पीवीएम में डिवाइसों के इस्तेमाल को सीमित करता है, क्योंकि उन्हें यह माना जाता है कि पहचान पर आधारित स्टेज 2 पर आधारित है.
वर्चुअल मशीनों को एक-दूसरे से अलग रखने के लिए यह ज़रूरी है कि अलग-अलग इकाइयों की ओर से जनरेट किए गए मेमोरी ट्रांज़ैक्शन के बीच IOMMU का अंतर बताने के लिए ज़रूरी हो, ताकि अनुवाद के लिए पेज टेबल के सही सेट का इस्तेमाल किया जा सके.
इसके अलावा, EL2 पर SoC के लिए बने कोड की मात्रा को कम करना, pKVM के कुल भरोसेमंद कंप्यूटिंग बेस (टीसीबी) को कम करने की सबसे अहम रणनीति है. साथ ही, यह Hypervisor में IOMMU ड्राइवर शामिल करने के ख़िलाफ़ विरोध करता है. इस समस्या को कम करने के लिए, EL1 पर मौजूद होस्ट की ज़िम्मेदारी IOMMU की सहायक सेवाओं को मैनेज करने की है. जैसे, पावर मैनेजमेंट, शुरू करना, और जहां ज़रूरी हो वहां काम में रुकावट डालना.
हालांकि, होस्ट को डिवाइस की स्थिति का कंट्रोल देने से, IOMMU हार्डवेयर के प्रोग्रामिंग इंटरफ़ेस के लिए अतिरिक्त ज़रूरी शर्तें लागू होती हैं. इससे यह पक्का होता है कि अनुमति की जांच को दूसरे तरीकों से बायपास न किया जाए. जैसे, डिवाइस को रीसेट करना.
आर्म सिस्टम मेमोरी मैनेजमेंट यूनिट (एसएमएमयू) आर्किटेक्चर आर्म डिवाइस के लिए एक स्टैंडर्ड और बेहतर तरीके से काम करने वाला IOMMU है, जो आइसोलेशन और डायरेक्ट असाइनमेंट दोनों को संभव बनाता है. इस आर्किटेक्चर को रेफ़रंस के तौर पर इस्तेमाल करने का सुझाव दिया जाता है.
मेमोरी का मालिकाना हक
बूट के समय, नॉन-हाइपरवाइज़र मेमोरी का मालिकाना हक, होस्ट के पास होता है. साथ ही, उसे हाइपरवाइज़र की तरह ट्रैक करता है. जब कोई पीवीएम पैदा होता है, तो होस्ट उसे चालू होने की अनुमति देने के लिए मेमोरी पेज दान करता है. हाइपरवाइज़र उन पेजों के मालिकाना हक को होस्ट से पीवीएम में बदल देता है. इसलिए, हाइपरवाइज़र, होस्ट के स्टेज 2 पेज टेबल में ऐक्सेस-कंट्रोल प्रतिबंध लागू कर देता है, ताकि वह होस्ट के पेज को फिर से ऐक्सेस न कर पाए. साथ ही, मेहमान की निजता बनाए रखते हुए ऐसा किया जा सकता है.
होस्ट और मेहमानों के बीच बातचीत को कंट्रोल तरीके से मेमोरी शेयर करने से संभव बनाया जाता है. हाइपरकॉल का इस्तेमाल करके, मेहमान अपने कुछ पेजों को होस्ट के साथ शेयर कर सकते हैं. इसमें हाइपरवाइज़र को होस्ट के दूसरे स्टेज की टेबल में, उन पेजों को फिर से मैप करने के लिए कहा जाता है. इसी तरह, TrustZone के साथ होस्ट का कम्यूनिकेशन, मेमोरी शेयर करने और/या क़र्ज़ देने की प्रोसेस की वजह से मुमकिन हो पाता है. इन सभी पर pKVM, बारीकी से नज़र रखता है और इन्हें कंट्रोल करता है. इसके लिए, फ़र्मवेयर फ़्रेमवर्क फ़ॉर आर्म (FF-A) स्पेसिफ़िकेशन की मदद ली जाती है.
पीवीएम की मेमोरी से जुड़ी ज़रूरी शर्तों में समय के साथ बदलाव हो सकता है. इसलिए, हाइपरकॉल दिया जाता है. इसकी मदद से, कॉलर से जुड़े कुछ खास पेजों का मालिकाना हक वापस होस्ट को दिया जाता है. व्यावहारिक तौर पर इस हाइपरकॉल का इस्तेमाल virtio बलून प्रोटोकॉल के साथ किया जाता है. इससे वीएमएम को पीवीएम से मेमोरी वापस पाने का अनुरोध किया जा सकता है. साथ ही, पीवीएम को कंट्रोल किए गए पेजों के बारे में वीएमएम की सूचना दी जा सकती है.
हाइपरवाइज़र, सिस्टम में मौजूद सभी मेमोरी पेजों के मालिकाना हक को ट्रैक करने के लिए ज़िम्मेदार है. साथ ही, यह भी देखता है कि उन्हें दूसरी इकाइयों के साथ शेयर किया जा रहा है या दिया जा रहा है. इस स्थिति की ज़्यादातर ट्रैकिंग, होस्ट और मेहमानों के स्टेज की दो पेज टेबल में जुड़े मेटाडेटा का इस्तेमाल करके की जाती है. इसके लिए, पेज टेबल एंट्री (पीटीई) में रिज़र्व किए गए बिट का इस्तेमाल किया जाता है. उनके नाम के मुताबिक ये बिट, सॉफ़्टवेयर के इस्तेमाल के लिए रिज़र्व होती हैं.
होस्ट को यह पक्का करना होगा कि वह ऐसे पेजों को ऐक्सेस करने की कोशिश न करे जिन्हें हायपरवाइज़र ने ऐक्सेस करने की अनुमति नहीं दी है. गैर-कानूनी होस्ट के ऐक्सेस की वजह से, हाइपरवाइज़र से होस्ट में सिंक्रोनस अपवाद डाला जाता है. इसकी वजह से, रिस्पॉन्सिबल यूज़रस्पेस टास्क को एसईजीवी सिग्नल मिल जाता है या होस्ट कर्नेल क्रैश हो जाता है. गलती से ऐक्सेस न हो, इसके लिए मेहमानों को दिए गए पेजों को होस्ट कर्नेल के ज़रिए स्वैप या मर्ज नहीं किया जा सकता.
हैंडलिंग और टाइमर बंद करें
मेहमान के डिवाइस से इंटरैक्ट करने और सीपीयू के बीच कम्यूनिकेशन के लिए, इंटरप्रोसेसर रुकावट (आईपीआई) मुख्य रूप से कम्यूनिकेशन के लिए होते हैं. KVM मॉडल का मकसद, EL1 में होस्ट को रुकावट डालने वाले सभी वर्चुअल मैनेजमेंट का ऐक्सेस देना है. इस वजह से, यह हायपरवाइज़र के गैर-भरोसेमंद हिस्से की तरह काम करता है.
pKVM, मौजूदा केवीएम कोड के आधार पर जेनेरिक इंटरप्ट कंट्रोलर वर्शन 3 (GICv3) एम्युलेशन की सुविधा देता है. टाइमर और आईपीआई को इस गैर-भरोसेमंद एम्युलेशन कोड के हिस्से के तौर पर मैनेज किया जाता है.
GICv3 सहायता
EL1 और EL2 के बीच के इंटरफ़ेस को यह पक्का करना चाहिए कि EL1 होस्ट को पूरी रुकावट की स्थिति दिखाई दे. इसमें रुकावट से जुड़े हाइपरवाइज़र रजिस्टर की कॉपी भी शामिल हैं. आम तौर पर, यह देखा जा सकता है कि शेयर की गई मेमोरी क्षेत्र का इस्तेमाल करके, हर वर्चुअल सीपीयू (vCPU) के लिए एक पैरामीटर तो उपलब्ध है.
सिस्टम रजिस्टर करने के रनटाइम सपोर्ट कोड को आसान बनाया जा सकता है, ताकि इसका इस्तेमाल करके सिर्फ़ सॉफ़्टवेयर जनरेट इंटरप्ट रजिस्टर (एसजीआईआर) और 'परेशान न करें' रजिस्ट्रेशन (डीआईआर) रजिस्ट्रेशन को आसानी से किया जा सके. आर्किटेक्चर के मुताबिक, ये रजिस्टर हमेशा ईएल2 तक ही सीमित रहते हैं. हालांकि, अब तक दूसरे जाल, गड़बड़ियों को कम करने में ही मददगार रहे हैं. बाकी सब कुछ हार्डवेयर में मैनेज किया जा रहा है.
एमएमआईओ की बात करें, तो हर चीज़ EL1 पर सिम्युलेट की जाती है और केवीएम के सभी मौजूदा इन्फ़्रास्ट्रक्चर का फिर से इस्तेमाल किया जाता है. आखिर में, इंटरप्रिट का इंतज़ार करें (डब्ल्यूएफ़आई) को हमेशा ईएल1 पर ही भेजा जाता है, क्योंकि यह केवीएम का इस्तेमाल करने वाले बुनियादी शेड्यूलिंग बुनियादी तरीकों में से एक है.
टाइमर की सुविधा
वर्चुअल टाइमर के लिए तुलना करने वाली वैल्यू, ट्रैपिंग वाले हर WFI में EL1 के सामने होनी चाहिए. इससे, vCPU के ब्लॉक होने पर EL1, टाइमर में रुकावट डाल सकता है. फ़िज़िकल टाइमर की नकल पूरी तरह से की गई है और सभी जाल ईएल1 पर रिले हो गए हैं.
एमएमआईओ हैंडलिंग
वर्चुअल मशीन मॉनिटर (वीएमएम) से संपर्क करने और जीआईसी एम्युलेशन करने के लिए, एमएमआईओ ट्रैप को EL1 में होस्ट को वापस रिले करना ज़रूरी है, ताकि प्राथमिकता का पता लगाया जा सके. pKVM को इसकी ज़रूरत होती है:
- आईपीए और ऐक्सेस का साइज़
- अनुरोध स्वीकार किए जाने पर डेटा
- जाल में फंसने की स्थिति में सीपीयू का खत्म होना
इसके अलावा, सोर्स/डेस्टिनेशन के तौर पर जनरल यूज़ रजिस्टर (जीपीआर) वाले जाल को ऐब्स्ट्रैक्ट ट्रांसफ़र pseudo-register का इस्तेमाल करके रिले किया जाता है.
मेहमान के लिए इंटरफ़ेस
हाइपरकॉल और फंसे हुए क्षेत्रों में मेमोरी ऐक्सेस के संयोजन का उपयोग करके एक मेहमान, एक सुरक्षित मेहमान के साथ संचार कर सकता है. हाइपरकॉल को एसएमसीसीसी स्टैंडर्ड के मुताबिक दिखाया जाता है. इसमें केवीएम की ओर से, वेंडर के बंटवारे के लिए तय की गई सीमा होती है. pKVM मेहमानों के लिए, नीचे दिए गए हाइपरकॉल खास तौर पर अहमियत रखते हैं.
सामान्य हाइपरकॉल
- PSCI, मेहमान को अपने vCPU के लाइफ़साइकल को कंट्रोल करने के लिए एक स्टैंडर्ड तरीका उपलब्ध कराता है. इसमें, ऑनलाइन करना, ऑफ़लाइन करना, और सिस्टम शटडाउन करना शामिल है.
- TRNG, मेहमान को pKVM से एंट्रॉपी का अनुरोध करने के लिए एक स्टैंडर्ड तरीका उपलब्ध कराता है. यह तरीका, EL3 को कॉल करने के लिए करता है. यह तरीका खास तौर पर तब काम आता है, जब किसी हार्डवेयर रैंडम नंबर जनरेटर (RNG) को वर्चुअलाइज़ करने के लिए होस्ट पर भरोसा नहीं किया जा सकता.
pKVM हाइपरकॉल
- होस्ट के साथ मेमोरी शेयर की जा रही है. शुरुआत में होस्ट, सभी मेहमानों की मेमोरी को ऐक्सेस नहीं कर सकता. हालांकि, शेयर किए गए मेमोरी वाले कम्यूनिकेशन और शेयर किए गए बफ़र का इस्तेमाल करने वाले पैरावर्चुअलाइज़्ड डिवाइसों के लिए, होस्ट का ऐक्सेस ज़रूरी है. होस्ट के साथ पेज शेयर करने और शेयर करने से रोकने के लिए हाइपरकॉल की मदद से मेहमान यह तय कर पाते हैं कि मेमोरी का कौनसा हिस्सा बाकी Android के लिए ऐक्सेस करने लायक है और इसके लिए हैंडशेक की ज़रूरत नहीं पड़ती.
- होस्ट की याददाश्त छोड़ना. आम तौर पर, मेहमानों की सभी मेमोरी तब तक रहती हैं,
जब तक कि उन्हें खत्म नहीं कर दिया जाता. ऐसा हो सकता है कि यह स्थिति, लंबे समय तक चलने वाली उन वीएम के लिए पूरी तरह से ठीक न हो जिनमें मेमोरी की ज़रूरत होती है और समय के साथ बदलती रहती है.
relinquish
हाइपरकॉल की मदद से, मेहमान को अपने पेजों का मालिकाना हक, होस्ट को वापस ट्रांसफ़र करने की अनुमति मिल जाती है. इसके लिए, उन्हें गेस्ट सेशन खत्म करने की ज़रूरत नहीं होती. - मेमोरी के ऐक्सेस को होस्ट के साथ अटैच किया जा रहा है. परंपरागत तौर पर, अगर कोई केवीएम मेहमान किसी ऐसे पते को ऐक्सेस करता है जो किसी मान्य मेमोरी क्षेत्र से मेल नहीं खाता, तो वीसीपीयू थ्रेड होस्ट से बाहर निकल जाता है और आम तौर पर एमएमआईओ के लिए ऐक्सेस का इस्तेमाल किया जाता है. साथ ही, वीएमएम थ्रेड उपयोगकर्ता के स्पेस में उसकी नकल करता है. इस हैंडलिंग को आसान बनाने के लिए, pKVM को गड़बड़ी वाले निर्देश के बारे में विज्ञापन देना ज़रूरी है, जैसे कि पता, पैरामीटर रजिस्टर करना, और होस्ट का कॉन्टेंट वापस होस्ट को ऐक्सेस करना. इससे अनजाने में किसी सुरक्षित मेहमान का संवेदनशील डेटा दिख सकता है. इसके लिए, pKVM गड़बड़ी वाले इस तरह की गड़बड़ी को घातक मानकर हल करता है. इस समाधान को MMIO गार्ड कहा जाता है.
वर्चुअल I/O डिवाइस (virtio)
Virtio, पैरावर्चुअलाइज़ेशन वाले डिवाइसों को लागू करने और इंटरैक्ट करने के लिए एक लोकप्रिय, पोर्टेबल, और मैच्योर स्टैंडर्ड है. सुरक्षित मेहमानों के संपर्क में आने वाले ज़्यादातर डिवाइस virtio का इस्तेमाल करते हैं. Virtio, एक सुरक्षित मेहमान और Android के बाकी प्लैटफ़ॉर्म के बीच बातचीत के लिए इस्तेमाल होने वाले Vsock को लागू करने की प्रोसेस को भी बेहतर बनाता है.
Virtio डिवाइसों को आम तौर पर होस्ट के उपयोगकर्ता स्पेस में वीएमएम लागू किया जाता है. यह मेहमान के डिवाइस में फंसी मेमोरी के ऐक्सेस को virtio डिवाइस के MMIO इंटरफ़ेस में रुकावट डालता है और सही व्यवहार को एम्युलेट करता है. एमएमआईओ ऐक्सेस काफ़ी महंगा है, क्योंकि डिवाइस पर हर ऐक्सेस के लिए, वीएमएम और वापस जाने की ज़रूरत होती है. इसलिए, डिवाइस और मेहमान के बीच डेटा का ज़्यादातर ट्रांसफ़र मेमोरी में मौजूद गुणों के आधार पर होता है. इसके पीछे एक मुख्य बात यह है कि होस्ट, मेहमानों की मेमोरी को अपने हिसाब से ऐक्सेस कर सकता है. यह अनुमान, प्रॉपर्टी के डिज़ाइन में साफ़ तौर पर दिखता है. इसमें मेहमान में बफ़र के लिए ऐसे पॉइंटर शामिल हो सकते हैं जिन्हें डिवाइस एम्युलेशन सीधे ऐक्सेस करने के लिए बनाया गया है.
हालांकि, मेहमान से होस्ट को वर्चुअल डेटा बफ़र शेयर करने के लिए, पहले बताए गए मेमोरी शेयरिंग हाइपरकॉल का इस्तेमाल किया जा सकता है, लेकिन यह शेयरिंग पेज की जानकारी के स्तर पर ज़रूरी है. अगर बफ़र का साइज़, पेज के साइज़ से कम है, तो इससे ज़्यादा डेटा मिल सकता है. इसके बजाय, मेहमान को प्रॉपर्टी की विशेषताएं और उनसे जुड़ा डेटा बफ़र, दोनों को शेयर की गई मेमोरी की एक तय विंडो से बांटने के लिए कॉन्फ़िगर किया जाता है. साथ ही, ज़रूरत के हिसाब से विंडो में और उससे डेटा कॉपी (बाउंस) किया जाता है.
TrustZone के साथ इंटरैक्शन
हालांकि, मेहमान TrustZone से सीधे इंटरैक्ट नहीं कर सकते, लेकिन होस्ट के पास यह ज़रूरी है कि वह SMC कॉल को सुरक्षित तरीके से जारी कर सके. इन कॉल में फ़िज़िकल तौर पर मौजूद उन मेमोरी बफ़र की जानकारी दी जा सकती है जिन्हें होस्ट ऐक्सेस नहीं कर सकता. आम तौर पर, सुरक्षित सॉफ़्टवेयर को बफ़र की सुलभता की जानकारी नहीं होती है. इसलिए, नुकसान पहुंचाने वाला होस्ट इस बफ़र का इस्तेमाल, दुविधा में डालने वाले हमले (डीएमए हमले के समान) के लिए कर सकता है. ऐसे हमलों को रोकने के लिए, pKVM सभी होस्ट SMC कॉल को EL2 पर फंसाता है और EL3 पर होस्ट और सुरक्षित मॉनिटर के बीच प्रॉक्सी की तरह काम करता है.
होस्ट के PSCI कॉल, कम से कम बदलाव के साथ EL3 फ़र्मवेयर को फ़ॉरवर्ड किए जाते हैं. खास तौर पर, सीपीयू के ऑनलाइन होने या निलंबन से फिर से शुरू करने के एंट्री पॉइंट को फिर से लिखा जाता है, ताकि EL1 पर होस्ट पर वापस जाने से पहले, दूसरे चरण की टेबल को EL2 पर इंस्टॉल किया जा सके. बूट के दौरान, यह सुरक्षा pKVM से लागू की जाती है.
यह आर्किटेक्चर, PSCI के साथ काम करने वाले SoC पर निर्भर करता है. आम तौर पर, यह EL3 फ़र्मवेयर के तौर पर TF-A के अप-टू-डेट वर्शन का इस्तेमाल करता है.
फ़र्मवेयर फ़्रेमवर्क फ़ॉर आर्म (FF-A) सामान्य और सुरक्षित दुनिया के बीच इंटरैक्शन का मानक तय करता है. खास तौर पर तब ऐसा होता है, जब कोई सुरक्षित हायपरवाइज़र मौजूद हो. इस स्पेसिफ़िकेशन का एक मुख्य हिस्सा सुरक्षित वर्ल्ड के साथ मेमोरी शेयर करने का तरीका तय करता है. इसमें सामान्य मैसेज फ़ॉर्मैट और बुनियादी पेजों के लिए अनुमतियों के बेहतर मॉडल, दोनों का इस्तेमाल किया जाता है. pKVM प्रॉक्सी FF-A मैसेज को दिखाती है, ताकि यह पक्का किया जा सके कि होस्ट ऐसे सुरक्षित-साइड के साथ मेमोरी शेयर करने की कोशिश नहीं कर रहा है जिसके लिए उसके पास ज़रूरी अनुमतियां नहीं हैं.
यह आर्किटेक्चर, मेमोरी ऐक्सेस मॉडल को लागू करने वाले सिक्योर वर्ल्ड सॉफ़्टवेयर पर निर्भर करता है. इससे यह पक्का किया जाता है कि भरोसेमंद ऐप्लिकेशन और सुरक्षित दुनिया में चलने वाले अन्य सॉफ़्टवेयर, मेमोरी को सिर्फ़ तब ऐक्सेस कर सकें, जब उसका मालिकाना हक खास तौर पर सुरक्षित दुनिया के पास हो या उसे FF-A का इस्तेमाल करके साफ़ तौर पर शेयर किया गया हो. एस-ईएल2 वाले सिस्टम पर, मेमोरी ऐक्सेस मॉडल को लागू करने का काम सिक्योर पार्टिशन मैनेजर कोर (एसपीएमसी) जैसे कि Hafnium को करना चाहिए. यह सुरक्षित दुनिया के लिए स्टेज 2 पेज टेबल मैनेज करता है. जिस सिस्टम पर S-EL2 नहीं है उस पर TEE, स्टेज 1 पेज टेबल से मेमोरी ऐक्सेस मॉडल लागू कर सकता है.
अगर EL2 को किया गया SMC कॉल, PSCI कॉल या FF-A से तय किया गया कोई मैसेज नहीं है, तो बिना कार्रवाई वाले एसएमसी को EL3 पर भेज दिया जाता है. ऐसा माना जाता है कि (ज़रूरी तौर पर भरोसेमंद) सुरक्षित फ़र्मवेयर, बिना हैंडल न किए गए एसएमसी को सुरक्षित तरीके से हैंडल कर सकता है. इसकी वजह यह है कि फ़र्मवेयर, पीवीएम आइसोलेशन के लिए ज़रूरी सावधानियों को समझता है.
वर्चुअल मशीन मॉनिटर
Crosvm एक वर्चुअल मशीन मॉनिटर (VMM) है, जो Linux के KVM इंटरफ़ेस से वर्चुअल मशीन को चलाता है. Crosvm खास तौर पर, इसे होस्ट कर्नेल की सुरक्षा करने के लिए, Rust प्रोग्रामिंग लैंग्वेज और वर्चुअल डिवाइसों के आस-पास मौजूद सैंडबॉक्स की मदद से सुरक्षा पर फ़ोकस किया गया है. Crosvm के बारे में ज़्यादा जानकारी के लिए, इसका आधिकारिक दस्तावेज़ यहां देखें.
फ़ाइल डिस्क्रिप्टर और ioctls
KVM, /dev/kvm
वर्ण डिवाइस को यूज़रस्पेस में ioctls के साथ दिखाता है, जो केवीएम एपीआई बनाता है. आईओसीटीएल इन कैटगरी में आते हैं:
- सिस्टम ioctls क्वेरी करता है और पूरे केवीएम सबसिस्टम पर असर डालने वाले ग्लोबल एट्रिब्यूट को सेट करता है. साथ ही, पीवीएम बनाता है.
- VM ioctls क्वेरी और ऐसे एट्रिब्यूट सेट करता है जो वर्चुअल सीपीयू (vCPU) और डिवाइस बनाते हैं और पूरे pVM पर असर डालते हैं. जैसे, मेमोरी लेआउट और वर्चुअल सीपीयू (vCPU) की संख्या (vCPU) और डिवाइसों की संख्या.
- vCPU ioctls क्वेरी करता है और ऐसे एट्रिब्यूट सेट करता है जो एक वर्चुअल सीपीयू की कार्रवाई को कंट्रोल करते हैं.
- डिवाइस ioctls क्वेरी करता है और ऐसे एट्रिब्यूट सेट करता है जो एक वर्चुअल डिवाइस की कार्रवाई को कंट्रोल करते हैं.
हर Crosvm प्रोसेस के लिए, वर्चुअल मशीन का सिर्फ़ एक इंस्टेंस चलता है. यह प्रोसेस, वीएम फ़ाइल डिस्क्रिप्टर बनाने के लिए, KVM_CREATE_VM
सिस्टम ioctl का इस्तेमाल करती है. इसका इस्तेमाल, पीवीएम ioctl जारी करने के लिए किया जा सकता है. वीएम एफ़डी पर KVM_CREATE_VCPU
या KVM_CREATE_DEVICE
ioctl, vCPU/डिवाइस बनाता है और नए संसाधन के बारे में बताने वाला फ़ाइल डिस्क्रिप्टर दिखाता है. vCPU या डिवाइस के एफ़डी पर मौजूद ioctl का इस्तेमाल, उस डिवाइस को कंट्रोल करने के लिए किया जा सकता है जिसे वीएम एफ़डी पर ioctl का इस्तेमाल करके बनाया गया है. vCPU के लिए, इसमें मेहमान कोड चलाने से जुड़ा अहम टास्क शामिल है.
अंदरूनी तौर पर, Crosvm, वीएम के फ़ाइल डिस्क्रिप्टर को कर्नेल के साथ रजिस्टर करता है. इसके लिए, किनारे से ट्रिगर होने वाले epoll
इंटरफ़ेस का इस्तेमाल किया जाता है. इसके बाद, कर्नेल किसी भी फ़ाइल डिस्क्रिप्टर में
कोई नया इवेंट होने पर, Crosvm को सूचना देता है.
pKVM में एक नई सुविधा जोड़ी गई है, जिसका नाम KVM_CAP_ARM_PROTECTED_VM
है. इसका इस्तेमाल पीवीएम एनवायरमेंट के बारे में जानकारी पाने और वीएम के लिए सुरक्षित मोड सेट अप करने के लिए किया जा सकता है. अगर --protected-vm
फ़्लैग पास हो जाता है, तो पीवीएम बनाने के दौरान Crosvm इसका इस्तेमाल करता है. इससे पीवीएम फ़र्मवेयर के लिए क्वेरी करने और ज़रूरी मेमोरी सुरक्षित रखने में मदद मिलती है. इसके बाद सुरक्षित मोड चालू किया जा सकता है.
मेमोरी का बंटवारा
वीएमएम की मेमोरी असाइन करना और उसके मेमोरी लेआउट को मैनेज करना, वीएमएम की मुख्य ज़िम्मेदारियों में से एक होता है. crsvm एक तय मेमोरी लेआउट जनरेट करता है. इस लेआउट के बारे में नीचे दी गई टेबल में आम तौर पर बताया गया है.
सामान्य मोड में FDT | PHYS_MEMORY_END - 0x200000
|
खाली जगह | ...
|
रैमडिस्क | ALIGN_UP(KERNEL_END, 0x1000000)
|
कर्नेल | 0x80080000
|
बूटलोडर | 0x80200000
|
बीआईओएस मोड में एफ़डीटी | 0x80000000
|
फ़िज़िकल मेमोरी बेस | 0x80000000
|
पीवीएम फ़र्मवेयर | 0x7FE00000
|
डिवाइस का स्टोरेज | 0x10000 - 0x40000000
|
फ़िज़िकल मेमोरी को mmap
के साथ बांटा जाता है और मेमोरी को वीएम को दान कर दिया जाता है, ताकि मेमोरी की जगह, यानी कि मेमस्लॉट को KVM_SET_USER_MEMORY_REGION
ioctl में अपने-आप भरा जा सके. इसलिए, सभी गेस्ट पीवीएम मेमोरी को
Crosvm इंस्टेंस को एट्रिब्यूट किया जाता है. यह इंस्टेंस इसे मैनेज करता है. अगर होस्ट की मेमोरी खत्म
होने लगती है, तो इस प्रोसेस को बंद किया जा सकता है (वीएम को बंद किया जा सकता है). जब वीएम को बंद किया जाता है, तो हाइपरवाइज़र मेमोरी को अपने-आप वाइप कर देता है. इसके बाद, वह होस्ट कर्नेल में वापस आ जाता है.
सामान्य केवीएम में, वीएमएम मेहमानों की सभी मेमोरी का ऐक्सेस बनाए रखता है. pKVM की मदद से, मेहमान की मेमोरी को मेहमान को दान किए जाने पर, उसे होस्ट के पते की जगह से मैप नहीं किया जाता है. हालांकि, इसमें सिर्फ़ एक अपवाद है, वह मेमोरी जिसे मेहमान ने साफ़ तौर पर शेयर किया है, जैसे कि virtio डिवाइसों के लिए.
मेहमान के पता स्पेस में मौजूद MMIO इलाके को मैप नहीं किया जाता. मेहमान के इन इलाकों में जाने की वजह से, वीएम एफ़डी पर I/O इवेंट हो जाता है. इस प्रोसेस का इस्तेमाल, वर्चुअल डिवाइसों को लागू करने के लिए किया जाता है. सुरक्षित मोड में, मेहमान को यह स्वीकार करना होगा कि इसके पते की जगह के एक क्षेत्र का इस्तेमाल, हाइपरकॉल का इस्तेमाल करके एमएमआईओ के लिए किया गया है. इससे, जानकारी के गलती से लीक होने का जोखिम कम किया जा सकता है.
शेड्यूलिंग
हर वर्चुअल सीपीयू को POSIX थ्रेड के ज़रिए दिखाया जाता है और इसे होस्ट Linux शेड्यूलर शेड्यूल करता है. थ्रेड, vCPU एफ़डी पर KVM_RUN
ioctl को कॉल करता है.
इस वजह से, हायपरवाइज़र, मेहमान vCPU कॉन्टेक्स्ट पर स्विच करता है. होस्ट शेड्यूलर, मेहमान के कॉन्टेक्स्ट में बिताए गए समय को इससे जुड़े vCPU थ्रेड में लगने वाले समय के हिसाब से तय करता है. KVM_RUN
तब लौटता है जब कोई ऐसा इवेंट होता है जिसे वीएमएम को हैंडल करना ज़रूरी होता है, जैसे कि I/O, रुकावट का खत्म होना या vCPU को रोका गया. वीएमएम इवेंट मैनेज करता है और KVM_RUN
को फिर से कॉल करता है.
KVM_RUN
के दौरान, होस्ट शेड्यूलर, थ्रेड को पहले से ही रोक सकता है. हालांकि, EL2 हाइपरवाइज़र कोड को लागू होने के बाद, थ्रेड को पहले से नहीं हटाया जा सकता. इस व्यवहार को कंट्रोल करने के लिए, मेहमान
पीवीएम का कोई तरीका नहीं होता.
सभी vCPU थ्रेड को अन्य यूज़रस्पेस टास्क की तरह शेड्यूल किया जाता है. इसलिए, वे सभी स्टैंडर्ड QoS मैकेनिज़्म पर निर्भर होते हैं. खास तौर पर, हर vCPU थ्रेड को फ़िज़िकल सीपीयू से जोड़ा जा सकता है, उसे सीपीयू में रखा जा सकता है, यूटिलाइज़ेशन क्लैम्पिंग का इस्तेमाल करके बूस्ट या कैप किया जा सकता है, उनकी प्राथमिकता/शेड्यूलिंग नीति में बदलाव किया जा सकता है वगैरह.
वर्चुअल डिवाइस
Crosvm कई डिवाइसों के साथ काम करता है. इनमें ये डिवाइस शामिल हैं:
- कंपोज़िट डिस्क इमेज, रीड-ओनली या रीड-राइट के लिए virtio-blk
- होस्ट से बातचीत करने के लिए vhost-vsock
- virtio-pci, virtio ट्रांसपोर्ट के रूप में
- pl030 रीयल टाइम क्लॉक (आरटीसी)
- सीरियल कम्यूनिकेशन के लिए 16550a UART
पीवीएम फ़र्मवेयर
पीवीएम फ़र्मवेयर (pvmfw), किसी डिवाइस के बूट ROM की तरह ही pVM से चलाया जाने वाला पहला कोड है. pvmfw का मुख्य मकसद बूटस्ट्रैप को सुरक्षित करना और पीवीएम का खास सीक्रेट पता करना है. pvmfw का किसी खास ओएस के साथ इस्तेमाल नहीं किया जा सकता, जैसे कि माइक्रोड्रोइड की सुविधा लंबे समय से इस्तेमाल की जा रही है.
pvmfw बाइनरी को उसी नाम के फ़्लैश पार्टीशन में सेव किया जाता है और OTA का इस्तेमाल करके अपडेट किया जाता है.
डिवाइस का बूट
pKVM की सुविधा वाले डिवाइस को चालू करने की प्रोसेस में, यह तरीका जोड़ा गया है:
- Android बूटलोडर (ABL) अपनी तय की गई सीमा से pvmfw को मेमोरी में लोड करता है और इमेज की पुष्टि करता है.
- ABL, रूट ऑफ़ ट्रस्ट से अपने डिवाइस आइडेंटिफ़ायर कंपोज़िशन इंजन (DICE) सीक्रेट (कंपाउंड डिवाइस आइडेंटिफ़ायर (सीडीआई) और डीआईसीई सर्टिफ़िकेट चेन) लेता है.
- एबीएल, pvmfw के लिए ज़रूरी सीडीआई इकट्ठा करता है और उन्हें pvmfw बाइनरी में जोड़ता है.
- एबीएल, DT में
linux,pkvm-guest-firmware-memory
रिज़र्व की गई मेमोरी का क्षेत्र नोड जोड़ता है. इसमें pvmfw बाइनरी की जगह और साइज़ के साथ-साथ, पिछले चरण में इससे मिले सीक्रेट की जानकारी होती है. - Linux और Linux पर ABL हैंड कंट्रोल, pKVM को शुरू करता है.
- pKVM, होस्ट की स्टेज 2 पेज टेबल से pvmfw मेमोरी क्षेत्र को अनमैप करता है. साथ ही, डिवाइस के पूरे चालू रहने के दौरान, इसे होस्ट (और मेहमानों) से सुरक्षित रखता है.
डिवाइस को चालू करने के बाद, माइक्रोड्रॉइड दस्तावेज़ के बूट क्रम सेक्शन में दिए गए चरणों के हिसाब से माइक्रोड्रॉइड को चालू किया जाता है.
पीवीएम बूट
पीवीएम बनाते समय, Crosvm (या कोई दूसरा वीएमएम) को एक बड़ा मेमस्लॉट बनाना चाहिए, ताकि हायपरवाइज़र से pvmfw इमेज अपने-आप भरी जा सके. वीएमएम को उन रजिस्टर की सूची में भी शामिल किया जाता है जिनकी शुरुआती वैल्यू सेट की जा सकती है. जैसे, मुख्य vCPU के लिए x0-x14, सेकंडरी vCPU के लिए कोई नहीं. बाकी के रजिस्टर रिज़र्व रखे जाते हैं और ये सुपरवाइज़र-pvmfw एबीआई का हिस्सा हैं.
जब पीवीएम चलाया जाता है, तो हाइपरवाइज़र सबसे पहले मुख्य वीसीपीयू को pvmfw पर कंट्रोल करता है. फ़र्मवेयर के लिए उम्मीद है कि क्रोज़म में एवीबी-हस्ताक्षर किया गया कर्नेल लोड किया गया है, जो बूटलोडर या कोई दूसरी इमेज हो सकता है. साथ ही, pvmfw एवीबी हस्ताक्षर की पुष्टि करता है. अगर मंज़ूरी मिल जाती है, तो वह मिले एफ़डीटी से भरोसेमंद डिवाइस ट्री जनरेट करता है. अगर पुष्टि का कोई भी चरण पूरा नहीं होता, तो फ़र्मवेयर, पीएससीआई SYSTEM_RESET
हाइपरकॉल को जारी करता है.
बूट के बीच, pVM इंस्टेंस की जानकारी एक पार्टिशन (virtio-blk device) में सेव की जाती है और pvmfw के सीक्रेट के साथ एन्क्रिप्ट की जाती है, ताकि यह पक्का किया जा सके कि, फिर से चालू होने के बाद, सीक्रेट को सही इंस्टेंस के लिए प्रावधान किया जा रहा है.