1ffc06211cc0381738461eaf8337d449a111bc7d
[lunaix-os.git] / lunaix-os / scripts / gdb / lunadbg / structs / pagetable.py
1 from gdb import Type, Value, lookup_type
2 from . import KernelStruct
3 from ..arch import PageTableHelper as TLB
4
5 class PageTableEntry(KernelStruct):
6     def __init__(self, gdb_inferior: Value, level, va) -> None:
7         self.level = level
8         self.pg_mask = self.get_page_mask()
9         self.va = va & ~self.pg_mask
10         self.base_page_order = TLB.translation_shift_bits(-1)
11
12         ptep = gdb_inferior[va // (self.pg_mask + 1)].address
13         super().__init__(ptep, PageTableEntry)
14         
15         try:
16             self.pte = int(self._kstruct.dereference())
17         except:
18             self.pte = 0
19
20         self.pa = TLB.physical_pfn(self.pte) << self.base_page_order
21
22     def print_abstract(self, pp, *args):
23         self.print_detailed(pp, *args)
24
25     def print_simple(self, pp, *args):
26         self.print_detailed(pp, *args)
27
28     def print_detailed(self, pp, *args):
29         if self.null():
30             pp.print("<Mapping not exists>")
31             return
32         
33         page_order = TLB.translation_shift_bits(self.level)
34         page_order -= self.base_page_order
35         
36         pp.printf("Level %d Translation", TLB.translation_level(self.level))
37
38         pp2 = pp.next_level()
39         pp2.printf("Entry value: 0x%x", self.pte)
40         pp2.printf("Virtual address: 0x%x (ptep=0x%x)", self.va, int(self._kstruct))
41         pp2.printf("Mapped physical: 0x%x (order %d page)", self.pa, page_order)
42         pp2.printf("Page Protection: %s", self.get_page_prot())
43         pp2.printf("Present: %s", self.present())
44         pp2.printf("Huge: %s", TLB.huge_page(self.pte))
45         pp2.print("Attributes:")
46         pp2.next_level().print(self.get_attributes())
47
48     @staticmethod
49     def get_type() -> Type:
50         return lookup_type("unsigned int").pointer()
51
52     def get_page_mask(self):
53         return PageTableEntry.get_level_shift(self.level) - 1
54     
55     def present(self):
56         return TLB.mapping_present(self.pte)
57     
58     def get_page_prot(self):
59         return ''.join(TLB.protections(self.pte))
60
61     def get_attributes(self):
62         attrs = [ self.get_page_prot(),
63                   *TLB.other_attributes(self.level, self.pte) ]
64         return ', '.join(attrs)
65     
66     def null(self):
67         return TLB.null_mapping(self.pte)
68     
69     def same_kind_to(self, pte2):
70         return TLB.same_kind(self.pte, pte2.pte)
71     
72     @staticmethod
73     def get_level_shift(level):
74         return 1 << TLB.translation_shift_bits(level)
75     
76     @staticmethod
77     def max_page_count():
78         return 1 << (TLB.vaddr_width() - TLB.translation_shift_bits(-1))
79
80 class PageTable():
81     def __init__(self) -> None:
82         self.levels = [
83             Value(0xFFFFF000).cast(PageTableEntry.get_type()),
84             Value(0xFFC00000).cast(PageTableEntry.get_type())
85         ]
86
87     def get_pte(self, va, level=-1) -> PageTableEntry:
88         return PageTableEntry(self.levels[level], level, va)
89     
90     def __print_pte_ranged(self, pp, pte_head, pte_tail):
91         start_va = pte_head.va
92         end_va = pte_tail.va
93         sz = end_va - start_va
94         if not (pte_head.null() and pte_tail.null()):
95             pp.printf("0x%016x...0x%016x, 0x%016x [0x%08x] %s", 
96                     start_va, end_va - 1, pte_head.pa, sz,
97                     pte_head.get_attributes())
98         else:
99             pp.printfa("0x{:016x}...0x{:016x}, {:^18s} [0x{:08x}] <no mapping>", 
100                     start_va, end_va - 1, "n/a", sz)
101     
102     def print_ptes_between(self, pp, va, va_end, level=-1):
103         shift = PageTableEntry.get_level_shift(level)
104         n = (va_end - va) // shift
105         self.print_ptes(pp, va, n, level)
106
107     def print_ptes(self, pp, va, pte_num, level=-1):
108         head_pte = PageTableEntry(self.levels[level], level, va)
109         curr_pte = head_pte
110         va = head_pte.va
111
112         pp.printfa("{:^18s}   {:^18s}  {:^18s}  {:^10s}  {:^20s}", 
113                    "va-start", "va-end", "physical", "size", "attributes")
114         for i in range(1, pte_num):
115             va_ = va + i * PageTableEntry.get_level_shift(level)
116             curr_pte = PageTableEntry(self.levels[level], level, va_)
117             
118             if not curr_pte.same_kind_to(head_pte):                
119                 self.__print_pte_ranged(pp, head_pte, curr_pte)
120                 head_pte = curr_pte
121         
122         if curr_pte != head_pte:
123             self.__print_pte_ranged(pp, head_pte, curr_pte)