Index: usr.bin/kdump/kdump.c =================================================================== --- usr.bin/kdump/kdump.c (revision 233798) +++ usr.bin/kdump/kdump.c (working copy) @@ -102,6 +102,8 @@ void ktrstat(struct stat *); void ktrstruct(char *, size_t); void ktrcapfail(struct ktr_cap_fail *); +void ktrfault(struct ktr_fault *); +void ktrfaultend(struct ktr_faultend *); void usage(void); void ioctlname(unsigned long, int); @@ -306,6 +308,13 @@ break; case KTR_CAPFAIL: ktrcapfail((struct ktr_cap_fail *)m); + break; + case KTR_FAULT: + ktrfault((struct ktr_fault *)m); + break; + case KTR_FAULTEND: + ktrfaultend((struct ktr_faultend *)m); + break; default: printf("\n"); break; @@ -448,6 +457,12 @@ case KTR_CAPFAIL: type = "CAP "; break; + case KTR_FAULT: + type = "PFLT"; + break; + case KTR_FAULTEND: + type = "PRET"; + break; default: sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type); type = unknown; @@ -1631,8 +1646,26 @@ capname((intmax_t)ktr->cap_held); break; } + printf("\n"); } +void +ktrfault(struct ktr_fault *ktr) +{ + + printf("0x%jx ", ktr->vaddr); + vmprotname(ktr->type); + printf("\n"); +} + +void +ktrfaultend(struct ktr_faultend *ktr) +{ + + vmresultname(ktr->result); + printf("\n"); +} + #if defined(__amd64__) || defined(__i386__) void linux_ktrsyscall(struct ktr_syscall *ktr) Index: usr.bin/kdump/mksubr =================================================================== --- usr.bin/kdump/mksubr (revision 233798) +++ usr.bin/kdump/mksubr (working copy) @@ -187,6 +187,8 @@ #include #include #include +#include +#include #include "kdump_subr.h" @@ -334,6 +336,26 @@ } } +/* + * MANUAL + * + * Used for page fault type. Cannot use auto_or_type since the macro + * values contain a cast. Also, VM_PROT_NONE has to be handled specially. + */ +void +vmprotname (int type) +{ + int or = 0; + + if (type == VM_PROT_NONE) { + (void)printf("VM_PROT_NONE"); + return; + } + if_print_or(type, VM_PROT_READ, or); + if_print_or(type, VM_PROT_WRITE, or); + if_print_or(type, VM_PROT_EXECUTE, or); + if_print_or(type, VM_PROT_COPY, or); +} _EOF_ auto_or_type "accessmodename" "[A-Z]_OK[[:space:]]+0?x?[0-9A-Fa-f]+" "sys/unistd.h" @@ -373,6 +395,7 @@ auto_switch_type "sockoptname" "SO_[A-Z]+[[:space:]]+0x[0-9]+" "sys/socket.h" auto_switch_type "socktypename" "SOCK_[A-Z]+[[:space:]]+[1-9]+[0-9]*" "sys/socket.h" auto_or_type "thrcreateflagsname" "THR_[A-Z]+[[:space:]]+0x[0-9]+" "sys/thr.h" +auto_switch_type "vmresultname" "KERN_[A-Z]+[[:space:]]+[0-9]+" "vm/vm_param.h" auto_or_type "wait4optname" "W[A-Z]+[[:space:]]+[0-9]+" "sys/wait.h" auto_switch_type "whencename" "SEEK_[A-Z]+[[:space:]]+[0-9]+" "sys/unistd.h" Index: usr.bin/ktrace/ktrace.h =================================================================== --- usr.bin/ktrace/ktrace.h (revision 233798) +++ usr.bin/ktrace/ktrace.h (working copy) @@ -32,7 +32,8 @@ #define DEF_POINTS (KTRFAC_SYSCALL | KTRFAC_SYSRET | KTRFAC_NAMEI | \ KTRFAC_GENIO | KTRFAC_PSIG | KTRFAC_USER | \ - KTRFAC_STRUCT | KTRFAC_SYSCTL | KTRFAC_CAPFAIL) + KTRFAC_STRUCT | KTRFAC_SYSCTL | KTRFAC_CAPFAIL | \ + KTRFAC_FAULT | KTRFAC_FAULTEND) #define PROC_ABI_POINTS (KTRFAC_PROCCTOR | KTRFAC_PROCDTOR) Index: usr.bin/ktrace/ktrace.1 =================================================================== --- usr.bin/ktrace/ktrace.1 (revision 233798) +++ usr.bin/ktrace/ktrace.1 (working copy) @@ -108,6 +108,8 @@ .Bl -tag -width flag -compact .It Cm c trace system calls +.It Cm f +trace page faults .It Cm i trace .Tn I/O @@ -129,7 +131,7 @@ requests .It Cm + trace the default set of trace points - -.Cm c , i , n , p , s , t , u , y +.Cm c , f , i , n , p , s , t , u , y .El .It Ar command Execute Index: usr.bin/ktrace/subr.c =================================================================== --- usr.bin/ktrace/subr.c (revision 233798) +++ usr.bin/ktrace/subr.c (working copy) @@ -64,6 +64,9 @@ case 'i': facs |= KTRFAC_GENIO; break; + case 'f': + facs |= KTRFAC_FAULT | KTRFAC_FAULTEND; + break; case 'n': facs |= KTRFAC_NAMEI; break; Index: sys/kern/kern_ktrace.c =================================================================== --- sys/kern/kern_ktrace.c (revision 233798) +++ sys/kern/kern_ktrace.c (working copy) @@ -101,6 +101,8 @@ struct ktr_genio ktr_genio; struct ktr_psig ktr_psig; struct ktr_csw ktr_csw; + struct ktr_fault ktr_fault; + struct ktr_faultend ktr_faultend; } ktr_data; STAILQ_ENTRY(ktr_request) ktr_list; }; @@ -119,6 +121,8 @@ sizeof(struct ktr_proc_ctor), /* KTR_PROCCTOR */ 0, /* KTR_PROCDTOR */ sizeof(struct ktr_cap_fail), /* KTR_CAPFAIL */ + sizeof(struct ktr_fault), /* KTR_FAULT */ + sizeof(struct ktr_faultend), /* KTR_FAULTEND */ }; static STAILQ_HEAD(, ktr_request) ktr_free; @@ -791,6 +795,42 @@ ktr_enqueuerequest(td, req); ktrace_exit(td); } + +void +ktrfault(vaddr, type) + vm_offset_t vaddr; + int type; +{ + struct thread *td = curthread; + struct ktr_request *req; + struct ktr_fault *kf; + + req = ktr_getrequest(KTR_FAULT); + if (req == NULL) + return; + kf = &req->ktr_data.ktr_fault; + kf->vaddr = vaddr; + kf->type = type; + ktr_enqueuerequest(td, req); + ktrace_exit(td); +} + +void +ktrfaultend(result) + int result; +{ + struct thread *td = curthread; + struct ktr_request *req; + struct ktr_faultend *kf; + + req = ktr_getrequest(KTR_FAULTEND); + if (req == NULL) + return; + kf = &req->ktr_data.ktr_faultend; + kf->result = result; + ktr_enqueuerequest(td, req); + ktrace_exit(td); +} #endif /* KTRACE */ /* Interface and common routines */ Index: sys/vm/vm_fault.c =================================================================== --- sys/vm/vm_fault.c (revision 233798) +++ sys/vm/vm_fault.c (working copy) @@ -74,6 +74,7 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_ktrace.h" #include "opt_vm.h" #include @@ -86,6 +87,9 @@ #include #include #include +#ifdef KTRACE +#include +#endif #include #include @@ -208,10 +212,23 @@ vm_fault(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type, int fault_flags) { + struct thread *td; + int result; - if ((curthread->td_pflags & TDP_NOFAULTING) != 0) + td = curthread; + if ((td->td_pflags & TDP_NOFAULTING) != 0) return (KERN_PROTECTION_FAILURE); - return (vm_fault_hold(map, vaddr, fault_type, fault_flags, NULL)); +#ifdef KTRACE + if (map != kernel_map && KTRPOINT(td, KTR_FAULT)) + ktrfault(vaddr, fault_type); +#endif + result = vm_fault_hold(map, trunc_page(vaddr), fault_type, fault_flags, + NULL); +#ifdef KTRACE + if (map != kernel_map && KTRPOINT(td, KTR_FAULTEND)) + ktrfaultend(result); +#endif + return (result); } int Index: sys/sys/ktrace.h =================================================================== --- sys/sys/ktrace.h (revision 233798) +++ sys/sys/ktrace.h (working copy) @@ -194,6 +194,23 @@ }; /* + * KTR_FAULT - page fault record + */ +#define KTR_FAULT 13 +struct ktr_fault { + vm_offset_t vaddr; + int type; +}; + +/* + * KTR_FAULTEND - end of page fault record + */ +#define KTR_FAULTEND 14 +struct ktr_faultend { + int result; +}; + +/* * KTR_DROP - If this bit is set in ktr_type, then at least one event * between the previous record and this record was dropped. */ @@ -215,6 +232,8 @@ #define KTRFAC_PROCCTOR (1<