Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/kern_kcov.c
Show First 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | |||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
#include <vm/vm_extern.h> | #include <vm/vm_extern.h> | ||||
#include <vm/vm_object.h> | #include <vm/vm_object.h> | ||||
#include <vm/vm_page.h> | #include <vm/vm_page.h> | ||||
#include <vm/vm_pager.h> | #include <vm/vm_pager.h> | ||||
#include <vm/vm_param.h> | |||||
MALLOC_DEFINE(M_KCOV_INFO, "kcovinfo", "KCOV info type"); | MALLOC_DEFINE(M_KCOV_INFO, "kcovinfo", "KCOV info type"); | ||||
#define KCOV_ELEMENT_SIZE sizeof(uint64_t) | #define KCOV_ELEMENT_SIZE sizeof(uint64_t) | ||||
/* | /* | ||||
* To know what the code can safely perform at any point in time we use a | * To know what the code can safely perform at any point in time we use a | ||||
* state machine. In the normal case the state transitions are: | * state machine. In the normal case the state transitions are: | ||||
▲ Show 20 Lines • Show All 273 Lines • ▼ Show 20 Lines | kcov_mmap_single(struct cdev *dev, vm_ooffset_t *offset, vm_size_t size, | ||||
if ((error = devfs_get_cdevpriv((void **)&info)) != 0) | if ((error = devfs_get_cdevpriv((void **)&info)) != 0) | ||||
return (error); | return (error); | ||||
if (info->kvaddr == 0 || size / KCOV_ELEMENT_SIZE != info->entries || | if (info->kvaddr == 0 || size / KCOV_ELEMENT_SIZE != info->entries || | ||||
info->mmap != false) | info->mmap != false) | ||||
return (EINVAL); | return (EINVAL); | ||||
vm_object_reference(info->bufobj); | |||||
info->mmap = true; | info->mmap = true; | ||||
*offset = 0; | *offset = 0; | ||||
*object = info->bufobj; | *object = info->bufobj; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
kcov_alloc(struct kcov_info *info, size_t entries) | kcov_alloc(struct kcov_info *info, size_t entries) | ||||
Show All 30 Lines | kcov_alloc(struct kcov_info *info, size_t entries) | ||||
info->entries = entries; | info->entries = entries; | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
kcov_free(struct kcov_info *info) | kcov_free(struct kcov_info *info) | ||||
{ | { | ||||
vm_page_t m; | |||||
size_t i; | |||||
if (info->kvaddr != 0) { | if (info->kvaddr != 0) { | ||||
pmap_qremove(info->kvaddr, info->bufsize / PAGE_SIZE); | pmap_qremove(info->kvaddr, info->bufsize / PAGE_SIZE); | ||||
kva_free(info->kvaddr, info->bufsize); | kva_free(info->kvaddr, info->bufsize); | ||||
} | } | ||||
if (info->bufobj != NULL && !info->mmap) | if (info->bufobj != NULL) { | ||||
VM_OBJECT_WLOCK(info->bufobj); | |||||
m = vm_page_lookup(info->bufobj, 0); | |||||
for (i = 0; i < info->bufsize / PAGE_SIZE; i++) { | |||||
vm_page_lock(m); | |||||
vm_page_unwire_noq(m); | |||||
vm_page_unlock(m); | |||||
m = vm_page_next(m); | |||||
} | |||||
VM_OBJECT_WUNLOCK(info->bufobj); | |||||
vm_object_deallocate(info->bufobj); | vm_object_deallocate(info->bufobj); | ||||
} | |||||
free(info, M_KCOV_INFO); | free(info, M_KCOV_INFO); | ||||
} | } | ||||
static int | static int | ||||
kcov_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag __unused, | kcov_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag __unused, | ||||
struct thread *td) | struct thread *td) | ||||
{ | { | ||||
struct kcov_info *info; | struct kcov_info *info; | ||||
▲ Show 20 Lines • Show All 154 Lines • Show Last 20 Lines |