diff --git a/arch/x86/include/asm/ds.h b/arch/x86/include/asm/ds.h index 72c5a19..fed664a 100644 --- a/arch/x86/include/asm/ds.h +++ b/arch/x86/include/asm/ds.h @@ -78,6 +78,7 @@ extern int ds_release_pebs(struct task_struct *task); */ extern int ds_get_bts_index(struct task_struct *task, size_t *pos); extern int ds_get_pebs_index(struct task_struct *task, size_t *pos); +extern int ds_get_pebs_thres(struct task_struct *task, size_t *pos); /* * Return the (array) index one record beyond the end of the array. diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c index 2b69994..5882014 100644 --- a/arch/x86/kernel/ds.c +++ b/arch/x86/kernel/ds.c @@ -30,7 +30,7 @@ #include #include #include - +#include /* * The configuration for a particular DS hardware implementation. @@ -131,7 +131,7 @@ static inline int ds_validate_access(struct ds_context *context, { if (!context) return -EPERM; - +return 0; if (context->owner[qual] == current) return 0; @@ -467,6 +467,7 @@ int ds_request_pebs(struct task_struct *task, void *base, size_t size, { return ds_request(task, base, size, ovfl, ds_pebs); } +EXPORT_SYMBOL(ds_request_pebs); static int ds_release(struct task_struct *task, enum ds_qualifier qual) { @@ -478,12 +479,14 @@ static int ds_release(struct task_struct *task, enum ds_qualifier qual) if (error < 0) goto out; - kfree(context->buffer[qual]); - context->buffer[qual] = NULL; + if (context->buffer[qual]) { + kfree(context->buffer[qual]); + context->buffer[qual] = NULL; - current->mm->total_vm -= context->pages[qual]; - current->mm->locked_vm -= context->pages[qual]; - context->pages[qual] = 0; + current->mm->total_vm -= context->pages[qual]; + current->mm->locked_vm -= context->pages[qual]; + context->pages[qual] = 0; + } context->owner[qual] = NULL; /* @@ -506,6 +509,7 @@ int ds_release_pebs(struct task_struct *task) { return ds_release(task, ds_pebs); } +EXPORT_SYMBOL(ds_release_pebs); static int ds_get_index(struct task_struct *task, size_t *pos, enum ds_qualifier qual) @@ -539,6 +543,32 @@ int ds_get_pebs_index(struct task_struct *task, size_t *pos) { return ds_get_index(task, pos, ds_pebs); } +EXPORT_SYMBOL(ds_get_pebs_index); + +int ds_get_pebs_thres(struct task_struct *task, size_t *pos) +{ + struct ds_context *context; + unsigned long base, thr; + int error; + + context = ds_get_context(task); + error = ds_validate_access(context, ds_pebs); + if (error < 0) + goto out; + + base = ds_get(context->ds, ds_pebs, ds_buffer_base); + thr = ds_get(context->ds, ds_pebs, ds_interrupt_threshold); + + error = ((thr - base) / ds_cfg.sizeof_rec[ds_pebs]); + if (pos) + *pos = error; + return error; + out: + ds_put_context(context); + return error; +} +EXPORT_SYMBOL(ds_get_pebs_thres); + static int ds_get_end(struct task_struct *task, size_t *pos, enum ds_qualifier qual) @@ -572,6 +602,7 @@ int ds_get_pebs_end(struct task_struct *task, size_t *pos) { return ds_get_end(task, pos, ds_pebs); } +EXPORT_SYMBOL(ds_get_pebs_end); static int ds_access(struct task_struct *task, size_t index, const void **record, enum ds_qualifier qual) @@ -747,6 +778,7 @@ int ds_reset_pebs(struct task_struct *task) { return ds_reset_or_clear(task, ds_pebs, /* clear = */ 0); } +EXPORT_SYMBOL(ds_reset_pebs); int ds_clear_bts(struct task_struct *task) { @@ -796,6 +828,7 @@ int ds_set_pebs_reset(struct task_struct *task, u64 value) ds_put_context(context); return error; } +EXPORT_SYMBOL(ds_set_pebs_reset); static const struct ds_configuration ds_cfg_var = { .sizeof_ds = sizeof(long) * 12, @@ -804,10 +837,10 @@ static const struct ds_configuration ds_cfg_var = { .sizeof_rec[ds_pebs] = sizeof(long) * 10 }; static const struct ds_configuration ds_cfg_64 = { - .sizeof_ds = 8 * 12, + .sizeof_ds = 8 * 9, .sizeof_field = 8, .sizeof_rec[ds_bts] = 8 * 3, - .sizeof_rec[ds_pebs] = 8 * 10 + .sizeof_rec[ds_pebs] = 8 * 18 }; static inline void