From: Chanwoo Choi Date: Mon, 28 Aug 2017 03:02:59 +0000 (+0900) Subject: pass: Add new fault_around_bytes feature for memory h/w device X-Git-Tag: submit/tizen/20170911.052326~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ed1a3f2059e2ca3b024a7c0e7ef4360bb57c835d;p=platform%2Fcore%2Fsystem%2Fpass.git pass: Add new fault_around_bytes feature for memory h/w device This patch adds the new 'fault_around_bytes'[1] feature of the memory h/w device. When the page fault happens, 'fault_around_bytes' is used. The 'fault_around_bytes' indicates the number of bytes to be mapped around the fault. If the value is low, it is able to increase the amount of empty memory on normal case. On the other hand, if the value is high, it is able to improve the performance by mapping the huge pages such as the app launching. It can be adjusted on the fly according to the user requirements. [1] https://lkml.org/lkml/2016/4/18/612 Change-Id: Ib33e071ac6f46dd746c00dd473bd48dfe48e1aea Signed-off-by: Chanwoo Choi --- diff --git a/src/pass/pass-hal.c b/src/pass/pass-hal.c index 6d1976d..ffcfbdb 100644 --- a/src/pass/pass-hal.c +++ b/src/pass/pass-hal.c @@ -521,6 +521,59 @@ int pass_get_tmu_policy(struct pass_resource *res, char *policy) return tmu->get_policy(res_thermal_name, policy); } +int pass_set_fault_around_bytes(struct pass_resource *res, + int fault_around_bytes) +{ + struct pass_resource_memory *memory; + char *res_name; + int res_type; + + if (!res) + return -EINVAL; + + res_name = res->cdata.res_name; + res_type = res->cdata.res_type; + + switch (res_type) { + case PASS_RESOURCE_MEMORY_ID: + memory = res->hal.memory; + break; + default: + return -EINVAL; + } + + if (!memory->set_fault_around_bytes) + return -EINVAL; + + return memory->set_fault_around_bytes(res_name, fault_around_bytes); +} + +int pass_get_fault_around_bytes(struct pass_resource *res) +{ + struct pass_resource_memory *memory; + char *res_name; + int res_type; + + if (!res) + return -EINVAL; + + res_name = res->cdata.res_name; + res_type = res->cdata.res_type; + + switch (res_type) { + case PASS_RESOURCE_MEMORY_ID: + memory = res->hal.memory; + break; + default: + return -EINVAL; + } + + if (!memory->get_fault_around_bytes) + return -EINVAL; + + return memory->get_fault_around_bytes(res_name); +} + int pass_set_pmqos_data(struct pass_resource *res, void *data) { struct pass_resource_nonstandard *nonstandard = NULL; @@ -602,6 +655,15 @@ static int pass_save_hotplug_initdata(struct pass_resource *res) return 0; } +static int pass_save_memory_initdata(struct pass_resource *res) +{ + struct pass_resource_initdata *initdata = &res->initdata; + + initdata->memory.fault_around_bytes = pass_get_fault_around_bytes(res); + + return 0; +} + static int pass_restore_dvfs_initdata(struct pass_resource *res) { struct pass_resource_initdata *initdata = &res->initdata; @@ -673,6 +735,21 @@ static int pass_restore_hotplug_initdata(struct pass_resource *res) return 0; } +static int pass_restore_memory_initdata(struct pass_resource *res) +{ + struct pass_resource_initdata *initdata = &res->initdata; + int fault_around_bytes = initdata->memory.fault_around_bytes; + int ret; + + if (fault_around_bytes >= 0) { + ret = pass_set_fault_around_bytes(res, fault_around_bytes); + if (ret < 0) + return ret; + } + + return 0; +} + int pass_save_initdata(struct pass_resource *res) { struct pass_conf_data *cdata; @@ -706,6 +783,12 @@ int pass_save_initdata(struct pass_resource *res) } break; case PASS_RESOURCE_MEMORY_ID: + ret = pass_save_memory_initdata(res); + if (ret < 0) { + _E("Failed to save memory initdata for '%s' resource", + res_name); + return ret; + } break; case PASS_RESOURCE_NONSTANDARD_ID: break; @@ -750,6 +833,12 @@ int pass_restore_initdata(struct pass_resource *res) } break; case PASS_RESOURCE_MEMORY_ID: + ret = pass_restore_memory_initdata(res); + if (ret < 0) { + _E("Failed to restore memory data for '%s' resource", + res_name); + return ret; + } break; case PASS_RESOURCE_NONSTANDARD_ID: break; diff --git a/src/pass/pass-hal.h b/src/pass/pass-hal.h index 3b45c84..c5c0da0 100644 --- a/src/pass/pass-hal.h +++ b/src/pass/pass-hal.h @@ -81,6 +81,14 @@ int pass_set_online_max_num(struct pass_resource *res, int num); */ int pass_get_cpu_stats(struct pass_policy *policy); +/*** + * Functions for Memory h/w resource + */ +/* Get and set the /sys/kernel/debug/fault_around_bytes */ +int pass_get_fault_around_bytes(struct pass_resource *res); +int pass_set_fault_around_bytes(struct pass_resource *res, + int fault_around_bytes); + /*** * Functions for Nonstandard H/W resources */ diff --git a/src/pass/pass-parser.c b/src/pass/pass-parser.c index 2fcbd47..6e8a072 100644 --- a/src/pass/pass-parser.c +++ b/src/pass/pass-parser.c @@ -126,6 +126,12 @@ static int pass_parse_level(struct parse_result *result, if (!result->section || !result->name || !result->value) return 0; + /* + * Properties for the following h/w resources: + * - PASS_RESOURCE_CPU_ID + * - PASS_RESOURCE_BUS_ID + * - PASS_RESOURCE_GPU_ID + */ if (MATCH(result->name, "limit_max_freq")) policy->pass_table[level].limit_max_freq = atoi(result->value); else if (MATCH(result->name, "limit_min_freq")) @@ -133,6 +139,10 @@ static int pass_parse_level(struct parse_result *result, else if (MATCH(result->name, "limit_min_cpu")) policy->pass_table[level].limit_min_cpu = atoi(result->value); + /* + * Properties for the following h/w resources: + * - PASS_RESOURCE_CPU_ID + */ else if (MATCH(result->name, "num_down_cond")) policy->pass_table[level].num_down_cond = atoi(result->value); else if (MATCH(result->name, "num_down_cond_freq")) @@ -177,6 +187,13 @@ static int pass_parse_level(struct parse_result *result, policy->pass_table[level].gov_timeout = gov_timeout; } + /* + * Properties for the following h/w resources: + * - PASS_RESOURCE_MEMORY_ID + */ + else if (MATCH(result->name, "fault_around_bytes")) + policy->pass_table[level].fault_around_bytes = atoi(result->value); + return 0; } @@ -635,6 +652,8 @@ static int pass_resource_config(struct parse_result *result, void *user_data) cur->initdata.hotplug.online_state = NULL; cur->initdata.hotplug.online_min_num = -1; cur->initdata.hotplug.online_max_num = -1; + + cur->initdata.memory.fault_around_bytes = -1; } } else { _E("cannot parse the number of resource\n"); diff --git a/src/pass/pass-rescon.c b/src/pass/pass-rescon.c index f025d75..f1938d2 100644 --- a/src/pass/pass-rescon.c +++ b/src/pass/pass-rescon.c @@ -79,6 +79,7 @@ int pass_rescon_set_level(struct pass_policy *policy, int new_level) int limit_max_freq; int limit_min_freq; int limit_min_cpu; + int fault_around_bytes; int ret; if (new_level > policy->max_level) @@ -90,12 +91,10 @@ int pass_rescon_set_level(struct pass_policy *policy, int new_level) if (new_level == curr_level) return 0; - /* - * Get the max/min frequency and the number of max online - * according to PASS level. - */ + /* Get the detailed resource value according to PASS level */ limit_max_freq = table[new_level].limit_max_freq; limit_min_freq = table[new_level].limit_min_freq; + fault_around_bytes = table[new_level].fault_around_bytes; policy->prev_level = curr_level; policy->curr_level = new_level; @@ -130,6 +129,16 @@ int pass_rescon_set_level(struct pass_policy *policy, int new_level) } } + /* Set fault_around_bytes for the memory h/w */ + if (fault_around_bytes) { + ret = pass_set_fault_around_bytes(res, fault_around_bytes); + if (ret < 0) { + _E("cannot set the fault_around_bytes of %s", + cdata->res_name); + return -EINVAL; + } + } + /* _I("[PASS %s] Level %4s '%d->%d' : 'max %d | min %d'Hz/'%d'Core\n", res->cdata.res_name, diff --git a/src/pass/pass.h b/src/pass/pass.h index f7ae375..060e94b 100644 --- a/src/pass/pass.h +++ b/src/pass/pass.h @@ -166,6 +166,9 @@ struct pass_level_condition { * - PASS_RESOURCE_CPU_ID * - PASS_RESOURCE_BUS_ID * - PASS_RESOURCE_GPU_ID + * @fault_around_bytes: the number of bytes to be mapped around the fault + * this property is used for the following resoures: + * - PASS_RESOURCE_MEMORY_ID * * @gov_timeout: the period of timer for each PASS's level * this property is used for the following resoures: @@ -186,6 +189,8 @@ struct pass_table { int limit_min_freq; int limit_min_cpu; + int fault_around_bytes; + /* Properties for the timer */ double gov_timeout; @@ -337,6 +342,8 @@ struct pass_conf_data { * - online_min_num: the initial minimum number of online resources * - online_max_num: the initial maximum number of online resources * @tmu: the initial value of tmu configuration + * @memory: the initial value of memory configuration + * - fault_around_bytes: the number of bytes to be mapped around the fault */ struct pass_resource_initdata { struct { @@ -355,6 +362,10 @@ struct pass_resource_initdata { struct { /* NOTE: tmu has no writable data yet. */ } tmu; + + struct { + int fault_around_bytes; + } memory; }; /*