Skip to content

Commit

Permalink
KVM: arm64: Declutter host PSCI 0.1 handling
Browse files Browse the repository at this point in the history
Although there is nothing wrong with the current host PSCI relay
implementation, we can clean it up and remove some of the helpers
that do not improve the overall readability of the legacy PSCI 0.1
handling.

Opportunity is taken to turn the bitmap into a set of booleans,
and creative use of preprocessor macros make init and check
more concise/readable.

Suggested-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
  • Loading branch information
Marc Zyngier committed Dec 22, 2020
1 parent 860a4c3 commit 767c973
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 70 deletions.
11 changes: 4 additions & 7 deletions arch/arm64/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,20 +241,17 @@ struct kvm_host_data {
struct kvm_pmu_events pmu_events;
};

#define KVM_HOST_PSCI_0_1_CPU_SUSPEND BIT(0)
#define KVM_HOST_PSCI_0_1_CPU_ON BIT(1)
#define KVM_HOST_PSCI_0_1_CPU_OFF BIT(2)
#define KVM_HOST_PSCI_0_1_MIGRATE BIT(3)

struct kvm_host_psci_config {
/* PSCI version used by host. */
u32 version;

/* Function IDs used by host if version is v0.1. */
struct psci_0_1_function_ids function_ids_0_1;

/* Bitmask of functions enabled for v0.1, bits KVM_HOST_PSCI_0_1_*. */
unsigned int enabled_functions_0_1;
bool psci_0_1_cpu_suspend_implemented;
bool psci_0_1_cpu_on_implemented;
bool psci_0_1_cpu_off_implemented;
bool psci_0_1_migrate_implemented;
};

extern struct kvm_host_psci_config kvm_nvhe_sym(kvm_host_psci_config);
Expand Down
12 changes: 7 additions & 5 deletions arch/arm64/kvm/arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1603,6 +1603,9 @@ static void init_cpu_logical_map(void)
hyp_cpu_logical_map[cpu] = cpu_logical_map(cpu);
}

#define init_psci_0_1_impl_state(config, what) \
config.psci_0_1_ ## what ## _implemented = psci_ops.what

