1
0
mirror of https://github.com/projectacrn/acrn-hypervisor.git synced 2025-05-02 21:46:58 +00:00

hv: sched: Add sched_params struct for thread parameters

Abstract out schedulers config data for vCPU threads and other hypervisor
threads to sched_params structure. And it's used to initialize per
thread scheduler private data. The sched_params for vCPU threads come
from vm_config generated by config tools while other hypervisor threads
need give them explicitly.

Tracked-On: 
Signed-off-by: Qiang Zhang <qiang4.zhang@intel.com>
This commit is contained in:
Qiang Zhang 2023-09-06 13:39:29 +08:00 committed by acrnsi-robot
parent c000a3f70b
commit 6a1d91c740
12 changed files with 68 additions and 27 deletions
hypervisor
misc/config_tools
data/generic_board/generic_code
xforms

View File

@ -986,8 +986,7 @@ int32_t prepare_vcpu(struct acrn_vm *vm, uint16_t pcpu_id)
vcpu->thread_obj.host_sp = build_stack_frame(vcpu);
vcpu->thread_obj.switch_out = context_switch_out;
vcpu->thread_obj.switch_in = context_switch_in;
vcpu->thread_obj.priority = get_vm_config(vm->vm_id)->vm_prio;
init_thread_data(&vcpu->thread_obj);
init_thread_data(&vcpu->thread_obj, &get_vm_config(vm->vm_id)->sched_params);
for (i = 0; i < VCPU_EVENT_NUM; i++) {
init_event(&vcpu->events[i]);
}

View File

