Commit 9295b7a07c859a42346221b5839be0ae612333b0
Committed by
Linus Torvalds
1 parent
a62e2f4f50
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
kbuild: install kernel-page-flags.h
Programs using /proc/kpageflags need to know about the various flags. The <linux/kernel-page-flags.h> provides them and the comments in the file indicate that it is supposed to be used by user-level code. But the file is not installed. Install the headers and mark the unstable flags as out-of-bounds. The page-type tool is also adjusted to not duplicate the definitions Signed-off-by: Ulrich Drepper <drepper@gmail.com> Acked-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Acked-by: Fengguang Wu <fengguang.wu@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 3 changed files with 6 additions and 27 deletions Inline Diff
include/linux/Kbuild
1 | header-y += byteorder/ | 1 | header-y += byteorder/ |
2 | header-y += can/ | 2 | header-y += can/ |
3 | header-y += caif/ | 3 | header-y += caif/ |
4 | header-y += dvb/ | 4 | header-y += dvb/ |
5 | header-y += hdlc/ | 5 | header-y += hdlc/ |
6 | header-y += hsi/ | 6 | header-y += hsi/ |
7 | header-y += isdn/ | 7 | header-y += isdn/ |
8 | header-y += mmc/ | 8 | header-y += mmc/ |
9 | header-y += nfsd/ | 9 | header-y += nfsd/ |
10 | header-y += raid/ | 10 | header-y += raid/ |
11 | header-y += spi/ | 11 | header-y += spi/ |
12 | header-y += sunrpc/ | 12 | header-y += sunrpc/ |
13 | header-y += tc_act/ | 13 | header-y += tc_act/ |
14 | header-y += tc_ematch/ | 14 | header-y += tc_ematch/ |
15 | header-y += netfilter/ | 15 | header-y += netfilter/ |
16 | header-y += netfilter_arp/ | 16 | header-y += netfilter_arp/ |
17 | header-y += netfilter_bridge/ | 17 | header-y += netfilter_bridge/ |
18 | header-y += netfilter_ipv4/ | 18 | header-y += netfilter_ipv4/ |
19 | header-y += netfilter_ipv6/ | 19 | header-y += netfilter_ipv6/ |
20 | header-y += usb/ | 20 | header-y += usb/ |
21 | header-y += wimax/ | 21 | header-y += wimax/ |
22 | 22 | ||
23 | objhdr-y += version.h | 23 | objhdr-y += version.h |
24 | 24 | ||
25 | ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/a.out.h \ | 25 | ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/a.out.h \ |
26 | $(srctree)/include/asm-$(SRCARCH)/a.out.h \ | 26 | $(srctree)/include/asm-$(SRCARCH)/a.out.h \ |
27 | $(INSTALL_HDR_PATH)/include/asm-*/a.out.h),) | 27 | $(INSTALL_HDR_PATH)/include/asm-*/a.out.h),) |
28 | header-y += a.out.h | 28 | header-y += a.out.h |
29 | endif | 29 | endif |
30 | ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm.h \ | 30 | ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm.h \ |
31 | $(srctree)/include/asm-$(SRCARCH)/kvm.h \ | 31 | $(srctree)/include/asm-$(SRCARCH)/kvm.h \ |
32 | $(INSTALL_HDR_PATH)/include/asm-*/kvm.h),) | 32 | $(INSTALL_HDR_PATH)/include/asm-*/kvm.h),) |
33 | header-y += kvm.h | 33 | header-y += kvm.h |
34 | endif | 34 | endif |
35 | ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm_para.h \ | 35 | ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm_para.h \ |
36 | $(srctree)/include/asm-$(SRCARCH)/kvm_para.h \ | 36 | $(srctree)/include/asm-$(SRCARCH)/kvm_para.h \ |
37 | $(INSTALL_HDR_PATH)/include/asm-*/kvm_para.h),) | 37 | $(INSTALL_HDR_PATH)/include/asm-*/kvm_para.h),) |
38 | header-y += kvm_para.h | 38 | header-y += kvm_para.h |
39 | endif | 39 | endif |
40 | 40 | ||
41 | header-y += acct.h | 41 | header-y += acct.h |
42 | header-y += adb.h | 42 | header-y += adb.h |
43 | header-y += adfs_fs.h | 43 | header-y += adfs_fs.h |
44 | header-y += affs_hardblocks.h | 44 | header-y += affs_hardblocks.h |
45 | header-y += agpgart.h | 45 | header-y += agpgart.h |
46 | header-y += aio_abi.h | 46 | header-y += aio_abi.h |
47 | header-y += apm_bios.h | 47 | header-y += apm_bios.h |
48 | header-y += arcfb.h | 48 | header-y += arcfb.h |
49 | header-y += atalk.h | 49 | header-y += atalk.h |
50 | header-y += atm.h | 50 | header-y += atm.h |
51 | header-y += atm_eni.h | 51 | header-y += atm_eni.h |
52 | header-y += atm_he.h | 52 | header-y += atm_he.h |
53 | header-y += atm_idt77105.h | 53 | header-y += atm_idt77105.h |
54 | header-y += atm_nicstar.h | 54 | header-y += atm_nicstar.h |
55 | header-y += atm_tcp.h | 55 | header-y += atm_tcp.h |
56 | header-y += atm_zatm.h | 56 | header-y += atm_zatm.h |
57 | header-y += atmapi.h | 57 | header-y += atmapi.h |
58 | header-y += atmarp.h | 58 | header-y += atmarp.h |
59 | header-y += atmbr2684.h | 59 | header-y += atmbr2684.h |
60 | header-y += atmclip.h | 60 | header-y += atmclip.h |
61 | header-y += atmdev.h | 61 | header-y += atmdev.h |
62 | header-y += atmioc.h | 62 | header-y += atmioc.h |
63 | header-y += atmlec.h | 63 | header-y += atmlec.h |
64 | header-y += atmmpc.h | 64 | header-y += atmmpc.h |
65 | header-y += atmppp.h | 65 | header-y += atmppp.h |
66 | header-y += atmsap.h | 66 | header-y += atmsap.h |
67 | header-y += atmsvc.h | 67 | header-y += atmsvc.h |
68 | header-y += audit.h | 68 | header-y += audit.h |
69 | header-y += auto_fs.h | 69 | header-y += auto_fs.h |
70 | header-y += auto_fs4.h | 70 | header-y += auto_fs4.h |
71 | header-y += auxvec.h | 71 | header-y += auxvec.h |
72 | header-y += ax25.h | 72 | header-y += ax25.h |
73 | header-y += b1lli.h | 73 | header-y += b1lli.h |
74 | header-y += baycom.h | 74 | header-y += baycom.h |
75 | header-y += bfs_fs.h | 75 | header-y += bfs_fs.h |
76 | header-y += binfmts.h | 76 | header-y += binfmts.h |
77 | header-y += blk_types.h | 77 | header-y += blk_types.h |
78 | header-y += blkpg.h | 78 | header-y += blkpg.h |
79 | header-y += blktrace_api.h | 79 | header-y += blktrace_api.h |
80 | header-y += bpqether.h | 80 | header-y += bpqether.h |
81 | header-y += bsg.h | 81 | header-y += bsg.h |
82 | header-y += can.h | 82 | header-y += can.h |
83 | header-y += capability.h | 83 | header-y += capability.h |
84 | header-y += capi.h | 84 | header-y += capi.h |
85 | header-y += cciss_defs.h | 85 | header-y += cciss_defs.h |
86 | header-y += cciss_ioctl.h | 86 | header-y += cciss_ioctl.h |
87 | header-y += cdk.h | 87 | header-y += cdk.h |
88 | header-y += cdrom.h | 88 | header-y += cdrom.h |
89 | header-y += cgroupstats.h | 89 | header-y += cgroupstats.h |
90 | header-y += chio.h | 90 | header-y += chio.h |
91 | header-y += cm4000_cs.h | 91 | header-y += cm4000_cs.h |
92 | header-y += cn_proc.h | 92 | header-y += cn_proc.h |
93 | header-y += coda.h | 93 | header-y += coda.h |
94 | header-y += coda_psdev.h | 94 | header-y += coda_psdev.h |
95 | header-y += coff.h | 95 | header-y += coff.h |
96 | header-y += comstats.h | 96 | header-y += comstats.h |
97 | header-y += connector.h | 97 | header-y += connector.h |
98 | header-y += const.h | 98 | header-y += const.h |
99 | header-y += cramfs_fs.h | 99 | header-y += cramfs_fs.h |
100 | header-y += cuda.h | 100 | header-y += cuda.h |
101 | header-y += cyclades.h | 101 | header-y += cyclades.h |
102 | header-y += cycx_cfm.h | 102 | header-y += cycx_cfm.h |
103 | header-y += dcbnl.h | 103 | header-y += dcbnl.h |
104 | header-y += dccp.h | 104 | header-y += dccp.h |
105 | header-y += dlm.h | 105 | header-y += dlm.h |
106 | header-y += dlm_device.h | 106 | header-y += dlm_device.h |
107 | header-y += dlm_netlink.h | 107 | header-y += dlm_netlink.h |
108 | header-y += dlm_plock.h | 108 | header-y += dlm_plock.h |
109 | header-y += dlmconstants.h | 109 | header-y += dlmconstants.h |
110 | header-y += dm-ioctl.h | 110 | header-y += dm-ioctl.h |
111 | header-y += dm-log-userspace.h | 111 | header-y += dm-log-userspace.h |
112 | header-y += dn.h | 112 | header-y += dn.h |
113 | header-y += dqblk_xfs.h | 113 | header-y += dqblk_xfs.h |
114 | header-y += edd.h | 114 | header-y += edd.h |
115 | header-y += efs_fs_sb.h | 115 | header-y += efs_fs_sb.h |
116 | header-y += elf-em.h | 116 | header-y += elf-em.h |
117 | header-y += elf-fdpic.h | 117 | header-y += elf-fdpic.h |
118 | header-y += elf.h | 118 | header-y += elf.h |
119 | header-y += elfcore.h | 119 | header-y += elfcore.h |
120 | header-y += errno.h | 120 | header-y += errno.h |
121 | header-y += errqueue.h | 121 | header-y += errqueue.h |
122 | header-y += ethtool.h | 122 | header-y += ethtool.h |
123 | header-y += eventpoll.h | 123 | header-y += eventpoll.h |
124 | header-y += fadvise.h | 124 | header-y += fadvise.h |
125 | header-y += falloc.h | 125 | header-y += falloc.h |
126 | header-y += fanotify.h | 126 | header-y += fanotify.h |
127 | header-y += fb.h | 127 | header-y += fb.h |
128 | header-y += fcntl.h | 128 | header-y += fcntl.h |
129 | header-y += fd.h | 129 | header-y += fd.h |
130 | header-y += fdreg.h | 130 | header-y += fdreg.h |
131 | header-y += fib_rules.h | 131 | header-y += fib_rules.h |
132 | header-y += fiemap.h | 132 | header-y += fiemap.h |
133 | header-y += filter.h | 133 | header-y += filter.h |
134 | header-y += firewire-cdev.h | 134 | header-y += firewire-cdev.h |
135 | header-y += firewire-constants.h | 135 | header-y += firewire-constants.h |
136 | header-y += flat.h | 136 | header-y += flat.h |
137 | header-y += fs.h | 137 | header-y += fs.h |
138 | header-y += fsl_hypervisor.h | 138 | header-y += fsl_hypervisor.h |
139 | header-y += fuse.h | 139 | header-y += fuse.h |
140 | header-y += futex.h | 140 | header-y += futex.h |
141 | header-y += gameport.h | 141 | header-y += gameport.h |
142 | header-y += gen_stats.h | 142 | header-y += gen_stats.h |
143 | header-y += generic_serial.h | 143 | header-y += generic_serial.h |
144 | header-y += genetlink.h | 144 | header-y += genetlink.h |
145 | header-y += gfs2_ondisk.h | 145 | header-y += gfs2_ondisk.h |
146 | header-y += gigaset_dev.h | 146 | header-y += gigaset_dev.h |
147 | header-y += hdlc.h | 147 | header-y += hdlc.h |
148 | header-y += hdlcdrv.h | 148 | header-y += hdlcdrv.h |
149 | header-y += hdreg.h | 149 | header-y += hdreg.h |
150 | header-y += hid.h | 150 | header-y += hid.h |
151 | header-y += hiddev.h | 151 | header-y += hiddev.h |
152 | header-y += hidraw.h | 152 | header-y += hidraw.h |
153 | header-y += hpet.h | 153 | header-y += hpet.h |
154 | header-y += hysdn_if.h | 154 | header-y += hysdn_if.h |
155 | header-y += i2c-dev.h | 155 | header-y += i2c-dev.h |
156 | header-y += i2c.h | 156 | header-y += i2c.h |
157 | header-y += i2o-dev.h | 157 | header-y += i2o-dev.h |
158 | header-y += i8k.h | 158 | header-y += i8k.h |
159 | header-y += icmp.h | 159 | header-y += icmp.h |
160 | header-y += icmpv6.h | 160 | header-y += icmpv6.h |
161 | header-y += if.h | 161 | header-y += if.h |
162 | header-y += if_addr.h | 162 | header-y += if_addr.h |
163 | header-y += if_addrlabel.h | 163 | header-y += if_addrlabel.h |
164 | header-y += if_alg.h | 164 | header-y += if_alg.h |
165 | header-y += if_arcnet.h | 165 | header-y += if_arcnet.h |
166 | header-y += if_arp.h | 166 | header-y += if_arp.h |
167 | header-y += if_bonding.h | 167 | header-y += if_bonding.h |
168 | header-y += if_bridge.h | 168 | header-y += if_bridge.h |
169 | header-y += if_cablemodem.h | 169 | header-y += if_cablemodem.h |
170 | header-y += if_eql.h | 170 | header-y += if_eql.h |
171 | header-y += if_ether.h | 171 | header-y += if_ether.h |
172 | header-y += if_fc.h | 172 | header-y += if_fc.h |
173 | header-y += if_fddi.h | 173 | header-y += if_fddi.h |
174 | header-y += if_frad.h | 174 | header-y += if_frad.h |
175 | header-y += if_hippi.h | 175 | header-y += if_hippi.h |
176 | header-y += if_infiniband.h | 176 | header-y += if_infiniband.h |
177 | header-y += if_link.h | 177 | header-y += if_link.h |
178 | header-y += if_ltalk.h | 178 | header-y += if_ltalk.h |
179 | header-y += if_packet.h | 179 | header-y += if_packet.h |
180 | header-y += if_phonet.h | 180 | header-y += if_phonet.h |
181 | header-y += if_plip.h | 181 | header-y += if_plip.h |
182 | header-y += if_ppp.h | 182 | header-y += if_ppp.h |
183 | header-y += if_pppol2tp.h | 183 | header-y += if_pppol2tp.h |
184 | header-y += if_pppox.h | 184 | header-y += if_pppox.h |
185 | header-y += if_slip.h | 185 | header-y += if_slip.h |
186 | header-y += if_strip.h | 186 | header-y += if_strip.h |
187 | header-y += if_team.h | 187 | header-y += if_team.h |
188 | header-y += if_tun.h | 188 | header-y += if_tun.h |
189 | header-y += if_tunnel.h | 189 | header-y += if_tunnel.h |
190 | header-y += if_vlan.h | 190 | header-y += if_vlan.h |
191 | header-y += if_x25.h | 191 | header-y += if_x25.h |
192 | header-y += igmp.h | 192 | header-y += igmp.h |
193 | header-y += in.h | 193 | header-y += in.h |
194 | header-y += in6.h | 194 | header-y += in6.h |
195 | header-y += in_route.h | 195 | header-y += in_route.h |
196 | header-y += sock_diag.h | 196 | header-y += sock_diag.h |
197 | header-y += inet_diag.h | 197 | header-y += inet_diag.h |
198 | header-y += unix_diag.h | 198 | header-y += unix_diag.h |
199 | header-y += inotify.h | 199 | header-y += inotify.h |
200 | header-y += input.h | 200 | header-y += input.h |
201 | header-y += ioctl.h | 201 | header-y += ioctl.h |
202 | header-y += ip.h | 202 | header-y += ip.h |
203 | header-y += ip6_tunnel.h | 203 | header-y += ip6_tunnel.h |
204 | header-y += ip_vs.h | 204 | header-y += ip_vs.h |
205 | header-y += ipc.h | 205 | header-y += ipc.h |
206 | header-y += ipmi.h | 206 | header-y += ipmi.h |
207 | header-y += ipmi_msgdefs.h | 207 | header-y += ipmi_msgdefs.h |
208 | header-y += ipsec.h | 208 | header-y += ipsec.h |
209 | header-y += ipv6.h | 209 | header-y += ipv6.h |
210 | header-y += ipv6_route.h | 210 | header-y += ipv6_route.h |
211 | header-y += ipx.h | 211 | header-y += ipx.h |
212 | header-y += irda.h | 212 | header-y += irda.h |
213 | header-y += irqnr.h | 213 | header-y += irqnr.h |
214 | header-y += isdn.h | 214 | header-y += isdn.h |
215 | header-y += isdn_divertif.h | 215 | header-y += isdn_divertif.h |
216 | header-y += isdn_ppp.h | 216 | header-y += isdn_ppp.h |
217 | header-y += isdnif.h | 217 | header-y += isdnif.h |
218 | header-y += iso_fs.h | 218 | header-y += iso_fs.h |
219 | header-y += ivtv.h | 219 | header-y += ivtv.h |
220 | header-y += ivtvfb.h | 220 | header-y += ivtvfb.h |
221 | header-y += ixjuser.h | 221 | header-y += ixjuser.h |
222 | header-y += jffs2.h | 222 | header-y += jffs2.h |
223 | header-y += joystick.h | 223 | header-y += joystick.h |
224 | header-y += kd.h | 224 | header-y += kd.h |
225 | header-y += kdev_t.h | 225 | header-y += kdev_t.h |
226 | header-y += kernel.h | 226 | header-y += kernel.h |
227 | header-y += kernelcapi.h | 227 | header-y += kernelcapi.h |
228 | header-y += kernel-page-flags.h | ||
228 | header-y += keyboard.h | 229 | header-y += keyboard.h |
229 | header-y += keyctl.h | 230 | header-y += keyctl.h |
230 | header-y += l2tp.h | 231 | header-y += l2tp.h |
231 | header-y += limits.h | 232 | header-y += limits.h |
232 | header-y += llc.h | 233 | header-y += llc.h |
233 | header-y += loop.h | 234 | header-y += loop.h |
234 | header-y += lp.h | 235 | header-y += lp.h |
235 | header-y += magic.h | 236 | header-y += magic.h |
236 | header-y += major.h | 237 | header-y += major.h |
237 | header-y += map_to_7segment.h | 238 | header-y += map_to_7segment.h |
238 | header-y += matroxfb.h | 239 | header-y += matroxfb.h |
239 | header-y += mdio.h | 240 | header-y += mdio.h |
240 | header-y += media.h | 241 | header-y += media.h |
241 | header-y += mei.h | 242 | header-y += mei.h |
242 | header-y += mempolicy.h | 243 | header-y += mempolicy.h |
243 | header-y += meye.h | 244 | header-y += meye.h |
244 | header-y += mii.h | 245 | header-y += mii.h |
245 | header-y += minix_fs.h | 246 | header-y += minix_fs.h |
246 | header-y += mman.h | 247 | header-y += mman.h |
247 | header-y += mmtimer.h | 248 | header-y += mmtimer.h |
248 | header-y += mqueue.h | 249 | header-y += mqueue.h |
249 | header-y += mroute.h | 250 | header-y += mroute.h |
250 | header-y += mroute6.h | 251 | header-y += mroute6.h |
251 | header-y += msdos_fs.h | 252 | header-y += msdos_fs.h |
252 | header-y += msg.h | 253 | header-y += msg.h |
253 | header-y += mtio.h | 254 | header-y += mtio.h |
254 | header-y += n_r3964.h | 255 | header-y += n_r3964.h |
255 | header-y += nbd.h | 256 | header-y += nbd.h |
256 | header-y += ncp.h | 257 | header-y += ncp.h |
257 | header-y += ncp_fs.h | 258 | header-y += ncp_fs.h |
258 | header-y += ncp_mount.h | 259 | header-y += ncp_mount.h |
259 | header-y += ncp_no.h | 260 | header-y += ncp_no.h |
260 | header-y += neighbour.h | 261 | header-y += neighbour.h |
261 | header-y += net.h | 262 | header-y += net.h |
262 | header-y += net_dropmon.h | 263 | header-y += net_dropmon.h |
263 | header-y += net_tstamp.h | 264 | header-y += net_tstamp.h |
264 | header-y += netdevice.h | 265 | header-y += netdevice.h |
265 | header-y += netfilter.h | 266 | header-y += netfilter.h |
266 | header-y += netfilter_arp.h | 267 | header-y += netfilter_arp.h |
267 | header-y += netfilter_bridge.h | 268 | header-y += netfilter_bridge.h |
268 | header-y += netfilter_decnet.h | 269 | header-y += netfilter_decnet.h |
269 | header-y += netfilter_ipv4.h | 270 | header-y += netfilter_ipv4.h |
270 | header-y += netfilter_ipv6.h | 271 | header-y += netfilter_ipv6.h |
271 | header-y += netlink.h | 272 | header-y += netlink.h |
272 | header-y += netrom.h | 273 | header-y += netrom.h |
273 | header-y += nfc.h | 274 | header-y += nfc.h |
274 | header-y += nfs.h | 275 | header-y += nfs.h |
275 | header-y += nfs2.h | 276 | header-y += nfs2.h |
276 | header-y += nfs3.h | 277 | header-y += nfs3.h |
277 | header-y += nfs4.h | 278 | header-y += nfs4.h |
278 | header-y += nfs4_mount.h | 279 | header-y += nfs4_mount.h |
279 | header-y += nfs_fs.h | 280 | header-y += nfs_fs.h |
280 | header-y += nfs_idmap.h | 281 | header-y += nfs_idmap.h |
281 | header-y += nfs_mount.h | 282 | header-y += nfs_mount.h |
282 | header-y += nfsacl.h | 283 | header-y += nfsacl.h |
283 | header-y += nl80211.h | 284 | header-y += nl80211.h |
284 | header-y += nubus.h | 285 | header-y += nubus.h |
285 | header-y += nvram.h | 286 | header-y += nvram.h |
286 | header-y += omap3isp.h | 287 | header-y += omap3isp.h |
287 | header-y += omapfb.h | 288 | header-y += omapfb.h |
288 | header-y += oom.h | 289 | header-y += oom.h |
289 | header-y += param.h | 290 | header-y += param.h |
290 | header-y += parport.h | 291 | header-y += parport.h |
291 | header-y += patchkey.h | 292 | header-y += patchkey.h |
292 | header-y += pci.h | 293 | header-y += pci.h |
293 | header-y += pci_regs.h | 294 | header-y += pci_regs.h |
294 | header-y += perf_event.h | 295 | header-y += perf_event.h |
295 | header-y += personality.h | 296 | header-y += personality.h |
296 | header-y += pfkeyv2.h | 297 | header-y += pfkeyv2.h |
297 | header-y += pg.h | 298 | header-y += pg.h |
298 | header-y += phantom.h | 299 | header-y += phantom.h |
299 | header-y += phonet.h | 300 | header-y += phonet.h |
300 | header-y += pkt_cls.h | 301 | header-y += pkt_cls.h |
301 | header-y += pkt_sched.h | 302 | header-y += pkt_sched.h |
302 | header-y += pktcdvd.h | 303 | header-y += pktcdvd.h |
303 | header-y += pmu.h | 304 | header-y += pmu.h |
304 | header-y += poll.h | 305 | header-y += poll.h |
305 | header-y += posix_types.h | 306 | header-y += posix_types.h |
306 | header-y += ppdev.h | 307 | header-y += ppdev.h |
307 | header-y += ppp-comp.h | 308 | header-y += ppp-comp.h |
308 | header-y += ppp-ioctl.h | 309 | header-y += ppp-ioctl.h |
309 | header-y += ppp_defs.h | 310 | header-y += ppp_defs.h |
310 | header-y += pps.h | 311 | header-y += pps.h |
311 | header-y += prctl.h | 312 | header-y += prctl.h |
312 | header-y += ptp_clock.h | 313 | header-y += ptp_clock.h |
313 | header-y += ptrace.h | 314 | header-y += ptrace.h |
314 | header-y += qnx4_fs.h | 315 | header-y += qnx4_fs.h |
315 | header-y += qnxtypes.h | 316 | header-y += qnxtypes.h |
316 | header-y += quota.h | 317 | header-y += quota.h |
317 | header-y += radeonfb.h | 318 | header-y += radeonfb.h |
318 | header-y += random.h | 319 | header-y += random.h |
319 | header-y += raw.h | 320 | header-y += raw.h |
320 | header-y += rds.h | 321 | header-y += rds.h |
321 | header-y += reboot.h | 322 | header-y += reboot.h |
322 | header-y += reiserfs_fs.h | 323 | header-y += reiserfs_fs.h |
323 | header-y += reiserfs_xattr.h | 324 | header-y += reiserfs_xattr.h |
324 | header-y += resource.h | 325 | header-y += resource.h |
325 | header-y += rfkill.h | 326 | header-y += rfkill.h |
326 | header-y += romfs_fs.h | 327 | header-y += romfs_fs.h |
327 | header-y += rose.h | 328 | header-y += rose.h |
328 | header-y += route.h | 329 | header-y += route.h |
329 | header-y += rtc.h | 330 | header-y += rtc.h |
330 | header-y += rtnetlink.h | 331 | header-y += rtnetlink.h |
331 | header-y += scc.h | 332 | header-y += scc.h |
332 | header-y += sched.h | 333 | header-y += sched.h |
333 | header-y += screen_info.h | 334 | header-y += screen_info.h |
334 | header-y += sdla.h | 335 | header-y += sdla.h |
335 | header-y += seccomp.h | 336 | header-y += seccomp.h |
336 | header-y += securebits.h | 337 | header-y += securebits.h |
337 | header-y += selinux_netlink.h | 338 | header-y += selinux_netlink.h |
338 | header-y += sem.h | 339 | header-y += sem.h |
339 | header-y += serial.h | 340 | header-y += serial.h |
340 | header-y += serial_core.h | 341 | header-y += serial_core.h |
341 | header-y += serial_reg.h | 342 | header-y += serial_reg.h |
342 | header-y += serio.h | 343 | header-y += serio.h |
343 | header-y += shm.h | 344 | header-y += shm.h |
344 | header-y += signal.h | 345 | header-y += signal.h |
345 | header-y += signalfd.h | 346 | header-y += signalfd.h |
346 | header-y += snmp.h | 347 | header-y += snmp.h |
347 | header-y += socket.h | 348 | header-y += socket.h |
348 | header-y += sockios.h | 349 | header-y += sockios.h |
349 | header-y += som.h | 350 | header-y += som.h |
350 | header-y += sonet.h | 351 | header-y += sonet.h |
351 | header-y += sonypi.h | 352 | header-y += sonypi.h |
352 | header-y += sound.h | 353 | header-y += sound.h |
353 | header-y += soundcard.h | 354 | header-y += soundcard.h |
354 | header-y += stat.h | 355 | header-y += stat.h |
355 | header-y += stddef.h | 356 | header-y += stddef.h |
356 | header-y += string.h | 357 | header-y += string.h |
357 | header-y += suspend_ioctls.h | 358 | header-y += suspend_ioctls.h |
358 | header-y += swab.h | 359 | header-y += swab.h |
359 | header-y += synclink.h | 360 | header-y += synclink.h |
360 | header-y += sysctl.h | 361 | header-y += sysctl.h |
361 | header-y += sysinfo.h | 362 | header-y += sysinfo.h |
362 | header-y += taskstats.h | 363 | header-y += taskstats.h |
363 | header-y += tcp.h | 364 | header-y += tcp.h |
364 | header-y += telephony.h | 365 | header-y += telephony.h |
365 | header-y += termios.h | 366 | header-y += termios.h |
366 | header-y += time.h | 367 | header-y += time.h |
367 | header-y += times.h | 368 | header-y += times.h |
368 | header-y += timex.h | 369 | header-y += timex.h |
369 | header-y += tiocl.h | 370 | header-y += tiocl.h |
370 | header-y += tipc.h | 371 | header-y += tipc.h |
371 | header-y += tipc_config.h | 372 | header-y += tipc_config.h |
372 | header-y += toshiba.h | 373 | header-y += toshiba.h |
373 | header-y += tty.h | 374 | header-y += tty.h |
374 | header-y += types.h | 375 | header-y += types.h |
375 | header-y += udf_fs_i.h | 376 | header-y += udf_fs_i.h |
376 | header-y += udp.h | 377 | header-y += udp.h |
377 | header-y += uinput.h | 378 | header-y += uinput.h |
378 | header-y += uio.h | 379 | header-y += uio.h |
379 | header-y += ultrasound.h | 380 | header-y += ultrasound.h |
380 | header-y += un.h | 381 | header-y += un.h |
381 | header-y += unistd.h | 382 | header-y += unistd.h |
382 | header-y += usbdevice_fs.h | 383 | header-y += usbdevice_fs.h |
383 | header-y += utime.h | 384 | header-y += utime.h |
384 | header-y += utsname.h | 385 | header-y += utsname.h |
385 | header-y += uuid.h | 386 | header-y += uuid.h |
386 | header-y += uvcvideo.h | 387 | header-y += uvcvideo.h |
387 | header-y += v4l2-dv-timings.h | 388 | header-y += v4l2-dv-timings.h |
388 | header-y += v4l2-mediabus.h | 389 | header-y += v4l2-mediabus.h |
389 | header-y += v4l2-subdev.h | 390 | header-y += v4l2-subdev.h |
390 | header-y += veth.h | 391 | header-y += veth.h |
391 | header-y += vhost.h | 392 | header-y += vhost.h |
392 | header-y += videodev2.h | 393 | header-y += videodev2.h |
393 | header-y += virtio_9p.h | 394 | header-y += virtio_9p.h |
394 | header-y += virtio_balloon.h | 395 | header-y += virtio_balloon.h |
395 | header-y += virtio_blk.h | 396 | header-y += virtio_blk.h |
396 | header-y += virtio_config.h | 397 | header-y += virtio_config.h |
397 | header-y += virtio_console.h | 398 | header-y += virtio_console.h |
398 | header-y += virtio_ids.h | 399 | header-y += virtio_ids.h |
399 | header-y += virtio_net.h | 400 | header-y += virtio_net.h |
400 | header-y += virtio_pci.h | 401 | header-y += virtio_pci.h |
401 | header-y += virtio_ring.h | 402 | header-y += virtio_ring.h |
402 | header-y += virtio_rng.h | 403 | header-y += virtio_rng.h |
403 | header-y += vt.h | 404 | header-y += vt.h |
404 | header-y += wait.h | 405 | header-y += wait.h |
405 | header-y += wanrouter.h | 406 | header-y += wanrouter.h |
406 | header-y += watchdog.h | 407 | header-y += watchdog.h |
407 | header-y += wimax.h | 408 | header-y += wimax.h |
408 | header-y += wireless.h | 409 | header-y += wireless.h |
409 | header-y += x25.h | 410 | header-y += x25.h |
410 | header-y += xattr.h | 411 | header-y += xattr.h |
411 | header-y += xfrm.h | 412 | header-y += xfrm.h |
412 | 413 |
include/linux/kernel-page-flags.h
1 | #ifndef LINUX_KERNEL_PAGE_FLAGS_H | 1 | #ifndef LINUX_KERNEL_PAGE_FLAGS_H |
2 | #define LINUX_KERNEL_PAGE_FLAGS_H | 2 | #define LINUX_KERNEL_PAGE_FLAGS_H |
3 | 3 | ||
4 | /* | 4 | /* |
5 | * Stable page flag bits exported to user space | 5 | * Stable page flag bits exported to user space |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #define KPF_LOCKED 0 | 8 | #define KPF_LOCKED 0 |
9 | #define KPF_ERROR 1 | 9 | #define KPF_ERROR 1 |
10 | #define KPF_REFERENCED 2 | 10 | #define KPF_REFERENCED 2 |
11 | #define KPF_UPTODATE 3 | 11 | #define KPF_UPTODATE 3 |
12 | #define KPF_DIRTY 4 | 12 | #define KPF_DIRTY 4 |
13 | #define KPF_LRU 5 | 13 | #define KPF_LRU 5 |
14 | #define KPF_ACTIVE 6 | 14 | #define KPF_ACTIVE 6 |
15 | #define KPF_SLAB 7 | 15 | #define KPF_SLAB 7 |
16 | #define KPF_WRITEBACK 8 | 16 | #define KPF_WRITEBACK 8 |
17 | #define KPF_RECLAIM 9 | 17 | #define KPF_RECLAIM 9 |
18 | #define KPF_BUDDY 10 | 18 | #define KPF_BUDDY 10 |
19 | 19 | ||
20 | /* 11-20: new additions in 2.6.31 */ | 20 | /* 11-20: new additions in 2.6.31 */ |
21 | #define KPF_MMAP 11 | 21 | #define KPF_MMAP 11 |
22 | #define KPF_ANON 12 | 22 | #define KPF_ANON 12 |
23 | #define KPF_SWAPCACHE 13 | 23 | #define KPF_SWAPCACHE 13 |
24 | #define KPF_SWAPBACKED 14 | 24 | #define KPF_SWAPBACKED 14 |
25 | #define KPF_COMPOUND_HEAD 15 | 25 | #define KPF_COMPOUND_HEAD 15 |
26 | #define KPF_COMPOUND_TAIL 16 | 26 | #define KPF_COMPOUND_TAIL 16 |
27 | #define KPF_HUGE 17 | 27 | #define KPF_HUGE 17 |
28 | #define KPF_UNEVICTABLE 18 | 28 | #define KPF_UNEVICTABLE 18 |
29 | #define KPF_HWPOISON 19 | 29 | #define KPF_HWPOISON 19 |
30 | #define KPF_NOPAGE 20 | 30 | #define KPF_NOPAGE 20 |
31 | 31 | ||
32 | #define KPF_KSM 21 | 32 | #define KPF_KSM 21 |
33 | #define KPF_THP 22 | 33 | #define KPF_THP 22 |
34 | 34 | ||
35 | #ifdef __KERNEL__ | ||
36 | |||
35 | /* kernel hacking assistances | 37 | /* kernel hacking assistances |
36 | * WARNING: subject to change, never rely on them! | 38 | * WARNING: subject to change, never rely on them! |
37 | */ | 39 | */ |
38 | #define KPF_RESERVED 32 | 40 | #define KPF_RESERVED 32 |
39 | #define KPF_MLOCKED 33 | 41 | #define KPF_MLOCKED 33 |
40 | #define KPF_MAPPEDTODISK 34 | 42 | #define KPF_MAPPEDTODISK 34 |
41 | #define KPF_PRIVATE 35 | 43 | #define KPF_PRIVATE 35 |
42 | #define KPF_PRIVATE_2 36 | 44 | #define KPF_PRIVATE_2 36 |
43 | #define KPF_OWNER_PRIVATE 37 | 45 | #define KPF_OWNER_PRIVATE 37 |
44 | #define KPF_ARCH 38 | 46 | #define KPF_ARCH 38 |
45 | #define KPF_UNCACHED 39 | 47 | #define KPF_UNCACHED 39 |
48 | |||
49 | #endif /* __KERNEL__ */ | ||
46 | 50 | ||
47 | #endif /* LINUX_KERNEL_PAGE_FLAGS_H */ | 51 | #endif /* LINUX_KERNEL_PAGE_FLAGS_H */ |
48 | 52 |
tools/vm/page-types.c
1 | /* | 1 | /* |
2 | * page-types: Tool for querying page flags | 2 | * page-types: Tool for querying page flags |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of the GNU General Public License as published by the Free | 5 | * under the terms of the GNU General Public License as published by the Free |
6 | * Software Foundation; version 2. | 6 | * Software Foundation; version 2. |
7 | * | 7 | * |
8 | * This program is distributed in the hope that it will be useful, but WITHOUT | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT |
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
11 | * more details. | 11 | * more details. |
12 | * | 12 | * |
13 | * You should find a copy of v2 of the GNU General Public License somewhere on | 13 | * You should find a copy of v2 of the GNU General Public License somewhere on |
14 | * your Linux system; if not, write to the Free Software Foundation, Inc., 59 | 14 | * your Linux system; if not, write to the Free Software Foundation, Inc., 59 |
15 | * Temple Place, Suite 330, Boston, MA 02111-1307 USA. | 15 | * Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
16 | * | 16 | * |
17 | * Copyright (C) 2009 Intel corporation | 17 | * Copyright (C) 2009 Intel corporation |
18 | * | 18 | * |
19 | * Authors: Wu Fengguang <fengguang.wu@intel.com> | 19 | * Authors: Wu Fengguang <fengguang.wu@intel.com> |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define _LARGEFILE64_SOURCE | 22 | #define _LARGEFILE64_SOURCE |
23 | #include <stdio.h> | 23 | #include <stdio.h> |
24 | #include <stdlib.h> | 24 | #include <stdlib.h> |
25 | #include <unistd.h> | 25 | #include <unistd.h> |
26 | #include <stdint.h> | 26 | #include <stdint.h> |
27 | #include <stdarg.h> | 27 | #include <stdarg.h> |
28 | #include <string.h> | 28 | #include <string.h> |
29 | #include <getopt.h> | 29 | #include <getopt.h> |
30 | #include <limits.h> | 30 | #include <limits.h> |
31 | #include <assert.h> | 31 | #include <assert.h> |
32 | #include <sys/types.h> | 32 | #include <sys/types.h> |
33 | #include <sys/errno.h> | 33 | #include <sys/errno.h> |
34 | #include <sys/fcntl.h> | 34 | #include <sys/fcntl.h> |
35 | #include <sys/mount.h> | 35 | #include <sys/mount.h> |
36 | #include <sys/statfs.h> | 36 | #include <sys/statfs.h> |
37 | #include "../../include/linux/magic.h" | 37 | #include "../../include/linux/magic.h" |
38 | #include "../../include/linux/kernel-page-flags.h" | ||
38 | 39 | ||
39 | 40 | ||
40 | #ifndef MAX_PATH | 41 | #ifndef MAX_PATH |
41 | # define MAX_PATH 256 | 42 | # define MAX_PATH 256 |
42 | #endif | 43 | #endif |
43 | 44 | ||
44 | #ifndef STR | 45 | #ifndef STR |
45 | # define _STR(x) #x | 46 | # define _STR(x) #x |
46 | # define STR(x) _STR(x) | 47 | # define STR(x) _STR(x) |
47 | #endif | 48 | #endif |
48 | 49 | ||
49 | /* | 50 | /* |
50 | * pagemap kernel ABI bits | 51 | * pagemap kernel ABI bits |
51 | */ | 52 | */ |
52 | 53 | ||
53 | #define PM_ENTRY_BYTES sizeof(uint64_t) | 54 | #define PM_ENTRY_BYTES sizeof(uint64_t) |
54 | #define PM_STATUS_BITS 3 | 55 | #define PM_STATUS_BITS 3 |
55 | #define PM_STATUS_OFFSET (64 - PM_STATUS_BITS) | 56 | #define PM_STATUS_OFFSET (64 - PM_STATUS_BITS) |
56 | #define PM_STATUS_MASK (((1LL << PM_STATUS_BITS) - 1) << PM_STATUS_OFFSET) | 57 | #define PM_STATUS_MASK (((1LL << PM_STATUS_BITS) - 1) << PM_STATUS_OFFSET) |
57 | #define PM_STATUS(nr) (((nr) << PM_STATUS_OFFSET) & PM_STATUS_MASK) | 58 | #define PM_STATUS(nr) (((nr) << PM_STATUS_OFFSET) & PM_STATUS_MASK) |
58 | #define PM_PSHIFT_BITS 6 | 59 | #define PM_PSHIFT_BITS 6 |
59 | #define PM_PSHIFT_OFFSET (PM_STATUS_OFFSET - PM_PSHIFT_BITS) | 60 | #define PM_PSHIFT_OFFSET (PM_STATUS_OFFSET - PM_PSHIFT_BITS) |
60 | #define PM_PSHIFT_MASK (((1LL << PM_PSHIFT_BITS) - 1) << PM_PSHIFT_OFFSET) | 61 | #define PM_PSHIFT_MASK (((1LL << PM_PSHIFT_BITS) - 1) << PM_PSHIFT_OFFSET) |
61 | #define PM_PSHIFT(x) (((u64) (x) << PM_PSHIFT_OFFSET) & PM_PSHIFT_MASK) | 62 | #define PM_PSHIFT(x) (((u64) (x) << PM_PSHIFT_OFFSET) & PM_PSHIFT_MASK) |
62 | #define PM_PFRAME_MASK ((1LL << PM_PSHIFT_OFFSET) - 1) | 63 | #define PM_PFRAME_MASK ((1LL << PM_PSHIFT_OFFSET) - 1) |
63 | #define PM_PFRAME(x) ((x) & PM_PFRAME_MASK) | 64 | #define PM_PFRAME(x) ((x) & PM_PFRAME_MASK) |
64 | 65 | ||
65 | #define PM_PRESENT PM_STATUS(4LL) | 66 | #define PM_PRESENT PM_STATUS(4LL) |
66 | #define PM_SWAP PM_STATUS(2LL) | 67 | #define PM_SWAP PM_STATUS(2LL) |
67 | 68 | ||
68 | 69 | ||
69 | /* | 70 | /* |
70 | * kernel page flags | 71 | * kernel page flags |
71 | */ | 72 | */ |
72 | 73 | ||
73 | #define KPF_BYTES 8 | 74 | #define KPF_BYTES 8 |
74 | #define PROC_KPAGEFLAGS "/proc/kpageflags" | 75 | #define PROC_KPAGEFLAGS "/proc/kpageflags" |
75 | |||
76 | /* copied from kpageflags_read() */ | ||
77 | #define KPF_LOCKED 0 | ||
78 | #define KPF_ERROR 1 | ||
79 | #define KPF_REFERENCED 2 | ||
80 | #define KPF_UPTODATE 3 | ||
81 | #define KPF_DIRTY 4 | ||
82 | #define KPF_LRU 5 | ||
83 | #define KPF_ACTIVE 6 | ||
84 | #define KPF_SLAB 7 | ||
85 | #define KPF_WRITEBACK 8 | ||
86 | #define KPF_RECLAIM 9 | ||
87 | #define KPF_BUDDY 10 | ||
88 | |||
89 | /* [11-20] new additions in 2.6.31 */ | ||
90 | #define KPF_MMAP 11 | ||
91 | #define KPF_ANON 12 | ||
92 | #define KPF_SWAPCACHE 13 | ||
93 | #define KPF_SWAPBACKED 14 | ||
94 | #define KPF_COMPOUND_HEAD 15 | ||
95 | #define KPF_COMPOUND_TAIL 16 | ||
96 | #define KPF_HUGE 17 | ||
97 | #define KPF_UNEVICTABLE 18 | ||
98 | #define KPF_HWPOISON 19 | ||
99 | #define KPF_NOPAGE 20 | ||
100 | #define KPF_KSM 21 | ||
101 | #define KPF_THP 22 | ||
102 | 76 | ||
103 | /* [32-] kernel hacking assistances */ | 77 | /* [32-] kernel hacking assistances */ |
104 | #define KPF_RESERVED 32 | 78 | #define KPF_RESERVED 32 |
105 | #define KPF_MLOCKED 33 | 79 | #define KPF_MLOCKED 33 |
106 | #define KPF_MAPPEDTODISK 34 | 80 | #define KPF_MAPPEDTODISK 34 |
107 | #define KPF_PRIVATE 35 | 81 | #define KPF_PRIVATE 35 |
108 | #define KPF_PRIVATE_2 36 | 82 | #define KPF_PRIVATE_2 36 |
109 | #define KPF_OWNER_PRIVATE 37 | 83 | #define KPF_OWNER_PRIVATE 37 |
110 | #define KPF_ARCH 38 | 84 | #define KPF_ARCH 38 |
111 | #define KPF_UNCACHED 39 | 85 | #define KPF_UNCACHED 39 |
112 | 86 | ||
113 | /* [48-] take some arbitrary free slots for expanding overloaded flags | 87 | /* [48-] take some arbitrary free slots for expanding overloaded flags |
114 | * not part of kernel API | 88 | * not part of kernel API |
115 | */ | 89 | */ |
116 | #define KPF_READAHEAD 48 | 90 | #define KPF_READAHEAD 48 |
117 | #define KPF_SLOB_FREE 49 | 91 | #define KPF_SLOB_FREE 49 |
118 | #define KPF_SLUB_FROZEN 50 | 92 | #define KPF_SLUB_FROZEN 50 |
119 | #define KPF_SLUB_DEBUG 51 | 93 | #define KPF_SLUB_DEBUG 51 |
120 | 94 | ||
121 | #define KPF_ALL_BITS ((uint64_t)~0ULL) | 95 | #define KPF_ALL_BITS ((uint64_t)~0ULL) |
122 | #define KPF_HACKERS_BITS (0xffffULL << 32) | 96 | #define KPF_HACKERS_BITS (0xffffULL << 32) |
123 | #define KPF_OVERLOADED_BITS (0xffffULL << 48) | 97 | #define KPF_OVERLOADED_BITS (0xffffULL << 48) |
124 | #define BIT(name) (1ULL << KPF_##name) | 98 | #define BIT(name) (1ULL << KPF_##name) |
125 | #define BITS_COMPOUND (BIT(COMPOUND_HEAD) | BIT(COMPOUND_TAIL)) | 99 | #define BITS_COMPOUND (BIT(COMPOUND_HEAD) | BIT(COMPOUND_TAIL)) |
126 | 100 | ||
127 | static const char * const page_flag_names[] = { | 101 | static const char * const page_flag_names[] = { |
128 | [KPF_LOCKED] = "L:locked", | 102 | [KPF_LOCKED] = "L:locked", |
129 | [KPF_ERROR] = "E:error", | 103 | [KPF_ERROR] = "E:error", |
130 | [KPF_REFERENCED] = "R:referenced", | 104 | [KPF_REFERENCED] = "R:referenced", |
131 | [KPF_UPTODATE] = "U:uptodate", | 105 | [KPF_UPTODATE] = "U:uptodate", |
132 | [KPF_DIRTY] = "D:dirty", | 106 | [KPF_DIRTY] = "D:dirty", |
133 | [KPF_LRU] = "l:lru", | 107 | [KPF_LRU] = "l:lru", |
134 | [KPF_ACTIVE] = "A:active", | 108 | [KPF_ACTIVE] = "A:active", |
135 | [KPF_SLAB] = "S:slab", | 109 | [KPF_SLAB] = "S:slab", |
136 | [KPF_WRITEBACK] = "W:writeback", | 110 | [KPF_WRITEBACK] = "W:writeback", |
137 | [KPF_RECLAIM] = "I:reclaim", | 111 | [KPF_RECLAIM] = "I:reclaim", |
138 | [KPF_BUDDY] = "B:buddy", | 112 | [KPF_BUDDY] = "B:buddy", |
139 | 113 | ||
140 | [KPF_MMAP] = "M:mmap", | 114 | [KPF_MMAP] = "M:mmap", |
141 | [KPF_ANON] = "a:anonymous", | 115 | [KPF_ANON] = "a:anonymous", |
142 | [KPF_SWAPCACHE] = "s:swapcache", | 116 | [KPF_SWAPCACHE] = "s:swapcache", |
143 | [KPF_SWAPBACKED] = "b:swapbacked", | 117 | [KPF_SWAPBACKED] = "b:swapbacked", |
144 | [KPF_COMPOUND_HEAD] = "H:compound_head", | 118 | [KPF_COMPOUND_HEAD] = "H:compound_head", |
145 | [KPF_COMPOUND_TAIL] = "T:compound_tail", | 119 | [KPF_COMPOUND_TAIL] = "T:compound_tail", |
146 | [KPF_HUGE] = "G:huge", | 120 | [KPF_HUGE] = "G:huge", |
147 | [KPF_UNEVICTABLE] = "u:unevictable", | 121 | [KPF_UNEVICTABLE] = "u:unevictable", |
148 | [KPF_HWPOISON] = "X:hwpoison", | 122 | [KPF_HWPOISON] = "X:hwpoison", |
149 | [KPF_NOPAGE] = "n:nopage", | 123 | [KPF_NOPAGE] = "n:nopage", |
150 | [KPF_KSM] = "x:ksm", | 124 | [KPF_KSM] = "x:ksm", |
151 | [KPF_THP] = "t:thp", | 125 | [KPF_THP] = "t:thp", |
152 | 126 | ||
153 | [KPF_RESERVED] = "r:reserved", | 127 | [KPF_RESERVED] = "r:reserved", |
154 | [KPF_MLOCKED] = "m:mlocked", | 128 | [KPF_MLOCKED] = "m:mlocked", |
155 | [KPF_MAPPEDTODISK] = "d:mappedtodisk", | 129 | [KPF_MAPPEDTODISK] = "d:mappedtodisk", |
156 | [KPF_PRIVATE] = "P:private", | 130 | [KPF_PRIVATE] = "P:private", |
157 | [KPF_PRIVATE_2] = "p:private_2", | 131 | [KPF_PRIVATE_2] = "p:private_2", |
158 | [KPF_OWNER_PRIVATE] = "O:owner_private", | 132 | [KPF_OWNER_PRIVATE] = "O:owner_private", |
159 | [KPF_ARCH] = "h:arch", | 133 | [KPF_ARCH] = "h:arch", |
160 | [KPF_UNCACHED] = "c:uncached", | 134 | [KPF_UNCACHED] = "c:uncached", |
161 | 135 | ||
162 | [KPF_READAHEAD] = "I:readahead", | 136 | [KPF_READAHEAD] = "I:readahead", |
163 | [KPF_SLOB_FREE] = "P:slob_free", | 137 | [KPF_SLOB_FREE] = "P:slob_free", |
164 | [KPF_SLUB_FROZEN] = "A:slub_frozen", | 138 | [KPF_SLUB_FROZEN] = "A:slub_frozen", |
165 | [KPF_SLUB_DEBUG] = "E:slub_debug", | 139 | [KPF_SLUB_DEBUG] = "E:slub_debug", |
166 | }; | 140 | }; |
167 | 141 | ||
168 | 142 | ||
169 | static const char * const debugfs_known_mountpoints[] = { | 143 | static const char * const debugfs_known_mountpoints[] = { |
170 | "/sys/kernel/debug", | 144 | "/sys/kernel/debug", |
171 | "/debug", | 145 | "/debug", |
172 | 0, | 146 | 0, |
173 | }; | 147 | }; |
174 | 148 | ||
175 | /* | 149 | /* |
176 | * data structures | 150 | * data structures |
177 | */ | 151 | */ |
178 | 152 | ||
179 | static int opt_raw; /* for kernel developers */ | 153 | static int opt_raw; /* for kernel developers */ |
180 | static int opt_list; /* list pages (in ranges) */ | 154 | static int opt_list; /* list pages (in ranges) */ |
181 | static int opt_no_summary; /* don't show summary */ | 155 | static int opt_no_summary; /* don't show summary */ |
182 | static pid_t opt_pid; /* process to walk */ | 156 | static pid_t opt_pid; /* process to walk */ |
183 | 157 | ||
184 | #define MAX_ADDR_RANGES 1024 | 158 | #define MAX_ADDR_RANGES 1024 |
185 | static int nr_addr_ranges; | 159 | static int nr_addr_ranges; |
186 | static unsigned long opt_offset[MAX_ADDR_RANGES]; | 160 | static unsigned long opt_offset[MAX_ADDR_RANGES]; |
187 | static unsigned long opt_size[MAX_ADDR_RANGES]; | 161 | static unsigned long opt_size[MAX_ADDR_RANGES]; |
188 | 162 | ||
189 | #define MAX_VMAS 10240 | 163 | #define MAX_VMAS 10240 |
190 | static int nr_vmas; | 164 | static int nr_vmas; |
191 | static unsigned long pg_start[MAX_VMAS]; | 165 | static unsigned long pg_start[MAX_VMAS]; |
192 | static unsigned long pg_end[MAX_VMAS]; | 166 | static unsigned long pg_end[MAX_VMAS]; |
193 | 167 | ||
194 | #define MAX_BIT_FILTERS 64 | 168 | #define MAX_BIT_FILTERS 64 |
195 | static int nr_bit_filters; | 169 | static int nr_bit_filters; |
196 | static uint64_t opt_mask[MAX_BIT_FILTERS]; | 170 | static uint64_t opt_mask[MAX_BIT_FILTERS]; |
197 | static uint64_t opt_bits[MAX_BIT_FILTERS]; | 171 | static uint64_t opt_bits[MAX_BIT_FILTERS]; |
198 | 172 | ||
199 | static int page_size; | 173 | static int page_size; |
200 | 174 | ||
201 | static int pagemap_fd; | 175 | static int pagemap_fd; |
202 | static int kpageflags_fd; | 176 | static int kpageflags_fd; |
203 | 177 | ||
204 | static int opt_hwpoison; | 178 | static int opt_hwpoison; |
205 | static int opt_unpoison; | 179 | static int opt_unpoison; |
206 | 180 | ||
207 | static char hwpoison_debug_fs[MAX_PATH+1]; | 181 | static char hwpoison_debug_fs[MAX_PATH+1]; |
208 | static int hwpoison_inject_fd; | 182 | static int hwpoison_inject_fd; |
209 | static int hwpoison_forget_fd; | 183 | static int hwpoison_forget_fd; |
210 | 184 | ||
211 | #define HASH_SHIFT 13 | 185 | #define HASH_SHIFT 13 |
212 | #define HASH_SIZE (1 << HASH_SHIFT) | 186 | #define HASH_SIZE (1 << HASH_SHIFT) |
213 | #define HASH_MASK (HASH_SIZE - 1) | 187 | #define HASH_MASK (HASH_SIZE - 1) |
214 | #define HASH_KEY(flags) (flags & HASH_MASK) | 188 | #define HASH_KEY(flags) (flags & HASH_MASK) |
215 | 189 | ||
216 | static unsigned long total_pages; | 190 | static unsigned long total_pages; |
217 | static unsigned long nr_pages[HASH_SIZE]; | 191 | static unsigned long nr_pages[HASH_SIZE]; |
218 | static uint64_t page_flags[HASH_SIZE]; | 192 | static uint64_t page_flags[HASH_SIZE]; |
219 | 193 | ||
220 | 194 | ||
221 | /* | 195 | /* |
222 | * helper functions | 196 | * helper functions |
223 | */ | 197 | */ |
224 | 198 | ||
225 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) | 199 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
226 | 200 | ||
227 | #define min_t(type, x, y) ({ \ | 201 | #define min_t(type, x, y) ({ \ |
228 | type __min1 = (x); \ | 202 | type __min1 = (x); \ |
229 | type __min2 = (y); \ | 203 | type __min2 = (y); \ |
230 | __min1 < __min2 ? __min1 : __min2; }) | 204 | __min1 < __min2 ? __min1 : __min2; }) |
231 | 205 | ||
232 | #define max_t(type, x, y) ({ \ | 206 | #define max_t(type, x, y) ({ \ |
233 | type __max1 = (x); \ | 207 | type __max1 = (x); \ |
234 | type __max2 = (y); \ | 208 | type __max2 = (y); \ |
235 | __max1 > __max2 ? __max1 : __max2; }) | 209 | __max1 > __max2 ? __max1 : __max2; }) |
236 | 210 | ||
237 | static unsigned long pages2mb(unsigned long pages) | 211 | static unsigned long pages2mb(unsigned long pages) |
238 | { | 212 | { |
239 | return (pages * page_size) >> 20; | 213 | return (pages * page_size) >> 20; |
240 | } | 214 | } |
241 | 215 | ||
242 | static void fatal(const char *x, ...) | 216 | static void fatal(const char *x, ...) |
243 | { | 217 | { |
244 | va_list ap; | 218 | va_list ap; |
245 | 219 | ||
246 | va_start(ap, x); | 220 | va_start(ap, x); |
247 | vfprintf(stderr, x, ap); | 221 | vfprintf(stderr, x, ap); |
248 | va_end(ap); | 222 | va_end(ap); |
249 | exit(EXIT_FAILURE); | 223 | exit(EXIT_FAILURE); |
250 | } | 224 | } |
251 | 225 | ||
252 | static int checked_open(const char *pathname, int flags) | 226 | static int checked_open(const char *pathname, int flags) |
253 | { | 227 | { |
254 | int fd = open(pathname, flags); | 228 | int fd = open(pathname, flags); |
255 | 229 | ||
256 | if (fd < 0) { | 230 | if (fd < 0) { |
257 | perror(pathname); | 231 | perror(pathname); |
258 | exit(EXIT_FAILURE); | 232 | exit(EXIT_FAILURE); |
259 | } | 233 | } |
260 | 234 | ||
261 | return fd; | 235 | return fd; |
262 | } | 236 | } |
263 | 237 | ||
264 | /* | 238 | /* |
265 | * pagemap/kpageflags routines | 239 | * pagemap/kpageflags routines |
266 | */ | 240 | */ |
267 | 241 | ||
268 | static unsigned long do_u64_read(int fd, char *name, | 242 | static unsigned long do_u64_read(int fd, char *name, |
269 | uint64_t *buf, | 243 | uint64_t *buf, |
270 | unsigned long index, | 244 | unsigned long index, |
271 | unsigned long count) | 245 | unsigned long count) |
272 | { | 246 | { |
273 | long bytes; | 247 | long bytes; |
274 | 248 | ||
275 | if (index > ULONG_MAX / 8) | 249 | if (index > ULONG_MAX / 8) |
276 | fatal("index overflow: %lu\n", index); | 250 | fatal("index overflow: %lu\n", index); |
277 | 251 | ||
278 | if (lseek(fd, index * 8, SEEK_SET) < 0) { | 252 | if (lseek(fd, index * 8, SEEK_SET) < 0) { |
279 | perror(name); | 253 | perror(name); |
280 | exit(EXIT_FAILURE); | 254 | exit(EXIT_FAILURE); |
281 | } | 255 | } |
282 | 256 | ||
283 | bytes = read(fd, buf, count * 8); | 257 | bytes = read(fd, buf, count * 8); |
284 | if (bytes < 0) { | 258 | if (bytes < 0) { |
285 | perror(name); | 259 | perror(name); |
286 | exit(EXIT_FAILURE); | 260 | exit(EXIT_FAILURE); |
287 | } | 261 | } |
288 | if (bytes % 8) | 262 | if (bytes % 8) |
289 | fatal("partial read: %lu bytes\n", bytes); | 263 | fatal("partial read: %lu bytes\n", bytes); |
290 | 264 | ||
291 | return bytes / 8; | 265 | return bytes / 8; |
292 | } | 266 | } |
293 | 267 | ||
294 | static unsigned long kpageflags_read(uint64_t *buf, | 268 | static unsigned long kpageflags_read(uint64_t *buf, |
295 | unsigned long index, | 269 | unsigned long index, |
296 | unsigned long pages) | 270 | unsigned long pages) |
297 | { | 271 | { |
298 | return do_u64_read(kpageflags_fd, PROC_KPAGEFLAGS, buf, index, pages); | 272 | return do_u64_read(kpageflags_fd, PROC_KPAGEFLAGS, buf, index, pages); |
299 | } | 273 | } |
300 | 274 | ||
301 | static unsigned long pagemap_read(uint64_t *buf, | 275 | static unsigned long pagemap_read(uint64_t *buf, |
302 | unsigned long index, | 276 | unsigned long index, |
303 | unsigned long pages) | 277 | unsigned long pages) |
304 | { | 278 | { |
305 | return do_u64_read(pagemap_fd, "/proc/pid/pagemap", buf, index, pages); | 279 | return do_u64_read(pagemap_fd, "/proc/pid/pagemap", buf, index, pages); |
306 | } | 280 | } |
307 | 281 | ||
308 | static unsigned long pagemap_pfn(uint64_t val) | 282 | static unsigned long pagemap_pfn(uint64_t val) |
309 | { | 283 | { |
310 | unsigned long pfn; | 284 | unsigned long pfn; |
311 | 285 | ||
312 | if (val & PM_PRESENT) | 286 | if (val & PM_PRESENT) |
313 | pfn = PM_PFRAME(val); | 287 | pfn = PM_PFRAME(val); |
314 | else | 288 | else |
315 | pfn = 0; | 289 | pfn = 0; |
316 | 290 | ||
317 | return pfn; | 291 | return pfn; |
318 | } | 292 | } |
319 | 293 | ||
320 | 294 | ||
321 | /* | 295 | /* |
322 | * page flag names | 296 | * page flag names |
323 | */ | 297 | */ |
324 | 298 | ||
325 | static char *page_flag_name(uint64_t flags) | 299 | static char *page_flag_name(uint64_t flags) |
326 | { | 300 | { |
327 | static char buf[65]; | 301 | static char buf[65]; |
328 | int present; | 302 | int present; |
329 | int i, j; | 303 | int i, j; |
330 | 304 | ||
331 | for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) { | 305 | for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) { |
332 | present = (flags >> i) & 1; | 306 | present = (flags >> i) & 1; |
333 | if (!page_flag_names[i]) { | 307 | if (!page_flag_names[i]) { |
334 | if (present) | 308 | if (present) |
335 | fatal("unknown flag bit %d\n", i); | 309 | fatal("unknown flag bit %d\n", i); |
336 | continue; | 310 | continue; |
337 | } | 311 | } |
338 | buf[j++] = present ? page_flag_names[i][0] : '_'; | 312 | buf[j++] = present ? page_flag_names[i][0] : '_'; |
339 | } | 313 | } |
340 | 314 | ||
341 | return buf; | 315 | return buf; |
342 | } | 316 | } |
343 | 317 | ||
344 | static char *page_flag_longname(uint64_t flags) | 318 | static char *page_flag_longname(uint64_t flags) |
345 | { | 319 | { |
346 | static char buf[1024]; | 320 | static char buf[1024]; |
347 | int i, n; | 321 | int i, n; |
348 | 322 | ||
349 | for (i = 0, n = 0; i < ARRAY_SIZE(page_flag_names); i++) { | 323 | for (i = 0, n = 0; i < ARRAY_SIZE(page_flag_names); i++) { |
350 | if (!page_flag_names[i]) | 324 | if (!page_flag_names[i]) |
351 | continue; | 325 | continue; |
352 | if ((flags >> i) & 1) | 326 | if ((flags >> i) & 1) |
353 | n += snprintf(buf + n, sizeof(buf) - n, "%s,", | 327 | n += snprintf(buf + n, sizeof(buf) - n, "%s,", |
354 | page_flag_names[i] + 2); | 328 | page_flag_names[i] + 2); |
355 | } | 329 | } |
356 | if (n) | 330 | if (n) |
357 | n--; | 331 | n--; |
358 | buf[n] = '\0'; | 332 | buf[n] = '\0'; |
359 | 333 | ||
360 | return buf; | 334 | return buf; |
361 | } | 335 | } |
362 | 336 | ||
363 | 337 | ||
364 | /* | 338 | /* |
365 | * page list and summary | 339 | * page list and summary |
366 | */ | 340 | */ |
367 | 341 | ||
368 | static void show_page_range(unsigned long voffset, | 342 | static void show_page_range(unsigned long voffset, |
369 | unsigned long offset, uint64_t flags) | 343 | unsigned long offset, uint64_t flags) |
370 | { | 344 | { |
371 | static uint64_t flags0; | 345 | static uint64_t flags0; |
372 | static unsigned long voff; | 346 | static unsigned long voff; |
373 | static unsigned long index; | 347 | static unsigned long index; |
374 | static unsigned long count; | 348 | static unsigned long count; |
375 | 349 | ||
376 | if (flags == flags0 && offset == index + count && | 350 | if (flags == flags0 && offset == index + count && |
377 | (!opt_pid || voffset == voff + count)) { | 351 | (!opt_pid || voffset == voff + count)) { |
378 | count++; | 352 | count++; |
379 | return; | 353 | return; |
380 | } | 354 | } |
381 | 355 | ||
382 | if (count) { | 356 | if (count) { |
383 | if (opt_pid) | 357 | if (opt_pid) |
384 | printf("%lx\t", voff); | 358 | printf("%lx\t", voff); |
385 | printf("%lx\t%lx\t%s\n", | 359 | printf("%lx\t%lx\t%s\n", |
386 | index, count, page_flag_name(flags0)); | 360 | index, count, page_flag_name(flags0)); |
387 | } | 361 | } |
388 | 362 | ||
389 | flags0 = flags; | 363 | flags0 = flags; |
390 | index = offset; | 364 | index = offset; |
391 | voff = voffset; | 365 | voff = voffset; |
392 | count = 1; | 366 | count = 1; |
393 | } | 367 | } |
394 | 368 | ||
395 | static void show_page(unsigned long voffset, | 369 | static void show_page(unsigned long voffset, |
396 | unsigned long offset, uint64_t flags) | 370 | unsigned long offset, uint64_t flags) |
397 | { | 371 | { |
398 | if (opt_pid) | 372 | if (opt_pid) |
399 | printf("%lx\t", voffset); | 373 | printf("%lx\t", voffset); |
400 | printf("%lx\t%s\n", offset, page_flag_name(flags)); | 374 | printf("%lx\t%s\n", offset, page_flag_name(flags)); |
401 | } | 375 | } |
402 | 376 | ||
403 | static void show_summary(void) | 377 | static void show_summary(void) |
404 | { | 378 | { |
405 | int i; | 379 | int i; |
406 | 380 | ||
407 | printf(" flags\tpage-count MB" | 381 | printf(" flags\tpage-count MB" |
408 | " symbolic-flags\t\t\tlong-symbolic-flags\n"); | 382 | " symbolic-flags\t\t\tlong-symbolic-flags\n"); |
409 | 383 | ||
410 | for (i = 0; i < ARRAY_SIZE(nr_pages); i++) { | 384 | for (i = 0; i < ARRAY_SIZE(nr_pages); i++) { |
411 | if (nr_pages[i]) | 385 | if (nr_pages[i]) |
412 | printf("0x%016llx\t%10lu %8lu %s\t%s\n", | 386 | printf("0x%016llx\t%10lu %8lu %s\t%s\n", |
413 | (unsigned long long)page_flags[i], | 387 | (unsigned long long)page_flags[i], |
414 | nr_pages[i], | 388 | nr_pages[i], |
415 | pages2mb(nr_pages[i]), | 389 | pages2mb(nr_pages[i]), |
416 | page_flag_name(page_flags[i]), | 390 | page_flag_name(page_flags[i]), |
417 | page_flag_longname(page_flags[i])); | 391 | page_flag_longname(page_flags[i])); |
418 | } | 392 | } |
419 | 393 | ||
420 | printf(" total\t%10lu %8lu\n", | 394 | printf(" total\t%10lu %8lu\n", |
421 | total_pages, pages2mb(total_pages)); | 395 | total_pages, pages2mb(total_pages)); |
422 | } | 396 | } |
423 | 397 | ||
424 | 398 | ||
425 | /* | 399 | /* |
426 | * page flag filters | 400 | * page flag filters |
427 | */ | 401 | */ |
428 | 402 | ||
429 | static int bit_mask_ok(uint64_t flags) | 403 | static int bit_mask_ok(uint64_t flags) |
430 | { | 404 | { |
431 | int i; | 405 | int i; |
432 | 406 | ||
433 | for (i = 0; i < nr_bit_filters; i++) { | 407 | for (i = 0; i < nr_bit_filters; i++) { |
434 | if (opt_bits[i] == KPF_ALL_BITS) { | 408 | if (opt_bits[i] == KPF_ALL_BITS) { |
435 | if ((flags & opt_mask[i]) == 0) | 409 | if ((flags & opt_mask[i]) == 0) |
436 | return 0; | 410 | return 0; |
437 | } else { | 411 | } else { |
438 | if ((flags & opt_mask[i]) != opt_bits[i]) | 412 | if ((flags & opt_mask[i]) != opt_bits[i]) |
439 | return 0; | 413 | return 0; |
440 | } | 414 | } |
441 | } | 415 | } |
442 | 416 | ||
443 | return 1; | 417 | return 1; |
444 | } | 418 | } |
445 | 419 | ||
446 | static uint64_t expand_overloaded_flags(uint64_t flags) | 420 | static uint64_t expand_overloaded_flags(uint64_t flags) |
447 | { | 421 | { |
448 | /* SLOB/SLUB overload several page flags */ | 422 | /* SLOB/SLUB overload several page flags */ |
449 | if (flags & BIT(SLAB)) { | 423 | if (flags & BIT(SLAB)) { |
450 | if (flags & BIT(PRIVATE)) | 424 | if (flags & BIT(PRIVATE)) |
451 | flags ^= BIT(PRIVATE) | BIT(SLOB_FREE); | 425 | flags ^= BIT(PRIVATE) | BIT(SLOB_FREE); |
452 | if (flags & BIT(ACTIVE)) | 426 | if (flags & BIT(ACTIVE)) |
453 | flags ^= BIT(ACTIVE) | BIT(SLUB_FROZEN); | 427 | flags ^= BIT(ACTIVE) | BIT(SLUB_FROZEN); |
454 | if (flags & BIT(ERROR)) | 428 | if (flags & BIT(ERROR)) |
455 | flags ^= BIT(ERROR) | BIT(SLUB_DEBUG); | 429 | flags ^= BIT(ERROR) | BIT(SLUB_DEBUG); |
456 | } | 430 | } |
457 | 431 | ||
458 | /* PG_reclaim is overloaded as PG_readahead in the read path */ | 432 | /* PG_reclaim is overloaded as PG_readahead in the read path */ |
459 | if ((flags & (BIT(RECLAIM) | BIT(WRITEBACK))) == BIT(RECLAIM)) | 433 | if ((flags & (BIT(RECLAIM) | BIT(WRITEBACK))) == BIT(RECLAIM)) |
460 | flags ^= BIT(RECLAIM) | BIT(READAHEAD); | 434 | flags ^= BIT(RECLAIM) | BIT(READAHEAD); |
461 | 435 | ||
462 | return flags; | 436 | return flags; |
463 | } | 437 | } |
464 | 438 | ||
465 | static uint64_t well_known_flags(uint64_t flags) | 439 | static uint64_t well_known_flags(uint64_t flags) |
466 | { | 440 | { |
467 | /* hide flags intended only for kernel hacker */ | 441 | /* hide flags intended only for kernel hacker */ |
468 | flags &= ~KPF_HACKERS_BITS; | 442 | flags &= ~KPF_HACKERS_BITS; |
469 | 443 | ||
470 | /* hide non-hugeTLB compound pages */ | 444 | /* hide non-hugeTLB compound pages */ |
471 | if ((flags & BITS_COMPOUND) && !(flags & BIT(HUGE))) | 445 | if ((flags & BITS_COMPOUND) && !(flags & BIT(HUGE))) |
472 | flags &= ~BITS_COMPOUND; | 446 | flags &= ~BITS_COMPOUND; |
473 | 447 | ||
474 | return flags; | 448 | return flags; |
475 | } | 449 | } |
476 | 450 | ||
477 | static uint64_t kpageflags_flags(uint64_t flags) | 451 | static uint64_t kpageflags_flags(uint64_t flags) |
478 | { | 452 | { |
479 | flags = expand_overloaded_flags(flags); | 453 | flags = expand_overloaded_flags(flags); |
480 | 454 | ||
481 | if (!opt_raw) | 455 | if (!opt_raw) |
482 | flags = well_known_flags(flags); | 456 | flags = well_known_flags(flags); |
483 | 457 | ||
484 | return flags; | 458 | return flags; |
485 | } | 459 | } |
486 | 460 | ||
487 | /* verify that a mountpoint is actually a debugfs instance */ | 461 | /* verify that a mountpoint is actually a debugfs instance */ |
488 | static int debugfs_valid_mountpoint(const char *debugfs) | 462 | static int debugfs_valid_mountpoint(const char *debugfs) |
489 | { | 463 | { |
490 | struct statfs st_fs; | 464 | struct statfs st_fs; |
491 | 465 | ||
492 | if (statfs(debugfs, &st_fs) < 0) | 466 | if (statfs(debugfs, &st_fs) < 0) |
493 | return -ENOENT; | 467 | return -ENOENT; |
494 | else if (st_fs.f_type != (long) DEBUGFS_MAGIC) | 468 | else if (st_fs.f_type != (long) DEBUGFS_MAGIC) |
495 | return -ENOENT; | 469 | return -ENOENT; |
496 | 470 | ||
497 | return 0; | 471 | return 0; |
498 | } | 472 | } |
499 | 473 | ||
500 | /* find the path to the mounted debugfs */ | 474 | /* find the path to the mounted debugfs */ |
501 | static const char *debugfs_find_mountpoint(void) | 475 | static const char *debugfs_find_mountpoint(void) |
502 | { | 476 | { |
503 | const char **ptr; | 477 | const char **ptr; |
504 | char type[100]; | 478 | char type[100]; |
505 | FILE *fp; | 479 | FILE *fp; |
506 | 480 | ||
507 | ptr = debugfs_known_mountpoints; | 481 | ptr = debugfs_known_mountpoints; |
508 | while (*ptr) { | 482 | while (*ptr) { |
509 | if (debugfs_valid_mountpoint(*ptr) == 0) { | 483 | if (debugfs_valid_mountpoint(*ptr) == 0) { |
510 | strcpy(hwpoison_debug_fs, *ptr); | 484 | strcpy(hwpoison_debug_fs, *ptr); |
511 | return hwpoison_debug_fs; | 485 | return hwpoison_debug_fs; |
512 | } | 486 | } |
513 | ptr++; | 487 | ptr++; |
514 | } | 488 | } |
515 | 489 | ||
516 | /* give up and parse /proc/mounts */ | 490 | /* give up and parse /proc/mounts */ |
517 | fp = fopen("/proc/mounts", "r"); | 491 | fp = fopen("/proc/mounts", "r"); |
518 | if (fp == NULL) | 492 | if (fp == NULL) |
519 | perror("Can't open /proc/mounts for read"); | 493 | perror("Can't open /proc/mounts for read"); |
520 | 494 | ||
521 | while (fscanf(fp, "%*s %" | 495 | while (fscanf(fp, "%*s %" |
522 | STR(MAX_PATH) | 496 | STR(MAX_PATH) |
523 | "s %99s %*s %*d %*d\n", | 497 | "s %99s %*s %*d %*d\n", |
524 | hwpoison_debug_fs, type) == 2) { | 498 | hwpoison_debug_fs, type) == 2) { |
525 | if (strcmp(type, "debugfs") == 0) | 499 | if (strcmp(type, "debugfs") == 0) |
526 | break; | 500 | break; |
527 | } | 501 | } |
528 | fclose(fp); | 502 | fclose(fp); |
529 | 503 | ||
530 | if (strcmp(type, "debugfs") != 0) | 504 | if (strcmp(type, "debugfs") != 0) |
531 | return NULL; | 505 | return NULL; |
532 | 506 | ||
533 | return hwpoison_debug_fs; | 507 | return hwpoison_debug_fs; |
534 | } | 508 | } |
535 | 509 | ||
536 | /* mount the debugfs somewhere if it's not mounted */ | 510 | /* mount the debugfs somewhere if it's not mounted */ |
537 | 511 | ||
538 | static void debugfs_mount(void) | 512 | static void debugfs_mount(void) |
539 | { | 513 | { |
540 | const char **ptr; | 514 | const char **ptr; |
541 | 515 | ||
542 | /* see if it's already mounted */ | 516 | /* see if it's already mounted */ |
543 | if (debugfs_find_mountpoint()) | 517 | if (debugfs_find_mountpoint()) |
544 | return; | 518 | return; |
545 | 519 | ||
546 | ptr = debugfs_known_mountpoints; | 520 | ptr = debugfs_known_mountpoints; |
547 | while (*ptr) { | 521 | while (*ptr) { |
548 | if (mount(NULL, *ptr, "debugfs", 0, NULL) == 0) { | 522 | if (mount(NULL, *ptr, "debugfs", 0, NULL) == 0) { |
549 | /* save the mountpoint */ | 523 | /* save the mountpoint */ |
550 | strcpy(hwpoison_debug_fs, *ptr); | 524 | strcpy(hwpoison_debug_fs, *ptr); |
551 | break; | 525 | break; |
552 | } | 526 | } |
553 | ptr++; | 527 | ptr++; |
554 | } | 528 | } |
555 | 529 | ||
556 | if (*ptr == NULL) { | 530 | if (*ptr == NULL) { |
557 | perror("mount debugfs"); | 531 | perror("mount debugfs"); |
558 | exit(EXIT_FAILURE); | 532 | exit(EXIT_FAILURE); |
559 | } | 533 | } |
560 | } | 534 | } |
561 | 535 | ||
562 | /* | 536 | /* |
563 | * page actions | 537 | * page actions |
564 | */ | 538 | */ |
565 | 539 | ||
566 | static void prepare_hwpoison_fd(void) | 540 | static void prepare_hwpoison_fd(void) |
567 | { | 541 | { |
568 | char buf[MAX_PATH + 1]; | 542 | char buf[MAX_PATH + 1]; |
569 | 543 | ||
570 | debugfs_mount(); | 544 | debugfs_mount(); |
571 | 545 | ||
572 | if (opt_hwpoison && !hwpoison_inject_fd) { | 546 | if (opt_hwpoison && !hwpoison_inject_fd) { |
573 | snprintf(buf, MAX_PATH, "%s/hwpoison/corrupt-pfn", | 547 | snprintf(buf, MAX_PATH, "%s/hwpoison/corrupt-pfn", |
574 | hwpoison_debug_fs); | 548 | hwpoison_debug_fs); |
575 | hwpoison_inject_fd = checked_open(buf, O_WRONLY); | 549 | hwpoison_inject_fd = checked_open(buf, O_WRONLY); |
576 | } | 550 | } |
577 | 551 | ||
578 | if (opt_unpoison && !hwpoison_forget_fd) { | 552 | if (opt_unpoison && !hwpoison_forget_fd) { |
579 | snprintf(buf, MAX_PATH, "%s/hwpoison/unpoison-pfn", | 553 | snprintf(buf, MAX_PATH, "%s/hwpoison/unpoison-pfn", |
580 | hwpoison_debug_fs); | 554 | hwpoison_debug_fs); |
581 | hwpoison_forget_fd = checked_open(buf, O_WRONLY); | 555 | hwpoison_forget_fd = checked_open(buf, O_WRONLY); |
582 | } | 556 | } |
583 | } | 557 | } |
584 | 558 | ||
585 | static int hwpoison_page(unsigned long offset) | 559 | static int hwpoison_page(unsigned long offset) |
586 | { | 560 | { |
587 | char buf[100]; | 561 | char buf[100]; |
588 | int len; | 562 | int len; |
589 | 563 | ||
590 | len = sprintf(buf, "0x%lx\n", offset); | 564 | len = sprintf(buf, "0x%lx\n", offset); |
591 | len = write(hwpoison_inject_fd, buf, len); | 565 | len = write(hwpoison_inject_fd, buf, len); |
592 | if (len < 0) { | 566 | if (len < 0) { |
593 | perror("hwpoison inject"); | 567 | perror("hwpoison inject"); |
594 | return len; | 568 | return len; |
595 | } | 569 | } |
596 | return 0; | 570 | return 0; |
597 | } | 571 | } |
598 | 572 | ||
599 | static int unpoison_page(unsigned long offset) | 573 | static int unpoison_page(unsigned long offset) |
600 | { | 574 | { |
601 | char buf[100]; | 575 | char buf[100]; |
602 | int len; | 576 | int len; |
603 | 577 | ||
604 | len = sprintf(buf, "0x%lx\n", offset); | 578 | len = sprintf(buf, "0x%lx\n", offset); |
605 | len = write(hwpoison_forget_fd, buf, len); | 579 | len = write(hwpoison_forget_fd, buf, len); |
606 | if (len < 0) { | 580 | if (len < 0) { |
607 | perror("hwpoison forget"); | 581 | perror("hwpoison forget"); |
608 | return len; | 582 | return len; |
609 | } | 583 | } |
610 | return 0; | 584 | return 0; |
611 | } | 585 | } |
612 | 586 | ||
613 | /* | 587 | /* |
614 | * page frame walker | 588 | * page frame walker |
615 | */ | 589 | */ |
616 | 590 | ||
617 | static int hash_slot(uint64_t flags) | 591 | static int hash_slot(uint64_t flags) |
618 | { | 592 | { |
619 | int k = HASH_KEY(flags); | 593 | int k = HASH_KEY(flags); |
620 | int i; | 594 | int i; |
621 | 595 | ||
622 | /* Explicitly reserve slot 0 for flags 0: the following logic | 596 | /* Explicitly reserve slot 0 for flags 0: the following logic |
623 | * cannot distinguish an unoccupied slot from slot (flags==0). | 597 | * cannot distinguish an unoccupied slot from slot (flags==0). |
624 | */ | 598 | */ |
625 | if (flags == 0) | 599 | if (flags == 0) |
626 | return 0; | 600 | return 0; |
627 | 601 | ||
628 | /* search through the remaining (HASH_SIZE-1) slots */ | 602 | /* search through the remaining (HASH_SIZE-1) slots */ |
629 | for (i = 1; i < ARRAY_SIZE(page_flags); i++, k++) { | 603 | for (i = 1; i < ARRAY_SIZE(page_flags); i++, k++) { |
630 | if (!k || k >= ARRAY_SIZE(page_flags)) | 604 | if (!k || k >= ARRAY_SIZE(page_flags)) |
631 | k = 1; | 605 | k = 1; |
632 | if (page_flags[k] == 0) { | 606 | if (page_flags[k] == 0) { |
633 | page_flags[k] = flags; | 607 | page_flags[k] = flags; |
634 | return k; | 608 | return k; |
635 | } | 609 | } |
636 | if (page_flags[k] == flags) | 610 | if (page_flags[k] == flags) |
637 | return k; | 611 | return k; |
638 | } | 612 | } |
639 | 613 | ||
640 | fatal("hash table full: bump up HASH_SHIFT?\n"); | 614 | fatal("hash table full: bump up HASH_SHIFT?\n"); |
641 | exit(EXIT_FAILURE); | 615 | exit(EXIT_FAILURE); |
642 | } | 616 | } |
643 | 617 | ||
644 | static void add_page(unsigned long voffset, | 618 | static void add_page(unsigned long voffset, |
645 | unsigned long offset, uint64_t flags) | 619 | unsigned long offset, uint64_t flags) |
646 | { | 620 | { |
647 | flags = kpageflags_flags(flags); | 621 | flags = kpageflags_flags(flags); |
648 | 622 | ||
649 | if (!bit_mask_ok(flags)) | 623 | if (!bit_mask_ok(flags)) |
650 | return; | 624 | return; |
651 | 625 | ||
652 | if (opt_hwpoison) | 626 | if (opt_hwpoison) |
653 | hwpoison_page(offset); | 627 | hwpoison_page(offset); |
654 | if (opt_unpoison) | 628 | if (opt_unpoison) |
655 | unpoison_page(offset); | 629 | unpoison_page(offset); |
656 | 630 | ||
657 | if (opt_list == 1) | 631 | if (opt_list == 1) |
658 | show_page_range(voffset, offset, flags); | 632 | show_page_range(voffset, offset, flags); |
659 | else if (opt_list == 2) | 633 | else if (opt_list == 2) |
660 | show_page(voffset, offset, flags); | 634 | show_page(voffset, offset, flags); |
661 | 635 | ||
662 | nr_pages[hash_slot(flags)]++; | 636 | nr_pages[hash_slot(flags)]++; |
663 | total_pages++; | 637 | total_pages++; |
664 | } | 638 | } |
665 | 639 | ||
666 | #define KPAGEFLAGS_BATCH (64 << 10) /* 64k pages */ | 640 | #define KPAGEFLAGS_BATCH (64 << 10) /* 64k pages */ |
667 | static void walk_pfn(unsigned long voffset, | 641 | static void walk_pfn(unsigned long voffset, |
668 | unsigned long index, | 642 | unsigned long index, |
669 | unsigned long count) | 643 | unsigned long count) |
670 | { | 644 | { |
671 | uint64_t buf[KPAGEFLAGS_BATCH]; | 645 | uint64_t buf[KPAGEFLAGS_BATCH]; |
672 | unsigned long batch; | 646 | unsigned long batch; |
673 | long pages; | 647 | long pages; |
674 | unsigned long i; | 648 | unsigned long i; |
675 | 649 | ||
676 | while (count) { | 650 | while (count) { |
677 | batch = min_t(unsigned long, count, KPAGEFLAGS_BATCH); | 651 | batch = min_t(unsigned long, count, KPAGEFLAGS_BATCH); |
678 | pages = kpageflags_read(buf, index, batch); | 652 | pages = kpageflags_read(buf, index, batch); |
679 | if (pages == 0) | 653 | if (pages == 0) |
680 | break; | 654 | break; |
681 | 655 | ||
682 | for (i = 0; i < pages; i++) | 656 | for (i = 0; i < pages; i++) |
683 | add_page(voffset + i, index + i, buf[i]); | 657 | add_page(voffset + i, index + i, buf[i]); |
684 | 658 | ||
685 | index += pages; | 659 | index += pages; |
686 | count -= pages; | 660 | count -= pages; |
687 | } | 661 | } |
688 | } | 662 | } |
689 | 663 | ||
690 | #define PAGEMAP_BATCH (64 << 10) | 664 | #define PAGEMAP_BATCH (64 << 10) |
691 | static void walk_vma(unsigned long index, unsigned long count) | 665 | static void walk_vma(unsigned long index, unsigned long count) |
692 | { | 666 | { |
693 | uint64_t buf[PAGEMAP_BATCH]; | 667 | uint64_t buf[PAGEMAP_BATCH]; |
694 | unsigned long batch; | 668 | unsigned long batch; |
695 | unsigned long pages; | 669 | unsigned long pages; |
696 | unsigned long pfn; | 670 | unsigned long pfn; |
697 | unsigned long i; | 671 | unsigned long i; |
698 | 672 | ||
699 | while (count) { | 673 | while (count) { |
700 | batch = min_t(unsigned long, count, PAGEMAP_BATCH); | 674 | batch = min_t(unsigned long, count, PAGEMAP_BATCH); |
701 | pages = pagemap_read(buf, index, batch); | 675 | pages = pagemap_read(buf, index, batch); |
702 | if (pages == 0) | 676 | if (pages == 0) |
703 | break; | 677 | break; |
704 | 678 | ||
705 | for (i = 0; i < pages; i++) { | 679 | for (i = 0; i < pages; i++) { |
706 | pfn = pagemap_pfn(buf[i]); | 680 | pfn = pagemap_pfn(buf[i]); |
707 | if (pfn) | 681 | if (pfn) |
708 | walk_pfn(index + i, pfn, 1); | 682 | walk_pfn(index + i, pfn, 1); |
709 | } | 683 | } |
710 | 684 | ||
711 | index += pages; | 685 | index += pages; |
712 | count -= pages; | 686 | count -= pages; |
713 | } | 687 | } |
714 | } | 688 | } |
715 | 689 | ||
716 | static void walk_task(unsigned long index, unsigned long count) | 690 | static void walk_task(unsigned long index, unsigned long count) |
717 | { | 691 | { |
718 | const unsigned long end = index + count; | 692 | const unsigned long end = index + count; |
719 | unsigned long start; | 693 | unsigned long start; |
720 | int i = 0; | 694 | int i = 0; |
721 | 695 | ||
722 | while (index < end) { | 696 | while (index < end) { |
723 | 697 | ||
724 | while (pg_end[i] <= index) | 698 | while (pg_end[i] <= index) |
725 | if (++i >= nr_vmas) | 699 | if (++i >= nr_vmas) |
726 | return; | 700 | return; |
727 | if (pg_start[i] >= end) | 701 | if (pg_start[i] >= end) |
728 | return; | 702 | return; |
729 | 703 | ||
730 | start = max_t(unsigned long, pg_start[i], index); | 704 | start = max_t(unsigned long, pg_start[i], index); |
731 | index = min_t(unsigned long, pg_end[i], end); | 705 | index = min_t(unsigned long, pg_end[i], end); |
732 | 706 | ||
733 | assert(start < index); | 707 | assert(start < index); |
734 | walk_vma(start, index - start); | 708 | walk_vma(start, index - start); |
735 | } | 709 | } |
736 | } | 710 | } |
737 | 711 | ||
738 | static void add_addr_range(unsigned long offset, unsigned long size) | 712 | static void add_addr_range(unsigned long offset, unsigned long size) |
739 | { | 713 | { |
740 | if (nr_addr_ranges >= MAX_ADDR_RANGES) | 714 | if (nr_addr_ranges >= MAX_ADDR_RANGES) |
741 | fatal("too many addr ranges\n"); | 715 | fatal("too many addr ranges\n"); |
742 | 716 | ||
743 | opt_offset[nr_addr_ranges] = offset; | 717 | opt_offset[nr_addr_ranges] = offset; |
744 | opt_size[nr_addr_ranges] = min_t(unsigned long, size, ULONG_MAX-offset); | 718 | opt_size[nr_addr_ranges] = min_t(unsigned long, size, ULONG_MAX-offset); |
745 | nr_addr_ranges++; | 719 | nr_addr_ranges++; |
746 | } | 720 | } |
747 | 721 | ||
748 | static void walk_addr_ranges(void) | 722 | static void walk_addr_ranges(void) |
749 | { | 723 | { |
750 | int i; | 724 | int i; |
751 | 725 | ||
752 | kpageflags_fd = checked_open(PROC_KPAGEFLAGS, O_RDONLY); | 726 | kpageflags_fd = checked_open(PROC_KPAGEFLAGS, O_RDONLY); |
753 | 727 | ||
754 | if (!nr_addr_ranges) | 728 | if (!nr_addr_ranges) |
755 | add_addr_range(0, ULONG_MAX); | 729 | add_addr_range(0, ULONG_MAX); |
756 | 730 | ||
757 | for (i = 0; i < nr_addr_ranges; i++) | 731 | for (i = 0; i < nr_addr_ranges; i++) |
758 | if (!opt_pid) | 732 | if (!opt_pid) |
759 | walk_pfn(0, opt_offset[i], opt_size[i]); | 733 | walk_pfn(0, opt_offset[i], opt_size[i]); |
760 | else | 734 | else |
761 | walk_task(opt_offset[i], opt_size[i]); | 735 | walk_task(opt_offset[i], opt_size[i]); |
762 | 736 | ||
763 | close(kpageflags_fd); | 737 | close(kpageflags_fd); |
764 | } | 738 | } |
765 | 739 | ||
766 | 740 | ||
767 | /* | 741 | /* |
768 | * user interface | 742 | * user interface |
769 | */ | 743 | */ |
770 | 744 | ||
771 | static const char *page_flag_type(uint64_t flag) | 745 | static const char *page_flag_type(uint64_t flag) |
772 | { | 746 | { |
773 | if (flag & KPF_HACKERS_BITS) | 747 | if (flag & KPF_HACKERS_BITS) |
774 | return "(r)"; | 748 | return "(r)"; |
775 | if (flag & KPF_OVERLOADED_BITS) | 749 | if (flag & KPF_OVERLOADED_BITS) |
776 | return "(o)"; | 750 | return "(o)"; |
777 | return " "; | 751 | return " "; |
778 | } | 752 | } |
779 | 753 | ||
780 | static void usage(void) | 754 | static void usage(void) |
781 | { | 755 | { |
782 | int i, j; | 756 | int i, j; |
783 | 757 | ||
784 | printf( | 758 | printf( |
785 | "page-types [options]\n" | 759 | "page-types [options]\n" |
786 | " -r|--raw Raw mode, for kernel developers\n" | 760 | " -r|--raw Raw mode, for kernel developers\n" |
787 | " -d|--describe flags Describe flags\n" | 761 | " -d|--describe flags Describe flags\n" |
788 | " -a|--addr addr-spec Walk a range of pages\n" | 762 | " -a|--addr addr-spec Walk a range of pages\n" |
789 | " -b|--bits bits-spec Walk pages with specified bits\n" | 763 | " -b|--bits bits-spec Walk pages with specified bits\n" |
790 | " -p|--pid pid Walk process address space\n" | 764 | " -p|--pid pid Walk process address space\n" |
791 | #if 0 /* planned features */ | 765 | #if 0 /* planned features */ |
792 | " -f|--file filename Walk file address space\n" | 766 | " -f|--file filename Walk file address space\n" |
793 | #endif | 767 | #endif |
794 | " -l|--list Show page details in ranges\n" | 768 | " -l|--list Show page details in ranges\n" |
795 | " -L|--list-each Show page details one by one\n" | 769 | " -L|--list-each Show page details one by one\n" |
796 | " -N|--no-summary Don't show summary info\n" | 770 | " -N|--no-summary Don't show summary info\n" |
797 | " -X|--hwpoison hwpoison pages\n" | 771 | " -X|--hwpoison hwpoison pages\n" |
798 | " -x|--unpoison unpoison pages\n" | 772 | " -x|--unpoison unpoison pages\n" |
799 | " -h|--help Show this usage message\n" | 773 | " -h|--help Show this usage message\n" |
800 | "flags:\n" | 774 | "flags:\n" |
801 | " 0x10 bitfield format, e.g.\n" | 775 | " 0x10 bitfield format, e.g.\n" |
802 | " anon bit-name, e.g.\n" | 776 | " anon bit-name, e.g.\n" |
803 | " 0x10,anon comma-separated list, e.g.\n" | 777 | " 0x10,anon comma-separated list, e.g.\n" |
804 | "addr-spec:\n" | 778 | "addr-spec:\n" |
805 | " N one page at offset N (unit: pages)\n" | 779 | " N one page at offset N (unit: pages)\n" |
806 | " N+M pages range from N to N+M-1\n" | 780 | " N+M pages range from N to N+M-1\n" |
807 | " N,M pages range from N to M-1\n" | 781 | " N,M pages range from N to M-1\n" |
808 | " N, pages range from N to end\n" | 782 | " N, pages range from N to end\n" |
809 | " ,M pages range from 0 to M-1\n" | 783 | " ,M pages range from 0 to M-1\n" |
810 | "bits-spec:\n" | 784 | "bits-spec:\n" |
811 | " bit1,bit2 (flags & (bit1|bit2)) != 0\n" | 785 | " bit1,bit2 (flags & (bit1|bit2)) != 0\n" |
812 | " bit1,bit2=bit1 (flags & (bit1|bit2)) == bit1\n" | 786 | " bit1,bit2=bit1 (flags & (bit1|bit2)) == bit1\n" |
813 | " bit1,~bit2 (flags & (bit1|bit2)) == bit1\n" | 787 | " bit1,~bit2 (flags & (bit1|bit2)) == bit1\n" |
814 | " =bit1,bit2 flags == (bit1|bit2)\n" | 788 | " =bit1,bit2 flags == (bit1|bit2)\n" |
815 | "bit-names:\n" | 789 | "bit-names:\n" |
816 | ); | 790 | ); |
817 | 791 | ||
818 | for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) { | 792 | for (i = 0, j = 0; i < ARRAY_SIZE(page_flag_names); i++) { |
819 | if (!page_flag_names[i]) | 793 | if (!page_flag_names[i]) |
820 | continue; | 794 | continue; |
821 | printf("%16s%s", page_flag_names[i] + 2, | 795 | printf("%16s%s", page_flag_names[i] + 2, |
822 | page_flag_type(1ULL << i)); | 796 | page_flag_type(1ULL << i)); |
823 | if (++j > 3) { | 797 | if (++j > 3) { |
824 | j = 0; | 798 | j = 0; |
825 | putchar('\n'); | 799 | putchar('\n'); |
826 | } | 800 | } |
827 | } | 801 | } |
828 | printf("\n " | 802 | printf("\n " |
829 | "(r) raw mode bits (o) overloaded bits\n"); | 803 | "(r) raw mode bits (o) overloaded bits\n"); |
830 | } | 804 | } |
831 | 805 | ||
832 | static unsigned long long parse_number(const char *str) | 806 | static unsigned long long parse_number(const char *str) |
833 | { | 807 | { |
834 | unsigned long long n; | 808 | unsigned long long n; |
835 | 809 | ||
836 | n = strtoll(str, NULL, 0); | 810 | n = strtoll(str, NULL, 0); |
837 | 811 | ||
838 | if (n == 0 && str[0] != '0') | 812 | if (n == 0 && str[0] != '0') |
839 | fatal("invalid name or number: %s\n", str); | 813 | fatal("invalid name or number: %s\n", str); |
840 | 814 | ||
841 | return n; | 815 | return n; |
842 | } | 816 | } |
843 | 817 | ||
844 | static void parse_pid(const char *str) | 818 | static void parse_pid(const char *str) |
845 | { | 819 | { |
846 | FILE *file; | 820 | FILE *file; |
847 | char buf[5000]; | 821 | char buf[5000]; |
848 | 822 | ||
849 | opt_pid = parse_number(str); | 823 | opt_pid = parse_number(str); |
850 | 824 | ||
851 | sprintf(buf, "/proc/%d/pagemap", opt_pid); | 825 | sprintf(buf, "/proc/%d/pagemap", opt_pid); |
852 | pagemap_fd = checked_open(buf, O_RDONLY); | 826 | pagemap_fd = checked_open(buf, O_RDONLY); |
853 | 827 | ||
854 | sprintf(buf, "/proc/%d/maps", opt_pid); | 828 | sprintf(buf, "/proc/%d/maps", opt_pid); |
855 | file = fopen(buf, "r"); | 829 | file = fopen(buf, "r"); |
856 | if (!file) { | 830 | if (!file) { |
857 | perror(buf); | 831 | perror(buf); |
858 | exit(EXIT_FAILURE); | 832 | exit(EXIT_FAILURE); |
859 | } | 833 | } |
860 | 834 | ||
861 | while (fgets(buf, sizeof(buf), file) != NULL) { | 835 | while (fgets(buf, sizeof(buf), file) != NULL) { |
862 | unsigned long vm_start; | 836 | unsigned long vm_start; |
863 | unsigned long vm_end; | 837 | unsigned long vm_end; |
864 | unsigned long long pgoff; | 838 | unsigned long long pgoff; |
865 | int major, minor; | 839 | int major, minor; |
866 | char r, w, x, s; | 840 | char r, w, x, s; |
867 | unsigned long ino; | 841 | unsigned long ino; |
868 | int n; | 842 | int n; |
869 | 843 | ||
870 | n = sscanf(buf, "%lx-%lx %c%c%c%c %llx %x:%x %lu", | 844 | n = sscanf(buf, "%lx-%lx %c%c%c%c %llx %x:%x %lu", |
871 | &vm_start, | 845 | &vm_start, |
872 | &vm_end, | 846 | &vm_end, |
873 | &r, &w, &x, &s, | 847 | &r, &w, &x, &s, |
874 | &pgoff, | 848 | &pgoff, |
875 | &major, &minor, | 849 | &major, &minor, |
876 | &ino); | 850 | &ino); |
877 | if (n < 10) { | 851 | if (n < 10) { |
878 | fprintf(stderr, "unexpected line: %s\n", buf); | 852 | fprintf(stderr, "unexpected line: %s\n", buf); |
879 | continue; | 853 | continue; |
880 | } | 854 | } |
881 | pg_start[nr_vmas] = vm_start / page_size; | 855 | pg_start[nr_vmas] = vm_start / page_size; |
882 | pg_end[nr_vmas] = vm_end / page_size; | 856 | pg_end[nr_vmas] = vm_end / page_size; |
883 | if (++nr_vmas >= MAX_VMAS) { | 857 | if (++nr_vmas >= MAX_VMAS) { |
884 | fprintf(stderr, "too many VMAs\n"); | 858 | fprintf(stderr, "too many VMAs\n"); |
885 | break; | 859 | break; |
886 | } | 860 | } |
887 | } | 861 | } |
888 | fclose(file); | 862 | fclose(file); |
889 | } | 863 | } |
890 | 864 | ||
891 | static void parse_file(const char *name) | 865 | static void parse_file(const char *name) |
892 | { | 866 | { |
893 | } | 867 | } |
894 | 868 | ||
895 | static void parse_addr_range(const char *optarg) | 869 | static void parse_addr_range(const char *optarg) |
896 | { | 870 | { |
897 | unsigned long offset; | 871 | unsigned long offset; |
898 | unsigned long size; | 872 | unsigned long size; |
899 | char *p; | 873 | char *p; |
900 | 874 | ||
901 | p = strchr(optarg, ','); | 875 | p = strchr(optarg, ','); |
902 | if (!p) | 876 | if (!p) |
903 | p = strchr(optarg, '+'); | 877 | p = strchr(optarg, '+'); |
904 | 878 | ||
905 | if (p == optarg) { | 879 | if (p == optarg) { |
906 | offset = 0; | 880 | offset = 0; |
907 | size = parse_number(p + 1); | 881 | size = parse_number(p + 1); |
908 | } else if (p) { | 882 | } else if (p) { |
909 | offset = parse_number(optarg); | 883 | offset = parse_number(optarg); |
910 | if (p[1] == '\0') | 884 | if (p[1] == '\0') |
911 | size = ULONG_MAX; | 885 | size = ULONG_MAX; |
912 | else { | 886 | else { |
913 | size = parse_number(p + 1); | 887 | size = parse_number(p + 1); |
914 | if (*p == ',') { | 888 | if (*p == ',') { |
915 | if (size < offset) | 889 | if (size < offset) |
916 | fatal("invalid range: %lu,%lu\n", | 890 | fatal("invalid range: %lu,%lu\n", |
917 | offset, size); | 891 | offset, size); |
918 | size -= offset; | 892 | size -= offset; |
919 | } | 893 | } |
920 | } | 894 | } |
921 | } else { | 895 | } else { |
922 | offset = parse_number(optarg); | 896 | offset = parse_number(optarg); |
923 | size = 1; | 897 | size = 1; |
924 | } | 898 | } |
925 | 899 | ||
926 | add_addr_range(offset, size); | 900 | add_addr_range(offset, size); |
927 | } | 901 | } |
928 | 902 | ||
929 | static void add_bits_filter(uint64_t mask, uint64_t bits) | 903 | static void add_bits_filter(uint64_t mask, uint64_t bits) |
930 | { | 904 | { |
931 | if (nr_bit_filters >= MAX_BIT_FILTERS) | 905 | if (nr_bit_filters >= MAX_BIT_FILTERS) |
932 | fatal("too much bit filters\n"); | 906 | fatal("too much bit filters\n"); |
933 | 907 | ||
934 | opt_mask[nr_bit_filters] = mask; | 908 | opt_mask[nr_bit_filters] = mask; |
935 | opt_bits[nr_bit_filters] = bits; | 909 | opt_bits[nr_bit_filters] = bits; |
936 | nr_bit_filters++; | 910 | nr_bit_filters++; |
937 | } | 911 | } |
938 | 912 | ||
939 | static uint64_t parse_flag_name(const char *str, int len) | 913 | static uint64_t parse_flag_name(const char *str, int len) |
940 | { | 914 | { |
941 | int i; | 915 | int i; |
942 | 916 | ||
943 | if (!*str || !len) | 917 | if (!*str || !len) |
944 | return 0; | 918 | return 0; |
945 | 919 | ||
946 | if (len <= 8 && !strncmp(str, "compound", len)) | 920 | if (len <= 8 && !strncmp(str, "compound", len)) |
947 | return BITS_COMPOUND; | 921 | return BITS_COMPOUND; |
948 | 922 | ||
949 | for (i = 0; i < ARRAY_SIZE(page_flag_names); i++) { | 923 | for (i = 0; i < ARRAY_SIZE(page_flag_names); i++) { |
950 | if (!page_flag_names[i]) | 924 | if (!page_flag_names[i]) |
951 | continue; | 925 | continue; |
952 | if (!strncmp(str, page_flag_names[i] + 2, len)) | 926 | if (!strncmp(str, page_flag_names[i] + 2, len)) |
953 | return 1ULL << i; | 927 | return 1ULL << i; |
954 | } | 928 | } |
955 | 929 | ||
956 | return parse_number(str); | 930 | return parse_number(str); |
957 | } | 931 | } |
958 | 932 | ||
959 | static uint64_t parse_flag_names(const char *str, int all) | 933 | static uint64_t parse_flag_names(const char *str, int all) |
960 | { | 934 | { |
961 | const char *p = str; | 935 | const char *p = str; |
962 | uint64_t flags = 0; | 936 | uint64_t flags = 0; |
963 | 937 | ||
964 | while (1) { | 938 | while (1) { |
965 | if (*p == ',' || *p == '=' || *p == '\0') { | 939 | if (*p == ',' || *p == '=' || *p == '\0') { |
966 | if ((*str != '~') || (*str == '~' && all && *++str)) | 940 | if ((*str != '~') || (*str == '~' && all && *++str)) |
967 | flags |= parse_flag_name(str, p - str); | 941 | flags |= parse_flag_name(str, p - str); |
968 | if (*p != ',') | 942 | if (*p != ',') |
969 | break; | 943 | break; |
970 | str = p + 1; | 944 | str = p + 1; |
971 | } | 945 | } |
972 | p++; | 946 | p++; |
973 | } | 947 | } |
974 | 948 | ||
975 | return flags; | 949 | return flags; |
976 | } | 950 | } |
977 | 951 | ||
978 | static void parse_bits_mask(const char *optarg) | 952 | static void parse_bits_mask(const char *optarg) |
979 | { | 953 | { |
980 | uint64_t mask; | 954 | uint64_t mask; |
981 | uint64_t bits; | 955 | uint64_t bits; |
982 | const char *p; | 956 | const char *p; |
983 | 957 | ||
984 | p = strchr(optarg, '='); | 958 | p = strchr(optarg, '='); |
985 | if (p == optarg) { | 959 | if (p == optarg) { |
986 | mask = KPF_ALL_BITS; | 960 | mask = KPF_ALL_BITS; |
987 | bits = parse_flag_names(p + 1, 0); | 961 | bits = parse_flag_names(p + 1, 0); |
988 | } else if (p) { | 962 | } else if (p) { |
989 | mask = parse_flag_names(optarg, 0); | 963 | mask = parse_flag_names(optarg, 0); |
990 | bits = parse_flag_names(p + 1, 0); | 964 | bits = parse_flag_names(p + 1, 0); |
991 | } else if (strchr(optarg, '~')) { | 965 | } else if (strchr(optarg, '~')) { |
992 | mask = parse_flag_names(optarg, 1); | 966 | mask = parse_flag_names(optarg, 1); |
993 | bits = parse_flag_names(optarg, 0); | 967 | bits = parse_flag_names(optarg, 0); |
994 | } else { | 968 | } else { |
995 | mask = parse_flag_names(optarg, 0); | 969 | mask = parse_flag_names(optarg, 0); |
996 | bits = KPF_ALL_BITS; | 970 | bits = KPF_ALL_BITS; |
997 | } | 971 | } |
998 | 972 | ||
999 | add_bits_filter(mask, bits); | 973 | add_bits_filter(mask, bits); |
1000 | } | 974 | } |
1001 | 975 | ||
1002 | static void describe_flags(const char *optarg) | 976 | static void describe_flags(const char *optarg) |
1003 | { | 977 | { |
1004 | uint64_t flags = parse_flag_names(optarg, 0); | 978 | uint64_t flags = parse_flag_names(optarg, 0); |
1005 | 979 | ||
1006 | printf("0x%016llx\t%s\t%s\n", | 980 | printf("0x%016llx\t%s\t%s\n", |
1007 | (unsigned long long)flags, | 981 | (unsigned long long)flags, |
1008 | page_flag_name(flags), | 982 | page_flag_name(flags), |
1009 | page_flag_longname(flags)); | 983 | page_flag_longname(flags)); |
1010 | } | 984 | } |
1011 | 985 | ||
1012 | static const struct option opts[] = { | 986 | static const struct option opts[] = { |
1013 | { "raw" , 0, NULL, 'r' }, | 987 | { "raw" , 0, NULL, 'r' }, |
1014 | { "pid" , 1, NULL, 'p' }, | 988 | { "pid" , 1, NULL, 'p' }, |
1015 | { "file" , 1, NULL, 'f' }, | 989 | { "file" , 1, NULL, 'f' }, |
1016 | { "addr" , 1, NULL, 'a' }, | 990 | { "addr" , 1, NULL, 'a' }, |
1017 | { "bits" , 1, NULL, 'b' }, | 991 | { "bits" , 1, NULL, 'b' }, |
1018 | { "describe" , 1, NULL, 'd' }, | 992 | { "describe" , 1, NULL, 'd' }, |
1019 | { "list" , 0, NULL, 'l' }, | 993 | { "list" , 0, NULL, 'l' }, |
1020 | { "list-each" , 0, NULL, 'L' }, | 994 | { "list-each" , 0, NULL, 'L' }, |
1021 | { "no-summary", 0, NULL, 'N' }, | 995 | { "no-summary", 0, NULL, 'N' }, |
1022 | { "hwpoison" , 0, NULL, 'X' }, | 996 | { "hwpoison" , 0, NULL, 'X' }, |
1023 | { "unpoison" , 0, NULL, 'x' }, | 997 | { "unpoison" , 0, NULL, 'x' }, |
1024 | { "help" , 0, NULL, 'h' }, | 998 | { "help" , 0, NULL, 'h' }, |
1025 | { NULL , 0, NULL, 0 } | 999 | { NULL , 0, NULL, 0 } |
1026 | }; | 1000 | }; |
1027 | 1001 | ||
1028 | int main(int argc, char *argv[]) | 1002 | int main(int argc, char *argv[]) |
1029 | { | 1003 | { |
1030 | int c; | 1004 | int c; |
1031 | 1005 | ||
1032 | page_size = getpagesize(); | 1006 | page_size = getpagesize(); |
1033 | 1007 | ||
1034 | while ((c = getopt_long(argc, argv, | 1008 | while ((c = getopt_long(argc, argv, |
1035 | "rp:f:a:b:d:lLNXxh", opts, NULL)) != -1) { | 1009 | "rp:f:a:b:d:lLNXxh", opts, NULL)) != -1) { |
1036 | switch (c) { | 1010 | switch (c) { |
1037 | case 'r': | 1011 | case 'r': |
1038 | opt_raw = 1; | 1012 | opt_raw = 1; |
1039 | break; | 1013 | break; |
1040 | case 'p': | 1014 | case 'p': |
1041 | parse_pid(optarg); | 1015 | parse_pid(optarg); |
1042 | break; | 1016 | break; |
1043 | case 'f': | 1017 | case 'f': |
1044 | parse_file(optarg); | 1018 | parse_file(optarg); |
1045 | break; | 1019 | break; |
1046 | case 'a': | 1020 | case 'a': |
1047 | parse_addr_range(optarg); | 1021 | parse_addr_range(optarg); |
1048 | break; | 1022 | break; |
1049 | case 'b': | 1023 | case 'b': |
1050 | parse_bits_mask(optarg); | 1024 | parse_bits_mask(optarg); |
1051 | break; | 1025 | break; |
1052 | case 'd': | 1026 | case 'd': |
1053 | describe_flags(optarg); | 1027 | describe_flags(optarg); |
1054 | exit(0); | 1028 | exit(0); |
1055 | case 'l': | 1029 | case 'l': |
1056 | opt_list = 1; | 1030 | opt_list = 1; |
1057 | break; | 1031 | break; |
1058 | case 'L': | 1032 | case 'L': |
1059 | opt_list = 2; | 1033 | opt_list = 2; |
1060 | break; | 1034 | break; |
1061 | case 'N': | 1035 | case 'N': |
1062 | opt_no_summary = 1; | 1036 | opt_no_summary = 1; |
1063 | break; | 1037 | break; |
1064 | case 'X': | 1038 | case 'X': |
1065 | opt_hwpoison = 1; | 1039 | opt_hwpoison = 1; |
1066 | prepare_hwpoison_fd(); | 1040 | prepare_hwpoison_fd(); |
1067 | break; | 1041 | break; |
1068 | case 'x': | 1042 | case 'x': |
1069 | opt_unpoison = 1; | 1043 | opt_unpoison = 1; |
1070 | prepare_hwpoison_fd(); | 1044 | prepare_hwpoison_fd(); |
1071 | break; | 1045 | break; |
1072 | case 'h': | 1046 | case 'h': |
1073 | usage(); | 1047 | usage(); |
1074 | exit(0); | 1048 | exit(0); |
1075 | default: | 1049 | default: |
1076 | usage(); | 1050 | usage(); |
1077 | exit(1); | 1051 | exit(1); |
1078 | } | 1052 | } |
1079 | } | 1053 | } |
1080 | 1054 | ||
1081 | if (opt_list && opt_pid) | 1055 | if (opt_list && opt_pid) |
1082 | printf("voffset\t"); | 1056 | printf("voffset\t"); |
1083 | if (opt_list == 1) | 1057 | if (opt_list == 1) |
1084 | printf("offset\tlen\tflags\n"); | 1058 | printf("offset\tlen\tflags\n"); |
1085 | if (opt_list == 2) | 1059 | if (opt_list == 2) |
1086 | printf("offset\tflags\n"); | 1060 | printf("offset\tflags\n"); |
1087 | 1061 | ||
1088 | walk_addr_ranges(); | 1062 | walk_addr_ranges(); |
1089 | 1063 | ||
1090 | if (opt_list == 1) | 1064 | if (opt_list == 1) |
1091 | show_page_range(0, 0, 0); /* drain the buffer */ | 1065 | show_page_range(0, 0, 0); /* drain the buffer */ |
1092 | 1066 | ||
1093 | if (opt_no_summary) | 1067 | if (opt_no_summary) |
1094 | return 0; | 1068 | return 0; |
1095 | 1069 | ||
1096 | if (opt_list) | 1070 | if (opt_list) |
1097 | printf("\n\n"); | 1071 | printf("\n\n"); |
1098 | 1072 | ||
1099 | show_summary(); | 1073 | show_summary(); |
1100 | 1074 | ||
1101 | return 0; | 1075 | return 0; |
1102 | } | 1076 | } |