Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 77b54e9f authored by Shreyas B. Prabhu's avatar Shreyas B. Prabhu Committed by Michael Ellerman
Browse files

powernv/powerpc: Add winkle support for offline cpus



Winkle is a deep idle state supported in power8 chips. A core enters
winkle when all the threads of the core enter winkle. In this state
power supply to the entire chiplet i.e core, private L2 and private L3
is turned off. As a result it gives higher powersavings compared to
sleep.

But entering winkle results in a total hypervisor state loss. Hence the
hypervisor context has to be preserved before entering winkle and
restored upon wake up.

Power-on Reset Engine (PORE) is a dedicated engine which is responsible
for powering on the chiplet during wake up. It can be programmed to
restore the register contests of a few specific registers. This patch
uses PORE to restore register state wherever possible and uses stack to
save and restore rest of the necessary registers.

With hypervisor state restore things fall under three categories-
per-core state, per-subcore state and per-thread state. To manage this,
extend the infrastructure introduced for sleep. Mainly we add a paca
variable subcore_sibling_mask. Using this and the core_idle_state we can
distingush first thread in core and subcore.

Signed-off-by: default avatarShreyas B. Prabhu <shreyas@linux.vnet.ibm.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: linuxppc-dev@lists.ozlabs.org
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 7cba160a
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -161,6 +161,7 @@ struct opal_sg_list {
#define OPAL_PCI_EEH_FREEZE_SET			97
#define OPAL_HANDLE_HMI				98
#define OPAL_CONFIG_CPU_IDLE_STATE		99
#define OPAL_SLW_SET_REG			100
#define OPAL_REGISTER_DUMP_REGION		101
#define OPAL_UNREGISTER_DUMP_REGION		102
#define OPAL_WRITE_TPO				103
@@ -176,6 +177,7 @@ struct opal_sg_list {
 */
#define OPAL_PM_NAP_ENABLED	0x00010000
#define OPAL_PM_SLEEP_ENABLED	0x00020000
#define OPAL_PM_WINKLE_ENABLED	0x00040000
#define OPAL_PM_SLEEP_ENABLED_ER1	0x00080000

#ifndef __ASSEMBLY__
@@ -913,6 +915,7 @@ int64_t opal_sensor_read(uint32_t sensor_hndl, int token, __be32 *sensor_data);
int64_t opal_handle_hmi(void);
int64_t opal_register_dump_region(uint32_t id, uint64_t start, uint64_t end);
int64_t opal_unregister_dump_region(uint32_t id);
int64_t opal_slw_set_reg(uint64_t cpu_pir, uint64_t sprn, uint64_t val);
int64_t opal_pci_set_phb_cxl_mode(uint64_t phb_id, uint64_t mode, uint64_t pe_number);
int64_t opal_ipmi_send(uint64_t interface, struct opal_ipmi_msg *msg,
		uint64_t msg_len);
+2 −0
Original line number Diff line number Diff line
@@ -158,6 +158,8 @@ struct paca_struct {
	u8 thread_idle_state;		/* PNV_THREAD_RUNNING/NAP/SLEEP	*/
	/* Mask to indicate thread id in core */
	u8 thread_mask;
	/* Mask to denote subcore sibling threads */
	u8 subcore_sibling_mask;
#endif

#ifdef CONFIG_PPC_BOOK3S_64
+2 −0
Original line number Diff line number Diff line
@@ -194,6 +194,7 @@

#define PPC_INST_NAP			0x4c000364
#define PPC_INST_SLEEP			0x4c0003a4
#define PPC_INST_WINKLE			0x4c0003e4

/* A2 specific instructions */
#define PPC_INST_ERATWE			0x7c0001a6
@@ -374,6 +375,7 @@

#define PPC_NAP			stringify_in_c(.long PPC_INST_NAP)
#define PPC_SLEEP		stringify_in_c(.long PPC_INST_SLEEP)
#define PPC_WINKLE		stringify_in_c(.long PPC_INST_WINKLE)

/* BHRB instructions */
#define PPC_CLRBHRB		stringify_in_c(.long PPC_INST_CLRBHRB)
+1 −0
Original line number Diff line number Diff line
@@ -453,6 +453,7 @@ enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF};
extern int powersave_nap;	/* set if nap mode can be used in idle loop */
extern unsigned long power7_nap(int check_irq);
extern unsigned long power7_sleep(void);
extern unsigned long power7_winkle(void);
extern void flush_instruction_cache(void);
extern void hard_reset_now(void);
extern void poweroff_now(void);
+2 −0
Original line number Diff line number Diff line
@@ -373,6 +373,7 @@
#define SPRN_DBAT7L	0x23F	/* Data BAT 7 Lower Register */
#define SPRN_DBAT7U	0x23E	/* Data BAT 7 Upper Register */
#define SPRN_PPR	0x380	/* SMT Thread status Register */
#define SPRN_TSCR	0x399	/* Thread Switch Control Register */

#define SPRN_DEC	0x016		/* Decrement Register */
#define SPRN_DER	0x095		/* Debug Enable Regsiter */
@@ -730,6 +731,7 @@
#define SPRN_BESCR	806	/* Branch event status and control register */
#define   BESCR_GE	0x8000000000000000ULL /* Global Enable */
#define SPRN_WORT	895	/* Workload optimization register - thread */
#define SPRN_WORC	863	/* Workload optimization register - core */

#define SPRN_PMC1	787
#define SPRN_PMC2	788
Loading