Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

3240
557
422294


[Arm프로세서] 하이퍼바이저: HCR_EL2 레지스터에 접근하는 어셈블리 코드 분석 Arm: Virtualization

이번에는 HCR_EL2 레지스터를 읽은 예시 코드를 소개합니다.
다음은 XEN 하이퍼바이저에서 호출되는 _show_registers() 함수의 어셈블리 명령어입니다.

01 000000000025c550 <_show_registers.isra.14>:
02  25c550: a9ba53f3  stp x19, x20, [sp, #-96]!
03  25c554: 12001c54  and w20, w2, #0xff
...
04  25c62c: d53c1101  mrs x1, hcr_el2
05  25c630: 90000140  adrp x0, 284000 <symbols_token_index+0x9700>
06  25c634: 91242000  add x0, x0, #0x908
07  25c638: 97ff7e2a  bl 23bee0 <printk>

04번째 줄을 보면 'mrs x1, hcr_el2' 명령어를 실행해 HCR_EL2 레지스터의 값을 x1 레지스터에 로딩합니다. 07번째 줄은 printk() 함수를 호출해 HCR_EL2 레지스터의 값을 담고 있는 x1 레지스터를 출력합니다.

이번에는 HCR_EL2 레지스터에 값을 써서 설정하는 예시 코드를 소개합니다.
다음은 XEN 하이퍼바이저가 부팅할 때 호출되는 init_traps() 함수의 어셈블리 명령어입니다.

01 000000000025c8a0 <init_traps>:
02  25c8a0: d0000060 adrp x0, 26a000 <guest_irq_compat+0x70>
03  25c8a4: 91200000 add x0, x0, #0x800
04  25c8a8: d51cc000 msr vbar_el2, x0
...
05  25c8c8: d2800700 mov x0, #0x38                   // #56
06  25c8cc: d51c1100 msr hcr_el2, x0
07  25c8d0: d5033fdf isb
08  25c8d4: d65f03c0 ret
먼저 05번째 줄을 보겠습니다. 0x38이란 값을 x0 레지스터에 이동하는 동작입니다. 06번째 줄은 x0 레지스터의 값을 hcr_el2 레지스터에 설정하는 명령어입니다.

[중요]
위 코드에서 0x38는 무엇을 의미할까요? 0x38을 2진수로는 111000로 표기할 수 있는데, 이는 HCR_EL2 레지스터를 구성하는 비트 맵에 대응됩니다.

HCR_EL2의 3번째 비트는 FMO, 4번째 비트는 IMO 그리고 5번째 비트는 AMO인데, 해당 비트를 1로 설정하면 비트 맵의 기능을 활성화하게 됩니다. 이 방식으로 HCR_EL2 레지스터를 설정합니다.

위에서 설명한 어셈블리 명령어에 대응되는 C 코드는 다음과 같습니다.

https://github.com/xen-project/xen/blob/stable-4.15/xen/arch/arm/traps.c
01 void init_traps(void)
02 {
...
03    /*
04     * Configure HCR_EL2 with the bare minimum to run Xen until a guest
05     * is scheduled. {A,I,F}MO bits are set to allow EL2 receiving
06     * interrupts.
07     */
08    WRITE_SYSREG(HCR_AMO | HCR_FMO | HCR_IMO, HCR_EL2);
09    isb();
10 }

08번째 줄은 HCR_EL2 레지스터에 첫 번째에 인자로 지정된 매크로 값을 써주는 WRITE_SYSREG() 매크로 함수를 사용합니다. HCR_AMO, HCR_FMO 그리고 HCR_IMO의 값을 OR 비트 연산할 결과를 HCR_EL2 레지스터에 써주는 동작입니다.


덧글

댓글 입력 영역