anolis: ccs: add CPU utilization control functionality

ANBZ: #20511

The "scan" command of the cmn700 cache scan misc device file can take
up to several hundreds milliseconds.  The CPU utilization during
command run will be 100%.  Although use cond_sched() during "scan"
running to release CPU resource for other workloads, the high CPU
utilization may be undesirable.

So, in the patch, add "cpu_percent" parameter to "set_param" command
of the misc device file.  If "cpu_percent" is less than 100, use
schedule_timeout_interruptible() in "scan" command running to reduce the
CPU usage to the specified value.

Signed-off-by: Huang Ying <ying.huang@linux.alibaba.com>
Reviewed-by: Feng Tang <feng.tang@linux.alibaba.com>
Reviewed-by: Guixin Liu <kanie@linux.alibaba.com>
Link: https://gitee.com/anolis/cloud-kernel/pulls/5427
This commit is contained in:
Huang Ying 2025-03-24 15:17:31 +08:00 committed by 小龙
parent 2a431733a2
commit 5e8fab7191
1 changed files with 60 additions and 3 deletions

View File

@ -19,6 +19,7 @@
#include <linux/parser.h>
#include <linux/sched/clock.h>
#include <linux/memory.h>
#include <linux/sched/cputime.h>
#include <linux/arm-smccc.h>
@ -101,11 +102,17 @@ struct cmn_scan_param {
#define CCS_STEP_DEFAULT 16
#define CCS_STEP_MIN 1
#define CCS_STEP_MAX 128
#define CCS_CPU_PERCENT_DEFAULT 100
#define CCS_CPU_PERCENT_MAX 100
#define CCS_CPU_PERCENT_MIN 1
#define CCS_SLEEP_MIN_MS 10
struct ccs_param {
int step;
int sf_check_mesi;
int sf_mesi;
int cpu_percent;
int hnf_start;
int hnf_end;
int max_frequ;
@ -182,6 +189,11 @@ struct ccs {
struct ccs_cml_stats cml_stats;
};
struct ccs_time {
u64 wall_time;
u64 run_time;
};
static struct kmem_cache *ccs_anode_cachep __read_mostly;
static struct ccs_paddr_hnode *ccs_alloc_anode(void)
@ -707,6 +719,35 @@ static int ccs_flush_paddrs(struct ccs *ccs, int hnf, int round)
return 0;
}
static void ccs_get_time(struct ccs_time *ct)
{
u64 utime, stime;
ct->wall_time = sched_clock();
task_cputime_adjusted(current, &utime, &stime);
ct->run_time = utime + stime;
}
static void ccs_sleep(struct ccs_time *ct_start, int cpu_percent)
{
struct ccs_time ct_now;
u64 wtime, rtime, sleep;
if (cpu_percent >= 100) {
cond_resched();
return;
}
ccs_get_time(&ct_now);
wtime = ct_now.wall_time - ct_start->wall_time;
rtime = ct_now.run_time - ct_start->run_time;
sleep = rtime * 100 / cpu_percent - wtime;
if ((s64)sleep < CCS_SLEEP_MIN_MS * NSEC_PER_MSEC) {
cond_resched();
return;
}
schedule_timeout_interruptible(nsecs_to_jiffies(sleep));
}
static int ccs_scan_hnf_round(struct ccs *ccs, int hnf, int round)
{
int rc;
@ -723,7 +764,7 @@ static int ccs_scan_hnf_round(struct ccs *ccs, int hnf, int round)
return 0;
}
static int ccs_scan_hnf(struct ccs *ccs, int hnf)
static int ccs_scan_hnf(struct ccs *ccs, int hnf, struct ccs_time *ct_start)
{
int round;
int rc;
@ -732,7 +773,7 @@ static int ccs_scan_hnf(struct ccs *ccs, int hnf)
rc = ccs_scan_hnf_round(ccs, hnf, round);
if (rc)
return rc;
cond_resched();
ccs_sleep(ct_start, ccs->param.cpu_percent);
}
return 0;
@ -763,14 +804,16 @@ static void ccs_cumulate_stats(struct ccs *ccs)
static int ccs_scan(struct ccs *ccs)
{
struct ccs_param *param = &ccs->param;
struct ccs_time ct_start;
int rc = 0, hnf;
ccs_get_time(&ct_start);
rc = ccs_addrs_setup(&ccs->addrs, param);
if (rc)
goto out;
memset(&ccs->stats, 0, sizeof(ccs->stats));
for (hnf = param->hnf_start; hnf <= param->hnf_end; hnf++) {
rc = ccs_scan_hnf(ccs, hnf);
rc = ccs_scan_hnf(ccs, hnf, &ct_start);
if (rc)
goto out;
}
@ -835,6 +878,7 @@ static void ccs_init_param(struct ccs_param *param)
.step = CCS_STEP_DEFAULT,
.sf_check_mesi = 1,
.sf_mesi = CSP_MESI_S,
.cpu_percent = CCS_CPU_PERCENT_DEFAULT,
});
param->hnf_start = ccs_die_id() * CSP_MAX_NR_HNF_DIE;
@ -1027,6 +1071,7 @@ enum {
CCS_PARAM_SF_CHECK_MESI,
CCS_PARAM_HNF,
CCS_PARAM_MAX_FREQU,
CCS_PARAM_CPU_PERCENT,
CCS_PARAM_NULL,
};
@ -1036,6 +1081,7 @@ static const match_table_t ccs_param_tokens = {
{ CCS_PARAM_SF_CHECK_MESI, "sf_check_mesi=%d" },
{ CCS_PARAM_HNF, "hnf=%d-%d" },
{ CCS_PARAM_MAX_FREQU, "max_frequ=%d" },
{ CCS_PARAM_CPU_PERCENT, "cpu_percent=%d" },
{ CCS_PARAM_NULL, NULL },
};
@ -1084,6 +1130,17 @@ static int ccs_parse_param(char *buf, struct ccs_param *param)
goto out;
}
break;
case CCS_PARAM_CPU_PERCENT:
if (match_int(&args[0], &param->cpu_percent)) {
rc = -EINVAL;
goto out;
}
if (param->cpu_percent > CCS_CPU_PERCENT_MAX ||
param->cpu_percent < CCS_CPU_PERCENT_MIN) {
rc = -EINVAL;
goto out;
}
break;
case CCS_PARAM_HNF:
if (match_int(&args[0], &param->hnf_start)) {
rc = -EINVAL;