From 7b638426f908576ebe89c9978688262213d8634d Mon Sep 17 00:00:00 2001 From: l00374334 Date: Thu, 9 Jul 2020 15:04:18 +0800 Subject: [PATCH] Add README and commit iocapacity limit code. --- README | 12 ++++++ prefetch_mod.c | 67 ++++++++++++++++++++++++++++-- prefetch_mod.h | 12 ++++++ prefetch_reg.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 196 insertions(+), 5 deletions(-) create mode 100644 README diff --git a/README b/README new file mode 100644 index 0000000..a45d941 --- /dev/null +++ b/README @@ -0,0 +1,12 @@ +This module is based on Kunpeng chip and provides some performance-sensitive chip parameters for adjustment. + +Build: + make clean && make + insmod pretetch_tuning.ko + +There will be some files under /sys/class/misc/prefetch/ + policy: Prefetch policy, can be set to 0~15. + read_unique: Whether to allow cross-numa access to cache. 0--allow 1--forbid. + +Configuration example: + echo 1 > /sys/class/misc/prefetch/read_unique diff --git a/prefetch_mod.c b/prefetch_mod.c index 98be275..aa67f3d 100644 --- a/prefetch_mod.c +++ b/prefetch_mod.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "prefetch_mod.h" #ifndef is_affinity_mask_valid @@ -44,7 +45,11 @@ static ssize_t prefetch_show(struct device* dev, static ssize_t prefetch_mask_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count); static ssize_t prefetch_mask_show(struct device* dev, - struct device_attribute* attr, char* buf); + struct device_attribute* attr, char* buf); +static ssize_t iocapacity_limit_store(struct device* dev, + struct device_attribute* attr, const char* buf, size_t count); +static ssize_t iocapacity_limit_show(struct device* dev, + struct device_attribute* attr, char* buf); /* Device create */ static DEVICE_ATTR(read_unique, S_IRUGO|S_IWUSR, @@ -56,11 +61,14 @@ static DEVICE_ATTR(policy, S_IRUGO|S_IWUSR, static DEVICE_ATTR(cpumask, S_IRUGO|S_IWUSR, prefetch_mask_show, prefetch_mask_store); +static DEVICE_ATTR(iocapacity_limit, S_IRUGO|S_IWUSR, + iocapacity_limit_show, iocapacity_limit_store); static struct attribute *prefetch_attrs[] = { &dev_attr_policy.attr, &dev_attr_cpumask.attr, &dev_attr_read_unique.attr, + &dev_attr_iocapacity_limit.attr, NULL, }; @@ -202,12 +210,60 @@ static ssize_t prefetch_mask_show(struct device* dev, return ret; } +/* 0--unlimit, 1--limit */ +static ssize_t iocapacity_limit_store(struct device* dev, + struct device_attribute* attr, const char* buf, size_t count) +{ + ssize_t ret = -1; + int iocapacity_limit = -1; + + ret = kstrtouint(buf, 0, &iocapacity_limit); + if (ret || (iocapacity_limit != 0 && iocapacity_limit != 1)) { + pr_err("invalid input!\n"); + return count; + } + + iocapacity_limit_set(&iocapacity_limit); + + return count; +} + +static ssize_t iocapacity_limit_show(struct device* dev, + struct device_attribute* attr, char* buf) +{ + int reg =1, count = 0; + unsigned int die_idx = 0, skt_idx = 0; + unsigned long skt_offset = 0x200000000000ULL; + unsigned nr_skt = 2, totem_num = 1; + nr_skt = get_nr_skt(); + totem_num = get_totem_num(); + skt_offset = get_skt_offset(); + for (skt_idx = 0; skt_idx < nr_skt; skt_idx++) { + for (die_idx = 0; die_idx < 2; die_idx++) { + unsigned long base2 = 0, addres = 0; + unsigned long base = skt_idx * skt_offset;//g_cpu_info_skt_offset; + unsigned val = 0; + if ((totem_num == 1) && (die_idx == 1)) + continue; + if (die_idx == 1) + base += TOTEM_OFFSET; + base2 = (unsigned long)ioremap(base + TB_L3T0_BASE, REG_RANGE); + if (!base2) + return count; + addres = base2 + L3T_DYNAMIC_CTRL; + val = iocapacity_limit_get(&addres); + count += scnprintf(buf + count, PAGE_SIZE, "register(%d): %d.\n", + reg++, val); + iounmap((volatile void*)base2); + } + } + return count; +} + /* * prefetch policy, can be 0~15: * 0: disable; 1~15: different thresholds for sms,amop algrithom; */ - - static int __init prefetch_init(void) { int ret = -1; @@ -244,6 +300,9 @@ static int __init prefetch_init(void) on_each_cpu(get_prefetch, old_cfg, 1); + /*get cpu infomation to identify iocapacity_limit registers*/ + initial_cpu_info(); + /* initial prefetch misc and initial prefetch_ops */ ret = misc_register(&misc); if (ret < 0) { @@ -274,4 +333,4 @@ static void __exit prefetch_exit(void) module_init(prefetch_init); module_exit(prefetch_exit); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL"); \ No newline at end of file diff --git a/prefetch_mod.h b/prefetch_mod.h index 387323f..bae47dc 100644 --- a/prefetch_mod.h +++ b/prefetch_mod.h @@ -22,6 +22,12 @@ enum { }; #define CACHE_READUNIQ_CTRL (1L << 40) +#define TB_L3T0_BASE 0x90180000 +#define L3T_DYNAMIC_CTRL 0x400 +#define TOTEM_OFFSET 0x8000000 +#define REG_RANGE 0x5000 +#define writel_reg(val, addr) (*(volatile unsigned int *)(addr) = (val)) +#define readl_reg(addr) (*(volatile unsigned int*)(addr)) #ifdef CONFIG_ARCH_HISI typedef struct { @@ -39,7 +45,13 @@ extern void get_prefetch(void* dummy); extern void read_unique_set(void *dummy); extern void read_unique_get(void *dummy); extern void reset_prefetch(void* dummy); +extern void initial_cpu_info(void); +extern int iocapacity_limit_get(void *dummy); +extern void iocapacity_limit_set(void *dummy); +unsigned get_totem_num(void); +unsigned get_nr_skt(void); +unsigned long get_skt_offset(void); extern int prefetch_policy_num(void); extern cfg_t *prefetch_policy(int policy); diff --git a/prefetch_reg.c b/prefetch_reg.c index b86a161..07b3736 100644 --- a/prefetch_reg.c +++ b/prefetch_reg.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "prefetch_mod.h" #ifdef CONFIG_ARCH_HISI @@ -140,6 +141,82 @@ void read_unique_get(void *dummy) *value = (reg_value >> readUniqueOffset) & 0x1; return; } + +static unsigned long skt_offset = 0x200000000000ULL; +static unsigned nr_skt = 2, totem_num = 1; +void initial_cpu_info(void) +{ + u32 midr = read_cpuid_id(); + unsigned cvariant = 0x1, core_per_skt = 48; + int max_cpu = nr_cpu_ids; + cvariant = MIDR_VARIANT(midr); + if (cvariant == 0x1) + skt_offset = 0x200000000000ULL; + else + skt_offset = 0x400000000000ULL; + if (max_cpu == 24 || max_cpu == 32 || max_cpu == 8 || max_cpu == 12) { + nr_skt = 1; + totem_num = 1; + } else { + core_per_skt = (max_cpu % 48 == 0) ? 48 : 64; + nr_skt = max_cpu / core_per_skt; + totem_num = 2; + } +} + +/*To modify the L3 register. Traverse the socket and totem(skt_idx, die_idx)*/ +/* 0--unlimit 1--limit*/ +static const u32 iocapacityLimitOffset = 13; +int iocapacity_limit_get(void *dummy) +{ + unsigned long *addr = (unsigned long *)dummy; + u32 reg_value = readl_reg(*addr); + int value = (reg_value >> iocapacityLimitOffset) & 0x1; + return value; +} + +void iocapacity_limit_set(void *dummy) +{ + int *value = (int *)dummy; + unsigned int die_idx = 0, skt_idx = 0; + for (skt_idx = 0; skt_idx < nr_skt; skt_idx++) { + for (die_idx = 0; die_idx < 2; die_idx++) { + unsigned long base = skt_idx * skt_offset, base2 = 0; + unsigned val = 0; + if ((totem_num == 1) && (die_idx == 1)) + continue; + if (die_idx == 1) + base += TOTEM_OFFSET; + base2 = (unsigned long)ioremap(base + TB_L3T0_BASE, REG_RANGE); + if (!base2) + return; + val = readl_reg(base2 + L3T_DYNAMIC_CTRL); + if (*value == ENABLE) + val |= (1<