สถาปัตยกรรม AVF

Android นำเสนอการใช้งานอ้างอิงขององค์ประกอบทั้งหมดที่จำเป็นในการใช้งาน Android Virtualization Framework ปัจจุบันการใช้งานนี้จำกัดอยู่ที่ ARM64 หน้านี้อธิบายสถาปัตยกรรมเฟรมเวิร์ก

พื้นหลัง

สถาปัตยกรรม Arm อนุญาตระดับข้อยกเว้นสูงสุดสี่ระดับ โดยระดับข้อยกเว้น 0 (EL0) เป็นสิทธิพิเศษน้อยที่สุด และระดับข้อยกเว้น 3 (EL3) มากที่สุด ส่วนที่ใหญ่ที่สุดของโค้ดเบส Android (ส่วนประกอบพื้นที่ผู้ใช้ทั้งหมด) ทำงานที่ EL0 ส่วนที่เหลือของสิ่งที่เรียกกันทั่วไปว่า "Android" คือเคอร์เนล Linux ซึ่งทำงานที่ EL1

เลเยอร์ EL2 ช่วยให้สามารถใช้งานไฮเปอร์ไวเซอร์ที่ช่วยให้สามารถแยกหน่วยความจำและอุปกรณ์ออกเป็น pVM แต่ละตัวที่ EL1/EL0 พร้อมการรับประกันการรักษาความลับและความสมบูรณ์ที่เข้มงวด

ไฮเปอร์ไวเซอร์

เครื่องเสมือนที่ใช้เคอร์เนล (pKVM) ที่ได้รับการป้องกัน สร้างขึ้นบน ไฮเปอร์ไวเซอร์ Linux KVM ซึ่งได้รับการขยายด้วยความสามารถในการจำกัดการเข้าถึงเพย์โหลดที่ทำงานในเครื่องเสมือนของแขกที่ทำเครื่องหมายว่า 'ป้องกัน' ในขณะที่สร้าง

KVM/arm64 รองรับโหมดการดำเนินการที่แตกต่างกัน ขึ้นอยู่กับความพร้อมใช้งานของคุณสมบัติ CPU บางอย่าง กล่าวคือ Virtualization Host Extensions (VHE) (ARMv8.1 และใหม่กว่า) ในโหมดใดโหมดหนึ่งหรือที่เรียกกันทั่วไปว่าโหมดที่ไม่ใช่ VHE โค้ดไฮเปอร์ไวเซอร์จะถูกแยกออกจากอิมเมจเคอร์เนลในระหว่างการบูตและติดตั้งที่ EL2 ในขณะที่เคอร์เนลเองจะทำงานที่ EL1 แม้ว่าจะเป็นส่วนหนึ่งของโค้ดเบส Linux แต่คอมโพเนนต์ EL2 ของ KVM ก็เป็นองค์ประกอบขนาดเล็กที่รับผิดชอบในการสลับระหว่าง EL1 หลายตัว และควบคุมโดยเคอร์เนลของโฮสต์ทั้งหมด คอมโพเนนต์ไฮเปอร์ไวเซอร์ได้รับการคอมไพล์ด้วย Linux แต่อยู่ในส่วนหน่วยความจำเฉพาะที่แยกต่างหากของอิมเมจ vmlinux pKVM ใช้ประโยชน์จากการออกแบบนี้โดยการขยายโค้ดไฮเปอร์ไวเซอร์ด้วยคุณสมบัติใหม่ๆ ที่ทำให้วางข้อจำกัดบนเคอร์เนลของโฮสต์ Android และพื้นที่ผู้ใช้ได้ และจำกัดการเข้าถึงโฮสต์ในหน่วยความจำของแขกและไฮเปอร์ไวเซอร์

โมดูลผู้จำหน่าย pKVM

โมดูลผู้จำหน่าย pKVM คือโมดูลเฉพาะฮาร์ดแวร์ที่มีฟังก์ชันการทำงานเฉพาะอุปกรณ์ เช่น ไดรเวอร์หน่วยจัดการหน่วยความจำอินพุต-เอาท์พุต (IOMMU) โมดูลเหล่านี้ช่วยให้คุณสามารถพอร์ตคุณลักษณะด้านความปลอดภัยที่ต้องการการเข้าถึง pKVM ระดับข้อยกเว้น 2 (EL2)

หากต้องการเรียนรู้วิธีใช้งานและโหลดโมดูลผู้จำหน่าย pKVM โปรดดูที่ การใช้งานโมดูลผู้จำหน่าย pKVM

ขั้นตอนการบูต

รูปภาพต่อไปนี้แสดงขั้นตอนการบูต pKVM:

ขั้นตอนการบูต pKVM

รูปที่ 1. ขั้นตอนการบูต pKVM

  1. bootloader เข้าสู่เคอร์เนลทั่วไปที่ EL2
  2. เคอร์เนลทั่วไปตรวจพบว่ามันทำงานที่ EL2 และลิดรอนสิทธิ์ตัวเองเป็น EL1 ในขณะที่ pKVM และโมดูลยังคงทำงานที่ EL2 นอกจากนี้ โมดูลผู้จำหน่าย pKVM ยังถูกโหลดในขณะนี้
  3. เคอร์เนลทั่วไปดำเนินการบูตตามปกติ โดยโหลดไดรเวอร์อุปกรณ์ที่จำเป็นทั้งหมดจนกว่าจะถึงพื้นที่ผู้ใช้ ณ จุดนี้ pKVM จะอยู่ในตำแหน่งและจัดการตารางเพจระยะที่ 2

ขั้นตอนการบู๊ตเชื่อถือ bootloader เพื่อรักษาความสมบูรณ์ของเคอร์เนลอิมเมจในระหว่างการบู๊ตก่อนเวลาเท่านั้น เมื่อเคอร์เนลถูกลิดรอน ไฮเปอร์ไวเซอร์จะไม่ถือว่าเคอร์เนลเชื่อถืออีกต่อไป ซึ่งจะต้องรับผิดชอบในการปกป้องตัวเองแม้ว่าเคอร์เนลจะถูกบุกรุกก็ตาม