@ -95,6 +95,7 @@ void run_idle_thread(void)
{
uint16_t pcpu_id = get_pcpu_id();
struct thread_object *idle = &per_cpu(idle, pcpu_id);
struct sched_params idle_params = {0};
char idle_name[16];
snprintf(idle_name, 16U, "idle%hu", pcpu_id);
@ -103,7 +104,8 @@ void run_idle_thread(void)
idle->thread_entry = default_idle;
idle->switch_out = NULL;
idle->switch_in = NULL;
idle->priority = PRIO_IDLE;
idle_params.prio = PRIO_IDLE;
init_thread_data(idle, &idle_params);
run_thread(idle);

View File

@ -168,7 +168,7 @@ static void sched_bvt_deinit(struct sched_control *ctl)
del_timer(&bvt_ctl->tick_timer);
}
static void sched_bvt_init_data(struct thread_object *obj)
static void sched_bvt_init_data(struct thread_object *obj, __unused struct sched_params * params)
{
struct sched_bvt_data *data;

View File

@ -132,7 +132,7 @@ void sched_iorr_deinit(struct sched_control *ctl)
del_timer(&iorr_ctl->tick_timer);
}
void sched_iorr_init_data(struct thread_object *obj)
void sched_iorr_init_data(struct thread_object *obj, __unused struct sched_params * params)
{
struct sched_iorr_data *data;

View File

@ -11,6 +11,7 @@
struct sched_prio_data {
/* keep list as the first item */
struct list_head list;
int priority;
};
static int sched_prio_init(struct sched_control *ctl)
@ -25,12 +26,13 @@ static int sched_prio_init(struct sched_control *ctl)
return 0;
}
static void sched_prio_init_data(struct thread_object *obj)
static void sched_prio_init_data(struct thread_object *obj, struct sched_params *params)
{
struct sched_prio_data *data;
data = (struct sched_prio_data *)obj->data;
INIT_LIST_HEAD(&data->list);
data->priority = params->priority;
}
static struct thread_object *sched_prio_pick_next(struct sched_control *ctl)
@ -52,15 +54,15 @@ static void prio_queue_add(struct thread_object *obj)
struct sched_prio_control *prio_ctl =
(struct sched_prio_control *)obj->sched_ctl->priv;
struct sched_prio_data *data = (struct sched_prio_data *)obj->data;
struct thread_object *iter_obj;
struct sched_prio_data *iter_data;
struct list_head *pos;
if (list_empty(&prio_ctl->prio_queue)) {
list_add(&data->list, &prio_ctl->prio_queue);
} else {
list_for_each(pos, &prio_ctl->prio_queue) {
iter_obj = container_of(pos, struct thread_object, data);
if (iter_obj->priority < obj->priority) {
iter_data = container_of(pos, struct sched_prio_data, list);
if (iter_data->priority < data->priority) {
list_add_node(&data->list, pos->prev, pos);
break;
}

View File

@ -98,14 +98,14 @@ void deinit_sched(uint16_t pcpu_id)
}
}
void init_thread_data(struct thread_object *obj)
void init_thread_data(struct thread_object *obj, struct sched_params *params)
{
struct acrn_scheduler *scheduler = get_scheduler(obj->pcpu_id);
uint64_t rflag;
obtain_schedule_lock(obj->pcpu_id, &rflag);
if (scheduler->init_data != NULL) {
scheduler->init_data(obj);
scheduler->init_data(obj, params);
}
/* initial as BLOCKED status, so we can wake it up to run */
set_thread_status(obj, THREAD_STS_BLOCKED);
@ -241,7 +241,6 @@ void run_thread(struct thread_object *obj)
{
uint64_t rflag;
init_thread_data(obj);
obtain_schedule_lock(obj->pcpu_id, &rflag);
get_cpu_var(sched_ctl).curr_obj = obj;
set_thread_status(obj, THREAD_STS_RUNNING);

View File

@ -15,6 +15,7 @@
#include <vm_configurations.h>
#include <asm/sgx.h>
#include <acrn_hv_defs.h>
#include <schedule.h>
#define AFFINITY_CPU(n) (1UL << (n))
#define MAX_VCPUS_PER_VM MAX_PCPU_NUM
@ -170,7 +171,7 @@ struct acrn_vm_config {
* GUEST_FLAG_LAPIC_PASSTHROUGH
* We could add more guest flags in future;
*/
uint32_t vm_prio; /* The priority for VM vCPU scheduling */
struct sched_params sched_params; /* Scheduler params for vCPUs of this VM */
uint16_t companion_vm_id; /* The companion VM id for this VM */
struct acrn_vm_mem_config memory; /* memory configuration of VM */
struct epc_section epc; /* EPC memory configuration of VM */

View File

@ -34,6 +34,16 @@ enum thread_priority {
PRIO_MAX
};
/*
* For now, we just have several parameters for all the schedulers. So we
* put them together here for simplicity. TODO When this structure grows big
* enough, we need to replace it with a union of parameters of different
* schedulers.
*/
struct sched_params {
uint32_t prio; /* The priority of a thread */
};
struct thread_object;
typedef void (*thread_entry_t)(struct thread_object *obj);
typedef void (*switch_t)(struct thread_object *obj);
@ -49,8 +59,6 @@ struct thread_object {
switch_t switch_out;
switch_t switch_in;
int priority;
uint8_t data[THREAD_DATA_SIZE];
};
@ -70,7 +78,7 @@ struct acrn_scheduler {
/* init scheduler */
int32_t (*init)(struct sched_control *ctl);
/* init private data of scheduler */
void (*init_data)(struct thread_object *obj);
void (*init_data)(struct thread_object *obj, struct sched_params *params);
/* pick the next thread object */
struct thread_object* (*pick_next)(struct sched_control *ctl);
/* put thread object into sleep */
@ -120,7 +128,7 @@ void deinit_sched(uint16_t pcpu_id);
void obtain_schedule_lock(uint16_t pcpu_id, uint64_t *rflag);
void release_schedule_lock(uint16_t pcpu_id, uint64_t rflag);
void init_thread_data(struct thread_object *obj);
void init_thread_data(struct thread_object *obj, struct sched_params *params);
void deinit_thread_data(struct thread_object *obj);
void make_reschedule_request(uint16_t pcpu_id);

View File

@ -22,7 +22,10 @@ struct acrn_vm_config
/* Static configured VM0 */
CONFIG_PRE_STD_VM,
.name = "SAFETY_VM0",
.vm_prio = PRIO_LOW,
.sched_params =
{
.prio = PRIO_LOW,
},
.companion_vm_id = 65535U,
.guest_flags = (GUEST_FLAG_STATIC_VM),
.cpu_affinity = VM0_CONFIG_CPU_AFFINITY,
@ -106,7 +109,10 @@ struct acrn_vm_config
CONFIG_SERVICE_VM,
.name = "ACRN_Service_VM",
/* Allow Service VM to reboot the system since it is the highest priority VM. */
.vm_prio = PRIO_LOW,
.sched_params =
{
.prio = PRIO_LOW,
},
.companion_vm_id = 65535U,
.guest_flags = (GUEST_FLAG_STATIC_VM),
.cpu_affinity = SERVICE_VM_CONFIG_CPU_AFFINITY,
@ -163,7 +169,10 @@ struct acrn_vm_config
/* Static configured VM2 */
CONFIG_POST_STD_VM,
.name = "POST_STD_VM1",
.vm_prio = PRIO_LOW,
.sched_params =
{
.prio = PRIO_LOW,
},
.companion_vm_id = 65535U,
.guest_flags = (GUEST_FLAG_STATIC_VM),
.cpu_affinity = VM2_CONFIG_CPU_AFFINITY,
@ -186,7 +195,10 @@ struct acrn_vm_config
/* Static configured VM3 */
CONFIG_POST_STD_VM,
.name = "POST_STD_VM2",
.vm_prio = PRIO_LOW,
.sched_params =
{
.prio = PRIO_LOW,
},
.companion_vm_id = 65535U,
.guest_flags = (GUEST_FLAG_STATIC_VM),
.cpu_affinity = VM3_CONFIG_CPU_AFFINITY,

View File

@ -25,7 +25,10 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {
/* Static configured VM0 */
CONFIG_PRE_STD_VM,
.name = "PRE_STD_VM0",
.vm_prio = PRIO_LOW,
.sched_params =
{
.prio = PRIO_LOW,
},
.companion_vm_id = 65535U,
.guest_flags = (GUEST_FLAG_STATIC_VM),
.cpu_affinity = VM0_CONFIG_CPU_AFFINITY,
@ -102,7 +105,10 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {
/* Static configured VM1 */
CONFIG_PRE_STD_VM,
.name = "PRE_STD_VM1",
.vm_prio = PRIO_LOW,
.sched_params =
{
.prio = PRIO_LOW,
},
.companion_vm_id = 65535U,
.guest_flags = (GUEST_FLAG_STATIC_VM),
.cpu_affinity = VM1_CONFIG_CPU_AFFINITY,

View File

@ -17,7 +17,10 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {
CONFIG_SERVICE_VM,
.name = "ACRN_Service_VM",
/* Allow Service VM to reboot the system since it is the highest priority VM. */
.vm_prio = PRIO_LOW,
.sched_params =
{
.prio = PRIO_LOW,
},
.companion_vm_id = 65535U,
.guest_flags = (GUEST_FLAG_STATIC_VM),
.cpu_affinity = SERVICE_VM_CONFIG_CPU_AFFINITY,
@ -74,7 +77,10 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {
/* Static configured VM1 */
CONFIG_POST_STD_VM,
.name = "POST_STD_VM1",
.vm_prio = PRIO_LOW,
.sched_params =
{
.prio = PRIO_LOW,
},
.companion_vm_id = 65535U,
.guest_flags = (GUEST_FLAG_STATIC_VM),
.cpu_affinity = VM1_CONFIG_CPU_AFFINITY,
@ -105,7 +111,10 @@ struct acrn_vm_config vm_configs[CONFIG_MAX_VM_NUM] = {
/* Static configured VM2 */
CONFIG_POST_RT_VM,
.name = "POST_RT_VM1",
.vm_prio = PRIO_LOW,
.sched_params =
{
.prio = PRIO_LOW,
},
.companion_vm_id = 65535U,
.guest_flags = (GUEST_FLAG_LAPIC_PASSTHROUGH | GUEST_FLAG_RT | GUEST_FLAG_STATIC_VM),
.cpu_affinity = VM2_CONFIG_CPU_AFFINITY,

View File

@ -110,7 +110,10 @@
<xsl:value-of select="acrn:comment('Allow Service VM to reboot the system since it is the highest priority VM.')" />
<xsl:value-of select="$newline" />
</xsl:if>
<xsl:value-of select="acrn:initializer('vm_prio', priority)" />
<xsl:value-of select="acrn:initializer('sched_params', '{', true())" />
<xsl:value-of select="acrn:initializer('prio', priority)" />
<xsl:text>},</xsl:text>
<xsl:value-of select="$newline" />
<xsl:value-of select="acrn:initializer('companion_vm_id', concat(companion_vmid, 'U'))" />
<xsl:call-template name="guest_flags" />