Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/813794/?format=api
{ "id": 813794, "url": "http://patchwork.ozlabs.org/api/patches/813794/?format=api", "web_url": "http://patchwork.ozlabs.org/project/skiboot/patch/20170914111346.11970-6-npiggin@gmail.com/", "project": { "id": 44, "url": "http://patchwork.ozlabs.org/api/projects/44/?format=api", "name": "skiboot firmware development", "link_name": "skiboot", "list_id": "skiboot.lists.ozlabs.org", "list_email": "skiboot@lists.ozlabs.org", "web_url": "http://github.com/open-power/skiboot", "scm_url": "http://github.com/open-power/skiboot", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20170914111346.11970-6-npiggin@gmail.com>", "list_archive_url": null, "date": "2017-09-14T11:13:46", "name": "[5/5] cpu: idle POWER9 power management implementation", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "cc46f85fa28bd0becc3f555480ee3f66aa8c0534", "submitter": { "id": 69518, "url": "http://patchwork.ozlabs.org/api/people/69518/?format=api", "name": "Nicholas Piggin", "email": "npiggin@gmail.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/skiboot/patch/20170914111346.11970-6-npiggin@gmail.com/mbox/", "series": [ { "id": 3075, "url": "http://patchwork.ozlabs.org/api/series/3075/?format=api", "web_url": "http://patchwork.ozlabs.org/project/skiboot/list/?series=3075", "date": "2017-09-14T11:13:41", "name": "POWER9 idle pm support", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/3075/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/813794/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/813794/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "skiboot@lists.ozlabs.org" ], "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "skiboot@lists.ozlabs.org" ], "Received": [ "from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68])\n\t(using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xtGCy0f8Rz9s7v\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 14 Sep 2017 21:15:26 +1000 (AEST)", "from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 3xtGCx6YVbzDrnS\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 14 Sep 2017 21:15:25 +1000 (AEST)", "from mail-pg0-x243.google.com (mail-pg0-x243.google.com\n\t[IPv6:2607:f8b0:400e:c05::243])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128\n\tbits)) (No client certificate requested)\n\tby lists.ozlabs.org (Postfix) with ESMTPS id 3xtGBp1RRdzDrRV\n\tfor <skiboot@lists.ozlabs.org>; Thu, 14 Sep 2017 21:14:26 +1000 (AEST)", "by mail-pg0-x243.google.com with SMTP id m30so1526672pgn.5\n\tfor <skiboot@lists.ozlabs.org>; Thu, 14 Sep 2017 04:14:26 -0700 (PDT)", "from roar.au.ibm.com (203-219-56-202.tpgi.com.au. [203.219.56.202])\n\tby smtp.gmail.com with ESMTPSA id\n\tc2sm29289224pgq.61.2017.09.14.04.14.19\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\n\tThu, 14 Sep 2017 04:14:21 -0700 (PDT)" ], "Authentication-Results": [ "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"prysfNwp\"; dkim-atps=neutral", "lists.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"prysfNwp\"; dkim-atps=neutral", "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=gmail.com\n\t(client-ip=2607:f8b0:400e:c05::243; helo=mail-pg0-x243.google.com;\n\tenvelope-from=npiggin@gmail.com; receiver=<UNKNOWN>)", "lists.ozlabs.org; dkim=pass (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"prysfNwp\"; dkim-atps=neutral" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references;\n\tbh=NUKS1mTkWPappXfINFyKaWYBdsisNUfUqbQlmTMH1+o=;\n\tb=prysfNwpVKjNq3mJMQmIW/SWsP12N2vNo6b7Am8HeN/Zrbu56ozFj1c5XZAxCWJ3x0\n\tRwcYgu6yzuMyf5JnTM4eFAmGo6MjMps20ffBHcqze+pi46Gk0w2MvvFzDdPLcU0Mh+Ta\n\tfHc7QIaoGLemavj0MEIEhA6Q/Eo7TRZfmTAj2QznS0oxTUdvjMDbyGlyB5+8ah9yDyoj\n\tVBtePUylT487E1O3Eu6FPX0QfgKkaCQWBKjOM95C6jEBBbQBO5qGwOYz/WP2Qx0cx2l3\n\trRhTep2K9MgJYm/ePNtuVh/eS7aWSImSNwqBxwnAnMSDQJnpGnyG3SCzCqGQbHMZPWfQ\n\tbvqg==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=NUKS1mTkWPappXfINFyKaWYBdsisNUfUqbQlmTMH1+o=;\n\tb=SLa3o3GLn+c0kKVXHET91tWzr1eyKwAP94N0wfIfEMtzNzukHA7xSXFuVJwz7dzZRK\n\tK0/YgSCP26uK8XsN91JEzhMrbO+VLwZF0ri5yUDjQXfXeRU950jNIh5nv50G69zDC9jX\n\twAMNoBZEZZD4plOKsBS1pk+pvTeS7NvER/8wwPuarw4uR7f//bptTHSZzcjweNIuhHz2\n\tMYyUpV3rmCauMpo9PZgruICyhAGawT7/+B61uo2bloDDIVU2HZtl0VlsmrWpltivcEyq\n\tz/pxKE5ANoUa7m/WYYh5IU/mhHzZteRCrlh72Qb4T/DvVOPL8d7W1ssrRzUyTIADeH3M\n\tQEeg==", "X-Gm-Message-State": "AHPjjUiHCMDgs8zWcJennVmKqiFhD0ses3X+8OwdknAI5LtLuIR9f0lX\n\tuU5RyFVF+HuO6rOm", "X-Google-Smtp-Source": "AOwi7QCGCHmO1ShI3jxiK3tKJrhc04BO7kS8lDshb8ihHA88nkf/16Qyl5+w+8HoKdsgj2+nVuVcCw==", "X-Received": "by 10.99.97.208 with SMTP id v199mr3750406pgb.92.1505387662667; \n\tThu, 14 Sep 2017 04:14:22 -0700 (PDT)", "From": "Nicholas Piggin <npiggin@gmail.com>", "To": "skiboot@lists.ozlabs.org", "Date": "Thu, 14 Sep 2017 21:13:46 +1000", "Message-Id": "<20170914111346.11970-6-npiggin@gmail.com>", "X-Mailer": "git-send-email 2.13.3", "In-Reply-To": "<20170914111346.11970-1-npiggin@gmail.com>", "References": "<20170914111346.11970-1-npiggin@gmail.com>", "Subject": "[Skiboot] [PATCH 5/5] cpu: idle POWER9 power management\n\timplementation", "X-BeenThere": "skiboot@lists.ozlabs.org", "X-Mailman-Version": "2.1.24", "Precedence": "list", "List-Id": "Mailing list for skiboot development <skiboot.lists.ozlabs.org>", "List-Unsubscribe": "<https://lists.ozlabs.org/options/skiboot>,\n\t<mailto:skiboot-request@lists.ozlabs.org?subject=unsubscribe>", "List-Archive": "<http://lists.ozlabs.org/pipermail/skiboot/>", "List-Post": "<mailto:skiboot@lists.ozlabs.org>", "List-Help": "<mailto:skiboot-request@lists.ozlabs.org?subject=help>", "List-Subscribe": "<https://lists.ozlabs.org/listinfo/skiboot>,\n\t<mailto:skiboot-request@lists.ozlabs.org?subject=subscribe>", "Cc": "\"Gautham R . Shenoy\" <ego@linux.vnet.ibm.com>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=\"utf-8\"", "Content-Transfer-Encoding": "base64", "Errors-To": "skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org", "Sender": "\"Skiboot\"\n\t<skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org>" }, "content": "Add pm idle support to POWER9. IPIs are implemented with doorbells.\nPOWER9 can use the EC=ESL=0 (lite) stop when sreset is not available.\n\nEC=ESL=1 state with RL=3 is enabled when we have a sreset wakeup.\n\nDeep idle states are not implemented.\n\nSigned-off-by: Nicholas Piggin <npiggin@gmail.com>\n---\n asm/head.S | 70 +++++++++++++++++++++---------\n core/cpu.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++--\n core/init.c | 2 +\n hw/slw.c | 2 +-\n include/processor.h | 31 +++++++++++++\n include/skiboot.h | 4 +-\n 6 files changed, 205 insertions(+), 27 deletions(-)", "diff": "diff --git a/asm/head.S b/asm/head.S\nindex badb567c..d6b58be9 100644\n--- a/asm/head.S\n+++ b/asm/head.S\n@@ -28,6 +28,8 @@\n #define PPC_INST_SLEEP\t\t.long 0x4c0003a4\n #define PPC_INST_RVWINKLE\t.long 0x4c0003e4\n \n+#define PPC_INST_STOP\t\t.long 0x4c0002e4\n+\n #define GET_STACK(stack_reg,pir_reg)\t\t\t\t\\\n \tsldi\tstack_reg,pir_reg,STACK_SHIFT;\t\t\t\\\n \taddis\tstack_reg,stack_reg,CPU_STACKS_OFFSET@ha;\t\\\n@@ -471,27 +473,7 @@ call_relocate:\n .long 0xa6037b7d; /* mtsrr1 r11 */ \\\n .long 0x2400004c /* rfid */\n \n-.global enter_pm_state\n-enter_pm_state:\n-\t/* Before entering map or rvwinkle, we create a stack frame\n-\t * and save our non-volatile registers.\n-\t *\n-\t * We also save these SPRs:\n-\t *\n-\t * - HSPRG0\tin GPR0 slot\n-\t * - HSPRG1\tin GPR1 slot\n-\t *\n-\t * - xxx TODO: HIDs\n-\t * - TODO: Mask MSR:ME during the process\n-\t *\n-\t * On entry, r3 indicates:\n-\t *\n-\t * 0 = nap\n-\t * 1 = rvwinkle\n-\t */\n-\tmflr\t%r0\n-\tstd\t%r0,16(%r1)\n-\tstdu\t%r1,-STACK_FRAMESIZE(%r1)\n+pm_save_regs:\n \tSAVE_GPR(2,%r1)\n \tSAVE_GPR(14,%r1)\n \tSAVE_GPR(15,%r1)\n@@ -519,6 +501,31 @@ enter_pm_state:\n \tstw\t%r5,STACK_XER(%r1)\n \tstd\t%r6,STACK_GPR0(%r1)\n \tstd\t%r7,STACK_GPR1(%r1)\n+\tblr\n+\n+.global enter_p8_pm_state\n+enter_p8_pm_state:\n+\t/* Before entering map or rvwinkle, we create a stack frame\n+\t * and save our non-volatile registers.\n+\t *\n+\t * We also save these SPRs:\n+\t *\n+\t * - HSPRG0\tin GPR0 slot\n+\t * - HSPRG1\tin GPR1 slot\n+\t *\n+\t * - xxx TODO: HIDs\n+\t * - TODO: Mask MSR:ME during the process\n+\t *\n+\t * On entry, r3 indicates:\n+\t *\n+\t * 0 = nap\n+\t * 1 = rvwinkle\n+\t */\n+\tmflr\t%r0\n+\tstd\t%r0,16(%r1)\n+\tstdu\t%r1,-STACK_FRAMESIZE(%r1)\n+\n+\tbl\tpm_save_regs\n \n \t/* Save stack pointer in struct cpu_thread */\n \tstd\t%r1,CPUTHREAD_SAVE_R1(%r13)\n@@ -543,6 +550,27 @@ enter_pm_state:\n \tPPC_INST_RVWINKLE\n \tb\t.\n \n+.global enter_p9_pm_lite_state\n+enter_p9_pm_lite_state:\n+\tmtspr\tSPR_PSSCR,%r3\n+\tPPC_INST_STOP\n+\tblr\n+\n+.global enter_p9_pm_state\n+enter_p9_pm_state:\n+\tmflr\t%r0\n+\tstd\t%r0,16(%r1)\n+\tstdu\t%r1,-STACK_FRAMESIZE(%r1)\n+\n+\tbl\tpm_save_regs\n+\n+\t/* Save stack pointer in struct cpu_thread */\n+\tstd\t%r1,CPUTHREAD_SAVE_R1(%r13)\n+\n+\tmtspr\tSPR_PSSCR,%r3\n+\tPPC_INST_STOP\n+\tb\t.\n+\n /* This is a little piece of code that is copied down to\n * 0x100 for handling power management wakeups\n */\ndiff --git a/core/cpu.c b/core/cpu.c\nindex 460094ad..297d1f3c 100644\n--- a/core/cpu.c\n+++ b/core/cpu.c\n@@ -94,8 +94,12 @@ static void cpu_wake(struct cpu_thread *cpu)\n \tif (!cpu->in_idle)\n \t\treturn;\n \n-\t/* Poke IPI */\n-\ticp_kick_cpu(cpu);\n+\tif (proc_gen == proc_gen_p8 || proc_gen == proc_gen_p7) {\n+\t\t/* Poke IPI */\n+\t\ticp_kick_cpu(cpu);\n+\t} else if (proc_gen == proc_gen_p9) {\n+\t\tp9_dbell_send(cpu->pir);\n+\t}\n }\n \n static struct cpu_thread *cpu_find_job_target(void)\n@@ -319,11 +323,14 @@ static void cpu_idle_p8(enum cpu_wake_cause wake_on)\n \t\tif (cpu_check_jobs(cpu) || !pm_enabled)\n \t\t\tgoto skip_sleep;\n \n+\t\t/* Setup wakup cause in LPCR: EE (for IPI) */\n \t\tlpcr |= SPR_LPCR_P8_PECE2;\n \t\tmtspr(SPR_LPCR, lpcr);\n \n \t} else {\n-\t\t/* Mark outselves sleeping so wakeup knows to send an IPI */\n+\t\t/* Mark outselves sleeping so cpu_set_pm_enable knows to\n+\t\t * send an IPI\n+\t\t */\n \t\tcpu->in_sleep = true;\n \t\tsync();\n \n@@ -331,12 +338,13 @@ static void cpu_idle_p8(enum cpu_wake_cause wake_on)\n \t\tif (!pm_enabled)\n \t\t\tgoto skip_sleep;\n \n+\t\t/* EE and DEC */\n \t\tlpcr |= SPR_LPCR_P8_PECE2 | SPR_LPCR_P8_PECE3;\n \t\tmtspr(SPR_LPCR, lpcr);\n \t}\n \n \t/* Enter nap */\n-\tenter_pm_state(false);\n+\tenter_p8_pm_state(false);\n \n skip_sleep:\n \t/* Restore */\n@@ -346,12 +354,78 @@ skip_sleep:\n \treset_cpu_icp();\n }\n \n+static void cpu_idle_p9(enum cpu_wake_cause wake_on)\n+{\n+\tuint64_t lpcr = mfspr(SPR_LPCR) & ~SPR_LPCR_P9_PECE;\n+\tuint64_t psscr;\n+\tstruct cpu_thread *cpu = this_cpu();\n+\n+\tif (!pm_enabled) {\n+\t\tprlog_once(PR_DEBUG, \"cpu_idle_p9 called pm disabled\\n\");\n+\t\treturn;\n+\t}\n+\n+\tmsgclr(); /* flush pending messages */\n+\n+\t/* Synchronize with wakers */\n+\tif (wake_on == cpu_wake_on_job) {\n+\t\t/* Mark ourselves in idle so other CPUs know to send an IPI */\n+\t\tcpu->in_idle = true;\n+\t\tsync();\n+\n+\t\t/* Check for jobs again */\n+\t\tif (cpu_check_jobs(cpu) || !pm_enabled)\n+\t\t\tgoto skip_sleep;\n+\n+\t\t/* HV DBELL for IPI */\n+\t\tlpcr |= SPR_LPCR_P9_PECEL1;\n+\t} else {\n+\t\t/* Mark outselves sleeping so cpu_set_pm_enable knows to\n+\t\t * send an IPI\n+\t\t */\n+\t\tcpu->in_sleep = true;\n+\t\tsync();\n+\n+\t\t/* Check if PM got disabled */\n+\t\tif (!pm_enabled)\n+\t\t\tgoto skip_sleep;\n+\n+\t\t/* HV DBELL and DEC */\n+\t\tlpcr |= SPR_LPCR_P9_PECEL1 | SPR_LPCR_P9_PECEL3;\n+\t\tmtspr(SPR_LPCR, lpcr);\n+\t}\n+\n+\tmtspr(SPR_LPCR, lpcr);\n+\n+\tif (sreset_enabled) {\n+\t\t/* stop with EC=1 (sreset) and ESL=1 (enable thread switch). */\n+\t\t/* PSSCR SD=0 ESL=1 EC=1 PSSL=0 TR=3 MTL=0 RL=3 */\n+\t\tpsscr = PPC_BIT(42) | PPC_BIT(43) |\n+\t\t\tPPC_BITMASK(54, 55) | PPC_BITMASK(62,63);\n+\t\tenter_p9_pm_state(psscr);\n+\t} else {\n+\t\t/* stop with EC=0 (resumes) which does not require sreset. */\n+\t\t/* PSSCR SD=0 ESL=0 EC=0 PSSL=0 TR=3 MTL=0 RL=3 */\n+\t\tpsscr = PPC_BITMASK(54, 55) | PPC_BITMASK(62,63);\n+\t\tenter_p9_pm_lite_state(psscr);\n+\t}\n+\n+skip_sleep:\n+\t/* Restore */\n+\tcpu->in_idle = false;\n+\tcpu->in_sleep = false;\n+\tp9_dbell_receive();\n+}\n+\n static void cpu_idle_pm(enum cpu_wake_cause wake_on)\n {\n \tswitch(proc_gen) {\n \tcase proc_gen_p8:\n \t\tcpu_idle_p8(wake_on);\n \t\tbreak;\n+\tcase proc_gen_p9:\n+\t\tcpu_idle_p9(wake_on);\n+\t\tbreak;\n \tdefault:\n \t\tprlog_once(PR_DEBUG, \"cpu_idle_pm called with bad processor type\\n\");\n \t\tbreak;\n@@ -429,6 +503,18 @@ static void cpu_pm_disable(void)\n \t\t\t\tcpu_relax();\n \t\t\t}\n \t\t}\n+\t} else if (proc_gen == proc_gen_p9) {\n+\t\tfor_each_available_cpu(cpu) {\n+\t\t\tif (cpu->in_sleep || cpu->in_idle)\n+\t\t\t\tp9_dbell_send(cpu->pir);\n+\t\t}\n+\n+\t\tsmt_lowest();\n+\t\tfor_each_available_cpu(cpu) {\n+\t\t\twhile (cpu->in_sleep || cpu->in_idle)\n+\t\t\t\tbarrier();\n+\t\t}\n+\t\tsmt_medium();\n \t}\n }\n \n@@ -451,6 +537,22 @@ void cpu_set_sreset_enable(bool enabled)\n \t\t\tif (ipi_enabled)\n \t\t\t\tpm_enabled = true;\n \t\t}\n+\n+\t} else if (proc_gen == proc_gen_p9) {\n+\t\t/* Don't use sreset idle on DD1 (has a number of bugs) */\n+\t\tuint32_t version = mfspr(SPR_PVR);\n+\t\tif (is_power9n(version) && (PVR_VERS_MAJ(version) == 1))\n+\t\t\treturn;\n+\n+\t\tsreset_enabled = enabled;\n+\t\tsync();\n+\t\t/*\n+\t\t * Kick everybody out of PM so they can adjust the PM\n+\t\t * mode they are using (EC=0/1).\n+\t\t */\n+\t\tcpu_pm_disable();\n+\t\tif (ipi_enabled)\n+\t\t\tpm_enabled = true;\n \t}\n }\n \n@@ -468,6 +570,19 @@ void cpu_set_ipi_enable(bool enabled)\n \t\t\tif (sreset_enabled)\n \t\t\t\tpm_enabled = true;\n \t\t}\n+\n+\t} else if (proc_gen == proc_gen_p9) {\n+\t\t/* Don't use doorbell on DD1 (requires darn for msgsync) */\n+\t\tuint32_t version = mfspr(SPR_PVR);\n+\t\tif (is_power9n(version) && (PVR_VERS_MAJ(version) == 1))\n+\t\t\treturn;\n+\n+\t\tipi_enabled = enabled;\n+\t\tsync();\n+\t\tif (!enabled)\n+\t\t\tcpu_pm_disable();\n+\t\telse\n+\t\t\tpm_enabled = true;\n \t}\n }\n \ndiff --git a/core/init.c b/core/init.c\nindex 42e6b560..7df20fc0 100644\n--- a/core/init.c\n+++ b/core/init.c\n@@ -922,6 +922,8 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt)\n \n \t/* Initialize the rest of the cpu thread structs */\n \tinit_all_cpus();\n+\tif (proc_gen == proc_gen_p9)\n+\t\tcpu_set_ipi_enable(true);\n \n \t/* Allocate our split trace buffers now. Depends add_opal_node() */\n \tinit_trace_buffers();\ndiff --git a/hw/slw.c b/hw/slw.c\nindex d8829a6b..d31e4f47 100644\n--- a/hw/slw.c\n+++ b/hw/slw.c\n@@ -82,7 +82,7 @@ static void slw_do_rvwinkle(void *data)\n \t/* Tell that we got it */\n \tcpu->state = cpu_state_rvwinkle;\n \n-\tenter_pm_state(1);\n+\tenter_p8_pm_state(1);\n \n \t/* Restore SPRs */\n \tinit_shared_sprs();\ndiff --git a/include/processor.h b/include/processor.h\nindex da483046..1f18762a 100644\n--- a/include/processor.h\n+++ b/include/processor.h\n@@ -77,6 +77,7 @@\n #define SPR_HMER\t0x150\t/* Hypervisor Maintenance Exception */\n #define SPR_HMEER\t0x151\t/* HMER interrupt enable mask */\n #define SPR_AMOR\t0x15d\n+#define SPR_PSSCR\t0x357 /* RW: Stop status and control (ISA 3) */\n #define SPR_TSCR\t0x399\n #define SPR_HID0\t0x3f0\n #define SPR_HID1\t0x3f1\n@@ -85,6 +86,7 @@\n #define SPR_HID5\t0x3f6\n #define SPR_PIR\t\t0x3ff\t/* RO: Processor Identification */\n \n+\n /* Bits in LPCR */\n \n /* Powersave Exit Cause Enable is different for P7 and P8 */\n@@ -99,6 +101,14 @@\n #define SPR_LPCR_P8_PECE2\tPPC_BIT(49) /* Wake on external interrupts */\n #define SPR_LPCR_P8_PECE3\tPPC_BIT(50) /* Wake on decrementer */\n #define SPR_LPCR_P8_PECE4\tPPC_BIT(51) /* Wake on MCs, HMIs, etc... */\n+\n+#define SPR_LPCR_P9_PECE\t(PPC_BITMASK(47,51) | PPC_BITMASK(17,17))\n+#define SPR_LPCR_P9_PECEU0\tPPC_BIT(17) /* Wake on HVI */\n+#define SPR_LPCR_P9_PECEL0\tPPC_BIT(47) /* Wake on priv doorbell */\n+#define SPR_LPCR_P9_PECEL1\tPPC_BIT(48) /* Wake on hv doorbell */\n+#define SPR_LPCR_P9_PECEL2\tPPC_BIT(49) /* Wake on external interrupts */\n+#define SPR_LPCR_P9_PECEL3\tPPC_BIT(50) /* Wake on decrementer */\n+#define SPR_LPCR_P9_PECEL4\tPPC_BIT(51) /* Wake on MCs, HMIs, etc... */\n #define SPR_LPCR_P9_LD\t\tPPC_BIT(46) /* Large decrementer mode bit */\n \n \n@@ -309,6 +319,27 @@ static inline void sync_icache(void)\n \tasm volatile(\"sync; icbi 0,%0; sync; isync\" : : \"r\" (0) : \"memory\");\n }\n \n+/*\n+ * Doorbells\n+ */\n+static inline void msgclr(void)\n+{\n+\tuint64_t rb = (0x05 << (63-36));\n+\tasm volatile(\"msgclr %0\" : : \"r\"(rb));\n+}\n+\n+static inline void p9_dbell_receive(void)\n+{\n+\tuint64_t rb = (0x05 << (63-36));\n+\t/* msgclr ; msgsync ; lwsync */\n+\tasm volatile(\"msgclr %0 ; .long 0x7c0006ec ; lwsync\" : : \"r\"(rb));\n+}\n+\n+static inline void p9_dbell_send(uint32_t pir)\n+{\n+\tuint64_t rb = (0x05 << (63-36)) | pir;\n+\tasm volatile(\"sync ; msgsnd %0\" : : \"r\"(rb));\n+}\n \n /*\n * Byteswap load/stores\ndiff --git a/include/skiboot.h b/include/skiboot.h\nindex 55aa9b8e..63d6e04f 100644\n--- a/include/skiboot.h\n+++ b/include/skiboot.h\n@@ -307,7 +307,9 @@ extern void fast_sleep_exit(void);\n extern void fake_rtc_init(void);\n \n /* Assembly in head.S */\n-extern void enter_pm_state(bool winkle);\n+extern void enter_p8_pm_state(bool winkle);\n+extern void enter_p9_pm_state(uint64_t psscr);\n+extern void enter_p9_pm_lite_state(uint64_t psscr);\n extern uint32_t reset_patch_start;\n extern uint32_t reset_patch_end;\n \n", "prefixes": [ "5/5" ] }