การมีเคอร์เนล Android และไฮเปอร์ไวเซอร์อยู่ในอิมเมจไบนารีเดียวกันทำให้มีอินเทอร์เฟซการสื่อสารที่เชื่อมโยงกันอย่างแน่นหนาระหว่างกัน การมีเพศสัมพันธ์ที่แน่นหนานี้รับประกันการอัพเดตระดับอะตอมของส่วนประกอบทั้งสอง ซึ่งหลีกเลี่ยงความจำเป็นในการรักษาส่วนต่อประสานระหว่างส่วนประกอบทั้งสองให้มั่นคง และให้ความยืดหยุ่นอย่างมากโดยไม่กระทบต่อการบำรุงรักษาในระยะยาว การมีเพศสัมพันธ์ที่แน่นหนายังช่วยให้เพิ่มประสิทธิภาพการทำงานได้เมื่อส่วนประกอบทั้งสองสามารถทำงานร่วมกันได้โดยไม่ส่งผลกระทบต่อการรับประกันความปลอดภัยที่ไฮเปอร์ไวเซอร์มอบให้

นอกจากนี้ การนำ GKI มาใช้ในระบบ Android จะทำให้ไฮเปอร์ไวเซอร์ pKVM สามารถปรับใช้กับอุปกรณ์ Android ในไบนารี่เดียวกันกับเคอร์เนลได้โดยอัตโนมัติ

การป้องกันการเข้าถึงหน่วยความจำ CPU

สถาปัตยกรรม Arm ระบุหน่วยการจัดการหน่วยความจำ (MMU) ที่แบ่งออกเป็นสองขั้นตอนอิสระ ซึ่งทั้งสองขั้นตอนสามารถใช้เพื่อดำเนินการแปลที่อยู่และการควบคุมการเข้าถึงส่วนต่างๆ ของหน่วยความจำ MMU ระยะที่ 1 ควบคุมโดย EL1 และอนุญาตให้มีการแปลที่อยู่ระดับแรกได้ MMU ขั้นที่ 1 ถูกใช้โดย Linux เพื่อจัดการพื้นที่ที่อยู่เสมือนที่จัดเตรียมให้กับแต่ละกระบวนการของพื้นที่ผู้ใช้และไปยังพื้นที่ที่อยู่เสมือนของตัวเอง

MMU ระยะที่ 2 ควบคุมโดย EL2 และเปิดใช้งานแอปพลิเคชันการแปลที่อยู่ที่สองบนที่อยู่เอาท์พุตของ MMU ระยะที่ 1 ซึ่งส่งผลให้เกิดที่อยู่ทางกายภาพ (PA) ไฮเปอร์ไวเซอร์สามารถใช้การแปลขั้นที่ 2 เพื่อควบคุมและแปลการเข้าถึงหน่วยความจำจาก Guest VM ทั้งหมด ดังแสดงในรูปที่ 2 เมื่อเปิดใช้งานการแปลทั้งสองขั้นตอน ที่อยู่เอาท์พุตของขั้นตอนที่ 1 เรียกว่าที่อยู่ทางกายภาพระดับกลาง (IPA) หมายเหตุ: ที่อยู่เสมือน (VA) จะถูกแปลเป็น IPA จากนั้นจึงแปลงเป็น PA

การป้องกันการเข้าถึงหน่วยความจำ CPU

รูปที่ 2 การป้องกันการเข้าถึงหน่วยความจำ CPU

ในอดีต KVM ทำงานโดยเปิดใช้งานการแปลระยะที่ 2 ในขณะที่รันแขก และปิดใช้งานระยะที่ 2 ในขณะที่รันเคอร์เนลโฮสต์ Linux สถาปัตยกรรมนี้อนุญาตให้เข้าถึงหน่วยความจำจากโฮสต์ระยะที่ 1 MMU เพื่อผ่าน MMU ระยะที่ 2 ดังนั้นจึงอนุญาตการเข้าถึงแบบไม่จำกัดจากโฮสต์ไปยังเพจหน่วยความจำของแขก ในทางกลับกัน pKVM เปิดใช้งานการป้องกันขั้นที่ 2 แม้ในบริบทของโฮสต์ และทำให้ไฮเปอร์ไวเซอร์รับผิดชอบในการปกป้องเพจหน่วยความจำของแขกแทนโฮสต์

KVM ใช้การแปลที่อยู่อย่างเต็มที่ในขั้นตอนที่ 2 เพื่อใช้การแมป IPA/PA ที่ซับซ้อนสำหรับผู้เยี่ยมชม ซึ่งสร้างภาพลวงตาของหน่วยความจำที่อยู่ติดกันสำหรับผู้เยี่ยมชมแม้จะมีการกระจายตัวทางกายภาพก็ตาม อย่างไรก็ตาม การใช้งาน MMU ระยะที่ 2 สำหรับโฮสต์นั้นจำกัดไว้เพียงการควบคุมการเข้าถึงเท่านั้น โฮสต์ระยะที่ 2 ได้รับการแมปเอกลักษณ์ เพื่อให้แน่ใจว่าหน่วยความจำที่ต่อเนื่องกันในพื้นที่ IPA ของโฮสต์จะต่อเนื่องกันในพื้นที่ PA สถาปัตยกรรมนี้อนุญาตให้ใช้การแมปขนาดใหญ่ในตารางเพจ และลดแรงกดดันต่อบัฟเฟอร์ lookaside การแปล (TLB) เนื่องจาก PA สามารถจัดทำดัชนีการแมปข้อมูลประจำตัวได้ โฮสต์ระยะที่ 2 ยังใช้เพื่อติดตามความเป็นเจ้าของเพจโดยตรงในตารางเพจอีกด้วย

การป้องกันการเข้าถึงหน่วยความจำโดยตรง (DMA)

ตามที่อธิบายไว้ก่อนหน้านี้ การยกเลิกการแมปเพจเกสต์จากโฮสต์ Linux ในตารางเพจ CPU ถือเป็นขั้นตอนที่จำเป็น แต่ยังไม่เพียงพอสำหรับการปกป้องหน่วยความจำเกสต์ pKVM ยังต้องป้องกันการเข้าถึงหน่วยความจำที่ทำโดยอุปกรณ์ที่รองรับ DMA ภายใต้การควบคุมของเคอร์เนลของโฮสต์ และความเป็นไปได้ที่จะเกิดการโจมตี DMA ที่เริ่มต้นโดยโฮสต์ที่เป็นอันตราย เพื่อป้องกันไม่ให้อุปกรณ์ดังกล่าวเข้าถึงหน่วยความจำของแขก pKVM ต้องใช้ฮาร์ดแวร์หน่วยจัดการหน่วยความจำอินพุต-เอาท์พุต (IOMMU) สำหรับอุปกรณ์ที่รองรับ DMA ทุกตัวในระบบ ดังแสดงในรูปที่ 3

