summaryrefslogtreecommitdiffstats
path: root/src/kernel/shutdown.S
diff options
context:
space:
mode:
authorPatrick Williams <iawillia@us.ibm.com>2012-08-14 12:15:47 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-08-22 14:39:24 -0500
commit59a63d52bee3c84b60cd04c2128ca8786e7e9035 (patch)
tree66a06d09a4e994bc49f366c9a192f182bb22616e /src/kernel/shutdown.S
parent45f1a20db38dc14a2afde1db1aea7c167666bf28 (diff)
downloadtalos-hostboot-59a63d52bee3c84b60cd04c2128ca8786e7e9035.tar.gz
talos-hostboot-59a63d52bee3c84b60cd04c2128ca8786e7e9035.zip
Ensure PHYP thread order is correct.
* Choose thread with the lowest PIR as the last to enter payload. * Use HRMOR update process from Murano Book IV. RTC: 43166 Change-Id: I629f4a55cba1967a13c31a16095697b7142ca407 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/1529 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/kernel/shutdown.S')
-rw-r--r--src/kernel/shutdown.S162
1 files changed, 162 insertions, 0 deletions
diff --git a/src/kernel/shutdown.S b/src/kernel/shutdown.S
new file mode 100644
index 000000000..30a81ea46
--- /dev/null
+++ b/src/kernel/shutdown.S
@@ -0,0 +1,162 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/kernel/shutdown.S $
+#
+# IBM CONFIDENTIAL
+#
+# COPYRIGHT International Business Machines Corp. 2012
+#
+# p1
+#
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
+#
+# The source code for this program is not published or other-
+# wise divested of its trade secrets, irrespective of what has
+# been deposited with the U.S. Copyright Office.
+#
+# Origin: 30
+#
+# IBM_PROLOG_END_TAG
+.include "kernel/ppcconsts.S"
+
+#define KERNEL_BARRIER(addr, count, temp) \
+ /* Increment thread count. */ \
+ 1: \
+ ldarx temp, 0, addr; \
+ addi temp, temp, 1; \
+ stdcx. temp, 0, addr; \
+ bne- 1b; \
+ isync; \
+ /* Wait for count to reach CPU count. */ \
+ 1: \
+ or 1,1,1; /* Drop thread priority */ \
+ ld temp, 0(addr); \
+ cmpd cr0, temp, count; \
+ bne 1b; \
+ /* Instruction barrier to ensure exit. */ \
+ isync; \
+ or 3,3,3; /* Increase thread priority */
+
+
+.section .text
+
+ ;// @fn kernel_shutdown
+ ;// Leave the Hostboot kernel and switch to the payload.
+ ;//
+ ;// There are four stages to switching to the payload, all of which
+ ;// must be synchronized across all of the threads.
+ ;// Steps:
+ ;// All threads enter "EA[0]=1" mode.
+ ;// <sync barrier 1>
+ ;// Thread0 on each core updates HRMOR.
+ ;// <sync barrier 2>
+ ;// All threads execute - isync ; slbia ; isync
+ ;// <sync barrier 3>
+ ;// All threads except "last thread" enters payload.
+ ;// * last thread waits for all other threads to leave.
+ ;//
+ ;// The design of the barrier stages comes from the BookIV chapter
+ ;// titled "HRMOR Update Sequence".
+ ;//
+ ;// @param[in] r3 - CPU count - Number of active CPUs.
+ ;// @param[in] r4 - Payload Base
+ ;// @param[in] r5 - Payload Entry
+ ;// @param[in] r6 - Last thread to enter payload.
+ ;//
+.global kernel_shutdown
+kernel_shutdown:
+ ;// Set R10 to 0x8000000000000000 so we can set "EA[0]=1" for addrs.
+ li r10, 1
+ rotldi r10, r10, 63
+ ;// Retrieve existing HRMOR.
+ mfspr r7, HRMOR
+ ;// Determine physical address of shutdown_barrier.
+ lis r8, kernel_shutdown_barriers@h
+ ori r8, r8, kernel_shutdown_barriers@l
+ or r8, r8, r7 ;// Apply HRMOR.
+ or r8, r8, r10 ;// Apply EA[0] = 1.
+ ;// Determine physical address of EA[0]=1 mode instruction.
+ lis r9, kernel_shutdown_ea0_1_mode@h
+ ori r9, r9, kernel_shutdown_ea0_1_mode@l
+ or r9, r9, r7 ;// Apply HRMOR.
+ or r9, r9, r10 ;// Apply EA[0] = 1.
+ ;// Jump to enter EA[0] = 1
+ mtlr r9
+ blr
+kernel_shutdown_ea0_1_mode:
+ ;// Perform barrier - 1
+ KERNEL_BARRIER(r8, r3, r11)
+ isync
+ or 3,3,3 ;// Increase thread priority
+ ;// Update HRMOR on master.
+ mfspr r10, PIR
+ andi. r10, r10, 7
+ bne+ 1f
+ mtspr HRMOR, r4
+1:
+ ;// Perform barrier - 2
+ addi r8, r8, 8
+ KERNEL_BARRIER(r8, r3, r11)
+
+ ;// Clear out SLBs, ERATs, etc.
+ isync
+ slbia
+ isync
+
+ ;// Perform barrier - 3
+ addi r8, r8, 8
+ KERNEL_BARRIER(r8, r3, r11)
+
+ ;// "Barrier" 4:
+ ;// Increment counter as leaving, except PIR == r6 waits.
+ addi r8, r8, 8
+ ;// Check for PIR == r6.
+ mfspr r10, PIR
+ cmp cr0, r10, r6
+ beq 3f
+ ;// Increment thread count.
+1:
+ ldarx r11, 0, r8
+ addi r11, r11, 1
+ stdcx. r11, 0, r8
+ bne- 1b
+ isync
+2:
+ ;// Enter Payload.
+ ;// Set HSRR0 to entry point.
+ mtspr HSRR0, r5
+ ;// Save MSR, move to HSRR1.
+ mfmsr r10
+ mtspr HSRR1, r10
+ ;// Jump to entry point. Causes HSRR0 -> NIA, HSSR1 -> MSR.
+ hrfid
+
+ ;// PIR == r6 waits here for all others to leave.
+3:
+ subi r3, r3, 1
+1:
+ or 1,1,1
+ ld r11, 0(r8)
+ cmp cr0, r3, r11
+ bne+ 1b
+ isync
+ ;// All other threads have left, so wait a little bit...
+ ;// Set CTR to 512.
+ li r11, 512
+ mtctr r11
+ ;// Execute thread-priority-low until CTR is 0.
+1:
+ or 1,1,1
+ bdnz 1b
+ isync
+ ;// Raise thread priority and leave ourselves.
+ or 3,3,3
+ b 2b
+
+.section .data
+kernel_shutdown_barriers:
+ .space 8*4 ;//
+
OpenPOWER on IntegriCloud