Rust 수행 준비

Rust 코드 실행을 시작하기 전에 몇 가지 초기화를 실행해야 합니다.

.section .init.entry, "ax" .global entry entry: /* * 메모리 관리 구성을 로드하고 적용합니다. MMU와 캐시를 * 사용 설정할 준비가 되었습니다. . */ adrp x30, idmap msr ttbr0_el1, x30 mov_i x30, .Lmairval msr mair_el1, x30 mov_i x30, .Ltcrval /* 지원되는 PA 범위를 TCR_EL1.IPS에 복사합니다. */ mrs x29, id_aa64mmfr0_el1 bfi x30, x29, #32, #4 msr tcr_el1, x30 mov_i x30, .Lsctlrval /* * 이 지점 앞에 오는 모든 내용이 완료되었는지 확인하고 * 오래된 로컬 TLB 항목을 사용하기 전에 무효화합니다. */ isb tlbi vmalle1 ic iallu dsb nsh isb /* * MMU와 캐시를 사용하도록 sctlr_el1을 구성하고 이 작업이 * 완료될 때까지 진행하지 않습니다. */ msr sctlr_el1, x30 isb /* EL1에서 트래핑 부동 소수점 액세스를 사용 중지합니다. */ mrs x30, cpacr_el1 orr x30, x30, #(0x3 << 20) msr cpacr_el1, x30 isb /* bss 섹션을 0으로 만듭니다. */ adr_l x29, bss_begin adr_l x30, bss_end 0: cmp x29, x30 b.hs 1f stp xzr, xzr, [x29], #16 b 0b 1: /* 스택을 준비합니다. */ adr_l x30, boot_stack_end mov sp, x30 /* 예외 벡터를 설정합니다. */ adr x30, vector_table_el1 msr vbar_el1, x30 /* Rust 코드를 호출합니다. */ bl main /* 루프가 인터럽트를 영원히 기다립니다. */ 2: wfi b 2b

Speaker Notes

  • 이는 C의 경우와 동일합니다. 프로세서 상태를 초기화하고 BSS를 0으로 설정하고 스택 포인터를 설정합니다.
    • BSS(역사적인 이유로, 블록 시작 기호 block starting symbol 이라고 불림)는 오브젝트 파일에서 0으로 초기화된 정적으로 할당된 변수들을 담고 있습니다. BSS는 실제로 이미지에 포함되지는 않습니다. 어차피 0으로 초기화 될 것이기 때문입니다. 컴파일러는 로더 프로그램이 BSS에 속하는 변수들을 0으로 초기화 할 것으로기대하고 오브젝트 파일을 만듭니다.
  • 메모리가 초기화되고 이미지가 로드되는 방식에 따라 BSS가 이미 0으로 설정되었을 수도 있지만 확실히 하기 위해 0으로 설정합니다.
  • 메모리를 읽거나 쓰기 전에 MMU와 캐시를 사용 설정해야 합니다. 그러지 않으면 다음과 같은 상황이 발생할 수 있습니다.
    • 정렬되지 않은 액세스에 오류가 발생합니다. 컴파일러가 정렬되지 않은 액세스를 생성하지 않도록 +strict-align을 설정하는 aarch64-unknown-none 타겟의 Rust 코드를 빌드하므로 이 경우에는 문제가 없지만, 일반적으로 반드시 그런 것은 아닙니다.
    • VM에서 실행한다면 캐시 일관성 문제가 발생할 수 있습니다. 문제는 VM은 캐시가 사용 중지된 상태로 메모리에 직접 액세스하는 반면 호스트에는 동일한 메모리에 대해 캐시할 수 있는 별칭이 있다는 점입니다. 호스트가 메모리에 명시적으로 액세스하지 않더라도 추측 액세스는 캐시 채우기로 이어질 수 있으며, 캐시가 정리되거나 VM이 캐시를 사용 설정하면 둘 중 하나의 변경사항이 손실됩니다. 캐시는 VA 또는 IPA가 아닌 실제 주소로 키가 지정됩니다.
  • 편의상 기기용 주소 공간의 처음 1GiB, DRAM용 다음 1GiB, 더 많은 기기를 위한 또 다른 1GiB를 ID 매핑하는 하드코딩된 페이지 테이블(idmap.S 참고)을 사용합니다. 이는 QEMU에서 사용하는 메모리 레이아웃과 일치합니다.
  • 예외 벡터(vbar_el1)도 설정합니다. 이에 관해서는 나중에 자세히 알아봅니다.
  • 오늘 오후의 모든 예에서는 예외 수준 1(EL1)에서 실행한다고 가정합니다. 다른 예외 수준에서 실행해야 하는 경우 이에 따라 entry.S를 수정해야 합니다.