Skip to content

Commit 6df80f4

Browse files
joaopeixoto13josecm
authored andcommitted
feat(core/cpu): decouple CPU standby from CPU power down
Decoupled the CPU idle state (now called standby) from the CPU power down state. This change allows future implementations requiring CPU standby — where the core may be needed shortly after an event — to avoid transitioning to a deeper power down state. This commit also removes the `PSCI_WAKEUP_IDLE` (or standby in this case) from `psci_wake_handlers` since the standby mode does not use the `entry_point_address` and `context_id` fields and, therefore, does not require a custom wake-up handler (e.g., psci_boot_entry). Signed-off-by: João Peixoto <[email protected]>
1 parent c8888a3 commit 6df80f4

File tree

16 files changed

+101
-63
lines changed

16 files changed

+101
-63
lines changed

src/arch/armv8/armv8-a/cpu.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,17 @@ void cpu_arch_profile_init(cpuid_t cpuid, paddr_t load_addr)
2727
}
2828
}
2929

30-
void cpu_arch_profile_idle()
30+
void cpu_arch_profile_standby()
3131
{
32-
int64_t err = psci_power_down(PSCI_WAKEUP_IDLE);
32+
int32_t err = psci_standby();
33+
if (err) {
34+
ERROR("PSCI cpu%d standby failed with error %ld", cpu()->id, err);
35+
}
36+
}
37+
38+
void cpu_arch_profile_powerdown()
39+
{
40+
int32_t err = psci_power_down();
3341
if (err) {
3442
ERROR("PSCI cpu%d power down failed with error %ld", cpu()->id, err);
3543
}

src/arch/armv8/armv8-a/psci.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,11 @@ static void psci_wake_from_powerdown(void)
5656
vcpu_run(cpu()->vcpu);
5757
}
5858

59-
static void psci_wake_from_idle(void)
60-
{
61-
cpu_idle_wakeup();
62-
}
63-
6459
void psci_wake_from_off(void);
6560

6661
void (*psci_wake_handlers[PSCI_WAKEUP_NUM])(void) = {
6762
[PSCI_WAKEUP_CPU_OFF] = psci_wake_from_off,
6863
[PSCI_WAKEUP_POWERDOWN] = psci_wake_from_powerdown,
69-
[PSCI_WAKEUP_IDLE] = psci_wake_from_idle,
7064
};
7165

7266
void psci_wake(uint32_t handler_id)
@@ -98,7 +92,7 @@ int32_t psci_standby()
9892
return psci_cpu_suspend(pwr_state_aux, 0, 0);
9993
}
10094

101-
int32_t psci_power_down(enum wakeup_reason reason)
95+
int32_t psci_power_down()
10296
{
10397
/* We've observed that some platforms behave unexpectedly when performing
10498
* power down. In these cases, after powerdown, the CPU cores are not awaken
@@ -111,7 +105,7 @@ int32_t psci_power_down(enum wakeup_reason reason)
111105

112106
uint32_t pwr_state_aux = PSCI_POWER_STATE_LVL_0 | PSCI_STATE_TYPE_POWERDOWN;
113107

114-
psci_save_state(reason);
108+
psci_save_state(PSCI_WAKEUP_POWERDOWN);
115109
paddr_t cntxt_paddr;
116110
paddr_t psci_wakeup_addr;
117111
mem_translate(&cpu()->as, (vaddr_t)&cpu()->arch.profile.psci_off_state, &cntxt_paddr);

src/arch/armv8/armv8-r/cpu.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ void cpu_arch_profile_init(cpuid_t cpuid, paddr_t load_addr)
1212
UNUSED_ARG(load_addr);
1313
}
1414

15-
void cpu_arch_profile_idle()
15+
void cpu_arch_profile_standby()
16+
{
17+
__asm__ volatile("wfi");
18+
}
19+
20+
void cpu_arch_profile_powerdown()
1621
{
1722
__asm__ volatile("wfi");
1823
}

src/arch/armv8/armv8-r/psci.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ int32_t psci_standby()
1818
return PSCI_E_SUCCESS;
1919
}
2020

21-
int32_t psci_power_down(enum wakeup_reason reason)
21+
int32_t psci_power_down()
2222
{
23-
UNUSED_ARG(reason);
24-
2523
return psci_standby();
2624
}

src/arch/armv8/cpu.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,32 @@ unsigned long cpu_id_to_mpidr(cpuid_t id)
2222
return platform_arch_cpuid_to_mpidr(&platform, id);
2323
}
2424

25-
void cpu_arch_idle()
25+
void cpu_arch_standby()
2626
{
27-
cpu_arch_profile_idle();
27+
cpu_arch_profile_standby();
2828

2929
/*
3030
* In case the profile implementation does not jump to a predefined wake-up point and just
31-
* returns from the profile, manually rewind stack and jump to idle wake up. Therefore, we
31+
* returns from the profile, manually rewind stack and jump to standby wake up. Therefore, we
3232
* should not return after this point.
3333
*/
3434
__asm__ volatile("mov sp, %0\n\r"
35-
"b cpu_idle_wakeup\n\r" ::"r"(&cpu()->stack[STACK_SIZE]));
35+
"b cpu_standby_wakeup\n\r" ::"r"(&cpu()->stack[STACK_SIZE]));
3636

