提交 e32a9072 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!9 新增iocapacity limit调节功能,以及README

Merge pull request !9 from liqiang2020/master
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
......@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/cpumask.h>
#include <linux/miscdevice.h>
#include <asm/io.h>
#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
......@@ -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);
......
......@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/cpumask.h>
#include <linux/miscdevice.h>
#include <asm/io.h>
#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<<iocapacityLimitOffset);
else if (*value == DISABLE)
val &= (~(1<<iocapacityLimitOffset));
writel_reg(val, base2 + L3T_DYNAMIC_CTRL);
iounmap((volatile void*)base2);
}
}
return;
}
unsigned long get_skt_offset(void)
{
return skt_offset;
}
unsigned get_nr_skt(void)
{
return nr_skt;
}
unsigned get_totem_num(void)
{
return totem_num;
}
#else
#define PREFETCH_POLICY_MAX 0
static cfg_t prefetch_cfg[] = {};
......@@ -163,6 +240,37 @@ void read_unique_get(void *dummy)
{
return;
}
void iocapacity_limit_set(void *dummy)
{
return;
}
void initial_cpu_information(void)
{
return;
}
int iocapacity_limit_get(void *dummy)
{
return -1;
}
unsigned long get_skt_offset(void)
{
return 0;
}
unsigned get_nr_skt(void)
{
return 0;
}
unsigned get_totem_num(void)
{
return 0;
}
#endif
int prefetch_policy_num(void)
......@@ -183,4 +291,4 @@ void reset_prefetch(void* dummy)
set_prefetch(pcfg);
}
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL");
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册