การป้องกันการเข้าถึงหน่วยความจำ Dma

รูปที่ 3 การป้องกันการเข้าถึงหน่วยความจำ DMA

อย่างน้อยที่สุด ฮาร์ดแวร์ IOMMU จัดเตรียมวิธีการอนุญาตและเพิกถอนการเข้าถึงการอ่าน/เขียนสำหรับอุปกรณ์ไปยังหน่วยความจำกายภาพในระดับรายละเอียดของหน้า อย่างไรก็ตาม ฮาร์ดแวร์ IOMMU นี้จำกัดการใช้อุปกรณ์ใน pVM เนื่องจากอุปกรณ์เหล่านั้นถือว่ามีการแมปข้อมูลประจำตัวระยะที่ 2

เพื่อให้แน่ใจว่ามีการแยกระหว่างเครื่องเสมือน ธุรกรรมหน่วยความจำที่สร้างขึ้นในนามของเอนทิตีที่แตกต่างกันจะต้องได้รับการแยกแยะโดย IOMMU เพื่อให้สามารถใช้ชุดตารางเพจที่เหมาะสมสำหรับการแปลได้

นอกจากนี้ การลดจำนวนโค้ดเฉพาะ SoC ที่ EL2 ยังเป็นกลยุทธ์สำคัญในการลดฐานการประมวลผลที่เชื่อถือได้โดยรวม (TCB) ของ pKVM และดำเนินการสวนทางกับการรวมไดรเวอร์ IOMMU ไว้ในไฮเปอร์ไวเซอร์ เพื่อบรรเทาปัญหานี้ โฮสต์ที่ EL1 มีหน้าที่รับผิดชอบงานการจัดการเสริมของ IOMMU เช่น การจัดการพลังงาน การเริ่มต้น และการขัดจังหวะการจัดการตามความเหมาะสม

อย่างไรก็ตาม การให้โฮสต์ควบคุมสถานะของอุปกรณ์ทำให้เกิดข้อกำหนดเพิ่มเติมเกี่ยวกับอินเทอร์เฟซการเขียนโปรแกรมของฮาร์ดแวร์ IOMMU เพื่อให้แน่ใจว่าการตรวจสอบสิทธิ์ไม่สามารถข้ามไปได้ด้วยวิธีอื่น เช่น หลังจากการรีเซ็ตอุปกรณ์

IOMMU มาตรฐานและได้รับการสนับสนุนอย่างดีสำหรับอุปกรณ์ Arm ที่ทำให้ทั้งการแยกและการกำหนดโดยตรงเป็นไปได้คือสถาปัตยกรรม Arm System Memory Management Unit (SMMU) สถาปัตยกรรมนี้เป็นโซลูชันอ้างอิงที่แนะนำ

ความเป็นเจ้าของหน่วยความจำ

ณ เวลาบูต หน่วยความจำที่ไม่ใช่ไฮเปอร์ไวเซอร์ทั้งหมดจะถือว่าโฮสต์เป็นเจ้าของ และไฮเปอร์ไวเซอร์จะติดตามเช่นกัน เมื่อ pVM เกิด โฮสต์จะบริจาคเพจหน่วยความจำเพื่อให้สามารถบู๊ตได้ และไฮเปอร์ไวเซอร์จะเปลี่ยนสิทธิ์การเป็นเจ้าของเพจเหล่านั้นจากโฮสต์ไปเป็น pVM ดังนั้นไฮเปอร์ไวเซอร์จึงวางข้อจำกัดการควบคุมการเข้าถึงไว้ในตารางเพจระยะที่ 2 ของโฮสต์เพื่อป้องกันไม่ให้เข้าถึงเพจอีกครั้ง โดยให้การรักษาความลับแก่แขก

การสื่อสารระหว่างโฮสต์และแขกเกิดขึ้นได้ด้วยการแบ่งปันหน่วยความจำที่มีการควบคุมระหว่างกัน ผู้เยี่ยมชมได้รับอนุญาตให้แบ่งปันเพจบางส่วนของตนกลับไปกับโฮสต์โดยใช้ไฮเปอร์คอล ซึ่งสั่งให้ไฮเปอร์ไวเซอร์ทำการแมปเพจเหล่านั้นใหม่ในตารางเพจโฮสต์ระยะที่ 2 ในทำนองเดียวกัน การสื่อสารของโฮสต์กับ TrustZone เกิดขึ้นได้ด้วยการแบ่งปันหน่วยความจำและ/หรือการดำเนินการให้ยืม ซึ่งทั้งหมดนี้ได้รับการตรวจสอบและควบคุมอย่างใกล้ชิดโดย pKVM โดยใช้ ข้อกำหนด Firmware Framework for Arm (FF-A)

เนื่องจากข้อกำหนดหน่วยความจำของ pVM สามารถเปลี่ยนแปลงได้ตลอดเวลา จึงมีการจัดให้มีไฮเปอร์คอลซึ่งช่วยให้เจ้าของเพจที่ระบุที่เป็นของผู้เรียกสามารถละทิ้งกลับไปยังโฮสต์ได้ ในทางปฏิบัติ ไฮเปอร์คอลนี้ใช้กับโปรโตคอล virtio Balloon เพื่ออนุญาตให้ VMM ขอหน่วยความจำกลับจาก pVM และเพื่อให้ pVM แจ้ง VMM เกี่ยวกับเพจที่ถูกละทิ้งในลักษณะที่ได้รับการควบคุม

ไฮเปอร์ไวเซอร์มีหน้าที่รับผิดชอบในการติดตามความเป็นเจ้าของเพจหน่วยความจำทั้งหมดในระบบ และไม่ว่าเพจเหล่านั้นจะถูกแชร์หรือให้ยืมกับหน่วยงานอื่นหรือไม่ การติดตามสถานะส่วนใหญ่ดำเนินการโดยใช้ข้อมูลเมตาที่แนบมากับโฮสต์และตารางเพจระยะที่ 2 ของผู้เยี่ยมชม โดยใช้บิตที่สงวนไว้ในรายการตารางเพจ (PTE) ซึ่งสงวนไว้สำหรับการใช้งานซอฟต์แวร์ตามชื่อ

