code offset

This commit is contained in:
Andreas Abel
2019-12-30 22:39:30 +01:00
parent d41d0b7681
commit 3334ea3cca
2 changed files with 50 additions and 26 deletions

View File

@@ -15,6 +15,7 @@
#include <linux/namei.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <linux/set_memory.h>
#include <linux/seq_file.h>
#include <../arch/x86/include/asm/fpu/api.h>
@@ -23,12 +24,18 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andreas Abel");
// 4 Mb is the maximum that kmalloc supports on my machines
#define KMALLOC_MAX (4*1024*1024)
char* runtime_code_base = NULL;
size_t code_offset = 0;
size_t code_memory_size = 0;
size_t code_init_memory_size = 0;
size_t code_one_time_init_memory_size = 0;
size_t pfc_config_memory_size = 0;
size_t msr_config_memory_size = 0;
size_t runtime_code_memory_size = 0;
size_t runtime_code_base_memory_size = 0;
size_t runtime_one_time_init_code_memory_size = 0;
void** r14_segments = NULL;
@@ -74,25 +81,11 @@ static int read_file_into_buffer(const char *file_name, char **buf, size_t *buf_
return 0;
}
static void extend_runtime_code(void) {
size_t new_runtime_code_memory_size = get_required_runtime_code_length();
if (new_runtime_code_memory_size > runtime_code_memory_size) {
runtime_code_memory_size = new_runtime_code_memory_size;
vfree(runtime_code);
runtime_code = __vmalloc(runtime_code_memory_size, GFP_KERNEL, PAGE_KERNEL_EXEC);
if (!runtime_code) {
runtime_code_memory_size = 0;
pr_debug("failed to allocate executable memory\n");
}
}
}
static ssize_t code_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) {
return 0;
}
static ssize_t code_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) {
read_file_into_buffer(buf, &code, &code_length, &code_memory_size);
extend_runtime_code();
return count;
}
static struct kobj_attribute code_attribute =__ATTR(code, 0660, code_show, code_store);
@@ -102,7 +95,6 @@ static ssize_t init_show(struct kobject *kobj, struct kobj_attribute *attr, char
}
static ssize_t init_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) {
read_file_into_buffer(buf, &code_init, &code_init_length, &code_init_memory_size);
extend_runtime_code();
return count;
}
static struct kobj_attribute code_init_attribute =__ATTR(init, 0660, init_show, init_store);
@@ -173,7 +165,6 @@ static ssize_t unroll_count_show(struct kobject *kobj, struct kobj_attribute *at
}
static ssize_t unroll_count_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) {
sscanf(buf, "%ld", &unroll_count);
extend_runtime_code();
return count;
}
static struct kobj_attribute unroll_count_attribute =__ATTR(unroll_count, 0660, unroll_count_show, unroll_count_store);
@@ -271,9 +262,6 @@ int cmpPtr(const void *a, const void *b) {
else return 1;
}
// 4 Mb is the maximum that kmalloc supports on my machines
#define R14_SEGMENT_SIZE (4*1024*1024)
static ssize_t r14_size_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) {
if (n_r14_segments == 0 || !r14_segments[0]) return sprintf(buf, "0\n");
@@ -285,7 +273,7 @@ static ssize_t r14_size_show(struct kobject *kobj, struct kobj_attribute *attr,
void* cur_virt_addr = r14_segments[i];
phys_addr_t cur_phys_addr = virt_to_phys(cur_virt_addr);
if ((cur_virt_addr - prev_virt_addr != R14_SEGMENT_SIZE) || (cur_phys_addr - prev_phys_addr != R14_SEGMENT_SIZE)) {
if ((cur_virt_addr - prev_virt_addr != KMALLOC_MAX) || (cur_phys_addr - prev_phys_addr != KMALLOC_MAX)) {
pr_debug("No physically contiguous memory area of the requested size found.\n");
pr_debug("Try rebooting your computer.\n");
break;
@@ -296,7 +284,7 @@ static ssize_t r14_size_show(struct kobject *kobj, struct kobj_attribute *attr,
}
phys_addr_t phys_addr = virt_to_phys(r14_segments[0]);
return sprintf(buf, "R14 size: %zu MB\nVirtual address: 0x%px\nPhysical address: %pa\n", i*R14_SEGMENT_SIZE/(1024*1024), r14_segments[0], &phys_addr);
return sprintf(buf, "R14 size: %zu MB\nVirtual address: 0x%px\nPhysical address: %pa\n", i*KMALLOC_MAX/(1024*1024), r14_segments[0], &phys_addr);
}
static ssize_t r14_size_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) {
if (n_r14_segments > 0) {
@@ -309,12 +297,12 @@ static ssize_t r14_size_store(struct kobject *kobj, struct kobj_attribute *attr,
size_t size_MB = 0;
sscanf(buf, "%zu", &size_MB);
n_r14_segments = (size_MB*1024*1024 + (R14_SEGMENT_SIZE-1)) / R14_SEGMENT_SIZE;
n_r14_segments = (size_MB*1024*1024 + (KMALLOC_MAX-1)) / KMALLOC_MAX;
vfree(r14_segments);
r14_segments = vmalloc(n_r14_segments * sizeof(void*));
for (size_t i=0; i<n_r14_segments; i++) {
r14_segments[i] = kmalloc(R14_SEGMENT_SIZE, GFP_KERNEL|__GFP_COMP);
r14_segments[i] = kmalloc(KMALLOC_MAX, GFP_KERNEL|__GFP_COMP);
}
sort(r14_segments, n_r14_segments, sizeof(void*), cmpPtr, NULL);
@@ -339,6 +327,15 @@ static ssize_t print_r14_store(struct kobject *kobj, struct kobj_attribute *attr
}
static struct kobj_attribute print_r14_attribute =__ATTR(print_r14, 0660, print_r14_show, print_r14_store);
static ssize_t code_offset_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) {
return sprintf(buf, "%zu\n", code_offset);
}
static ssize_t code_offset_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) {
sscanf(buf, "%zu", &code_offset);
return count;
}
static struct kobj_attribute code_offset_attribute =__ATTR(code_offset, 0660, code_offset_show, code_offset_store);
static ssize_t verbose_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) {
return sprintf(buf, "%u\n", verbose);
}
@@ -372,6 +369,7 @@ static ssize_t reset_show(struct kobject *kobj, struct kobj_attribute *attr, cha
code_init_length = 0;
code_length = 0;
code_offset = 0;
n_pfc_configs = 0;
n_msr_configs = 0;
@@ -390,6 +388,13 @@ static int show(struct seq_file *m, void *v) {
}
}
size_t req_code_length = code_offset + get_required_runtime_code_length();
if (req_code_length > runtime_code_base_memory_size) {
printk(KERN_ERR "Maximum supported code size %zu kB; requested %zu kB\n", runtime_code_base_memory_size/1024, req_code_length/1024);
return -1;
}
runtime_code = runtime_code_base + code_offset;
kernel_fpu_begin();
long base_unroll_count = (basic_mode?0:unroll_count);
@@ -574,6 +579,15 @@ static int __init nb_init(void) {
runtime_rsi += RUNTIME_R_SIZE/2;
runtime_rsp += RUNTIME_R_SIZE/2;
runtime_code_base = kmalloc(KMALLOC_MAX, GFP_KERNEL);
if (!runtime_code_base) {
printk(KERN_ERR "Could not allocate memory for runtime_code\n");
return -1;
}
runtime_code_base_memory_size = KMALLOC_MAX;
set_memory_x((unsigned long)runtime_code_base, runtime_code_base_memory_size/PAGE_SIZE);
runtime_code = runtime_code_base;
nb_kobject = kobject_create_and_add("nb", kernel_kobj->parent);
if (!nb_kobject) {
pr_debug("failed to create and add nb\n");
@@ -597,6 +611,7 @@ static int __init nb_init(void) {
error |= sysfs_create_file(nb_kobject, &no_mem_attribute.attr);
error |= sysfs_create_file(nb_kobject, &r14_size_attribute.attr);
error |= sysfs_create_file(nb_kobject, &print_r14_attribute.attr);
error |= sysfs_create_file(nb_kobject, &code_offset_attribute.attr);
error |= sysfs_create_file(nb_kobject, &verbose_attribute.attr);
if (error) {
@@ -619,13 +634,17 @@ static void __exit nb_exit(void) {
kfree(code_one_time_init);
kfree(pfc_config_file_content);
kfree(msr_config_file_content);
vfree(runtime_code);
vfree(runtime_one_time_init_code);
vfree(runtime_rbp - RUNTIME_R_SIZE/2);
vfree(runtime_rdi - RUNTIME_R_SIZE/2);
vfree(runtime_rsi - RUNTIME_R_SIZE/2);
vfree(runtime_rsp - RUNTIME_R_SIZE/2);
if (runtime_code_base) {
set_memory_nx((unsigned long)runtime_code_base, runtime_code_base_memory_size/PAGE_SIZE);
kfree(runtime_code_base);
}
if (n_r14_segments > 0) {
for (int i=0; i<n_r14_segments; i++) {
kfree(r14_segments[i]);

View File

@@ -53,7 +53,7 @@ paramDict = dict()
# Assumes that no changes to the corresponding files in /sys/nb/ were made since the last call to setNanoBenchParameters().
# Otherwise, reset() needs to be called first.
def setNanoBenchParameters(config=None, configFile=None, msrConfig=None, msrConfigFile=None, nMeasurements=None, unrollCount=None, loopCount=None,
warmUpCount=None, initialWarmUpCount=None, aggregateFunction=None, basicMode=None, noMem=None, verbose=None):
warmUpCount=None, initialWarmUpCount=None, aggregateFunction=None, basicMode=None, noMem=None, codeOffset=0, verbose=None):
if not ramdiskCreated: createRamdisk()
if config is not None:
@@ -112,6 +112,11 @@ def setNanoBenchParameters(config=None, configFile=None, msrConfig=None, msrConf
writeFile('/sys/nb/no_mem', str(int(noMem)))
paramDict['noMem'] = noMem
if codeOffset is not None:
if paramDict.get('codeOffset', None) != codeOffset:
writeFile('/sys/nb/code_offset', str(codeOffset))
paramDict['codeOffset'] = codeOffset
if verbose is not None:
if paramDict.get('verbose', None) != verbose:
writeFile('/sys/nb/verbose', str(int(verbose)))