티스토리 뷰
TTBR
- Translation Table Base Register
- 가상 주소를 싥제 주소로 매핑시 사용하는 레지스터
TTBR0_EL1 : 유저 스페이스
- Holds the base address of the translation table for the initial lookup for stage 1 of the translation of an address from the lower VA range in the EL1&0 translation regime, and other information for this translation regime.
TTBR1: 커널 스페이스
- Holds the base address of the translation table for the initial lookup for stage 1 of the translation of an address from the higher VA range in the EL1&0 stage 1 translation regime, and other information for this translation regime.
TTBRx_EL1 에서 적절한 base address 를 찾고 VA 상위 비트를 사용해 페이지 테이블을 탐색합니다.
(base_address 로 PGD 를 찾는걸까? pgd = va(ttbr0_el1) ?)
cpu_uninstall_idmap
- TTBR0 를 부팅 시점에서는 idmapping 용도로만 사용 (identity maaping = VA = PA)
- TTBR0 에 접근하더라도 pgd 가 아니라 zero page 로 들어가도록 함
- 그래서 이 설정을 제거할 것
void __init __no_sanitize_address setup_arch(char **cmdline_p)
{
/*
* TTBR0 is only used for the identity mapping at this stage. Make it
* point to zero page to avoid speculatively fetching new entries.
*/
cpu_uninstall_idmap();
- 부팅 초기에 사용한 TTBR0_EL1 idmap 을 제거하고, 현재 실행중인 mm 을 설치해야함
- TCR_EL1.T0SZ (유저 공간의 가상 주소 공간 크기)
- idmap 은 유저공간과 같은 가상 주소 영역에 위치하지만, global entry (pgd) 를 사용하고, T0SZ 도 다를 수 있다.
- TLB 를 invalidate 하고 T0SZ 를 설정하기 전까지는 reserved table 을 임시로 설정한다.
- 현재 task 가 커널 전용 테스크라면 별도 처리를 하지 않는다.
/*
* Remove the idmap from TTBR0_EL1 and install the pgd of the active mm.
*
* The idmap lives in the same VA range as userspace, but uses global entries
* and may use a different TCR_EL1.T0SZ. To avoid issues resulting from
* speculative TLB fetches, we must temporarily install the reserved page
* tables while we invalidate the TLBs and set up the correct TCR_EL1.T0SZ.
*
* If current is a not a user task, the mm covers the TTBR1_EL1 page tables,
* which should not be installed in TTBR0_EL1. In this case we can leave the
* reserved page tables in place.
*/
static inline void cpu_uninstall_idmap(void)
{
// arm64 의 current 는 현재 task. 즉 Init_task
// activie_mm = init_mm
struct mm_struct *mm = current->active_mm;
// 임시로 사용하는 예약된 pgd 의 물리 주소를 ttbr0 에 설정
// t0sz 를 설정하기 전에 문제가 될 수 있으니 미리 변경
cpu_set_reserved_ttbr0();
local_flush_tlb_all();
// #define cpu_set_default_tcr_t0sz() __cpu_set_tcr_t0sz(TCR_T0SZ(vabits_actual))
// tcr.t0sz 설정. 유저스페이스의 가상 주소 사이즈
cpu_set_default_tcr_t0sz();
// pan : privileged access never
// 커널 공간에서 유저공간 (ttbr0)을 접근하지 않겠다라는 설정
// !pan 이기 때문에 커널에서 유저 mm 에 접근할 수 있음
if (mm != &init_mm && !system_uses_ttbr0_pan())
cpu_switch_mm(mm->pgd, mm);
}
/*
* Set TTBR0 to reserved_pg_dir. No translations will be possible via TTBR0.
*/
static inline void cpu_set_reserved_ttbr0_nosync(void)
{
unsigned long ttbr = phys_to_ttbr(__pa_symbol(reserved_pg_dir));
write_sysreg(ttbr, ttbr0_el1);
}
static inline void cpu_set_reserved_ttbr0(void)
{
cpu_set_reserved_ttbr0_nosync();
isb();
}
cpu_switch_mm
context switch 시 메모리 매핑을 전환
infos
- mm->pgd 는 프로세스의 최상위 페이지 테이블 (커널 가상 주소)
- ttbr base address 는 물리주소
mm->pgd 를 pa 로 변환 후 ttbr 로 변환해서 레지스터에 등록
#ifdef CONFIG_ARM64_PA_BITS_52
#define phys_to_ttbr(addr) (((addr) | ((addr) >> 46)) & TTBR_BADDR_MASK_52)
#else
#define phys_to_ttbr(addr) (addr)
#endif
void cpu_do_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm)
{
unsigned long ttbr1 = read_sysreg(ttbr1_el1);
unsigned long asid = ASID(mm);
unsigned long ttbr0 = phys_to_ttbr(pgd_phys);
/* Skip CNP for the reserved ASID */
if (system_supports_cnp() && asid)
ttbr0 |= TTBR_CNP_BIT;
/* SW PAN needs a copy of the ASID in TTBR0 for entry */
if (IS_ENABLED(CONFIG_ARM64_SW_TTBR0_PAN))
ttbr0 |= FIELD_PREP(TTBR_ASID_MASK, asid);
/* Set ASID in TTBR1 since TCR.A1 is set */
ttbr1 &= ~TTBR_ASID_MASK;
ttbr1 |= FIELD_PREP(TTBR_ASID_MASK, asid);
cpu_set_reserved_ttbr0_nosync();
write_sysreg(ttbr1, ttbr1_el1);
write_sysreg(ttbr0, ttbr0_el1);
isb();
post_ttbr_update_workaround();
}
static inline void cpu_switch_mm(pgd_t *pgd, struct mm_struct *mm)
{
BUG_ON(pgd == swapper_pg_dir);
cpu_do_switch_mm(virt_to_phys(pgd),mm);
}
'개발 > arm64 linux 6 분석' 카테고리의 다른 글
local_daif_restore (setup_arch) (0) | 2025.05.31 |
---|---|
SHADOW_CALL_STACK [SCS] (setup_arch) (0) | 2025.05.31 |
early_param (setup_arch) (0) | 2025.05.31 |
jump_label (setup_arch) (0) | 2025.05.31 |
start_kernel 2 setup_arch (0) | 2025.05.24 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- Visual Studio
- set value
- cockroach db
- it's called a vrpit
- vrpit
- shared_from_this
- boost
- 면접
- hole-punching
- 봄날에 스케치
- mysql
- C++
- Golang
- 우리는 vr핏이라고 부릅니다
- SuffixArray
- red underline
- 클래스 맴버 변수 출력하기
- Reciprocal n-body Collision Avoidance
- 카카오
- Obstacle Avoidance
- print shared_ptr class member variable
- 영상 픽셀화 하기
- 잘못된 빨간줄
- Quest2
- chrome-extension
- RVO
- 코어 남기기
- 에러 위치 찾기
- ad skip
- vr핏
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
글 보관함