โฮสต์ต้องแน่ใจว่าไม่ได้พยายามเข้าถึงเพจที่ไฮเปอร์ไวเซอร์ไม่สามารถเข้าถึงได้ การเข้าถึงโฮสต์ที่ผิดกฎหมายทำให้เกิดข้อยกเว้นแบบซิงโครนัสที่จะแทรกเข้าไปในโฮสต์โดยไฮเปอร์ไวเซอร์ ซึ่งอาจส่งผลให้งานพื้นที่ผู้ใช้ที่รับผิดชอบได้รับสัญญาณ SEGV หรือเคอร์เนลของโฮสต์หยุดทำงาน เพื่อป้องกันการเข้าถึงโดยไม่ได้ตั้งใจ เพจที่บริจาคให้กับแขกจะไม่มีสิทธิ์ในการแลกเปลี่ยนหรือรวมเข้าด้วยกันโดยเคอร์เนลของโฮสต์

การจัดการขัดจังหวะและตัวจับเวลา

การขัดจังหวะเป็นส่วนสำคัญของวิธีที่แขกโต้ตอบกับอุปกรณ์และสำหรับการสื่อสารระหว่าง CPU โดยที่การขัดจังหวะระหว่างโปรเซสเซอร์ (IPI) เป็นกลไกการสื่อสารหลัก โมเดล KVM คือการมอบหมายการจัดการการขัดจังหวะเสมือนทั้งหมดให้กับโฮสต์ใน EL1 ซึ่งเพื่อจุดประสงค์นั้นจะทำหน้าที่เป็นส่วนที่ไม่น่าเชื่อถือของไฮเปอร์ไวเซอร์

pKVM นำเสนอการจำลอง Generic Interrupt Controller เวอร์ชัน 3 (GICv3) เต็มรูปแบบโดยอิงตามโค้ด KVM ที่มีอยู่ ตัวจับเวลาและ IPI ได้รับการจัดการโดยเป็นส่วนหนึ่งของโค้ดการจำลองที่ไม่น่าเชื่อถือนี้

รองรับ GICv3

อินเทอร์เฟซระหว่าง EL1 และ EL2 ต้องแน่ใจว่าโฮสต์ EL1 สามารถมองเห็นสถานะการขัดจังหวะแบบเต็มได้ รวมถึงสำเนาของรีจิสเตอร์ไฮเปอร์ไวเซอร์ที่เกี่ยวข้องกับการขัดจังหวะ โดยทั่วไปการมองเห็นนี้สามารถทำได้โดยใช้ขอบเขตหน่วยความจำที่ใช้ร่วมกัน หนึ่งรายการต่อ CPU เสมือน (vCPU)

รหัสสนับสนุนรันไทม์การลงทะเบียนระบบสามารถทำให้ง่ายขึ้นเพื่อรองรับเฉพาะการดักจับการลงทะเบียน Software Generated Interrupt Register (SGIR) และ Deactivate Interrupt Register (DIR) สถาปัตยกรรมกำหนดให้รีจิสเตอร์เหล่านี้ดักจับกับ EL2 เสมอ ในขณะที่กับดักอื่นๆ มีประโยชน์ในการลดความผิดพลาดเท่านั้น ทุกสิ่งทุกอย่างได้รับการจัดการในฮาร์ดแวร์

ในด้าน MMIO ทุกอย่างจะถูกจำลองที่ EL1 โดยนำโครงสร้างพื้นฐานปัจจุบันทั้งหมดใน KVM กลับมาใช้ใหม่ สุดท้าย Wait for Interrupt (WFI) จะถูกส่งต่อไปยัง EL1 เสมอ เนื่องจากนี่เป็นหนึ่งในกำหนดการพื้นฐานพื้นฐานที่ KVM ใช้

การสนับสนุนการจับเวลา

ค่าตัวเปรียบเทียบสำหรับตัวจับเวลาเสมือนจะต้องเปิดเผยกับ EL1 บน WFI ที่ดักจับแต่ละตัว เพื่อให้ EL1 สามารถแทรกการขัดจังหวะตัวจับเวลาในขณะที่ vCPU ถูกบล็อก ตัวจับเวลาทางกายภาพได้รับการจำลองทั้งหมด และกับดักทั้งหมดจะถ่ายทอดไปยัง EL1

การจัดการ MMIO

หากต้องการสื่อสารกับ Virtual Machine Monitor (VMM) และดำเนินการจำลอง GIC จะต้องถ่ายทอดกับดัก MMIO กลับไปยังโฮสต์ใน EL1 เพื่อทำการคัดแยกต่อไป pKVM ต้องการสิ่งต่อไปนี้:

  • IPA และขนาดของการเข้าถึง
  • ข้อมูลในกรณีที่เขียน
  • Endianness ของ CPU ณ จุดที่ดักจับ

นอกจากนี้ กับดักที่มีการลงทะเบียนวัตถุประสงค์ทั่วไป (GPR) เป็นแหล่งที่มา/ปลายทางจะถูกถ่ายทอดโดยใช้การลงทะเบียนหลอกแบบนามธรรม

อินเทอร์เฟซสำหรับแขก

แขกสามารถสื่อสารกับแขกที่ได้รับการป้องกันโดยใช้การผสมผสานระหว่างไฮเปอร์คอลและการเข้าถึงหน่วยความจำไปยังภูมิภาคที่ติดอยู่ Hypercalls เปิดเผยตาม มาตรฐาน SMCCC โดยมีช่วงที่สงวนไว้สำหรับการจัดสรรผู้ขายโดย KVM ไฮเปอร์คอลต่อไปนี้มีความสำคัญเป็นพิเศษต่อแขก pKVM

ไฮเปอร์คอลทั่วไป

  • PSCI จัดเตรียมกลไกมาตรฐานสำหรับแขกในการควบคุมวงจรชีวิตของ vCPU รวมถึงการออนไลน์ ออฟไลน์ และการปิดระบบ
  • TRNG จัดเตรียมกลไกมาตรฐานสำหรับแขกในการขอเอนโทรปีจาก pKVM ซึ่งจะถ่ายทอดการโทรไปยัง EL3 กลไกนี้มีประโยชน์อย่างยิ่งในกรณีที่โฮสต์ไม่สามารถเชื่อถือได้ในการจำลองเสมือนของตัวสร้างตัวเลขสุ่ม (RNG) ของฮาร์ดแวร์

