def page_table_walk(self, virt): self.ttbr = self.ramdump.kernel_virt_to_phys( self.ramdump.swapper_pg_dir_addr) virt_r = Register(virt, zl_index=(47, 39), fl_index=(38, 30), sl_index=(29, 21), tl_index=(20, 12), page_index=(11, 0)) try: fl_desc = self.do_fl_sl_level_lookup(self.ttbr, virt_r.fl_index, 12, 30) except: return None if fl_desc.dtype == Armv8MMU.DESCRIPTOR_BLOCK: return self.fl_block_desc_2_phys(fl_desc, virt_r) base = Register(base=(47, 12)) base.base = fl_desc.next_level_base_addr_upper try: sl_desc = self.do_sl_level_lookup(base.value, virt_r.sl_index) except: return None if sl_desc.dtype == Armv8MMU.DESCRIPTOR_BLOCK: r = self.sl_block_desc_2_phys(sl_desc, virt_r) return r base.base = sl_desc.next_level_base_addr_upper try: tl_desc = self.do_tl_level_lookup(base.value, virt_r.tl_index) except: return None r = self.tl_page_desc_2_phys(tl_desc, virt_r) return r
def translate_first_level(self, virt_r): try: fl_desc = self.do_fl_sl_level_lookup(self.pgtbl, virt_r.fl_index, 30, virtual=self.virt_for_fl) except Armv7LPAEMMU.LookupExceptionFLSL: return None # if we got a block descriptor we're done: if fl_desc.dtype == Armv7LPAEMMU.DESCRIPTOR_BLOCK: return Armv7LPAEMMU.FLBlockMapping(virt_r, fl_desc) base = Register(base=(39, 12)) base.base = fl_desc.next_level_base_addr_upper return Armv7LPAEMMU.FLTableMapping(base.value)
def page_table_walk(self, virt): self.ttbr = self.ramdump.swapper_pg_dir_addr + self.ramdump.phys_offset virt_r = Register(virt, zl_index=(47,39), fl_index=(38,30), sl_index=(29,21), tl_index=(20,12), page_index=(11,0)) fl_desc = self.do_fl_sl_level_lookup(self.ttbr, virt_r.fl_index, 12, 30) if fl_desc.dtype == Armv8MMU.DESCRIPTOR_BLOCK: return self.fl_block_desc_2_phys(fl_desc, virt_r) base = Register(base=(47, 12)) base.base = fl_desc.next_level_base_addr_upper try: sl_desc = self.do_sl_level_lookup( base.value, virt_r.sl_index) except: return None if sl_desc.dtype == Armv8MMU.DESCRIPTOR_BLOCK: r = self.sl_block_desc_2_phys(sl_desc, virt_r) return r base.base = sl_desc.next_level_base_addr_upper try: tl_desc = self.do_tl_level_lookup(base.value, virt_r.tl_index) except: return None r = self.tl_page_desc_2_phys(tl_desc, virt_r) return r
def do_level_lookup(self, table_base_address, table_index, input_addr_split): """Does a base + index descriptor lookup. Returns a tuple with the Register object representing the found descriptor and a Register object representing the the computed descriptor address. """ n = input_addr_split # these Registers are overkill but nice documentation :). table_base = Register(table_base_address, base=(39, n)) descriptor_addr = Register(base=(39, n), offset=(n - 1, 3)) descriptor_addr.base = table_base.base descriptor_addr.offset = table_index descriptor_val = self.read_phys_dword(descriptor_addr.value) descriptor = Register(descriptor_val, dtype=(1, 0)) return descriptor, descriptor_addr
def translate_second_level(self, virt_r, level2_table_addr, block_split=None): if block_split is None: block_split = self.initial_block_split try: sl_desc = self.do_fl_sl_level_lookup( level2_table_addr, virt_r.sl_index, block_split) # res.next_table_addr, virt_r.sl_index, 12, 21) except Armv7LPAEMMU.LookupExceptionFLSL: return None # if we got a block descriptor we're done: if sl_desc.dtype == Armv7LPAEMMU.DESCRIPTOR_BLOCK: return Armv7LPAEMMU.SLBlockMapping(virt_r, sl_desc) base = Register(base=(39, 12)) base.base = sl_desc.next_level_base_addr_upper return Armv7LPAEMMU.SLTableMapping(base.value)
def do_level_lookup(self, table_base_address, table_index, virtual=False): """Does a base + index descriptor lookup. Returns a tuple with the Register object representing the found descriptor and a Register object representing the the computed descriptor address. """ n = self.input_addr_split # these Registers are overkill but nice documentation:). table_base = Register(table_base_address, base=(39, n)) descriptor_addr = Register(base=(39, n), offset=(n - 1, 3)) descriptor_addr.base = table_base.base descriptor_addr.offset = table_index descriptor_val = self.ramdump.read_dword( descriptor_addr.value, virtual=virtual) descriptor = Register(descriptor_val, dtype=(1, 0)) return descriptor, descriptor_addr
def translate_second_level(self, virt_r, level2_table_addr, block_split=None): if block_split is None: block_split = self.initial_block_split try: sl_desc = self.do_fl_sl_level_lookup(level2_table_addr, virt_r.sl_index, block_split) # res.next_table_addr, virt_r.sl_index, 12, 21) except Armv7LPAEMMU.LookupExceptionFLSL: return None # if we got a block descriptor we're done: if sl_desc.dtype == Armv7LPAEMMU.DESCRIPTOR_BLOCK: return Armv7LPAEMMU.SLBlockMapping(virt_r, sl_desc) base = Register(base=(39, 12)) base.base = sl_desc.next_level_base_addr_upper return Armv7LPAEMMU.SLTableMapping(base.value)
def page_table_walk(self, virt): text_offset = 0x8000 pg_dir_size = 0x5000 # 0x4000 for non-LPAE swapper_pg_dir_addr = self.ramdump.phys_offset + text_offset - pg_dir_size # We deduce ttbr1 and ttbcr.t1sz based on the value of # PAGE_OFFSET. This is based on v7_ttb_setup in # arch/arm/mm/proc-v7-3level.S: # * TTBR0/TTBR1 split (PAGE_OFFSET): # * 0x40000000: T0SZ = 2, T1SZ = 0 (not used) # * 0x80000000: T0SZ = 0, T1SZ = 1 # * 0xc0000000: T0SZ = 0, T1SZ = 2 ttbr = swapper_pg_dir_addr self.ttbr = ttbr if self.ramdump.page_offset == 0x40000000: t1sz = 0 initial_lkup_level = 1 elif self.ramdump.page_offset == 0x80000000: t1sz = 1 initial_lkup_level = 1 elif self.ramdump.page_offset == 0xc0000000: t1sz = 2 # need to fixup ttbr1 since we'll be skipping the # first-level lookup (see v7_ttb_setup): # /* PAGE_OFFSET == 0xc0000000, T1SZ == 2 */ # add \ttbr1, \ttbr1, #4096 * (1 + 3) @ only L2 used, skip pgd+3*pmd ttbr += (4096 * (1 + 3)) initial_lkup_level = 2 else: raise Exception( "Invalid phys_offset for page_table_walk: 0x%x" \ % self.ramdump.page_offset) if initial_lkup_level == 1: # see the ARMv7 ARM B3.6.6 (rev 0406C.b): input_addr_split = 5 - t1sz if input_addr_split not in [4, 5]: raise Exception("Invalid stage 1 first-level `n' value: 0x%x" % input_addr_split) virt_r = Register(virt, fl_index=(input_addr_split + 26, 30), sl_index=(29, 21), tl_index=(20, 12), page_index=(11, 0)) fl_desc = self.do_fl_level_lookup(ttbr, virt_r.fl_index, input_addr_split) # if we got a block descriptor we're done: if fl_desc.dtype == Armv7LPAEMMU.DESCRIPTOR_BLOCK: return self.fl_block_desc_2_phys(fl_desc, virt_r) base = Register(base=(39, 12)) base.base = fl_desc.next_level_base_addr_upper sl_desc = self.do_sl_level_lookup(base.value, virt_r.sl_index) elif initial_lkup_level == 2: # see the ARMv7 ARM B3.6.6 (rev 0406C.b): input_addr_split = 14 - t1sz if input_addr_split not in range(7, 13): raise Exception( "Invalid stage 1 second-level (initial) `n' value: 0x%x" % input_addr_split) virt_r = Register(virt, sl_index=(input_addr_split + 17, 21), tl_index=(20, 12), page_index=(11, 0)) try: sl_desc = self.do_fl_sl_level_lookup(ttbr, virt_r.sl_index, input_addr_split, 21) except: return None else: raise Exception("Invalid initial lookup level (0x%x)" % initial_lkup_level) # if we got a block descriptor we're done: if sl_desc.dtype == Armv7LPAEMMU.DESCRIPTOR_BLOCK: return self.sl_block_desc_2_phys(sl_desc, virt_r) base = Register(base=(39, 12)) base.base = sl_desc.next_level_base_addr_upper try: tl_desc = self.do_tl_level_lookup(base.value, virt_r.tl_index) except: return None return self.tl_page_desc_2_phys(tl_desc, virt_r)
def page_table_walk(self, virt): text_offset = 0x8000 pg_dir_size = 0x5000 # 0x4000 for non-LPAE swapper_pg_dir_addr = self.ramdump.phys_offset + text_offset - pg_dir_size # We deduce ttbr1 and ttbcr.t1sz based on the value of # PAGE_OFFSET. This is based on v7_ttb_setup in # arch/arm/mm/proc-v7-3level.S: # * TTBR0/TTBR1 split (PAGE_OFFSET): # * 0x40000000: T0SZ = 2, T1SZ = 0 (not used) # * 0x80000000: T0SZ = 0, T1SZ = 1 # * 0xc0000000: T0SZ = 0, T1SZ = 2 ttbr = swapper_pg_dir_addr self.ttbr = ttbr if self.ramdump.page_offset == 0x40000000: t1sz = 0 initial_lkup_level = 1 elif self.ramdump.page_offset == 0x80000000: t1sz = 1 initial_lkup_level = 1 elif self.ramdump.page_offset == 0xc0000000: t1sz = 2 # need to fixup ttbr1 since we'll be skipping the # first-level lookup (see v7_ttb_setup): # /* PAGE_OFFSET == 0xc0000000, T1SZ == 2 */ # add \ttbr1, \ttbr1, #4096 * (1 + 3) @ only L2 used, skip pgd+3*pmd ttbr += (4096 * (1 + 3)) initial_lkup_level = 2 else: raise Exception( "Invalid phys_offset for page_table_walk: 0x%x" \ % self.ramdump.page_offset) if initial_lkup_level == 1: # see the ARMv7 ARM B3.6.6 (rev 0406C.b): input_addr_split = 5 - t1sz if input_addr_split not in [4, 5]: raise Exception("Invalid stage 1 first-level `n' value: 0x%x" % input_addr_split) virt_r = Register(virt, fl_index=(input_addr_split + 26, 30), sl_index=(29, 21), tl_index=(20, 12), page_index=(11, 0)) fl_desc = self.do_fl_level_lookup( ttbr, virt_r.fl_index, input_addr_split) # if we got a block descriptor we're done: if fl_desc.dtype == Armv7LPAEMMU.DESCRIPTOR_BLOCK: return self.fl_block_desc_2_phys(fl_desc, virt_r) base = Register(base=(39, 12)) base.base = fl_desc.next_level_base_addr_upper sl_desc = self.do_sl_level_lookup( base.value, virt_r.sl_index) elif initial_lkup_level == 2: # see the ARMv7 ARM B3.6.6 (rev 0406C.b): input_addr_split = 14 - t1sz if input_addr_split not in range(7, 13): raise Exception("Invalid stage 1 second-level (initial) `n' value: 0x%x" % input_addr_split) virt_r = Register(virt, sl_index=(input_addr_split + 17, 21), tl_index=(20, 12), page_index=(11, 0)) try: sl_desc = self.do_fl_sl_level_lookup( ttbr, virt_r.sl_index, input_addr_split, 21) except: return None else: raise Exception("Invalid initial lookup level (0x%x)" % initial_lkup_level) # if we got a block descriptor we're done: if sl_desc.dtype == Armv7LPAEMMU.DESCRIPTOR_BLOCK: return self.sl_block_desc_2_phys(sl_desc, virt_r) base = Register(base=(39, 12)) base.base = sl_desc.next_level_base_addr_upper try: tl_desc = self.do_tl_level_lookup( base.value, virt_r.tl_index) except: return None return self.tl_page_desc_2_phys(tl_desc, virt_r)