[커널 20차] 24주차
2023.10.22 17:44
2023.10.21 (24주차) - 약 10명 참여
head.S : __cpu_setup 완료, __primary_switch의 __enable_mmu의 phys_to_ttbr 까지 진행.
개념 정리) __cpu_setup의 tlbi vmalle1 코드에서 local TLB를 invalidate하는데, TLB에 대해서 알고 넘어가면 좋겠다.
1)http://www.iamroot.org/xe/index.php?mid=Programming&listStyle=viewer&document_srl=219053&page=1
2) https://www.bhral.com/post/arm-v8-linux-kernel-head-s-6
3) https://www.techtarget.com/whatis/definition/translation-look-aside-buffer-TLB
4) https://en.wikipedia.org/wiki/Translation_lookaside_buffer
Q: .req 지시자
mair .req x17 tcr .req x16 |
A: define
|
정리)
< MAIR_EL1에 들어갈 값 설정 >
1. default 값 설정 (0x4_0044_ffff)
#define MAIR_EL1_SET \ (MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRnE, MT_DEVICE_nGnRnE) | \ MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRE, MT_DEVICE_nGnRE) | \ MAIR_ATTRIDX(MAIR_ATTR_NORMAL_NC, MT_NORMAL_NC) | \ MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL) | \ MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL_TAGGED)) |
1) MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRnE, MT_DEVICE_nGnRnE) 0x00 << (3 * 8)
2) MAIR_ATTRIDX(MAIR_ATTR_DEVICE_nGnRE, MT_DEVICE_nGnRE) 0x04 << (4 * 8)
3) MAIR_ATTRIDX(MAIR_ATTR_NORMAL_NC, MT_NORMAL_NC) 0x44 << (2 * 8)
4) MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL) 0xff << (0 * 8)
5) MAIR_ATTRIDX(MAIR_ATTR_NORMAL, MT_NORMAL_TAGGED)) 0xff << (1 * 8)
(정확한지는 모르겠다.)
1) Attr0 1111_1111
- Normal memory, Outer Write-Back Non-transient
- Normal memory, Inner Write-Back Non-transient
2) Attr1 1111_1111
- Normal memory, Outer Write-Back Non-transient
- Normal memory, Inner Write-Back Non-transient
3) Attr2 0100_0100
- Normal memory, Outer Non-cacheable
- Normar memory, Inner Non-cacheable
4) Attr3 0000_0000
- Device-nGnRnE memory
5) Attr4 0000_0100
- Device-nGnRE memory
< TCR (Tranlsation Control Register) 에 들어갈 값 설정 >
1. default 값 설정
|
1) TCR_TxSZ(VA_BITS) : T0SZ와 T1SZ 값을 (64 - VA_BITS)로 설정
2) TCR_CACHE_FLAGS : Inner cacheability / Outer cacheability 특성을 WBWA로 설정
(Write Back, Write Allocate)
3) TCR_SMP_FLAGS : Sharability 특성을 Inner sharable로 설정
4) TCR_TG_FLAGS : 페이지 크기에 따라 granule 설정
5) TCR_KASLR_FLAGS : KASLR 설정
6) TCR_ASID16 : ASID 크기 설정
7) TCR_TBI0 : TTBR0_EL1 영역에서 주소 계산 시 Top byte 무시 설정
8) TCR_A1 : TTBR0_EL1과 TTBR1_EL1 중 어느 것에서 ASID 비트를 사용할 것인지 설정
9) TCR_KASAN_SW_FLAGS : TTBR1_EL1 영역에서 주소 계산 시 Top byte 무시 설정, top byte 사용 시 명령어와 데이터 접근에 사용할 것인지, 데이터 접근에만 사용할 것인지 설정
10) TCR_MTE_FLAGS : MTE 설정 (Memory Tagging Extension)
2. errata 처리
|
특정 CPU에서 errata 발생시 TCR bits를 클리어
3. T0SZ / T1SZ 값 재설정
#ifdef CONFIG_ARM64_VA_BITS_52 sub x9, xzr, x0 add x9, x9, #64 tcr_set_t1sz tcr, x9 #else idmap_get_t0sz x9 #endif tcr_set_t0sz tcr, x9 |
1) VA_BITS가 52인 경우 T0SZ / T1SZ
x0는 VA_BITS_MIN이 들어있다. 결국 (64 - VA_BITS_MIN) 값으로 재설정하는 것이다.
VA_BITS가 52인데, 지원하지 않는 경우 VA_BITS_MIN = 48이다. 지원하는 경우 52이다.
T0SZ는 T1SZ와 같다.
2) VA_BITS가 52가 아닌 경우 T0SZ / T1SZ
T1SZ는 default 값 설정과 같다. (64 - VA_BITS)이다.
T0SZ는 idmap_get_t0sz 매크로를 통해서 얻어온다. 커널의 끝 주소를 통해 idmap을 커버할 T0SZ 값을 구한다. VA_BITS로 표현할 수 있는 주소 범위보다 커널이 더 높은 위치에 있는 경우에 T0SZ 값을 변경함으로써 idmap을 커버할 수 있게 한다.
4. TCR_EL1의 IPS 비트 값 설정 (Intermediate Physical address Size)
|
/* * tcr_compute_pa_size - set TCR.(I)PS to the highest supported * ID_AA64MMFR0_EL1.PARange value * * tcr: register with the TCR_ELx value to be updated * pos: IPS or PS bitfield position * tmp{0,1}: temporary registers */ .macro tcr_compute_pa_size, tcr, pos, tmp0, tmp1 mrs \tmp0, ID_AA64MMFR0_EL1 // Narrow PARange to fit the PS field in TCR_ELx ubfx \tmp0, \tmp0, #ID_AA64MMFR0_EL1_PARANGE_SHIFT, #3 mov \tmp1, #ID_AA64MMFR0_EL1_PARANGE_MAX cmp \tmp0, \tmp1 csel \tmp0, \tmp1, \tmp0, hi bfi \tcr, \tmp0, \pos, #3 .endm |
1) ID_AA64MMFR0_EL1 레지스터로부터 PS 필드의 값을 읽어온다.
2) 읽어온 값과 ID_AA64MMFR0_EL1_PARANGE_MAX 값을 비교해 작은 값을 가져온다.
3) 가져온 작은 값을 TCR_EL1의 IPS로 설정한다.
부팅 시 들어가는 ID_AA64MMFR0_EL1.PARANGE(PS) 값과 커널에서 config된 PA_BITS에 따른 PARANGE_MAX 값을 비교해서 작은 값을 선택하는 것이다.
아래 사진을 통해 ID_AA64MMFR0_EL1.PS 와 TCR_EL1.IPS는 대응하는 것을 확인할 수 있다.
5. Access Flags bit를 설정한다. (TCR.HA)
|
1) ID_AA64MMFR1_EL1의 값을 읽어와서 하위 4비트가 0인지 확인해, 아니라면 TCR.HA 비트를 설정해준다.
Access Flag의 의미는 다음과 같다.
Q: Access flag
A: 사용 중인 페이지를 알 수 있다.
하드웨어적으로 Access Flag 비트를 업데이트 하는 것을 허용한다는 의미는 다음과 같다.
Q: hardware update of the Access Flag bit
A: The Page fault handler records that this page is now being used and manually sets the AF bit in the table entry. 를 보면 페이지 폴트 핸들러는 페이지가 사용중이라고 기록하고, 수동으로 AF bit를 기록한다고 나와있다. 수동의 의미는 O/S가 처리해준다는 것인데, 이 과정을 하드웨어적으로 지원한다는 의미인 것 같다.
< 설정한 값을 시스템에 반영 >
1. 설정한 mair, tcr 값을 MAIR_EL1, TCR_EL1 레지스터에 반영한다. SCTLR에는 INIT_SCTLR_EL1_MMU_ON 값을 저장한다.
#endif /* CONFIG_ARM64_HW_AFDBM */ msr mair_el1, mair msr tcr_el1, tcr /* * Prepare SCTLR */ mov_q x0, INIT_SCTLR_EL1_MMU_ON ret |
< __primary_switch 초반부 >
Q: reserved_pg_dir?
A: http://jake.dothome.co.kr/head-64-60/
보안 상향을 위해 copy_from_user() 등의 별도의 전용 API 사용을 제외하고 무단으로 커널 space에서 유저 공간에 접근 못하게 금지하는 SW 에뮬레이션 방식에서 필요한 zero 페이지 테이블이다. ARMv8.0까지 사용되며, ARMv8.1-PAN HW 기능을 사용하면서 이 테이블은 사용하지 않는다.
< __enable_mmu >
1. ID_AA64MMFR0_EL1.TGRAN 값을 통해 지원하는 granule 인지 확인한다.
|
cf)
#define ID_AA64MMFR0_EL1_TGRAN4_SHIFT 28
#define ID_AA64MMFR0_EL1_TGRAN16_SHIFT 20
#define ID_AA64MMFR0_EL1_TGRAN64_SHIFT 24
ID_AA64MMFR0_EL1.TGRAN
ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN 과 MAX 값을 통해 읽어온 granule 필드 값이 MIN 보다 작거나 MAX 보다 큰 경우 __no_granule_suport로 이동.
Q: 왜 ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN, MAX의 값이 0x0, 0x7, 0x15로 설정되었을까요?
A: https://lore.kernel.org/linux-arm-kernel/20221102022057.553634951@linuxfoundation.org/t/
패치 노트를 보면, 이전에는 지원하는지 지원하지 않는지를 .ne로 비교했는데,
위 사진과 같이 52bit를 지원하면서 범위를 설정하게 되었다.
MIN보다 작은 경우에 __no_granule_support로 이동하는 코드는 16KB granule일 때 not supported를 확인하기 위함인 것 같고, MAX보다 큰 경우에 __no_granule_support로 이동하는 코드는 4K, 64KB granule일 때 not supported를 확인하기 위함인 것 같다.
각 MIN,MAX 값이 위와 같이 설정된 이유는 정확히는 모르겠지만, 확장성을 고려하지 않았을까 싶다.
참고:
https://lore.kernel.org/lkml/718f4b0c-20d9-8588-1268-e5b26690899d@arm.com/T/
2. __no_granule_support
|
early_cpu_boot_status 영역에 (CPU_STUCK_IN_KERNEL | CPU_STUCK_REASON_NO_GRAN) 값을 저장한다. (로그로 활용하기 위함인 것 같다.)
(arch/arm64/mm/mmu.c)
/* * The booting CPU updates the failed status @__early_cpu_boot_status, * with MMU turned off. */ long __section(".mmuoff.data.write") __early_cpu_boot_status; |
MMU가 꺼진 상태에서 부팅에 실패하면 __early_cpu_boot_status에 실패 상태를 저장한다.
< 미결 질문 >
Q: __no_granule_support에서 wfi만 무한 루프 돌면 재부팅이 되는 것으로 알고 있습니다. 왜 wfe와 wfi를 중복 사용했을까요?
cf) cold boot(메모리에 값이 없는 상태로 부팅) / warm boot? (메모리에 값이 쓰여진 채로 부팅)
참고:
http://www.iamroot.org/xe/index.php?mid=Programming&document_srl=219128
https://developer.arm.com/documentation/ka001283/latest/
3. TTBR 레지스터에 들어갈 값을 설정한다.
/* * Arrange a physical address in a TTBR register, taking care of 52-bit * addresses. * * phys: physical address, preserved * ttbr: returns the TTBR value */ .macro phys_to_ttbr, ttbr, phys #ifdef CONFIG_ARM64_PA_BITS_52 orr \ttbr, \phys, \phys, lsr #46 and \ttbr, \ttbr, #TTBR_BADDR_MASK_52 #else mov \ttbr, \phys #endif .endm |
1) PA_BITS가 52로 설정된 경우
주소 값에서 상위 6비트를 하위 6비트로 옮긴 후 TTBR_BADDR_MASK_52 값을 통해 masking 해준다. 이 연산을 완료하면, TTBR의 BADDR(Base address)에 해당하는 값만 남게 된다.
Q: TTBR_BADDR_MASK_52 값은 0x0000000000000000_1111111111111111_1111111111111111_1111111111111100 입니다. 왜 하위 2비트는 0일까요?
A2: https://github.com/iamroot20/linux-stable/commit/529c4b05a3cb2f324aac347042ee6d641478e946
2) PA_BITS가 52가 아닌 경우
idmap의 시작 주소를 ttbr 값으로 한다.
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
공지 | [공지] 스터디 정리 노트 공간입니다. | woos | 2016.05.14 | 626 |
248 | [커널 19차] 103 주차 | Min | 2024.04.28 | 1 |
247 | [커널 20차] 48주차 | 무한질주 | 2024.04.25 | 21 |
246 | [커널 19차] 102 주차 | Min | 2024.04.20 | 36 |
245 | [커널 19차] 101 주차 | Min | 2024.04.13 | 63 |
244 | [커널 19차] 100 주차 | Min | 2024.04.13 | 16 |
243 | [커널 19차] 99 주차 | Min | 2024.03.30 | 82 |
242 | [커널 19차] 98 주차 | Min | 2024.03.23 | 55 |
241 | [커널 19차] 97 주차 | Min | 2024.03.16 | 50 |
240 | [커널 19차] 96 주차 | Min | 2024.03.14 | 32 |
239 | [커널 19차] 95 주차 [2] | Min | 2024.03.03 | 111 |
238 | [커널 20차] 32주차 | brw | 2023.12.16 | 386 |
237 | [커널 20차] 29주차 | brw | 2023.11.27 | 161 |
236 | [커널 20차] 27주차 | brw | 2023.11.21 | 86 |
235 | [커널 20차] 26주차 | brw | 2023.11.21 | 48 |
234 | [커널 20차] 28주차 | 이민찬 | 2023.11.19 | 64 |
233 | [커널 20차] 25주차 | 이민찬 | 2023.10.30 | 120 |
» | [커널 20차] 24주차 | 이민찬 | 2023.10.22 | 737 |
231 | [커널 20차] 23주차 | 이민찬 | 2023.10.14 | 81 |
230 | [커널 20차] 22주차 | 이민찬 | 2023.10.08 | 76 |
229 | [커널 20차] 21주차 | 이민찬 | 2023.09.23 | 116 |
.