mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-09-22 01:07:57 +00:00
hv: add priority based scheduler
This patch adds a new priority based scheduler to support vCPU scheduling based on their pre-configured priorities. A vCPU can be running only if there is no higher priority vCPU running on the same pCPU. Tracked-On: #6571 Signed-off-by: Jie Deng <jie.deng@intel.com>
This commit is contained in:
@@ -244,6 +244,9 @@ endif
|
||||
ifeq ($(CONFIG_SCHED_BVT),y)
|
||||
HW_C_SRCS += common/sched_bvt.c
|
||||
endif
|
||||
ifeq ($(CONFIG_SCHED_PRIO),y)
|
||||
HW_C_SRCS += common/sched_prio.c
|
||||
endif
|
||||
HW_C_SRCS += hw/pci.c
|
||||
HW_C_SRCS += arch/x86/configs/vm_config.c
|
||||
HW_C_SRCS += boot/acpi_base.c
|
||||
|
@@ -963,6 +963,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);
|
||||
for (i = 0; i < VCPU_EVENT_NUM; i++) {
|
||||
init_event(&vcpu->events[i]);
|
||||
|
@@ -105,6 +105,7 @@ void run_idle_thread(void)
|
||||
idle->thread_entry = default_idle;
|
||||
idle->switch_out = NULL;
|
||||
idle->switch_in = NULL;
|
||||
idle->priority = PRIO_IDLE;
|
||||
|
||||
run_thread(idle);
|
||||
|
||||
|
98
hypervisor/common/sched_prio.c
Normal file
98
hypervisor/common/sched_prio.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <list.h>
|
||||
#include <asm/per_cpu.h>
|
||||
#include <schedule.h>
|
||||
|
||||
struct sched_prio_data {
|
||||
/* keep list as the first item */
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
static int sched_prio_init(struct sched_control *ctl)
|
||||
{
|
||||
struct sched_prio_control *prio_ctl = &per_cpu(sched_prio_ctl, ctl->pcpu_id);
|
||||
|
||||
ASSERT(ctl->pcpu_id == get_pcpu_id(), "Init scheduler on wrong CPU!");
|
||||
|
||||
ctl->priv = prio_ctl;
|
||||
INIT_LIST_HEAD(&prio_ctl->prio_queue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sched_prio_init_data(struct thread_object *obj)
|
||||
{
|
||||
struct sched_prio_data *data;
|
||||
|
||||
data = (struct sched_prio_data *)obj->data;
|
||||
INIT_LIST_HEAD(&data->list);
|
||||
}
|
||||
|
||||
static struct thread_object *sched_prio_pick_next(struct sched_control *ctl)
|
||||
{
|
||||
struct sched_prio_control *prio_ctl = (struct sched_prio_control *)ctl->priv;
|
||||
struct thread_object *next = NULL;
|
||||
|
||||
if (!list_empty(&prio_ctl->prio_queue)) {
|
||||
next = get_first_item(&prio_ctl->prio_queue, struct thread_object, data);
|
||||
} else {
|
||||
next = &get_cpu_var(idle);
|
||||
}
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
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 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) {
|
||||
list_add_node(&data->list, pos->prev, pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (list_empty(&data->list)) {
|
||||
list_add_tail(&data->list, &prio_ctl->prio_queue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void prio_queue_remove(struct thread_object *obj)
|
||||
{
|
||||
struct sched_prio_data *data = (struct sched_prio_data *)obj->data;
|
||||
|
||||
list_del_init(&data->list);
|
||||
}
|
||||
|
||||
static void sched_prio_sleep(struct thread_object *obj)
|
||||
{
|
||||
prio_queue_remove(obj);
|
||||
}
|
||||
|
||||
static void sched_prio_wake(struct thread_object *obj)
|
||||
{
|
||||
prio_queue_add(obj);
|
||||
}
|
||||
|
||||
struct acrn_scheduler sched_prio = {
|
||||
.name = "sched_prio",
|
||||
.init = sched_prio_init,
|
||||
.init_data = sched_prio_init_data,
|
||||
.pick_next = sched_prio_pick_next,
|
||||
.sleep = sched_prio_sleep,
|
||||
.wake = sched_prio_wake,
|
||||
};
|
@@ -77,6 +77,9 @@ void init_sched(uint16_t pcpu_id)
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_BVT
|
||||
ctl->scheduler = &sched_bvt;
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_PRIO
|
||||
ctl->scheduler = &sched_prio;
|
||||
#endif
|
||||
if (ctl->scheduler->init != NULL) {
|
||||
ctl->scheduler->init(ctl);
|
||||
|
@@ -41,6 +41,7 @@ struct per_cpu_region {
|
||||
struct sched_noop_control sched_noop_ctl;
|
||||
struct sched_iorr_control sched_iorr_ctl;
|
||||
struct sched_bvt_control sched_bvt_ctl;
|
||||
struct sched_prio_control sched_prio_ctl;
|
||||
struct thread_object idle;
|
||||
struct host_gdt gdt;
|
||||
struct tss_64 tss;
|
||||
|
@@ -169,6 +169,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 acrn_vm_mem_config memory; /* memory configuration of VM */
|
||||
struct epc_section epc; /* EPC memory configuration of VM */
|
||||
uint16_t pci_dev_num; /* indicate how many PCI devices in VM */
|
||||
|
@@ -28,6 +28,14 @@ enum sched_notify_mode {
|
||||
SCHED_NOTIFY_IPI
|
||||
};
|
||||
|
||||
/* Tools can configure a VM to use PRIO_LOW or PRIO_HIGH */
|
||||
enum thread_priority {
|
||||
PRIO_IDLE = 0,
|
||||
PRIO_LOW,
|
||||
PRIO_HIGH,
|
||||
PRIO_MAX
|
||||
};
|
||||
|
||||
struct thread_object;
|
||||
typedef void (*thread_entry_t)(struct thread_object *obj);
|
||||
typedef void (*switch_t)(struct thread_object *obj);
|
||||
@@ -44,6 +52,8 @@ struct thread_object {
|
||||
switch_t switch_out;
|
||||
switch_t switch_in;
|
||||
|
||||
int priority;
|
||||
|
||||
uint8_t data[THREAD_DATA_SIZE];
|
||||
};
|
||||
|
||||
@@ -97,6 +107,11 @@ struct sched_bvt_control {
|
||||
struct hv_timer tick_timer;
|
||||
};
|
||||
|
||||
extern struct acrn_scheduler sched_prio;
|
||||
struct sched_prio_control {
|
||||
struct list_head prio_queue;
|
||||
};
|
||||
|
||||
bool is_idle_thread(const struct thread_object *obj);
|
||||
uint16_t sched_get_pcpuid(const struct thread_object *obj);
|
||||
struct thread_object *sched_get_current(uint16_t pcpu_id);
|
||||
|
Reference in New Issue
Block a user