Skip to content

Instantly share code, notes, and snippets.

@bazad
Created May 17, 2019 05:22
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bazad/07f6d748246b6a16fb77ff938fcd4fb3 to your computer and use it in GitHub Desktop.
Save bazad/07f6d748246b6a16fb77ff938fcd4fb3 to your computer and use it in GitHub Desktop.
A C implementation of a simple page table walk on A12 devices (iOS 12.1.2).
uint64_t
aarch64_page_table_lookup(uint64_t ttbr, uint64_t vaddr,
uint64_t *l1_tte_, uint64_t *l2_tte_, uint64_t *l3_tte_) {
const uint64_t pg_bits = 14;
const uint64_t l1_size = 3;
const uint64_t l2_size = 11;
const uint64_t l3_size = 11;
const uint64_t tte_physaddr_mask = ((1uLL << 40) - 1) & ~((1 << pg_bits) - 1);
uint64_t l1_index = (vaddr >> (l2_size + l3_size + pg_bits)) & ((1 << l1_size) - 1);
uint64_t l2_index = (vaddr >> (l3_size + pg_bits)) & ((1 << l2_size) - 1);
uint64_t l3_index = (vaddr >> pg_bits) & ((1 << l3_size) - 1);
uint64_t pg_offset = vaddr & ((1 << pg_bits) - 1);
uint64_t l1_table = ttbr;
uint64_t l1_tte = phys_read64(l1_table + 8 * l1_index);
if (l1_tte_ != NULL) {
*l1_tte_ = l1_tte;
}
if ((l1_tte & 3) != 3) {
return -1;
}
uint64_t l2_table = l1_tte & tte_physaddr_mask;
uint64_t l2_tte = phys_read64(l2_table + 8 * l2_index);
if (l2_tte_ != NULL) {
*l2_tte_ = l2_tte;
}
if ((l2_tte & 3) != 3) {
return -1;
}
uint64_t l3_table = l2_tte & tte_physaddr_mask;
uint64_t l3_tte = phys_read64(l3_table + 8 * l3_index);
if (l3_tte_ != NULL) {
*l3_tte_ = l3_tte;
}
if ((l3_tte & 3) != 3) {
return -1;
}
uint64_t frame = l3_tte & tte_physaddr_mask;
return frame | pg_offset;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment