Skip to content
Permalink
Browse files
powerpc/book3s_hv: Add new idle-hint attribute in VPA region
In lppaca region, add a new attribute idle_hint which can allow guest scheduler for
better cpu selection. Hypervisor can update idle_hint attribute based on
the prediction that if vCPU needs to be scheduled then can it be scheduled
instantly or not.

Signed-off-by: Parth Shah <parth@linux.ibm.com>
  • Loading branch information
Parth Shah authored and intel-lab-lkp committed Jul 13, 2021
1 parent 019b3fd commit 09b5719b7516bcf50add81162e131d53ec10aeca
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 1 deletion.
@@ -0,0 +1,28 @@
#ifndef _ASM_POWERPC_IDLEHINT_H
#define _ASM_POWERPC_IDLEHINT_H

#include <linux/kvm_host.h>

extern void kvmppc_idle_hint_set(struct kvm_vcpu *vcpu, int idle_hint);

extern int idle_hint_is_active;

extern void set_idle_hint(int cpu, int value);

static inline int prev_cpu_of_kvm(struct kvm_vcpu *vcpu)
{
struct pid *pid;
struct task_struct *task = NULL;

rcu_read_lock();
pid = rcu_dereference(vcpu->pid);
if (pid)
task = get_pid_task(pid, PIDTYPE_PID);
rcu_read_unlock();

if (!task)
return -1;

return task_cpu(task);
}
#endif
@@ -111,7 +111,8 @@ struct lppaca {
__be32 page_ins; /* CMO Hint - # page ins by OS */
u8 reserved11[148];
volatile __be64 dtl_idx; /* Dispatch Trace Log head index */
u8 reserved12[96];
volatile __be32 idle_hint; /* Can vCPU be scheduled instantly? */
u8 reserved12[92];
} ____cacheline_aligned;

#define lppaca_of(cpu) (*paca_ptrs[cpu]->lppaca_ptr)
@@ -7,6 +7,8 @@
#ifndef __POWERPC_KVM_BOOK3S_H__
#define __POWERPC_KVM_BOOK3S_H__

#include <asm/idle_hint.h>

extern void kvmppc_core_flush_memslot_hv(struct kvm *kvm,
struct kvm_memory_slot *memslot);
extern bool kvm_unmap_gfn_range_hv(struct kvm *kvm, struct kvm_gfn_range *range);
@@ -441,6 +441,7 @@ static void init_vpa(struct kvm_vcpu *vcpu, struct lppaca *vpa)
{
vpa->__old_status |= LPPACA_OLD_SHARED_PROC;
vpa->yield_count = cpu_to_be32(1);
vpa->idle_hint = cpu_to_be32(0);
}

static int set_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *v,
@@ -910,6 +911,17 @@ static int kvm_arch_vcpu_yield_to(struct kvm_vcpu *target)
return kvm_vcpu_yield_to(target);
}

void kvmppc_idle_hint_set(struct kvm_vcpu *vcpu, int idle_hint)
{
struct lppaca *lppaca;

if (!vcpu) return;

lppaca = (struct lppaca *)vcpu->arch.vpa.pinned_addr;
if (lppaca)
lppaca->idle_hint = cpu_to_be32(idle_hint);
}

static int kvmppc_get_yield_count(struct kvm_vcpu *vcpu)
{
int yield_count = 0;
@@ -3056,6 +3068,28 @@ static int on_primary_thread(void)
return 1;
}

void set_idle_hint_for_kvm(struct kvm *kvm, int cpu, int value)
{
int i;
struct kvm_vcpu *vcpu;

kvm_for_each_vcpu(i, vcpu, kvm) {
if (cpu == prev_cpu_of_kvm(vcpu)) {
kvmppc_idle_hint_set(vcpu, value);
}
}
}

void set_idle_hint(int cpu, int value)
{
struct kvm *kvm;
struct kvm *tmp;

list_for_each_entry_safe(kvm, tmp, &vm_list, vm_list) {
set_idle_hint_for_kvm(kvm, cpu, value);
}
}

/*
* A list of virtual cores for each physical CPU.
* These are vcores that could run but their runner VCPU tasks are

0 comments on commit 09b5719

Please sign in to comment.