ไฮเปอร์คอล pKVM

  • การแชร์หน่วยความจำกับโฮสต์ หน่วยความจำเกสต์ทั้งหมดไม่สามารถเข้าถึงได้ในโฮสต์ในตอนแรก แต่การเข้าถึงโฮสต์จำเป็นสำหรับการสื่อสารหน่วยความจำที่ใช้ร่วมกัน และสำหรับอุปกรณ์พาราเวอร์ชวลไลซ์ที่ต้องอาศัยบัฟเฟอร์ที่ใช้ร่วมกัน ไฮเปอร์คอลสำหรับการแชร์และยกเลิกการแชร์เพจกับโฮสต์ทำให้แขกตัดสินใจได้อย่างแน่ชัดว่าส่วนใดของหน่วยความจำที่เปิดให้เข้าถึงได้สำหรับส่วนที่เหลือของ Android โดยไม่ต้องจับมือกัน
  • การสละหน่วยความจำให้กับโฮสต์ หน่วยความจำของแขกทั้งหมดมักจะเป็นของแขกจนกว่าจะถูกทำลาย สถานะนี้อาจไม่เพียงพอสำหรับ VM ที่มีอายุยาวนานซึ่งมีความต้องการหน่วยความจำซึ่งเปลี่ยนแปลงไปตามกาลเวลา ไฮเปอร์คอล relinquish ช่วยให้เกสต์สามารถโอนความเป็นเจ้าของเพจกลับไปยังโฮสต์ได้อย่างชัดเจน โดยไม่ต้องมีการยกเลิกเกสต์
  • การเข้าถึงหน่วยความจำที่ดักจับกับโฮสต์ ตามเนื้อผ้า หากแขก KVM เข้าถึงที่อยู่ที่ไม่สอดคล้องกับขอบเขตหน่วยความจำที่ถูกต้อง เธรด vCPU จะออกจากโฮสต์และโดยทั่วไปการเข้าถึงจะใช้สำหรับ MMIO และจำลองโดย VMM ในพื้นที่ผู้ใช้ เพื่ออำนวยความสะดวกในการจัดการนี้ pKVM จำเป็นต้องโฆษณารายละเอียดเกี่ยวกับคำสั่งที่ผิดพลาด เช่น ที่อยู่ พารามิเตอร์การลงทะเบียน และเนื้อหาที่อาจเป็นไปได้กลับไปยังโฮสต์ ซึ่งอาจเปิดเผยข้อมูลที่ละเอียดอ่อนจากแขกที่ได้รับการป้องกันโดยไม่ได้ตั้งใจ หากไม่คาดคิดว่ามีกับดัก pKVM แก้ปัญหานี้โดยถือว่าข้อบกพร่องเหล่านี้เป็นอันตรายถึงชีวิต เว้นแต่แขกจะเคยออกไฮเปอร์คอลเพื่อระบุช่วง IPA ที่มีข้อบกพร่องเป็นช่วงที่อนุญาตให้เข้าถึงเพื่อดักกลับไปยังโฮสต์ โซลูชันนี้เรียกว่า MMIO guard

อุปกรณ์ I/O เสมือน (virtio)

Virtio เป็นมาตรฐานที่ได้รับความนิยม พกพาสะดวก และเป็นผู้ใหญ่สำหรับการนำไปใช้และการโต้ตอบกับอุปกรณ์พาราเวอร์ชวลไลซ์ อุปกรณ์ส่วนใหญ่ที่เปิดเผยต่อแขกที่ได้รับการคุ้มครองนั้นถูกใช้งานโดยใช้ virtio Virtio ยังสนับสนุนการใช้งาน vsock ที่ใช้สำหรับการสื่อสารระหว่างแขกที่ได้รับการคุ้มครองและส่วนที่เหลือของ Android

โดยทั่วไปอุปกรณ์ Virtio จะถูกนำไปใช้ในพื้นที่ผู้ใช้ของโฮสต์โดย VMM ซึ่งจะขัดขวางการเข้าถึงหน่วยความจำที่ดักจับจากแขกไปยังอินเทอร์เฟซ MMIO ของอุปกรณ์ virtio และจำลองลักษณะการทำงานที่คาดหวัง การเข้าถึง MMIO มีราคาค่อนข้างแพง เนื่องจากการเข้าถึงอุปกรณ์แต่ละครั้งต้องมีการเดินทางไปกลับที่ VMM และย้อนกลับ ดังนั้นการถ่ายโอนข้อมูลจริงส่วนใหญ่ระหว่างอุปกรณ์และแขกจึงเกิดขึ้นโดยใช้ชุดคุณธรรมในหน่วยความจำ ข้อสันนิษฐานสำคัญของ virtio คือโฮสต์สามารถเข้าถึงหน่วยความจำของแขกได้โดยพลการ สมมติฐานนี้ชัดเจนในการออกแบบคุณธรรม ซึ่งอาจมีตัวชี้ไปยังบัฟเฟอร์ในแขกที่การจำลองอุปกรณ์มีจุดประสงค์เพื่อเข้าถึงโดยตรง

แม้ว่าไฮเปอร์คอลการแชร์หน่วยความจำที่อธิบายไว้ก่อนหน้านี้สามารถใช้เพื่อแชร์บัฟเฟอร์ข้อมูล virtio จากแขกไปยังโฮสต์ได้ แต่การแชร์นี้จำเป็นต้องดำเนินการที่รายละเอียดของเพจ และอาจจบลงด้วยการเปิดเผยข้อมูลมากกว่าที่จำเป็น หากขนาดบัฟเฟอร์น้อยกว่าของเพจ . แต่แขกจะได้รับการกำหนดค่าให้จัดสรรทั้งคุณธรรมและบัฟเฟอร์ข้อมูลที่เกี่ยวข้องจากหน้าต่างคงที่ของหน่วยความจำที่ใช้ร่วมกัน โดยมีการคัดลอกข้อมูล (ตีกลับ) ไปยังและจากหน้าต่างตามต้องการ

