Virtual Machine Management 발표자 : 선준규 Virtual Machine Management
Contents Overview Data Structures Guest OS의 생성 Guest OS의 제거
Overview Hypervisor는 vcpu 0번으로 동작한다. Guest OS 생성 시 하나의 고유한 vcpu를 할당 받는다. Guest OS의 초기 페이지 테이블 생성 시 OS binary만을 맵핑한다. 각각의 Guest OS는 고유한 주소공간을 갖는다. Guest OS 주소공간은 address_space로 관리되며, 여러 개의 mem_region으로 구성되어 있다. 속도 향상을 위해 자주 사용되는 자료구조를 사전에 캐시로 만들어 요청 시 빠르게 할당해 줄 수 있도록 한다. vcpu context switching 시 vcpu의 모드에 따라 복구할 Context가 달라지게 된다.
Data Structures
struct vcpu 필드 구성 및 설명 long vcpu_id; struct guest_os_info *guest_info; 각 Virtual CPU의 고유 ID struct guest_os_info *guest_info; vcpu에서 동작하는 guest os struct regs_ctx regs; vcpu간 context switching시 레지스터들의 값을 저장하기 위해 사용될 공간 struct list_head vcpu_list; vcpu들의 이중 연결 리스트 struct address_space *address; vcpu가 실제 사용하는 주소 공간 void *master_table; vcpu의 주소공간을 구성하기위한 page table struct timer timer; vcpu의 timer 정보
struct vcpu (Cont’d) unsigned long state; long current_running_mode; 현재 vcpu의 상태정보를 나타냄 (INITIAL, READY, RUNNING, SUSPENDED, TERMINATED ) long current_running_mode; 현재 vcpu가 동작중인 모드를 나타냄 ( HYPERVISOR / GUEST OS ) unsigned int top_stack; vcpu가 사용하는 stack의 top unsigned int guarded; 스택을 보호하기위한 guarded space unsigned int vcpu_stack[VCPU_STACKSIZE]; 스택 공간 unsigned long bottom_stack; vcpu 스택의 시작 주소
struct guest_os_info 필드 구성 및 설명 long guest_id; Guest OS의 고유 ID char name[MAX_OS_NAME_LENGTH] Guest OS의 name long state; 현재 Guest OS의 상태 ( UNINITIALIZED/BOOTING/RUNNING/MIGRATING/HALTING) long requested_exception; 요청된 Migration, IRQ등의 정보를 표시 struct vcpu *cpu; Guest OS가 동작하는 vcpu struct regs_ctx saved_regs_ctx; Guest OS가 Context Switching 될 때 레지스터 값들이 저장될 장소
struct guest_os_info (Cont’d) unsigned long interrupt_vector; Guest OS의 interrupt vector 주소 struct list_head guest_os_info; guest_os_info구조체를 이중 연결리스트로 구성하기 위한 필드 void (*boot_kernel)(); 커널이 수행되기 전에 필요한 초기화 작업 void (*migrate)(); Migration 요청 시 수행할 핸들러 void (*shutdown)(); OS 종료 시 수행될 핸들러 void (*reset)(); Reset 요청이 들어오는 경우 수행되는 핸들러
struct guest_os_info (Cont’d) void (*pause)(); 일시적으로 Guest OS의 동작을 멈추기 위해 사용 void (*suspend)(); 장시간 Guest OS의 동작을 멈추는 경우 사용 (Swap Out) unsigned long top_stack; Guest OS Stack 의 Top unsigned long guarded; Stack Overflow를 감지하기 위한 guard 영역 unsigned long guest_os_stack[VCPU_STACKSIZE-2]; Guest OS의 특별한 동작을 위해 사용되는 임시 스택 unsigned long bottom_stack; Stack의 시작 위치
vcpu 와 guest_os_info의 관계도 guest_os_head_g guest_os_info guest_os_info vcpu0_g vcpu vcpu
struct regs_ctx 필드 구성 및 설명 unsigned long reg[NUM_REGS] 레지스터 R0 ~ R15가 저장 될 장소 Unsigned long cpsr flag 레지스터인 cpsr이 저장 될 장소
struct timer 필드 구성 및 설명 unsigned long long expires_time; Guest OS생성 후, 현재까지 지난 시간 unsigned long long real_time; RTC로 부터 얻은 실제 시간 unsigned long long logical_time; 순수 Guest OS만 수행된 시간 unsigned long long time_quantum; Round Robin Scheduling을 위한 퀀텀
struct address_space 필드 구성 및 설명 struct vcpu *cpu; struct address_space *next; address_space를 이중연결리스트로 구성 하기 위한 필드 struct mem_region *active_region; Guest OS 가 사용하는 메모리 구역에 대한 연결리스트 long pages_count; 사용중인 총 페이지 수 long mem_region_count; 사용중인 메모리 구역 수
struct mem_region 필드 구성 및 설명 struct address_space *belongs_to; 해당 메모리 구역이 속한 주소공간 struct list_head mem_region_list; mem_region을 이중연결리스트로 구성하 기 위한 필드 long page_attribute; 이 mem_region이 기술하고 있는 페이지 테이블 엔트리들의 default 속성 정보를 저장 (User/Supervisor, Locked, etc..) unsigned long start_vaddr; unsigned long end_vaddr; 메모리 구역이 관리할 가상 주소의 시작과 끝 주소 unsigned long start_paddr unsigned long end_paddr; 메모리 구역이 관리할 물리 주소의 시작과 끝 주소
Guest OS의 주소 공간 구성도 < Virtual Memory > guest_os_info vcpu address_space mem_region page In Use active_region Unused < Virtual Memory >
새로운 Guest OS의 생성(1) 생성 방법 …. struct vcpu* vcpu = setup_vcpu(1) setup_guest_os_info(vcpu,0x00010000, 0x10000, “uCOS”); activate_vcpu(vcpu); ….
새로운 Guest OS의 생성(2) 생성과정(Overview) 새로운 vcpu 할당 새로운 guest_os_info 할당 및 초기화 할당받은 guest_os_info를 vcpu에 assign 스택 생성 및 초기화 guest_os_info정보를 통해 vcpu의 address_space 범위 조정 페이지 테이블 구성
setup_vcpu() struct vcpu *setup_vcpu(int cpu_num) { struct vcpu *vcpu= create_vcpu() ; vcpu_map에서 vcpu_id번째 비트가 비어있는지 확인 if 비어있다면 , vcpu_id에 cpu_num 할당 else return 에러 init_vcpu_stack(vcpu) vcpu->current_running_mode = HYPERVISOR_MODE; vcpu->state = INITIAL vcpu->master_table = 페이지 테이블을 위한 공간 할당 struct address_space *address = alloc_cache(address_space) init_address_space(address, vcpu, 디폴트 가상메모리 시작 주소 ,디폴트 가상 메모리 크기, 디폴트 페이지 속성) vcpu->address = address vcpu를 vcpu_list_g 연결리스트에 삽입 return vcpu }
create_vcpu() struct vcpu *create_vcpu(void) { return alloc_cache(vcpu) }
init_vcpu_stack() void init_vcpu_stack(struct vcpu *cpu) { cpu-> top_stack = cpu->bottom_stack top_stack에 vcpu 시작 문맥 (레지스터 값) 저장 }
init_address_space() int init_address_space( struct address_space *address, struct vcpu *vcpu, unsigned int start_addr, int len, unsigned long page_attribute) { address->vcpu = vcpu; 기타 address_space필드 초기화; create_mem_region(start_addr,len) address를 vcpu0_g ->address_space의 연결리스트에 추가 }
create_mem_region() create_mem_region( struct address_space *address, unsigned int start_addr, int len, unsigned int default_page_attr) { 현재 address_space에 해당 메모리 구역이 존재하지 않으면, struct mem_region *region = alloc_cache(mem_region) Page allocator를 통해 [start_addr,start_addr+len-1]구간 안 의 페이지를 할당 실제로 페이지 테이블 구성 및 페이지 프레임 할당 default_page_attr로 페이지 테이블 엔트리 속성 설정 address_space에 메모리 구역 추가 }
find_mem_region() struct mem_region *find_mem_region( struct address_space *address, unsigned int addr, int len) { address_space에서 해당 mem_region을 포함하거나 인접한 mem_region을 반환 없으면 NULL을 리턴 }
merge_mem_regions() int merge_mem_regions( struct address_space *address, struct mem_region *region) { 주위에 region과 인접한 mem_region이 있으면 합침 }
setup_guest_os_info() void setup_guest_os_info( struct vcpu *cpu, unsigned int phys_loc_addr, unsigned int len, char *name) { struct guest_os_info *guest = alloc_cache(guest_os_info); guest의 각 필드 초기화 assign_guest_os(cpu,guest); }
assign_guest_os() int assign_guest_os(struct vcpu *vcpu, struct guest_os_info *guest) { init_guest_os_stack(guest); guest정보를 이용해 vcpu의 address_space 범위 조정 페이지 테이블 구성 vcpu->guest =guest; guest->vcpu = vcpu; guest_os_head_g 연결리스트에 guest추가 }
init_guest_os_stack() void init_guest_os_stack(struct guest_os_info *guest) { guest->saved_regs_ctx에 초기 레지스터값 셋팅 }
vcpu0의 생성(1) 설명 관련 전역 변수 vcpu0는 전역 변수로 선언되며 하이퍼바이저 부팅 시 초기화 시켜 준다. struct vcpu *vcpu0_g 처음 부팅시 동작하는 virtual cpu struct vcpu *current_vcpu; 현재 동작중인 vcpu에 대한 포인터 unsigned char vcpu_map_g[MAX_NUM_VCPU/8]; 각 vcpu의 id를 관리하기 위한 Bit Map
vcpu0의 생성(2) 생성방법 위 과정은 인터럽트가 해지된 상태에서 진행되어야 함 Guest OS 의 생성 방법과 유사 vcpu0_g = setup_vcpu(0) current_vcpu = vcpu0_g; guest_os_info의 설정(setup_guest_os_info())은 하지 않음 activate_vcpu(current_vcpu); 위 과정은 인터럽트가 해지된 상태에서 진행되어야 함
Guest OS의 제거(1) 제거방법 vcpu0 의 커맨드 입력창에서 VM_ …. 1. Guest OS 스케줄링 큐에서 삭제할 guest os를 찾음 2. guest os를 큐에서 제거 3. address_space를 참고하여 메모리 해제 4. vm이 사용중이던 각 자료구조 해제 ….