37-
ERROR("returned from idle wake up");
37+
ERROR("returned from standby wake up");
38+
}
39+
40+
void cpu_arch_powerdown()
41+
{
42+
cpu_arch_profile_powerdown();
43+
44+
/*
45+
* In case the profile implementation does not jump to a predefined wake-up point and just
46+
* returns from the profile, manually rewind stack and jump to powerdown wake up. Therefore, we
47+
* should not return after this point.
48+
*/
49+
__asm__ volatile("mov sp, %0\n\r"
50+
"b cpu_powerdown_wakeup\n\r" ::"r"(&cpu()->stack[STACK_SIZE]));
51+
52+
ERROR("returned from powerdown wake up");
3853
}

src/arch/armv8/inc/arch/cpu.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ struct cpu_arch {
1818

1919
unsigned long cpu_id_to_mpidr(cpuid_t id);
2020
void cpu_arch_profile_init(cpuid_t cpuid, paddr_t load_addr);
21-
void cpu_arch_profile_idle(void);
21+
void cpu_arch_profile_standby(void);
22+
void cpu_arch_profile_powerdown(void);
2223

2324
extern cpuid_t CPU_MASTER;
2425

src/arch/armv8/inc/arch/psci.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,7 @@ struct psci_off_state {
9090
struct gicc_state gicc_state __attribute__((aligned(8)));
9191
} __attribute__((packed, aligned(8)));
9292

93-
enum wakeup_reason {
94-
PSCI_WAKEUP_CPU_OFF,
95-
PSCI_WAKEUP_POWERDOWN,
96-
PSCI_WAKEUP_IDLE,
97-
PSCI_WAKEUP_NUM
98-
};
93+
enum wakeup_reason { PSCI_WAKEUP_CPU_OFF, PSCI_WAKEUP_POWERDOWN, PSCI_WAKEUP_NUM };
9994

10095
/* --------------------------------
10196
SMC Trapping
@@ -104,7 +99,7 @@ enum wakeup_reason {
10499
int32_t psci_smc_handler(uint32_t smc_fid, unsigned long x1, unsigned long x2, unsigned long x3);
105100

106101
int32_t psci_standby(void);
107-
int32_t psci_power_down(enum wakeup_reason reason);
102+
int32_t psci_power_down(void);
108103
void psci_wake_from_off(void);
109104
void psci_wake(uint32_t handler_id);
110105

src/arch/armv8/psci.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ static int32_t psci_cpu_suspend_handler(uint32_t power_state, unsigned long entr
6666
cpu()->vcpu->arch.psci_ctx.entrypoint = entrypoint;
6767
cpu()->vcpu->arch.psci_ctx.context_id = context_id;
6868
spin_unlock(&cpu()->vcpu->arch.psci_ctx.lock);
69-
ret = psci_power_down(PSCI_WAKEUP_POWERDOWN);
69+
ret = psci_power_down();
7070
} else {
7171
// PSCI_STATE_TYPE_STANDBY:
7272
ret = psci_standby();
@@ -86,7 +86,7 @@ static int32_t psci_cpu_off_handler(void)
8686
cpu()->vcpu->arch.psci_ctx.state = OFF;
8787
spin_unlock(&cpu()->vcpu->arch.psci_ctx.lock);
8888

89-
cpu_idle();
89+
cpu_powerdown();
9090

9191
spin_lock(&cpu()->vcpu->arch.psci_ctx.lock);
9292
cpu()->vcpu->arch.psci_ctx.state = ON;

src/arch/armv8/vm.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,7 @@ void vcpu_arch_reset(struct vcpu* vcpu, vaddr_t entry)
8080
*/
8181
}
8282

83-
static inline bool vcpu_psci_state_on(struct vcpu* vcpu)
83+
bool vcpu_arch_is_on(struct vcpu* vcpu)
8484
{
8585
return vcpu->arch.psci_ctx.state == ON;
8686
}
87-
88-
void vcpu_arch_run(struct vcpu* vcpu)
89-
{
90-
if (vcpu_psci_state_on(vcpu)) {
91-
vcpu_arch_entry();
92-
} else {
93-
cpu_idle();
94-
}
95-
}

src/arch/riscv/cpu.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,21 @@ void cpu_arch_init(cpuid_t cpuid, paddr_t load_addr)
2727
}
2828
}
2929

30-
void cpu_arch_idle(void)
30+
void cpu_arch_standby(void)
3131
{
3232
struct sbiret ret = sbi_hart_suspend(SBI_HSM_SUSPEND_RET_DEFAULT, 0, 0);
3333
if (ret.error < 0) {
3434
ERROR("failed to suspend hart %d", cpu()->id);
3535
}
3636
__asm__ volatile("mv sp, %0\n\r"
37-
"j cpu_idle_wakeup\n\r" ::"r"(&cpu()->stack[STACK_SIZE]));
38-
ERROR("returned from idle wake up");
37+
"j cpu_standby_wakeup\n\r" ::"r"(&cpu()->stack[STACK_SIZE]));
38+
ERROR("returned from standby wake up");
39+
}
40+
41+
void cpu_arch_powerdown(void)
42+
{
43+
__asm__ volatile("wfi\n\t" ::: "memory");
44+
__asm__ volatile("mv sp, %0\n\r"
45+
"j cpu_powerdown_wakeup\n\r" ::"r"(&cpu()->stack[STACK_SIZE]));
46+
ERROR("returned from powerdown wake up");
3947
}

0 commit comments

Comments
 (0)