อุปกรณ์เสมือน

รูปที่ 4 อุปกรณ์ Virtio

การโต้ตอบกับ TrustZone

แม้ว่าแขกจะไม่สามารถโต้ตอบกับ TrustZone ได้โดยตรง แต่โฮสต์จะต้องสามารถโทรออก SMC ในโลกที่ปลอดภัยได้ การเรียกเหล่านี้สามารถระบุบัฟเฟอร์หน่วยความจำที่อยู่ทางกายภาพซึ่งไม่สามารถเข้าถึงโฮสต์ได้ เนื่องจากโดยทั่วไปซอฟต์แวร์ที่ปลอดภัยไม่ทราบถึงการเข้าถึงบัฟเฟอร์ โฮสต์ที่เป็นอันตรายจึงสามารถใช้บัฟเฟอร์นี้เพื่อทำการโจมตีรองที่สับสน (คล้ายกับการโจมตี DMA) เพื่อป้องกันการโจมตีดังกล่าว pKVM จะดักจับการเรียก SMC โฮสต์ทั้งหมดไปยัง EL2 และทำหน้าที่เป็นพร็อกซีระหว่างโฮสต์และมอนิเตอร์ที่ปลอดภัยที่ EL3

การโทร PSCI จากโฮสต์จะถูกส่งต่อไปยังเฟิร์มแวร์ EL3 โดยมีการแก้ไขเพียงเล็กน้อย โดยเฉพาะอย่างยิ่ง จุดเริ่มต้นสำหรับ CPU ที่ออนไลน์หรือกลับมาทำงานต่อจากการหยุดชั่วคราวจะถูกเขียนใหม่เพื่อให้ตารางเพจระยะที่ 2 ได้รับการติดตั้งที่ EL2 ก่อนที่จะกลับไปยังโฮสต์ที่ EL1 ในระหว่างการบูต การป้องกันนี้บังคับใช้โดย pKVM

สถาปัตยกรรมนี้อาศัย SoC ที่รองรับ PSCI โดยควรใช้ TF-A เวอร์ชันล่าสุดเป็นเฟิร์มแวร์ EL3

Firmware Framework for Arm (FF-A) สร้างมาตรฐานการโต้ตอบระหว่างโลกปกติและโลกที่ปลอดภัย โดยเฉพาะอย่างยิ่งเมื่อมีไฮเปอร์ไวเซอร์ที่ปลอดภัย ส่วนสำคัญของข้อกำหนดกำหนดกลไกในการแบ่งปันหน่วยความจำกับโลกที่ปลอดภัย โดยใช้ทั้งรูปแบบข้อความทั่วไปและรูปแบบการอนุญาตที่กำหนดไว้อย่างดีสำหรับเพจที่เกี่ยวข้อง พร็อกซี pKVM ข้อความ FF-A เพื่อให้แน่ใจว่าโฮสต์ไม่ได้พยายามแชร์หน่วยความจำกับฝั่งที่ปลอดภัยซึ่งไม่มีสิทธิ์เพียงพอ

สถาปัตยกรรมนี้อาศัยซอฟต์แวร์โลกที่ปลอดภัยที่บังคับใช้โมเดลการเข้าถึงหน่วยความจำ เพื่อให้แน่ใจว่าแอปที่เชื่อถือได้และซอฟต์แวร์อื่น ๆ ที่ทำงานในโลกที่ปลอดภัยจะสามารถเข้าถึงหน่วยความจำได้ก็ต่อเมื่อเป็นของโลกที่ปลอดภัยแต่เพียงผู้เดียวหรือได้รับการแชร์อย่างชัดเจนกับมันโดยใช้ FF -ก. บนระบบที่มี S-EL2 การบังคับใช้โมเดลการเข้าถึงหน่วยความจำควรทำโดย Secure Partition Manager Core (SPMC) เช่น Hafnium ซึ่งดูแลตารางเพจระยะที่ 2 สำหรับโลกที่ปลอดภัย บนระบบที่ไม่มี S-EL2 TEE สามารถบังคับใช้โมเดลการเข้าถึงหน่วยความจำผ่านตารางเพจระยะที่ 1 แทน

หากการเรียก SMC ไปยัง EL2 ไม่ใช่การเรียก PSCI หรือข้อความที่กำหนดโดย FF-A SMC ที่ไม่มีการจัดการจะถูกส่งต่อไปยัง EL3 สมมติฐานก็คือเฟิร์มแวร์ที่ปลอดภัย (ที่เชื่อถือได้โดยจำเป็น) สามารถจัดการ SMC ที่ไม่มีการจัดการได้อย่างปลอดภัย เนื่องจากเฟิร์มแวร์เข้าใจข้อควรระวังที่จำเป็นในการรักษาการแยก pVM

การตรวจสอบเครื่องเสมือน

crosvm เป็น virtual machine monitor (VMM) ซึ่งรันเครื่องเสมือนผ่านอินเทอร์เฟซ KVM ของ Linux สิ่งที่ทำให้ crosvm มีเอกลักษณ์เฉพาะตัวคือการมุ่งเน้นไปที่ความปลอดภัยด้วยการใช้ภาษาการเขียนโปรแกรม Rust และแซนด์บ็อกซ์รอบอุปกรณ์เสมือนเพื่อปกป้องเคอร์เนลของโฮสต์ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ crosvm โปรดดูเอกสารอย่างเป็นทางการ ที่นี่

ตัวอธิบายไฟล์และ ioctls

KVM เปิดเผยอุปกรณ์อักขระ /dev/kvm ไปยังพื้นที่ผู้ใช้ด้วย ioctls ที่ประกอบขึ้นเป็น KVM API ioctls อยู่ในหมวดหมู่ต่อไปนี้:

  • ระบบ ioctls สืบค้นและตั้งค่าคุณลักษณะส่วนกลางที่ส่งผลต่อระบบย่อย KVM ทั้งหมด และสร้าง pVM
  • VM ioctls จะสอบถามและตั้งค่าคุณลักษณะที่สร้าง CPU เสมือน (vCPU) และอุปกรณ์ และส่งผลต่อ pVM ทั้งหมด เช่น การรวมเค้าโครงหน่วยความจำและจำนวน CPU เสมือน (vCPU) และอุปกรณ์
  • vCPU ioctls จะสอบถามและตั้งค่าคุณลักษณะที่ควบคุมการทำงานของ CPU เสมือนตัวเดียว
  • อุปกรณ์ ioctls สืบค้นและตั้งค่าแอ็ตทริบิวต์ที่ควบคุมการทำงานของอุปกรณ์เสมือนเครื่องเดียว

