Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1# SPDX-License-Identifier: GPL-2.0
2#
3# Copyright (c) 2023 MediaTek Inc.
4#
5# Authors:
6# Kuan-Ying Lee <Kuan-Ying.Lee@mediatek.com>
7#
8
9import gdb
10import math
11from linux import utils, constants
12
13def DIV_ROUND_UP(n,d):
14 return ((n) + (d) - 1) // (d)
15
16def test_bit(nr, addr):
17 if addr.dereference() & (0x1 << nr):
18 return True
19 else:
20 return False
21
22class page_ops():
23 ops = None
24 def __init__(self):
25 if not constants.LX_CONFIG_SPARSEMEM_VMEMMAP:
26 raise gdb.GdbError('Only support CONFIG_SPARSEMEM_VMEMMAP now')
27 if constants.LX_CONFIG_ARM64 and utils.is_target_arch('aarch64'):
28 self.ops = aarch64_page_ops()
29 elif utils.is_target_arch('x86_64') or utils.is_target_arch('x86-64'):
30 self.ops = x86_page_ops()
31 else:
32 raise gdb.GdbError('Only support aarch64 and x86_64 now')
33
34class x86_page_ops():
35 def __init__(self):
36 self.struct_page_size = utils.get_page_type().sizeof
37 self.PAGE_SHIFT = constants.LX_CONFIG_PAGE_SHIFT
38 self.PAGE_SIZE = 1 << self.PAGE_SHIFT
39 self.PAGE_MASK = (~(self.PAGE_SIZE - 1)) & ((1 << 64) - 1)
40
41 self.PAGE_OFFSET = int(gdb.parse_and_eval("page_offset_base"))
42 self.VMEMMAP_START = int(gdb.parse_and_eval("vmemmap_base"))
43 self.PHYS_BASE = int(gdb.parse_and_eval("phys_base"))
44 self.START_KERNEL_map = 0xffffffff80000000
45
46 self.KERNEL_START = gdb.parse_and_eval("_text")
47 self.KERNEL_END = gdb.parse_and_eval("_end")
48
49 self.VMALLOC_START = int(gdb.parse_and_eval("vmalloc_base"))
50 if self.VMALLOC_START == 0xffffc90000000000:
51 self.VMALLOC_END = self.VMALLOC_START + (32 * 1024 * 1024 * 1024 * 1024) - 1
52 elif self.VMALLOC_START == 0xffa0000000000000:
53 self.VMALLOC_END = self.VMALLOC_START + (12800 * 1024 * 1024 * 1024 * 1024) - 1
54 else:
55 self.VMALLOC_END = self.VMALLOC_START + (12800 * 1024 * 1024 * 1024 * 1024) - 1
56
57 self.MAX_PHYSMEM_BITS = 46
58 self.SECTION_SIZE_BITS = 27
59 self.MAX_ORDER = 10
60
61 self.SECTIONS_SHIFT = self.MAX_PHYSMEM_BITS - self.SECTION_SIZE_BITS
62 self.NR_MEM_SECTIONS = 1 << self.SECTIONS_SHIFT
63 self.PFN_SECTION_SHIFT = self.SECTION_SIZE_BITS - self.PAGE_SHIFT
64 self.PAGES_PER_SECTION = 1 << self.PFN_SECTION_SHIFT
65 self.PAGE_SECTION_MASK = (~(self.PAGES_PER_SECTION - 1)) & ((1 << 64) - 1)
66
67 if constants.LX_CONFIG_SPARSEMEM_EXTREME:
68 self.SECTIONS_PER_ROOT = self.PAGE_SIZE // gdb.lookup_type("struct mem_section").sizeof
69 else:
70 self.SECTIONS_PER_ROOT = 1
71
72 self.NR_SECTION_ROOTS = DIV_ROUND_UP(self.NR_MEM_SECTIONS, self.SECTIONS_PER_ROOT)
73 self.SECTION_ROOT_MASK = self.SECTIONS_PER_ROOT - 1
74
75 try:
76 self.SECTION_HAS_MEM_MAP = 1 << int(gdb.parse_and_eval('SECTION_HAS_MEM_MAP_BIT'))
77 self.SECTION_IS_EARLY = 1 << int(gdb.parse_and_eval('SECTION_IS_EARLY_BIT'))
78 except:
79 self.SECTION_HAS_MEM_MAP = 1 << 0
80 self.SECTION_IS_EARLY = 1 << 3
81
82 self.SUBSECTION_SHIFT = 21
83 self.PAGES_PER_SUBSECTION = 1 << (self.SUBSECTION_SHIFT - self.PAGE_SHIFT)
84
85 if constants.LX_CONFIG_NUMA and constants.LX_CONFIG_NODES_SHIFT:
86 self.NODE_SHIFT = constants.LX_CONFIG_NODES_SHIFT
87 else:
88 self.NODE_SHIFT = 0
89
90 self.MAX_NUMNODES = 1 << self.NODE_SHIFT
91
92 self.vmemmap = gdb.Value(self.VMEMMAP_START).cast(utils.get_page_type().pointer())
93
94 def kasan_reset_tag(self, addr):
95 return addr
96
97 def SECTION_NR_TO_ROOT(self, sec):
98 return sec // self.SECTIONS_PER_ROOT
99
100 def __nr_to_section(self, nr):
101 root = self.SECTION_NR_TO_ROOT(nr)
102 mem_section = gdb.parse_and_eval("mem_section")
103 return mem_section[root][nr & self.SECTION_ROOT_MASK]
104
105 def pfn_to_section_nr(self, pfn):
106 return pfn >> self.PFN_SECTION_SHIFT
107
108 def section_nr_to_pfn(self, sec):
109 return sec << self.PFN_SECTION_SHIFT
110
111 def __pfn_to_section(self, pfn):
112 return self.__nr_to_section(self.pfn_to_section_nr(pfn))
113
114 def pfn_to_section(self, pfn):
115 return self.__pfn_to_section(pfn)
116
117 def subsection_map_index(self, pfn):
118 return (pfn & ~(self.PAGE_SECTION_MASK)) // self.PAGES_PER_SUBSECTION
119
120 def pfn_section_valid(self, ms, pfn):
121 if constants.LX_CONFIG_SPARSEMEM_VMEMMAP:
122 idx = self.subsection_map_index(pfn)
123 return test_bit(idx, ms['usage']['subsection_map'])
124 else:
125 return True
126
127 def valid_section(self, mem_section):
128 if mem_section != None and (mem_section['section_mem_map'] & self.SECTION_HAS_MEM_MAP):
129 return True
130 return False
131
132 def early_section(self, mem_section):
133 if mem_section != None and (mem_section['section_mem_map'] & self.SECTION_IS_EARLY):
134 return True
135 return False
136
137 def pfn_valid(self, pfn):
138 ms = None
139 if self.PHYS_PFN(self.PFN_PHYS(pfn)) != pfn:
140 return False
141 if self.pfn_to_section_nr(pfn) >= self.NR_MEM_SECTIONS:
142 return False
143 ms = self.__pfn_to_section(pfn)
144
145 if not self.valid_section(ms):
146 return False
147 return self.early_section(ms) or self.pfn_section_valid(ms, pfn)
148
149 def PFN_PHYS(self, pfn):
150 return pfn << self.PAGE_SHIFT
151
152 def PHYS_PFN(self, phys):
153 return phys >> self.PAGE_SHIFT
154
155 def __phys_to_virt(self, pa):
156 return pa + self.PAGE_OFFSET
157
158 def __virt_to_phys(self, va):
159 if va >= self.START_KERNEL_map:
160 return va - self.START_KERNEL_map + self.PHYS_BASE
161 else:
162 return va - self.PAGE_OFFSET
163
164 def virt_to_phys(self, va):
165 return self.__virt_to_phys(va)
166
167 def virt_to_page(self, va):
168 return self.pfn_to_page(self.virt_to_pfn(va))
169
170 def __pa(self, va):
171 return self.__virt_to_phys(va)
172
173 def __va(self, pa):
174 return self.__phys_to_virt(pa)
175
176 def pfn_to_kaddr(self, pfn):
177 return self.__va(pfn << self.PAGE_SHIFT)
178
179 def virt_to_pfn(self, va):
180 return self.PHYS_PFN(self.__virt_to_phys(va))
181
182 def sym_to_pfn(self, x):
183 return self.PHYS_PFN(self.__virt_to_phys(x))
184
185 def page_to_pfn(self, page):
186 return int(page.cast(utils.get_page_type().pointer()) - self.vmemmap)
187
188 def pfn_to_page(self, pfn):
189 return self.vmemmap + pfn
190
191 def page_to_phys(self, page):
192 return self.PFN_PHYS(self.page_to_pfn(page))
193
194 def page_to_virt(self, page):
195 return self.__va(self.page_to_phys(page))
196
197 def page_address(self, page):
198 return self.page_to_virt(page)
199
200 def folio_address(self, folio):
201 return self.page_address(folio['page'].address)
202
203class aarch64_page_ops():
204 def __init__(self):
205 self.SUBSECTION_SHIFT = 21
206 self.SEBSECTION_SIZE = 1 << self.SUBSECTION_SHIFT
207 self.MODULES_VSIZE = 2 * 1024 * 1024 * 1024
208
209 if constants.LX_CONFIG_ARM64_64K_PAGES:
210 self.SECTION_SIZE_BITS = 29
211 else:
212 self.SECTION_SIZE_BITS = 27
213 self.MAX_PHYSMEM_BITS = constants.LX_CONFIG_ARM64_VA_BITS
214
215 self.PAGE_SHIFT = constants.LX_CONFIG_PAGE_SHIFT
216 self.PAGE_SIZE = 1 << self.PAGE_SHIFT
217 self.PAGE_MASK = (~(self.PAGE_SIZE - 1)) & ((1 << 64) - 1)
218
219 self.VA_BITS = constants.LX_CONFIG_ARM64_VA_BITS
220 if self.VA_BITS > 48:
221 if constants.LX_CONFIG_ARM64_16K_PAGES:
222 self.VA_BITS_MIN = 47
223 else:
224 self.VA_BITS_MIN = 48
225 tcr_el1 = gdb.execute("info registers $TCR_EL1", to_string=True)
226 tcr_el1 = int(tcr_el1.split()[1], 16)
227 self.vabits_actual = 64 - ((tcr_el1 >> 16) & 63)
228 else:
229 self.VA_BITS_MIN = self.VA_BITS
230 self.vabits_actual = self.VA_BITS
231 self.kimage_voffset = gdb.parse_and_eval('kimage_voffset') & ((1 << 64) - 1)
232
233 self.SECTIONS_SHIFT = self.MAX_PHYSMEM_BITS - self.SECTION_SIZE_BITS
234
235 if str(constants.LX_CONFIG_ARCH_FORCE_MAX_ORDER).isdigit():
236 self.MAX_ORDER = constants.LX_CONFIG_ARCH_FORCE_MAX_ORDER
237 else:
238 self.MAX_ORDER = 10
239
240 self.MAX_ORDER_NR_PAGES = 1 << (self.MAX_ORDER)
241 self.PFN_SECTION_SHIFT = self.SECTION_SIZE_BITS - self.PAGE_SHIFT
242 self.NR_MEM_SECTIONS = 1 << self.SECTIONS_SHIFT
243 self.PAGES_PER_SECTION = 1 << self.PFN_SECTION_SHIFT
244 self.PAGE_SECTION_MASK = (~(self.PAGES_PER_SECTION - 1)) & ((1 << 64) - 1)
245
246 if constants.LX_CONFIG_SPARSEMEM_EXTREME:
247 self.SECTIONS_PER_ROOT = self.PAGE_SIZE // gdb.lookup_type("struct mem_section").sizeof
248 else:
249 self.SECTIONS_PER_ROOT = 1
250
251 self.NR_SECTION_ROOTS = DIV_ROUND_UP(self.NR_MEM_SECTIONS, self.SECTIONS_PER_ROOT)
252 self.SECTION_ROOT_MASK = self.SECTIONS_PER_ROOT - 1
253 self.SUBSECTION_SHIFT = 21
254 self.SEBSECTION_SIZE = 1 << self.SUBSECTION_SHIFT
255 self.PFN_SUBSECTION_SHIFT = self.SUBSECTION_SHIFT - self.PAGE_SHIFT
256 self.PAGES_PER_SUBSECTION = 1 << self.PFN_SUBSECTION_SHIFT
257
258 self.SECTION_HAS_MEM_MAP = 1 << int(gdb.parse_and_eval('SECTION_HAS_MEM_MAP_BIT'))
259 self.SECTION_IS_EARLY = 1 << int(gdb.parse_and_eval('SECTION_IS_EARLY_BIT'))
260
261 self.struct_page_size = utils.get_page_type().sizeof
262 self.STRUCT_PAGE_MAX_SHIFT = (int)(math.log(self.struct_page_size, 2))
263
264 self.PAGE_OFFSET = self._PAGE_OFFSET(self.VA_BITS)
265 self.MODULES_VADDR = self._PAGE_END(self.VA_BITS_MIN)
266 self.MODULES_END = self.MODULES_VADDR + self.MODULES_VSIZE
267
268 self.VMEMMAP_RANGE = self._PAGE_END(self.VA_BITS_MIN) - self.PAGE_OFFSET
269 self.VMEMMAP_SIZE = (self.VMEMMAP_RANGE >> self.PAGE_SHIFT) * self.struct_page_size
270 self.VMEMMAP_END = (-(1 * 1024 * 1024 * 1024)) & 0xffffffffffffffff
271 self.VMEMMAP_START = self.VMEMMAP_END - self.VMEMMAP_SIZE
272
273 self.VMALLOC_START = self.MODULES_END
274 self.VMALLOC_END = self.VMEMMAP_START - 256 * 1024 * 1024
275
276 self.memstart_addr = gdb.parse_and_eval("memstart_addr")
277 self.PHYS_OFFSET = self.memstart_addr
278 self.vmemmap = gdb.Value(self.VMEMMAP_START).cast(utils.get_page_type().pointer()) - (self.memstart_addr >> self.PAGE_SHIFT)
279
280 self.KERNEL_START = gdb.parse_and_eval("_text")
281 self.KERNEL_END = gdb.parse_and_eval("_end")
282
283 if constants.LX_CONFIG_KASAN_GENERIC or constants.LX_CONFIG_KASAN_SW_TAGS:
284 if constants.LX_CONFIG_KASAN_GENERIC:
285 self.KASAN_SHADOW_SCALE_SHIFT = 3
286 else:
287 self.KASAN_SHADOW_SCALE_SHIFT = 4
288 self.KASAN_SHADOW_OFFSET = constants.LX_CONFIG_KASAN_SHADOW_OFFSET
289 self.KASAN_SHADOW_END = (1 << (64 - self.KASAN_SHADOW_SCALE_SHIFT)) + self.KASAN_SHADOW_OFFSET
290 self.PAGE_END = self.KASAN_SHADOW_END - (1 << (self.vabits_actual - self.KASAN_SHADOW_SCALE_SHIFT))
291 else:
292 self.PAGE_END = self._PAGE_END(self.VA_BITS_MIN)
293
294 if constants.LX_CONFIG_NUMA and constants.LX_CONFIG_NODES_SHIFT:
295 self.NODE_SHIFT = constants.LX_CONFIG_NODES_SHIFT
296 else:
297 self.NODE_SHIFT = 0
298
299 self.MAX_NUMNODES = 1 << self.NODE_SHIFT
300
301 def SECTION_NR_TO_ROOT(self, sec):
302 return sec // self.SECTIONS_PER_ROOT
303
304 def __nr_to_section(self, nr):
305 root = self.SECTION_NR_TO_ROOT(nr)
306 mem_section = gdb.parse_and_eval("mem_section")
307 return mem_section[root][nr & self.SECTION_ROOT_MASK]
308
309 def pfn_to_section_nr(self, pfn):
310 return pfn >> self.PFN_SECTION_SHIFT
311
312 def section_nr_to_pfn(self, sec):
313 return sec << self.PFN_SECTION_SHIFT
314
315 def __pfn_to_section(self, pfn):
316 return self.__nr_to_section(self.pfn_to_section_nr(pfn))
317
318 def pfn_to_section(self, pfn):
319 return self.__pfn_to_section(pfn)
320
321 def subsection_map_index(self, pfn):
322 return (pfn & ~(self.PAGE_SECTION_MASK)) // self.PAGES_PER_SUBSECTION
323
324 def pfn_section_valid(self, ms, pfn):
325 if constants.LX_CONFIG_SPARSEMEM_VMEMMAP:
326 idx = self.subsection_map_index(pfn)
327 return test_bit(idx, ms['usage']['subsection_map'])
328 else:
329 return True
330
331 def valid_section(self, mem_section):
332 if mem_section != None and (mem_section['section_mem_map'] & self.SECTION_HAS_MEM_MAP):
333 return True
334 return False
335
336 def early_section(self, mem_section):
337 if mem_section != None and (mem_section['section_mem_map'] & self.SECTION_IS_EARLY):
338 return True
339 return False
340
341 def pfn_valid(self, pfn):
342 ms = None
343 if self.PHYS_PFN(self.PFN_PHYS(pfn)) != pfn:
344 return False
345 if self.pfn_to_section_nr(pfn) >= self.NR_MEM_SECTIONS:
346 return False
347 ms = self.__pfn_to_section(pfn)
348
349 if not self.valid_section(ms):
350 return False
351 return self.early_section(ms) or self.pfn_section_valid(ms, pfn)
352
353 def _PAGE_OFFSET(self, va):
354 return (-(1 << (va))) & 0xffffffffffffffff
355
356 def _PAGE_END(self, va):
357 return (-(1 << (va - 1))) & 0xffffffffffffffff
358
359 def kasan_reset_tag(self, addr):
360 if constants.LX_CONFIG_KASAN_SW_TAGS or constants.LX_CONFIG_KASAN_HW_TAGS:
361 return int(addr) | (0xff << 56)
362 else:
363 return addr
364
365 def __is_lm_address(self, addr):
366 if (addr - self.PAGE_OFFSET) < (self.PAGE_END - self.PAGE_OFFSET):
367 return True
368 else:
369 return False
370 def __lm_to_phys(self, addr):
371 return addr - self.PAGE_OFFSET + self.PHYS_OFFSET
372
373 def __kimg_to_phys(self, addr):
374 return addr - self.kimage_voffset
375
376 def __virt_to_phys_nodebug(self, va):
377 untagged_va = self.kasan_reset_tag(va)
378 if self.__is_lm_address(untagged_va):
379 return self.__lm_to_phys(untagged_va)
380 else:
381 return self.__kimg_to_phys(untagged_va)
382
383 def __virt_to_phys(self, va):
384 if constants.LX_CONFIG_DEBUG_VIRTUAL:
385 if not self.__is_lm_address(self.kasan_reset_tag(va)):
386 raise gdb.GdbError("Warning: virt_to_phys used for non-linear address: 0x%lx\n" % va)
387 return self.__virt_to_phys_nodebug(va)
388
389 def virt_to_phys(self, va):
390 return self.__virt_to_phys(va)
391
392 def PFN_PHYS(self, pfn):
393 return pfn << self.PAGE_SHIFT
394
395 def PHYS_PFN(self, phys):
396 return phys >> self.PAGE_SHIFT
397
398 def __phys_to_virt(self, pa):
399 return (pa - self.PHYS_OFFSET) | self.PAGE_OFFSET
400
401 def __phys_to_pfn(self, pa):
402 return self.PHYS_PFN(pa)
403
404 def __pfn_to_phys(self, pfn):
405 return self.PFN_PHYS(pfn)
406
407 def __pa_symbol_nodebug(self, x):
408 return self.__kimg_to_phys(x)
409
410 def __phys_addr_symbol(self, x):
411 if constants.LX_CONFIG_DEBUG_VIRTUAL:
412 if x < self.KERNEL_START or x > self.KERNEL_END:
413 raise gdb.GdbError("0x%x exceed kernel range" % x)
414 return self.__pa_symbol_nodebug(x)
415
416 def __pa_symbol(self, x):
417 return self.__phys_addr_symbol(x)
418
419 def __va(self, pa):
420 return self.__phys_to_virt(pa)
421
422 def pfn_to_kaddr(self, pfn):
423 return self.__va(pfn << self.PAGE_SHIFT)
424
425 def virt_to_pfn(self, va):
426 return self.__phys_to_pfn(self.__virt_to_phys(va))
427
428 def sym_to_pfn(self, x):
429 return self.__phys_to_pfn(self.__pa_symbol(x))
430
431 def page_to_pfn(self, page):
432 return int(page.cast(utils.get_page_type().pointer()) - self.vmemmap.cast(utils.get_page_type().pointer()))
433
434 def page_to_phys(self, page):
435 return self.__pfn_to_phys(self.page_to_pfn(page))
436
437 def pfn_to_page(self, pfn):
438 return (self.vmemmap + pfn).cast(utils.get_page_type().pointer())
439
440 def page_to_virt(self, page):
441 if constants.LX_CONFIG_DEBUG_VIRTUAL:
442 return self.__va(self.page_to_phys(page))
443 else:
444 __idx = int((page.cast(gdb.lookup_type("unsigned long")) - self.VMEMMAP_START).cast(utils.get_ulong_type())) // self.struct_page_size
445 return self.PAGE_OFFSET + (__idx * self.PAGE_SIZE)
446
447 def virt_to_page(self, va):
448 if constants.LX_CONFIG_DEBUG_VIRTUAL:
449 return self.pfn_to_page(self.virt_to_pfn(va))
450 else:
451 __idx = int(self.kasan_reset_tag(va) - self.PAGE_OFFSET) // self.PAGE_SIZE
452 addr = self.VMEMMAP_START + (__idx * self.struct_page_size)
453 return gdb.Value(addr).cast(utils.get_page_type().pointer())
454
455 def page_address(self, page):
456 return self.page_to_virt(page)
457
458 def folio_address(self, folio):
459 return self.page_address(folio['page'].address)
460
461class LxPFN2Page(gdb.Command):
462 """PFN to struct page"""
463
464 def __init__(self):
465 super(LxPFN2Page, self).__init__("lx-pfn_to_page", gdb.COMMAND_USER)
466
467 def invoke(self, arg, from_tty):
468 argv = gdb.string_to_argv(arg)
469 pfn = int(argv[0])
470 page = page_ops().ops.pfn_to_page(pfn)
471 gdb.write("pfn_to_page(0x%x) = 0x%x\n" % (pfn, page))
472
473LxPFN2Page()
474
475class LxPage2PFN(gdb.Command):
476 """struct page to PFN"""
477
478 def __init__(self):
479 super(LxPage2PFN, self).__init__("lx-page_to_pfn", gdb.COMMAND_USER)
480
481 def invoke(self, arg, from_tty):
482 argv = gdb.string_to_argv(arg)
483 struct_page_addr = int(argv[0], 16)
484 page = gdb.Value(struct_page_addr).cast(utils.get_page_type().pointer())
485 pfn = page_ops().ops.page_to_pfn(page)
486 gdb.write("page_to_pfn(0x%x) = 0x%x\n" % (page, pfn))
487
488LxPage2PFN()
489
490class LxPageAddress(gdb.Command):
491 """struct page to linear mapping address"""
492
493 def __init__(self):
494 super(LxPageAddress, self).__init__("lx-page_address", gdb.COMMAND_USER)
495
496 def invoke(self, arg, from_tty):
497 argv = gdb.string_to_argv(arg)
498 struct_page_addr = int(argv[0], 16)
499 page = gdb.Value(struct_page_addr).cast(utils.get_page_type().pointer())
500 addr = page_ops().ops.page_address(page)
501 gdb.write("page_address(0x%x) = 0x%x\n" % (page, addr))
502
503LxPageAddress()
504
505class LxPage2Phys(gdb.Command):
506 """struct page to physical address"""
507
508 def __init__(self):
509 super(LxPage2Phys, self).__init__("lx-page_to_phys", gdb.COMMAND_USER)
510
511 def invoke(self, arg, from_tty):
512 argv = gdb.string_to_argv(arg)
513 struct_page_addr = int(argv[0], 16)
514 page = gdb.Value(struct_page_addr).cast(utils.get_page_type().pointer())
515 phys_addr = page_ops().ops.page_to_phys(page)
516 gdb.write("page_to_phys(0x%x) = 0x%x\n" % (page, phys_addr))
517
518LxPage2Phys()
519
520class LxVirt2Phys(gdb.Command):
521 """virtual address to physical address"""
522
523 def __init__(self):
524 super(LxVirt2Phys, self).__init__("lx-virt_to_phys", gdb.COMMAND_USER)
525
526 def invoke(self, arg, from_tty):
527 argv = gdb.string_to_argv(arg)
528 linear_addr = int(argv[0], 16)
529 phys_addr = page_ops().ops.virt_to_phys(linear_addr)
530 gdb.write("virt_to_phys(0x%x) = 0x%x\n" % (linear_addr, phys_addr))
531
532LxVirt2Phys()
533
534class LxVirt2Page(gdb.Command):
535 """virtual address to struct page"""
536
537 def __init__(self):
538 super(LxVirt2Page, self).__init__("lx-virt_to_page", gdb.COMMAND_USER)
539
540 def invoke(self, arg, from_tty):
541 argv = gdb.string_to_argv(arg)
542 linear_addr = int(argv[0], 16)
543 page = page_ops().ops.virt_to_page(linear_addr)
544 gdb.write("virt_to_page(0x%x) = 0x%x\n" % (linear_addr, page))
545
546LxVirt2Page()
547
548class LxSym2PFN(gdb.Command):
549 """symbol address to PFN"""
550
551 def __init__(self):
552 super(LxSym2PFN, self).__init__("lx-sym_to_pfn", gdb.COMMAND_USER)
553
554 def invoke(self, arg, from_tty):
555 argv = gdb.string_to_argv(arg)
556 sym_addr = int(argv[0], 16)
557 pfn = page_ops().ops.sym_to_pfn(sym_addr)
558 gdb.write("sym_to_pfn(0x%x) = %d\n" % (sym_addr, pfn))
559
560LxSym2PFN()
561
562class LxPFN2Kaddr(gdb.Command):
563 """PFN to kernel address"""
564
565 def __init__(self):
566 super(LxPFN2Kaddr, self).__init__("lx-pfn_to_kaddr", gdb.COMMAND_USER)
567
568 def invoke(self, arg, from_tty):
569 argv = gdb.string_to_argv(arg)
570 pfn = int(argv[0])
571 kaddr = page_ops().ops.pfn_to_kaddr(pfn)
572 gdb.write("pfn_to_kaddr(%d) = 0x%x\n" % (pfn, kaddr))
573
574LxPFN2Kaddr()