Linux v6.18.37 · 개념과 코드 읽기

KVM virtualization: EL2, VMX/SVM과 RISC-V H-extension

이 코드는 어떤 문제를 푸나요?

가상 CPU가 대기 중일 때 계속 실제 CPU를 차지하게 할 필요는 없습니다. 그러나 가상 인터럽트가 도착하면 다시 실행할 수 있어야 합니다. arm64는 EL2·HCR·vGIC, x86은 VMX/SVM 및 가상 APIC, RISC-V는 H 확장 및 가상 인터럽트 상태를 사용합니다. 대표로 arm64의 runnable 판단 함수를 읽습니다.

읽을 범위: v6.18.37 · arch/arm64/kvm/arm.c · kvm_arch_vcpu_runnable 756–766행입니다. 아래에 이 범위의 원문과 각 줄의 설명을 실었습니다. 주제 전체의 흐름과 다른 경로는 기존 분석에서 함께 읽으실 수 있습니다.

먼저 알아둘 개념

vCPU와 task

vCPU는 가상 CPU 상태이며 실제 실행은 호스트 스케줄러의 task가 담당합니다.

가상 인터럽트

게스트가 볼 인터럽트 상태입니다. 실제 장치 인터럽트와 한 번에 같은 번호로 전달되는 것은 아닙니다.

정지와 일시 중지

인터럽트가 있어도 관리자가 vCPU를 stopped 또는 pause 상태로 두면 바로 실행할 수 없습니다.

처음 읽을 때

게스트 대기와 호스트 task 대기를 구별한 뒤 인터럽트 하나가 깨우는 과정을 그려 보십시오.

더 깊이 살펴볼 때

커널 irqchip 사용 여부에 따라 timer·PMU의 사용자 공간 통지가 어떻게 달라지는지 추적하십시오.

그림으로 보는 변화

KVM virtualization: EL2, VMX/SVM과 RISC-V H-extension의 단계별 개념 그림
각 단계에 화살표 의미와 생략 범위를 표시했습니다. 주소·숫자 예제는 실제 장치 값을 뜻하지 않습니다.
1단계 설명

1단계 고정

GIF 원본 열기

1. 가상 요청 확인

HCR의 IRQ·FIQ·SError 주입 상태를 확인합니다.

화살표는 물리 IRQ 수신이 아니라 가상 상태 조회입니다.

2. 추가 깨움 조건

사용자 공간 irqchip의 timer·PMU와 vGIC pending을 확인합니다.

여러 깨움 원인을 하나의 조건으로 합칩니다.

3. 실행 가능 판정

stopped와 pause가 아닌지 확인해 결과를 반환합니다.

참이라는 결과가 여기서 직접 게스트를 실행한다는 뜻은 아닙니다.

kvm_arch_vcpu_runnable를 한 줄씩 읽기

줄 번호는 v6.18.37 원문 기준입니다. 주석·빈 줄을 포함한 함수 전체를 먼저 보고, 그 아래에서 각 줄을 설명합니다.

int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
{
	bool irq_lines = *vcpu_hcr(v) & (HCR_VI | HCR_VF | HCR_VSE);

	irq_lines |= (!irqchip_in_kernel(v->kvm) &&
		      (kvm_timer_should_notify_user(v) ||
		       kvm_pmu_should_notify_user(v)));

	return ((irq_lines || kvm_vgic_vcpu_pending_irq(v))
		&& !kvm_arm_vcpu_stopped(v) && !v->arch.pause);
}
int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)

vCPU가 대기 상태에서 실행할 사유가 있는지 판단할 정수 결과를 반환합니다. 게스트 진입 명령 자체는 여기 없습니다.

	bool irq_lines = *vcpu_hcr(v) & (HCR_VI | HCR_VF | HCR_VSE);

vCPU HCR 상태의 가상 IRQ·FIQ·SError 주입 비트를 읽습니다. 물리 GIC pending 전체를 직접 읽는 식이 아닙니다.

	irq_lines |= (!irqchip_in_kernel(v->kvm) &&

irqchip을 커널 안에서 관리하지 않는 경우의 깨움 사유도 기존 irq_lines에 합칩니다.

		      (kvm_timer_should_notify_user(v) ||

가상 timer 사건을 사용자 공간에 알려야 한다면 실행을 다시 진행할 이유로 삼습니다.

		       kvm_pmu_should_notify_user(v)));

가상 PMU의 통지 필요도 같은 조건에 포함하고 괄호를 닫습니다.

	return ((irq_lines || kvm_vgic_vcpu_pending_irq(v))

위에서 계산한 주입 상태 또는 vGIC의 pending IRQ가 있는지 확인합니다.

		&& !kvm_arm_vcpu_stopped(v) && !v->arch.pause);

그렇더라도 vCPU가 stopped이거나 pause이면 실행 가능으로 보지 않습니다. 논리 AND 때문에 깨움 사유와 관리 상태를 함께 만족해야 합니다.

함께 생각해 볼 질문

이 함수가 게스트로 진입합니까?

아닙니다. 실행 가능 여부를 판정하는 helper입니다.

pending IRQ가 있으면 항상 runnable입니까?

이 함수에서는 stopped와 pause 상태도 함께 검사합니다.

가상화 기능이 있으면 Realm도 자동 지원됩니까?

아닙니다. 일반 VM 실행과 Realm의 보호 모델·펌웨어 인터페이스는 구분해야 합니다.

출처와 읽은 범위

Linux stable v6.18.37 · arch/arm64/kvm/arm.c

해당 버전 원본 파일 · 기존 코드 분석 · 설명 원고

맨 위로 ↑