แต่ละกระบวนการ crosvm จะรันหนึ่งอินสแตนซ์ของเครื่องเสมือนเท่านั้น กระบวนการนี้ใช้ ioctl ระบบ KVM_CREATE_VM เพื่อสร้างตัวอธิบายไฟล์ VM ที่สามารถใช้เพื่อออก pVM ioctls KVM_CREATE_VCPU หรือ KVM_CREATE_DEVICE ioctl บน VM FD จะสร้าง vCPU/อุปกรณ์ และส่งคืนตัวอธิบายไฟล์ที่ชี้ไปยังทรัพยากรใหม่ ioctls บน vCPU หรืออุปกรณ์ FD สามารถใช้เพื่อควบคุมอุปกรณ์ที่สร้างขึ้นโดยใช้ ioctl บน VM FD สำหรับ vCPU นี่รวมถึงงานสำคัญในการรันโค้ดเกสต์ด้วย

ภายใน crosvm จะลงทะเบียนตัวอธิบายไฟล์ของ VM กับเคอร์เนลโดยใช้อินเทอร์เฟ epoll ที่กระตุ้นโดย Edge เคอร์เนลจะแจ้งเตือน crosvm ทุกครั้งที่มีเหตุการณ์ใหม่ที่ค้างอยู่ในตัวอธิบายไฟล์ใด ๆ

pKVM เพิ่มความสามารถใหม่ KVM_CAP_ARM_PROTECTED_VM ซึ่งสามารถใช้เพื่อรับข้อมูลเกี่ยวกับสภาพแวดล้อม pVM และตั้งค่าโหมดที่ได้รับการป้องกันสำหรับ VM crosvm ใช้สิ่งนี้ในระหว่างการสร้าง pVM หากส่งแฟล็ก --protected-vm เพื่อสอบถามและจองจำนวนหน่วยความจำที่เหมาะสมสำหรับเฟิร์มแวร์ pVM จากนั้นเพื่อเปิดใช้งานโหมดที่ได้รับการป้องกัน

การจัดสรรหน่วยความจำ

ความรับผิดชอบหลักประการหนึ่งของ VMM คือการจัดสรรหน่วยความจำของ VM และการจัดการเค้าโครงหน่วยความจำ crosvm สร้าง รูปแบบหน่วยความจำคงที่ตามที่อธิบายไว้ในตารางด้านล่าง

FDT ในโหมดปกติ PHYS_MEMORY_END - 0x200000
ที่ว่าง ...
แรมดิสก์ ALIGN_UP(KERNEL_END, 0x1000000)
เคอร์เนล 0x80080000
บูตโหลดเดอร์ 0x80200000
FDT ในโหมด BIOS 0x80000000
ฐานหน่วยความจำกายภาพ 0x80000000
เฟิร์มแวร์ pVM 0x7FE00000
หน่วยความจำของอุปกรณ์ 0x10000 - 0x40000000

หน่วยความจำกายภาพได้รับการจัดสรรด้วย mmap และหน่วยความจำจะถูกบริจาคให้กับ VM เพื่อเติมพื้นที่หน่วยความจำที่เรียกว่า memslots ด้วย KVM_SET_USER_MEMORY_REGION ioctl ดังนั้น หน่วยความจำ pVM ของแขกทั้งหมดจึงมาจากอินสแตนซ์ crosvm ที่จัดการและอาจส่งผลให้กระบวนการถูกหยุดทำงาน (ยุติ VM) หากโฮสต์เริ่มมีหน่วยความจำว่างไม่เพียงพอ เมื่อ VM หยุดทำงาน หน่วยความจำจะถูกล้างโดยไฮเปอร์ไวเซอร์โดยอัตโนมัติ และส่งคืนไปยังเคอร์เนลของโฮสต์

ภายใต้ KVM ปกติ VMM จะรักษาการเข้าถึงหน่วยความจำของแขกทั้งหมด ด้วย pKVM หน่วยความจำของแขกจะถูกยกเลิกการแมปจากพื้นที่ที่อยู่จริงของโฮสต์เมื่อมีการบริจาคให้กับแขก ข้อยกเว้นประการเดียวคือหน่วยความจำที่แขกแชร์กลับอย่างชัดเจน เช่น สำหรับอุปกรณ์ virtio

ภูมิภาค MMIO ในพื้นที่ที่อยู่ของแขกจะไม่ถูกแมป การเข้าถึงภูมิภาคเหล่านี้โดยแขกติดอยู่และส่งผลให้เกิดเหตุการณ์ I/O บน VM FD กลไกนี้ใช้เพื่อปรับใช้อุปกรณ์เสมือน ในโหมดที่ได้รับการป้องกัน แขกจะต้องรับทราบว่าพื้นที่ของพื้นที่ที่อยู่นั้นถูกใช้สำหรับ MMIO โดยใช้ไฮเปอร์คอล เพื่อลดความเสี่ยงของการรั่วไหลของข้อมูลโดยไม่ตั้งใจ

การจัดตารางเวลา

CPU เสมือนแต่ละตัวจะแสดงด้วยเธรด POSIX และกำหนดเวลาโดยตัวกำหนดตารางเวลาโฮสต์ Linux เธรดเรียก KVM_RUN ioctl บน vCPU FD ส่งผลให้ไฮเปอร์ไวเซอร์สลับไปที่บริบท vCPU ของแขก ตัวกำหนดเวลาโฮสต์จะพิจารณาเวลาที่ใช้ในบริบทของผู้เยี่ยมชมเป็นเวลาที่ใช้โดยเธรด vCPU ที่เกี่ยวข้อง KVM_RUN ส่งคืนเมื่อมีเหตุการณ์ที่ต้องจัดการโดย VMM เช่น I/O การสิ้นสุดการขัดจังหวะ หรือ vCPU หยุดทำงาน VMM จัดการเหตุการณ์และเรียก KVM_RUN อีกครั้ง

