2 Constants and routines for manipulating kernel page struct.
3 Copyright 2014-2017 Cray Inc. All Rights Reserved
6 from pykdump.API import *
9 import crashlib.cid.machdep_table
10 import crashlib.cid.page_flags
11 import crashlib.cid.phys_mem_map
12 import crashlib.memarray
14 # --------------------------------------------------------------------------
16 page_struct_size = getSizeOf('struct page')
18 # --------------------------------------------------------------------------
20 # Create a function for determining whether a page is controlled by the
21 # buddy allocator. Note that earlier kernels (< 3.0) have a page flag, while
22 # later kernels use the _mapcount field.
24 if hasattr(crashlib.cid.pgflags, 'PG_buddy'):
25 def is_buddy_page(page):
26 return page.flags & crashlib.cid.pgflags.PG_buddy.mask;
28 def is_buddy_page(page):
29 # Early implementations used -2, later use -128
30 return page._mapcount.counter == -128 or page._mapcount.counter == -2
32 if hasattr(crashlib.cid.pgflags, 'PG_compound'):
33 def is_compound_page_head(page):
34 return (page.flags & (crashlib.cid.pgflags.PG_reclaim.mask |
35 crashlib.cid.pgflags.PG_compound.mask)
36 ) == crashlib.cid.pgflags.PG_compound
38 def is_compound_page_tail(page):
39 return (page.flags & (crashlib.cid.pgflags.PG_reclaim.mask |
40 crashlib.cid.pgflags.PG_compound.mask)
41 ) == (crashlib.cid.pgflags.PG_reclaim.mask |
42 crashlib.cid.pgflags.PG_compound.mask)
44 def is_compound_page(page):
45 return page.flags & crashlib.cid.pgflags.PG_compound.mask
47 elif hasattr(crashlib.cid.pgflags, 'PG_tail'):
48 # PG_head and PG_tail defined
49 def is_compound_page_head(page):
50 return page.flags & (crashlib.cid.pgflags.PG_head.mask)
52 def is_compound_page_tail(page):
53 return page.flags & (crashlib.cid.pgflags.PG_tail.mask)
55 def is_compound_page(page):
56 return is_compound_page_head(page) or is_compound_page_tail(page)
59 # Only PG_head is defined
60 def is_compound_page_head(page):
61 return page.flags & (crashlib.cid.pgflags.PG_head.mask)
63 def is_compound_page_tail(page):
64 return page.compound_head & 1
66 def is_compound_page(page):
67 return is_compound_page_head(page) or is_compound_page_tail(page)
69 # --------------------------------------------------------------------------
71 # Find the page order of a buddy page
73 def buddy_order(page):
74 """Retrieve the order of a page in the buddy allocator"""
77 # --------------------------------------------------------------------------
79 # Create a function to determine the page order of a compound page
81 if member_offset('struct page', 'compound_order') > -1:
82 def compound_order(page):
83 """Retrieve the page order for a compound page."""
84 # A compound page is a series of contiguous pages, thus there are
85 # at least two page structs. The second page struct (first tail page)
86 # contains the page order; the head page uses the space for a
88 return page[1].compound_order
91 def compound_order(page):
92 """Retrieve the page order for a compound page."""
93 # A compound page is a series of contiguous pages, thus there are
94 # at least two page structs. The second page struct (first tail page)
95 # contains the page order stored in the lru.prev field; the head page
96 # uses the space for a different purpose.
97 return page[1].lru.prev
99 # --------------------------------------------------------------------------
102 """Returns the pfn for the supplied page struct or page struct address."""
103 vmemmap_vaddr = crashlib.cid.mdtbl.vmemmap_vaddr
104 return (page - vmemmap_vaddr) / page_struct_size
106 # --------------------------------------------------------------------------
109 """Return a list-like class of page structs indexed by pfn.
111 This implementation assumes the kernel is configured with a virtually
114 # If the kernel doesn't have a virtually contiguous mem_map, this could
115 # be changed to return a chained list of MemCArray objects.
117 PAGE_SHIFT = crashlib.cid.mdtbl.pageshift
118 pfn_start = crashlib.cid.physmap[0].start >> PAGE_SHIFT
119 pfn_end = crashlib.cid.physmap[-1].end >> PAGE_SHIFT
121 # Find page map and create an array of page_struct
122 vmemmap_addr = crashlib.cid.mdtbl.vmemmap_vaddr
124 return crashlib.memarray.MemCArray(vmemmap_addr,
125 lambda a:readSU('struct page',a),
126 getSizeOf('struct page'),