Commit 9295b7a07c859a42346221b5839be0ae612333b0

Authored by Ulrich Drepper
Committed by Linus Torvalds
1 parent a62e2f4f50

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 }