ในระหว่าง KVM_RUN เธรดจะยังคงถูกขัดจังหวะโดยตัวกำหนดเวลาโฮสต์ ยกเว้นการดำเนินการของโค้ดไฮเปอร์ไวเซอร์ EL2 ซึ่งไม่สามารถขัดจังหวะได้ Guest pVM เองไม่มีกลไกในการควบคุมพฤติกรรมนี้

เนื่องจากเธรด vCPU ทั้งหมดได้รับการกำหนดเวลาเช่นเดียวกับงานพื้นที่ผู้ใช้อื่นๆ เธรดเหล่านั้นจึงอยู่ภายใต้กลไก QoS มาตรฐานทั้งหมด โดยเฉพาะอย่างยิ่ง แต่ละเธรด vCPU สามารถเชื่อมโยงกับ CPU จริง วางใน cpusets เพิ่มหรือต่อยอดโดยใช้การหนีบการใช้งาน เปลี่ยนแปลงนโยบายลำดับความสำคัญ/กำหนดเวลา และอื่นๆ

อุปกรณ์เสมือน

crosvm รองรับอุปกรณ์จำนวนหนึ่ง รวมถึงอุปกรณ์ต่อไปนี้:

  • virtio-blk สำหรับอิมเมจดิสก์คอมโพสิต อ่านอย่างเดียวหรืออ่าน-เขียน
  • vhost-vsock สำหรับการสื่อสารกับโฮสต์
  • virtio-pci เป็นการขนส่ง virtio
  • pl030 นาฬิกาเรียลไทม์ (RTC)
  • 16550a UART สำหรับการสื่อสารแบบอนุกรม

เฟิร์มแวร์ pVM

เฟิร์มแวร์ pVM (pvmfw) เป็นโค้ดแรกที่ดำเนินการโดย pVM ซึ่งคล้ายกับ ROM สำหรับบูตของอุปกรณ์ฟิสิคัล เป้าหมายหลักของ pvmfw คือการบูตสแตรปการบูตอย่างปลอดภัย และรับความลับเฉพาะของ pVM pvmfw ไม่ได้จำกัดอยู่เพียงการใช้งานกับระบบปฏิบัติการเฉพาะใดๆ เช่น Microdroid ตราบใดที่ระบบปฏิบัติการนั้นรองรับ crosvm และได้รับการลงนามอย่างถูกต้อง

ไบนารี pvmfw ถูกจัดเก็บไว้ในพาร์ติชันแฟลชที่มีชื่อเดียวกันและอัปเดตโดยใช้ OTA

บูตอุปกรณ์

ลำดับขั้นตอนต่อไปนี้จะถูกเพิ่มเข้าไปในขั้นตอนการบู๊ตของอุปกรณ์ที่เปิดใช้งาน pKVM:

  1. Android Bootloader (ABL) โหลด pvmfw จากพาร์ติชันลงในหน่วยความจำและยืนยันรูปภาพ
  2. ABL ได้รับความลับ Device Identifier Composition Engine (DICE) (Compound Device Identifiers (CDI) และ Boot Certificate Chain (BCC)) จาก Root of Trust
  3. ABL ดำเนินการวัดและหา DICE มาจากความลับของ pvmfw (CDI) และผนวกเข้ากับไบนารี pvmfw
  4. ABL เพิ่มโหนดขอบเขตหน่วยความจำที่สงวนไว้ linux,pkvm-guest-firmware-memory ให้กับ DT โดยอธิบายตำแหน่งและขนาดของไบนารี pvmfw และความลับที่ได้รับในขั้นตอนก่อนหน้า
  5. ABL แฮนด์ควบคุมไปยัง Linux และ Linux เตรียมใช้งาน pKVM
  6. pKVM ยกเลิกการแมปขอบเขตหน่วยความจำ pvmfw จากตารางเพจระยะที่ 2 ของโฮสต์ และปกป้องจากโฮสต์ (และแขก) ตลอดระยะเวลาทำงานของอุปกรณ์

หลังจากการบู๊ตอุปกรณ์ Microdroid จะถูกบู๊ตตามขั้นตอนในส่วน ลำดับการบู๊ต ของเอกสาร Microdroid

บูต pVM

เมื่อสร้าง pVM นั้น crosvm (หรือ VMM อื่น) จะต้องสร้าง memslot ที่มีขนาดใหญ่พอที่จะเติมอิมเมจ pvmfw โดยไฮเปอร์ไวเซอร์ VMM ยังถูกจำกัดไว้ในรายการรีจิสเตอร์ที่สามารถตั้งค่าเริ่มต้นได้ (x0-x14 สำหรับ vCPU หลัก และไม่มีสำหรับ vCPU รอง) รีจิสเตอร์ที่เหลือจะถูกสงวนไว้และเป็นส่วนหนึ่งของ Hypervisor-pvmfw ABI

เมื่อ pVM ถูกรัน ไฮเปอร์ไวเซอร์จะควบคุม vCPU หลักไปที่ pvmfw ก่อน เฟิร์มแวร์คาดว่า crosvm จะโหลดเคอร์เนลที่ลงนาม AVB ซึ่งอาจเป็นตัวโหลดบูตหรืออิมเมจอื่น ๆ และ FDT ที่ไม่ได้ลงนามไปยังหน่วยความจำที่ออฟเซ็ตที่ทราบ pvmfw ตรวจสอบความถูกต้องของลายเซ็น AVB และหากสำเร็จ จะสร้างโครงสร้างอุปกรณ์ที่เชื่อถือได้จาก FDT ที่ได้รับ ลบความลับออกจากหน่วยความจำ และแยกสาขาไปยังจุดเริ่มต้นของเพย์โหลด หากขั้นตอนการตรวจสอบข้อใดข้อหนึ่งล้มเหลว เฟิร์มแวร์จะออกไฮเปอร์คอล PSCI SYSTEM_RESET

ระหว่างการบูท ข้อมูลเกี่ยวกับอินสแตนซ์ pVM จะถูกจัดเก็บไว้ในพาร์ติชัน (อุปกรณ์ virtio-blk) และเข้ารหัสด้วยข้อมูลลับของ pvmfw เพื่อให้แน่ใจว่าหลังจากการรีบูต ข้อมูลลับจะถูกจัดเตรียมให้กับอินสแตนซ์ที่ถูกต้อง