본문 바로가기
Compiler & Computer Architecture

Hypervisor ( x64 )

by 탁종민 2022. 1. 16.

# CPU/MMU Memory Mapping

Memory Mapping

http://haifux.org/lectures/312/High-Level%20Introduction%20to%20the%20Low-Level%20of%20Virtualization.pdf

 

x64라도 access 하려는 virtual address의 [63:48] 비트는 쓰이지 않는다. CR3 레지스터는 PM L4 (PageMap Level4) 물리 주소를 가리키고 access 하려는 virtual address의 [47:39] 비트는 PM L4에 Offset값으로 쓰인다. 

 




PML4 엔트리의 구조는 다음과 같다. PML4 Entry의 [51:12] 비트는 다음 레벨( PDPT ) 테이블의 물리 주소를 가리킨다. 같은방식으로 반복해서 마지막 PTE까지 찾아내면 PTE는 페이지의 주소를 가리키고 access 하려는 Virtual Address의 [11:0] 비트가 페이지의 오프셋으로 쓰인다.

 

TLB ( Translation Lookaside Buffer )

https://www.youtube.com/watch?v=95QpHJX55bM

 

Virtual Page Address Prefix를 Physical Page Address Prefix로 맵핑해주는 맵핑 버퍼다. CPU에서 자동으로 처리되는 VADDR 0x00003204로 접근한다고 하자. TLB에 0x00003 이라는 Tag값이 없다. 결국 Page Direction -> Page Table 을 거쳐 물리주소를 알아내야 한다.

 

이때 0x00003000에 해당하는 페이지의 물리 주소를 0x00006000 이라고 하자. 그러면 0x00003 -> 0x00006 이라는 맵핑정보가 TLB에 저장된다. 

이제 0x00003208 과 같이 이미 TLB에 있는 VADDR로 접근하게 되면 바로 CPU는 Physical Address 0x00006208 를 계산해 내어 바로 접근할 수 있게된다.



# Hypervisor

참고 (High-level introduction to virtualization's low-level) :

http://haifux.org/lectures/312/High-Level%20Introduction%20to%20the%20Low-Level%20of%20Virtualization.pdf

https://rayanfam.com/topics/hypervisor-from-scratch-part-4/

 

용어정리

vmm : Virtual Machine Monitor

GVA : Guest Virtual Address

GPA : Guest Physical Address  ( Guest OS가 생각하는 물리주소 )

HPA : Host Physical Address  ( Host의 물리주소 = 실제 물리주소 )

 

Instruction 가상화

VMLAUNCH Instruction 실행 시 Guest OS가 시작된다. Sensitive한 Instruction들은 모두 Trap을 유발해 vmexit가 되고 vmm ( virtual machine monitor)으로 제어권이 넘어간다. vmm은 Sensitive한 Instruction들을 해석해 대신 작업을 처리해주고 다시 VMRESUME Instruction으로 Guest OS를 실행한다.

 

메모리 가상화 : Shadow Page Table 방식

http://www.cs.cmu.edu/~410-f06/lectures/L31_Virtualization.pdf

https://cseweb.ucsd.edu/~yiying/cse291j-winter20/reading/Virtualize-Memory.pdf

 

Guest OS가 부팅되고 가장 처음 CR3 레지스터에 Root Page Directory를 설정할 때 부터 Tracing을 시작한다.

예를들어 Guest OS가 Guest Page Table 주소를 CR3에 저장하려고 한다면 아래와 같이 trap이 발생한다. 그리고는 Guest OS의 페이지 테이블을 읽어 들여 Host 물리 메모리로 맵핑하는 Shadow Page Table을 만들고 그대로 Page Table을 CR3 ( Page Table Pointer)에 셋팅한다음 Guest OS를 실행한다.

하지만 Guest OS가 CR3를 읽으려고 할 때마다 VMM이 Guest Page Table주소를 대신 반환해주기 때문에 Guest OS는 마치 CR3에 Guest Page Table이 CR3에 설정된 것 처럼 착각하게 된다.



 

Guest Page Table을 이용해서 Shadow Page Table을 만들 때 Guest Page Table위치하는 메모리 페이지는  Read Only로 설정해야한다.

그러면 Guest OS에서는 Guest Page Table이 Read Only이기 때문에 테이블을 변경을 하려고 할 때 마다 Page Fault가 나면서 제어권이 Host OS에게 넘어간다. Host OS는 이때 Shadow Page Table및 GPA->HPA 테이블을 그에 맞춰 변경한다. 이때 Guest OS가 Page Table에 Write할 때는 해당  Page Fault가 난다고 해도 Guest OS 입장에서는 막상 Guest Page Table을 읽었을 땐 Page Table이 존재하는 메모리가 R/W 영역이다. Read Only 설정은 Host가 관리하는 Shadow Page Table에 설정되어 있기 때문이다.

( *CPU는 Guest <-> Host간에 스위칭이 발생할 때 마다 TLB를 Flush 해야한다. Host가 사용하던 TLB를 Guest OS에서 사용하게 되면 Guest OS가 TLB를 이용해 Host OS의 메모리에 접근할 수 있게되고 Host OS역시 Guest OS가 사용하던 TLB를 쓰게 되면 엉뚱한 메모리로 접근하게 되기 때문이다.

Guest OS에서 발생하는 Page Table에 대한 모든 Write는 결국 Trap 및 Guest -> Host로의 스위칭을 유발시키는데, 결국 그만큼 TLB Flush를 발생시켜 성능저하를 발생시킨다. )


 

메모리 가상화 : SLAT ( Second Level Address Transition = EPT, NPT 방식 )

https://revers.engineering/day-2-entering-vmx-operation/

https://rayanfam.com/topics/hypervisor-from-scratch-part-4/

MMU를 이용해 Mapping을 할때 지금 Guest인 상태( 지금 vmenter 한 상태라면)라면 CPU & MMU가 자동으로 2단 맵핑을 진행한다. 

 

그림 : https://rayanfam.com/topics/hypervisor-from-scratch-part-4/

 

 

EPT를 사용하려면 먼저 VMCS에 있는 EPT Pointer를 Initialization 해줘야 한다. 

VMCS는 VMWRITE Instruction을 이용해 [VMWRITE Value, 인코딩 값] 형식으로 수정할 수 있다. 인코딩은 VMCS에 존재하는 프로퍼티들에 접근하기 위한 Flag, ID값들의 조합값이다. 예를들어 CR3 target-count 값의 인코딩은 아래 예제에서 볼 수 있듯 0x400A 이다.

https://gist.github.com/wbenny/d0fdb53425de2641e207b8c4ef672cbc

 

EPT Pointer의 경우 인코딩이 0x201A이다.

 

댓글