summaryrefslogtreecommitdiffstats
path: root/libpdbg/ram.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpdbg/ram.c')
-rw-r--r--libpdbg/ram.c306
1 files changed, 0 insertions, 306 deletions
diff --git a/libpdbg/ram.c b/libpdbg/ram.c
deleted file mode 100644
index 4d9954b..0000000
--- a/libpdbg/ram.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/* Copyright 2016 IBM Corp.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- * implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ccan/array_size/array_size.h>
-
-#include "operations.h"
-#include "bitutils.h"
-
-#define RAS_STATUS_TIMEOUT 100
-
-#define DIRECT_CONTROLS_REG 0x10013000
-#define DIRECT_CONTROL_SP_START PPC_BIT(62)
-#define DIRECT_CONTROL_SP_STOP PPC_BIT(63)
-#define RAS_STATUS_REG 0x10013002
-#define RAS_STATUS_SRQ_EMPTY PPC_BIT(8)
-#define RAS_STATUS_NCU_QUIESCED PPC_BIT(10)
-#define RAS_STATUS_TS_QUIESCE PPC_BIT(49)
-#define THREAD_ACTIVE_REG 0x1001310E
-#define THREAD_ACTIVE PPC_BITMASK(0, 7)
-#define RAM_THREAD_ACTIVE PPC_BITMASK(8, 15)
-#define SPR_MODE_REG 0x10013281
-#define SPR_MODE_SPRC_WR_EN PPC_BIT(3)
-#define SPR_MODE_SPRC_SEL PPC_BITMASK(16, 19)
-#define SPR_MODE_SPRC_T_SEL PPC_BITMASK(20, 27)
-#define L0_SCOM_SPRC_REG 0x10013280
-#define SCOM_SPRC_SCRATCH_SPR 0x40
-#define SCR0_REG 0x10013283
-#define RAM_MODE_REG 0x10013c00
-#define RAM_MODE_ENABLE PPC_BIT(0)
-#define RAM_CTRL_REG 0x10013c01
-#define RAM_THREAD_SELECT PPC_BITMASK(0, 2)
-#define RAM_INSTR PPC_BITMASK(3, 34)
-#define RAM_STATUS_REG 0x10013c02
-#define RAM_CONTROL_RECOV PPC_BIT(0)
-#define RAM_STATUS PPC_BIT(1)
-#define RAM_EXCEPTION PPC_BIT(2)
-#define LSU_EMPTY PPC_BIT(3)
-#define PMSPCWKUPFSP_REG 0x100f010b
-#define FSP_SPECIAL_WAKEUP PPC_BIT(0)
-
-/* Opcodes */
-#define MFNIA_OPCODE 0x00000004UL
-#define MFSPR_OPCODE 0x7c0002a6UL
-#define MTSPR_OPCODE 0x7c0003a6UL
-
-static uint64_t mfspr(uint64_t reg, uint64_t spr)
-{
- if (reg > 31)
- PR_ERROR("Invalid register specified\n");
-
- return MFSPR_OPCODE | (reg << 21) | ((spr & 0x1f) << 16) | ((spr & 0x3e0) << 6);
-}
-
-static uint64_t mtspr(uint64_t spr, uint64_t reg)
-{
- if (reg > 31)
- PR_ERROR("Invalid register specified\n");
-
- return MTSPR_OPCODE | (reg << 21) | ((spr & 0x1f) << 16) | ((spr & 0x3e0) << 6);
-}
-
-static uint64_t mfnia(uint64_t reg)
-{
- if (reg > 31)
- PR_ERROR("Invalid register specified\n");
-
- return MFNIA_OPCODE | (reg << 21);
-}
-
-/*
- * Return a mask of currently active threads.
- */
-int ram_running_threads(uint64_t chip, uint64_t *running_threads)
-{
- uint64_t addr, val;
- int thread;
-
- chip <<= 24;
- *running_threads = 0;
-
- for (thread = 0; thread < THREADS_PER_CORE; thread++) {
- /* Wait for thread to quiese */
- addr = RAS_STATUS_REG | chip;
- addr |= thread << 4;
- CHECK_ERR(getscom(&val, addr));
-
- if (!((val & RAS_STATUS_SRQ_EMPTY)
- && (val & RAS_STATUS_TS_QUIESCE)))
- *running_threads |= 1 << (THREADS_PER_CORE - thread - 1);
- }
- return 0;
-}
-
-/*
- * Stop active threads on the chip. Returns the active_threads in
- * *active_threads. This should be passed to ram_start_chip() to
- * restart the stopped threads.
- */
-int ram_stop_chip(uint64_t chip, uint64_t *active_threads)
-{
- int i = 0, thread;
- uint64_t addr, val, thread_active;
-
- chip <<= 24;
-
- /* Assert special wakeup to prevent low power states */
- addr = PMSPCWKUPFSP_REG | chip;
- CHECK_ERR(putscom(FSP_SPECIAL_WAKEUP, addr));
-
- /* Read active threads */
- addr = THREAD_ACTIVE_REG | chip;
- CHECK_ERR(getscom(&val, addr));
- thread_active = GETFIELD(THREAD_ACTIVE, val);
-
- for (thread = 0; thread < THREADS_PER_CORE; thread++) {
- /* Skip inactive threads (stupid IBM bit ordering) */
- if (!(thread_active & (1 << (THREADS_PER_CORE - thread - 1))))
- continue;
-
- /* Quiese active thread */
- addr = DIRECT_CONTROLS_REG | chip;
- addr |= thread << 4;
- val = DIRECT_CONTROL_SP_STOP;
- CHECK_ERR(putscom(val, addr));
-
- /* Wait for thread to quiese */
- addr = RAS_STATUS_REG | chip;
- addr |= thread << 4;
- i = 0;
- do {
- CHECK_ERR(getscom(&val, addr));
- if (i++ > RAS_STATUS_TIMEOUT) {
- PR_ERROR("Unable to quiesce thread %d (0x%016llx).\n",
- thread, val);
- PR_ERROR("Continuing anyway.\n");
- break;
- }
- } while (!((val & RAS_STATUS_SRQ_EMPTY)
- /*
- * Workbook says check for bit 10 but it
- * never seems to get set and everything
- * still works as expected.
- */
- /* && (val & RAS_STATUS_NCU_QUIESCED) */
- && (val & RAS_STATUS_TS_QUIESCE)));
- }
-
- /* Make the RAM threads active */
- addr = THREAD_ACTIVE_REG | chip;
- CHECK_ERR(getscom(&val, addr));
- val = SETFIELD(RAM_THREAD_ACTIVE, val, (1 << THREADS_PER_CORE) - 1);
- CHECK_ERR(putscom(val, addr));
-
- /* Activate RAM mode */
- addr = RAM_MODE_REG | chip;
- CHECK_ERR(getscom(&val, addr));
- val |= RAM_MODE_ENABLE;
- CHECK_ERR(putscom(val, addr));
-
- *active_threads = thread_active;
- return 0;
-}
-
-int ram_start_chip(uint64_t chip, uint64_t thread_active)
-{
- uint64_t addr, val;
- int thread;
-
- chip <<= 24;
-
- /* De-activate RAM mode */
- addr = RAM_MODE_REG | chip;
- CHECK_ERR(putscom(0, addr));
-
- /* Start cores which were active */
- for (thread = 0; thread < THREADS_PER_CORE; thread++) {
- if (!(thread_active & (1 << (THREADS_PER_CORE - thread - 1))))
- continue;
-
- /* Activate thread */
- addr = DIRECT_CONTROLS_REG | chip;
- addr |= thread << 4;
- val = DIRECT_CONTROL_SP_START;
- CHECK_ERR(putscom(val, addr));
- }
-
- /* De-assert special wakeup to enable low power states */
- addr = PMSPCWKUPFSP_REG | chip;
- CHECK_ERR(putscom(0, addr));
-
- return 0;
-}
-
-/*
- * RAMs the opcodes in *opcodes and store the results of each opcode
- * into *results. *results must point to an array the same size as
- * *opcodes. Note that only register r0 is saved and restored so
- * opcodes must not touch other registers.
- */
-static int ram_instructions(uint64_t *opcodes, uint64_t *results, int len,
- uint64_t chip, unsigned int lpar, uint64_t thread)
-{
- uint64_t addr, val, opcode, r0 = 0;
- int i;
-
- /* Setup SPRC to use SPRD */
- chip <<= 24;
- addr = SPR_MODE_REG | chip;
- val = SPR_MODE_SPRC_WR_EN;
- val = SETFIELD(SPR_MODE_SPRC_SEL, val, 1 << (3 - lpar));
- val = SETFIELD(SPR_MODE_SPRC_T_SEL, val, 1 << (7 - thread));
- CHECK_ERR(putscom(val, addr));
-
- addr = L0_SCOM_SPRC_REG | chip;
- val = SCOM_SPRC_SCRATCH_SPR;
- CHECK_ERR(putscom(val, addr));
-
- /* RAM instructions */
- addr = RAM_CTRL_REG | chip;
- for (i = -1; i <= len; i++) {
- if (i < 0)
- /* Save r0 (assumes opcodes don't touch other registers) */
- opcode = mtspr(277, 0);
- else if (i < len)
- opcode = opcodes[i];
- else if (i >= len) {
- /* Restore r0 */
- CHECK_ERR(putscom(r0, SCR0_REG | chip));
- opcode = mfspr(0, 277);
- }
-
- /* ram instruction */
- val = SETFIELD(RAM_THREAD_SELECT, 0ULL, thread);
- val = SETFIELD(RAM_INSTR, val, opcode);
- CHECK_ERR(putscom(val, addr));
-
- /* wait for completion */
- do {
- CHECK_ERR(getscom(&val, RAM_STATUS_REG | chip));
- } while (!val);
-
- if (!(val & RAM_STATUS))
- PR_ERROR("RAMMING failed with status 0x%llx\n", val);
-
- /* Save the results */
- CHECK_ERR(getscom(&val, SCR0_REG | chip));
- if (i < 0)
- r0 = val;
- else if (i < len)
- results[i] = val;
- }
-
- return 0;
-}
-
-/*
- * Get gpr value. Chip must be stopped.
- */
-int ram_getgpr(int chip, int thread, int gpr, uint64_t *value)
-{
- uint64_t opcodes[] = {mtspr(277, gpr)};
- uint64_t results[] = {0};
-
- CHECK_ERR(ram_instructions(opcodes, results, ARRAY_SIZE(opcodes),
- chip, 0, thread));
- *value = results[0];
- return 0;
-}
-
-int ram_getnia(int chip, int thread, uint64_t *value)
-{
- uint64_t opcodes[] = {mfnia(0), mtspr(277, 0)};
- uint64_t results[] = {0, 0};
-
- CHECK_ERR(ram_instructions(opcodes, results, ARRAY_SIZE(opcodes),
- chip, 0, thread));
- *value = results[0];
- return 0;
-}
-
-int ram_getspr(int chip, int thread, int spr, uint64_t *value)
-{
- uint64_t opcodes[] = {mfspr(0, spr), mtspr(277, 0)};
- uint64_t results[] = {0, 0};
-
- CHECK_ERR(ram_instructions(opcodes, results, ARRAY_SIZE(opcodes),
- chip, 0, thread));
- *value = results[1];
- return 0;
-}
OpenPOWER on IntegriCloud