summaryrefslogtreecommitdiffstats
path: root/src/usr/secureboot/base/purge.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/secureboot/base/purge.C')
-rw-r--r--src/usr/secureboot/base/purge.C140
1 files changed, 140 insertions, 0 deletions
diff --git a/src/usr/secureboot/base/purge.C b/src/usr/secureboot/base/purge.C
new file mode 100644
index 000000000..af21a7b02
--- /dev/null
+++ b/src/usr/secureboot/base/purge.C
@@ -0,0 +1,140 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/secureboot/base/purge.C $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2013 */
+/* */
+/* 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 otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include <stdint.h>
+#include <sys/task.h>
+#include <sys/time.h>
+#include <devicefw/userif.H>
+#include <secureboot/secure_reasoncodes.H>
+
+#include "purge.H"
+
+namespace SECUREBOOT
+{
+ errlHndl_t issueBlindPurge()
+ {
+ static const uint64_t PURGE_REG = 0x1001080e;
+
+ // Bits : Value
+ // 0 : 0b1 = Initiate Purge
+ // 1:4 : 0b0100 = Full Blind Purge
+ // 13:28 : 0x1000 = CGC is (512k / 128 byte line size)
+ // CGC means "Congruence Class", ie. cache row.
+ static const uint64_t PURGE_VALUE = 0xa000800000000000;
+
+ // Bit 0 - Purge Pending.
+ static const uint64_t PURGE_PENDING = 0x8000000000000000;
+
+ static const size_t RETRY_COUNT = 100;
+ static const size_t RETRY_WAIT_NS = ONE_CTX_SWITCH_NS;
+
+ errlHndl_t l_errl = NULL;
+ do
+ {
+ size_t coreId = (task_getcpuid() / 8) & 0xF;
+ uint64_t regAddr = PURGE_REG + 0x01000000 * coreId;
+
+ uint64_t data = 0;
+ size_t size = sizeof(data);
+
+ // Read purge register to ensure no operation is pending.
+ l_errl =
+ deviceRead(TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &data, size,
+ DEVICE_SCOM_ADDRESS(regAddr));
+ if (l_errl)
+ {
+ break;
+ }
+
+ if (data & PURGE_PENDING)
+ {
+ /*@
+ * @errortype
+ * @moduleid SECUREBOOT::MOD_SECURE_BLINDPURGE
+ * @reasoncode SECUREBOOT::RC_PURGEOP_PENDING
+ * @userdata1 SCOM value.
+ * @userdata2 CPU ID (PIR) encountering failure.
+ * @devdesc Attemped to purge cache while purge operation
+ * was pending.
+ */
+ l_errl =
+ new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_SECURE_BLINDPURGE,
+ RC_PURGEOP_PENDING,
+ data, task_getcpuid());
+ break;
+ }
+
+ // Initiate purge operation
+ data = PURGE_VALUE;
+ l_errl =
+ deviceWrite(TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &data, size,
+ DEVICE_SCOM_ADDRESS(regAddr));
+ if (l_errl)
+ {
+ break;
+ }
+
+ // Wait for purge to complete.
+ for(size_t i = 0; i < RETRY_COUNT; i++)
+ {
+ l_errl =
+ deviceRead(TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL,
+ &data, size,
+ DEVICE_SCOM_ADDRESS(regAddr));
+
+ if ((l_errl) || !(data & PURGE_PENDING))
+ {
+ break;
+ }
+
+ nanosleep(0, RETRY_WAIT_NS);
+ }
+ if (l_errl)
+ {
+ break;
+ }
+ if (data & PURGE_PENDING) // Ensure op did complete.
+ {
+ /*@
+ * @errortype
+ * @moduleid SECUREBOOT::MOD_SECURE_BLINDPURGE
+ * @reasoncode SECUREBOOT::RC_PURGEOP_FAIL_COMPLETE
+ * @userdata1 SCOM value.
+ * @devdesc Purge operation never completed.
+ */
+ l_errl =
+ new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_SECURE_BLINDPURGE,
+ RC_PURGEOP_FAIL_COMPLETE,
+ data);
+ break;
+ }
+
+ } while(0);
+
+ return l_errl;
+ }
+
+}
OpenPOWER on IntegriCloud