static bool init_psci_relay(void)
{
/*
Expand All @@ -1618,11 +1621,10 @@ static bool init_psci_relay(void)

if (kvm_host_psci_config.version == PSCI_VERSION(0, 1)) {
kvm_host_psci_config.function_ids_0_1 = get_psci_0_1_function_ids();
kvm_host_psci_config.enabled_functions_0_1 =
(psci_ops.cpu_suspend ? KVM_HOST_PSCI_0_1_CPU_SUSPEND : 0) |
(psci_ops.cpu_off ? KVM_HOST_PSCI_0_1_CPU_OFF : 0) |
(psci_ops.cpu_on ? KVM_HOST_PSCI_0_1_CPU_ON : 0) |
(psci_ops.migrate ? KVM_HOST_PSCI_0_1_MIGRATE : 0);
init_psci_0_1_impl_state(kvm_host_psci_config, cpu_suspend);
init_psci_0_1_impl_state(kvm_host_psci_config, cpu_on);
init_psci_0_1_impl_state(kvm_host_psci_config, cpu_off);
init_psci_0_1_impl_state(kvm_host_psci_config, migrate);
}
return true;
}
Expand Down
77 changes: 19 additions & 58 deletions arch/arm64/kvm/hyp/nvhe/psci-relay.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,48 +43,16 @@ struct psci_boot_args {
static DEFINE_PER_CPU(struct psci_boot_args, cpu_on_args) = PSCI_BOOT_ARGS_INIT;
static DEFINE_PER_CPU(struct psci_boot_args, suspend_args) = PSCI_BOOT_ARGS_INIT;

static u64 get_psci_func_id(struct kvm_cpu_context *host_ctxt)
{
DECLARE_REG(u64, func_id, host_ctxt, 0);

return func_id;
}

static inline bool is_psci_0_1_function_enabled(unsigned int fn_bit)
{
return kvm_host_psci_config.enabled_functions_0_1 & fn_bit;
}

static inline bool is_psci_0_1_cpu_suspend(u64 func_id)
{
return is_psci_0_1_function_enabled(KVM_HOST_PSCI_0_1_CPU_SUSPEND) &&
(func_id == kvm_host_psci_config.function_ids_0_1.cpu_suspend);
}

static inline bool is_psci_0_1_cpu_on(u64 func_id)
{
return is_psci_0_1_function_enabled(KVM_HOST_PSCI_0_1_CPU_ON) &&
(func_id == kvm_host_psci_config.function_ids_0_1.cpu_on);
}

static inline bool is_psci_0_1_cpu_off(u64 func_id)
{
return is_psci_0_1_function_enabled(KVM_HOST_PSCI_0_1_CPU_OFF) &&
(func_id == kvm_host_psci_config.function_ids_0_1.cpu_off);
}

static inline bool is_psci_0_1_migrate(u64 func_id)
{
return is_psci_0_1_function_enabled(KVM_HOST_PSCI_0_1_MIGRATE) &&
(func_id == kvm_host_psci_config.function_ids_0_1.migrate);
}
#define is_psci_0_1(what, func_id) \
(kvm_host_psci_config.psci_0_1_ ## what ## _implemented && \
(func_id) == kvm_host_psci_config.function_ids_0_1.what)

static bool is_psci_0_1_call(u64 func_id)
{
return is_psci_0_1_cpu_suspend(func_id) ||
is_psci_0_1_cpu_on(func_id) ||
is_psci_0_1_cpu_off(func_id) ||
is_psci_0_1_migrate(func_id);
return (is_psci_0_1(cpu_suspend, func_id) ||
is_psci_0_1(cpu_on, func_id) ||
is_psci_0_1(cpu_off, func_id) ||
is_psci_0_1(migrate, func_id));
}

static bool is_psci_0_2_call(u64 func_id)
Expand All @@ -94,16 +62,6 @@ static bool is_psci_0_2_call(u64 func_id)
(PSCI_0_2_FN64(0) <= func_id && func_id <= PSCI_0_2_FN64(31));
}

static bool is_psci_call(u64 func_id)
{
switch (kvm_host_psci_config.version) {
case PSCI_VERSION(0, 1):
return is_psci_0_1_call(func_id);
default:
return is_psci_0_2_call(func_id);
}
}

static unsigned long psci_call(unsigned long fn, unsigned long arg0,
unsigned long arg1, unsigned long arg2)
{
Expand Down Expand Up @@ -273,14 +231,14 @@ asmlinkage void __noreturn kvm_host_psci_cpu_entry(bool is_cpu_on)

static unsigned long psci_0_1_handler(u64 func_id, struct kvm_cpu_context *host_ctxt)
{
if (is_psci_0_1_cpu_off(func_id) || is_psci_0_1_migrate(func_id))
if (is_psci_0_1(cpu_off, func_id) || is_psci_0_1(migrate, func_id))
return psci_forward(host_ctxt);
else if (is_psci_0_1_cpu_on(func_id))
if (is_psci_0_1(cpu_on, func_id))
return psci_cpu_on(func_id, host_ctxt);
else if (is_psci_0_1_cpu_suspend(func_id))
if (is_psci_0_1(cpu_suspend, func_id))
return psci_cpu_suspend(func_id, host_ctxt);
else
return PSCI_RET_NOT_SUPPORTED;

return PSCI_RET_NOT_SUPPORTED;
}

static unsigned long psci_0_2_handler(u64 func_id, struct kvm_cpu_context *host_ctxt)
Expand Down Expand Up @@ -322,20 +280,23 @@ static unsigned long psci_1_0_handler(u64 func_id, struct kvm_cpu_context *host_

bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt)
{
u64 func_id = get_psci_func_id(host_ctxt);
DECLARE_REG(u64, func_id, host_ctxt, 0);
unsigned long ret;

if (!is_psci_call(func_id))
return false;

switch (kvm_host_psci_config.version) {
case PSCI_VERSION(0, 1):
if (!is_psci_0_1_call(func_id))
return false;
ret = psci_0_1_handler(func_id, host_ctxt);
break;
case PSCI_VERSION(0, 2):
if (!is_psci_0_2_call(func_id))
return false;
ret = psci_0_2_handler(func_id, host_ctxt);
break;
default:
if (!is_psci_0_2_call(func_id))
return false;
ret = psci_1_0_handler(func_id, host_ctxt);
break;
}
Expand Down

0 comments on commit 767c973

Please sign in to comment.