// memory/vm related tapset // Copyright (C) 2005, 2006 IBM Corp. // Copyright (C) 2006 Intel Corporation. // // This file is part of systemtap, and is free software. You can // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. // // This family of probe points is used to probe memory-related events. // %{ #include %} global VM_FAULT_OOM=0, VM_FAULT_SIGBUS=1, VM_FAULT_MINOR=2, VM_FAULT_MAJOR=3 global VM_FAULT_NOPAGE=4, VM_FAULT_LOCKED=5, VM_FAULT_ERROR=6 /** * sfunction vm_fault_contains - Test return value for page fault reason * @value: The fault_type returned by vm.page_fault.return * @test: The type of fault to test for (VM_FAULT_OOM or similar) */ function vm_fault_contains:long (value:long, test:long) %{ int res; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) switch (THIS->test){ case 0: res = THIS->value == VM_FAULT_OOM; break; case 1: res = THIS->value == VM_FAULT_SIGBUS; break; case 2: res = THIS->value == VM_FAULT_MINOR; break; case 3: res = THIS->value == VM_FAULT_MAJOR; break; default: res = 0; break; } #else switch (THIS->test){ case 0: res = THIS->value & VM_FAULT_OOM; break; case 1: res = THIS->value & VM_FAULT_SIGBUS; break; case 2: /* VM_FAULT_MINOR infered by that flags off */ res = !((VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_MAJOR) & THIS->value); break; case 3: res = THIS->value & VM_FAULT_MAJOR; break; case 4: res = THIS->value & VM_FAULT_NOPAGE; break; case 5: res = THIS->value & VM_FAULT_LOCKED; break; case 6: res = THIS->value & VM_FAULT_ERROR; break; default: res = 0; } #endif THIS->__retvalue = (res != 0); return; %} /** * probe vm.pagefault - Records that a page fault occurred. * @address: The address of the faulting memory access; i.e. the address that caused the page fault. * @write_access: Indicates whether this was a write or read access; 1 indicates a write, * while 0 indicates a read. * * Context: The process which triggered the fault */ probe vm.pagefault = kernel.function("__handle_mm_fault@mm/memory.c") ?, kernel.function("handle_mm_fault@mm/memory.c") ? { write_access = $write_access address = $address } /** * probe vm.pagefault.return - Indicates what type of fault occurred. * @fault_type: Returns either * 0 (VM_FAULT_OOM) for out of memory faults, * 2 (VM_FAULT_MINOR) for minor faults, 3 (VM_FAULT_MAJOR) for * major faults, or 1 (VM_FAULT_SIGBUS) if the fault was neither OOM, minor fault, * nor major fault. */ probe vm.pagefault.return = kernel.function("__handle_mm_fault@mm/memory.c").return ?, kernel.function("handle_mm_fault@mm/memory.c").return ? { fault_type = $return } /** * sfunction addr_to_node - Returns which node a given address belongs to within a NUMA system. * @addr: The address of the faulting memory access. * */ function addr_to_node:long(addr:long) %{ /* pure */ int nid; int pfn = __pa(THIS->addr) >> PAGE_SHIFT; for_each_online_node(nid) if ( NODE_DATA(nid)->node_start_pfn <= pfn && pfn < (NODE_DATA(nid)->node_start_pfn + NODE_DATA(nid)->node_spanned_pages) ) { THIS->__retvalue = nid; break; } %} // Return whether a page to be copied is a zero page. function _IS_ZERO_PAGE:long(from:long, vaddr:long) %{ /* pure */ THIS->__retvalue = (THIS->from == (long) ZERO_PAGE(THIS->vaddr)); %} /** * probe vm.write_shared - Attempts at writing to a shared page. * @address: The address of the shared write. * * Context: * The context is the process attempting the write. * * Fires when a process attempts to write to a shared page. * If a copy is necessary, this will be followed by a * vm.write_shared_copy. */ probe vm.write_shared = kernel.function("do_wp_page") { address = $address } /** * probe vm.write_shared_copy - Page copy for shared page write. * @address: The address of the shared write. * @zero: Boolean indicating whether it is a zero page * (can do a clear instead of a copy). * * Context: * The process attempting the write. * * Fires when a write to a shared page requires a page copy. This is * always preceded by a vm.shared_write. */ probe vm.write_shared_copy = kernel.function("copy_cow_page")? { address = $address zero = _IS_ZERO_PAGE($from, address); } /** * probe vm.mmap - Fires when an mmap is requested. * @address: The requested address * @length: The length of the memory segment * * Context: * The process calling mmap. */ probe vm.mmap = kernel.function("do_mmap"), kernel.function("do_mmap2")? { address = $addr length = $len } /** * probe vm.munmap - Fires when an munmap is requested. * @address: The requested address * @length: The length of the memory segment * * Context: * The process calling munmap. */ probe vm.munmap = kernel.function("do_munmap") { address = $start length = $len } /** * probe vm.brk - Fires when a brk is requested (i.e. the heap will be resized). * @address: The requested address * @length: The length of the memory segment * * Context: * The process calling brk. */ probe vm.brk = kernel.function("do_brk") { address = $addr length = $len } /** * probe vm.oom_kill - Fires when a thread is selected for termination by the OOM killer. * @task: The task being killed * * Context: * The process that tried to consume excessive memory, and thus * triggered the OOM. (is this correct?) */ probe vm.oom_kill = kernel.function("__oom_kill_task") { task = $p }