diff options
-rw-r--r-- | src/include/kernel/syscalls.H | 4 | ||||
-rw-r--r-- | src/include/sys/mmio.h | 52 | ||||
-rw-r--r-- | src/kernel/cpuid.C | 2 | ||||
-rw-r--r-- | src/kernel/start.S | 22 | ||||
-rw-r--r-- | src/lib/syscall_misc.C | 2 | ||||
-rw-r--r-- | src/lib/syscall_mmio.C | 42 |
6 files changed, 120 insertions, 4 deletions
diff --git a/src/include/kernel/syscalls.H b/src/include/kernel/syscalls.H index dad90056c..aabab15d8 100644 --- a/src/include/kernel/syscalls.H +++ b/src/include/kernel/syscalls.H @@ -84,6 +84,10 @@ namespace Systemcalls MMIO_HMER_READ = 0x0800, /** mmio_hmer_write() */ MMIO_HMER_WRITE = 0x0801, + /** mmio_scratch_read() */ + MMIO_SCRATCH_READ = 0x0802, + /** mmio_scratch_write() */ + MMIO_SCRATCH_WRITE = 0x0803, SYSCALL_FASTPATH_MAX }; diff --git a/src/include/sys/mmio.h b/src/include/sys/mmio.h index 37c0a029d..8ceb74bc9 100644 --- a/src/include/sys/mmio.h +++ b/src/include/sys/mmio.h @@ -47,7 +47,6 @@ int mmio_dev_unmap(void *ea); */ uint64_t mmio_hmer_read(); - /** @fn mmio_hmer_write() * @brief Writes the protected HMER register. * @@ -55,6 +54,57 @@ uint64_t mmio_hmer_read(); */ void mmio_hmer_write(uint64_t value); +/** @enum MMIO_Scratch_Register + * @brief Enumeration of the available scratch registers and their assigned + * purpose. + * + * These enumeration values should be used as the 'which' parameter of + * mmio_scratch_read / mmio_scratch_write. + * + * These values come from the Chip Pervasive Spec. + * + * TODO: Verify that P7/P8 offsets are the same. + */ +enum MMIO_Scratch_Register +{ + /** Thread0 Scratch Register - Progress Code / Status. */ + MMIO_SCRATCH_PROGRESS_CODE = 0x0, + /** Thread1 Scratch Register - IPL Step Command Register. */ + MMIO_SCRATCH_IPLSTEP_COMMAND = 0x8, + /** Thread2 Scratch Register - IPL Step Status Register. */ + MMIO_SCRATCH_IPLSTEP_STATUS = 0x10, + /** Thread3 Scratch Register - IPL Step Config Register. */ + MMIO_SCRATCH_IPLSTEP_CONFIG = 0x18, // TODO: This one is temporary until + // IPL by steps in configurable in + // PNOR. +}; + +/** @fn mmio_scratch_read() + * @brief Reads and returns protected SCRATCH register. + * + * @param[in] which - Which SCRATCH register to read (MMIO_Scratch_Register). + * @return Requested SCRATCH register value + * + * @note SCRATCH registers can only be modified from the master processor, + * so this call may have the side effect of migrating your task to + * another core or hardware thread. Beware that any affinity settings + * for the task are ignored by this call. + */ +uint64_t mmio_scratch_read(uint64_t which); + +/** @fn mmio_scratch_write() + * @brief Writes the protected SCRATCH register. + * + * @param[in] which - Which SCRATCH register to write (MMIO_Scratch_Register). + * @param[in] value - The value to write into the SCRATCH. + * + * @note SCRATCH registers can only be modified from the master processor, + * so this call may have the side effect of migrating your task to + * another core or hardware thread. Beware that any affinity settings + * for the task are ignored by this call. + */ +void mmio_scratch_write(uint64_t which, uint64_t value); + /** @fn mmio_xscom_mutex() * @brief Returns the per-CPU mutex for the XSCOM hardware logic. diff --git a/src/kernel/cpuid.C b/src/kernel/cpuid.C index 78ce382e1..bbbe71190 100644 --- a/src/kernel/cpuid.C +++ b/src/kernel/cpuid.C @@ -18,6 +18,8 @@ namespace CpuID // 1 nibble reserved. // 1 nibble minor DD. + // TODO: Salerno PVR support. + switch(l_pvr & 0xFFFF0000) { case 0x003F0000: diff --git a/src/kernel/start.S b/src/kernel/start.S index d67cb7790..1f7fc7163 100644 --- a/src/kernel/start.S +++ b/src/kernel/start.S @@ -360,6 +360,8 @@ kernel_dispatch_task: ;// Handle fast path system calls. ;// 0x800 = HMER read (HMER -> r3). ;// 0x801 = HMER write (r4 -> HMER). + ;// 0x802 = SCRATCH read (r4 -> SPRC, SPRD -> r3). + ;// 0x803 = SCRATCH write (r4 -> SPRC, r5 -> SPRD). system_call_fast_path: ;// Check if this is HMER read (0x800). ;// Compare was already done in system call path. @@ -373,9 +375,25 @@ system_call_fast_path: mtspr HMER, r4 li r3, 0 b 1f ;// Jump to exit point. - ;// Invalid system call, loop for debug. + ;// Check if this is SCRATCH read (0x802). 3: - b 3b + cmpi cr0, r3, 0x802 + bne cr0, 4f + mtspr 276, r4 + isync + mfspr r3, 277 + b 1f ;// Jump to exit point. + ;// Check if this is SCRATCH write (0x803). +4: + cmpi cr0, r3, 0x803 + bne cr0, 5f + mtspr 276, r4 + isync + mtspr 277, r5 + b 1f ;// Jump to exit point. + ;// Invalid system call, loop for debug. +5: + b 5b 1: rfid ;// Return from interrupt. diff --git a/src/lib/syscall_misc.C b/src/lib/syscall_misc.C index d1bccf8f1..ec2125d63 100644 --- a/src/lib/syscall_misc.C +++ b/src/lib/syscall_misc.C @@ -1,10 +1,12 @@ #include <sys/misc.h> #include <sys/syscall.h> +#include <sys/mmio.h> using namespace Systemcalls; void shutdown(uint64_t i_status) { + mmio_scratch_write(MMIO_SCRATCH_IPLSTEP_CONFIG, 0x1234ABCD); _syscall1(MISC_SHUTDOWN, reinterpret_cast<void*>(i_status)); } diff --git a/src/lib/syscall_mmio.C b/src/lib/syscall_mmio.C index 411dfdb41..f771129b7 100644 --- a/src/lib/syscall_mmio.C +++ b/src/lib/syscall_mmio.C @@ -3,6 +3,7 @@ #include <assert.h> #include <kernel/task.H> #include <kernel/cpu.H> +#include <kernel/cpuid.H> using namespace Systemcalls; @@ -36,6 +37,45 @@ void mmio_hmer_write(uint64_t value) _syscall1(MMIO_HMER_WRITE, (void*)value); } +/** @brief Determine the base register address of the mmio_scratch_base. + * + * Since this code is called from within the kernel as part of static + * construction of g_mmio_scratch_base, we can use internal kernel + * functions here (and not system calls) to determine the CPU type. + * + * @return Base address (SPRC value) of the scratch registers. + */ +static uint64_t mmio_scratch_base() +{ + ProcessorCoreType cpuType = CpuID::getCpuType(); + switch (cpuType) + { + case CORE_POWER7: + case CORE_POWER7_PLUS: + return 0x20; + + case CORE_POWER8_SALERNO: + case CORE_POWER8_VENICE: + case CORE_UNKNOWN: + default: + return 0x40; + } +} + /** Global cache of the scratch register SPRC base address. */ +uint64_t g_mmio_scratch_base = mmio_scratch_base(); + +uint64_t mmio_scratch_read(uint64_t which) +{ + return (uint64_t) _syscall1(MMIO_SCRATCH_READ, + (void*)(which + g_mmio_scratch_base)); +} + +void mmio_scratch_write(uint64_t which, uint64_t value) +{ + _syscall2(MMIO_SCRATCH_WRITE, + (void*)(which + g_mmio_scratch_base), (void*)value); +} + mutex_t * mmio_xscom_mutex() { // Get task structure. @@ -44,7 +84,7 @@ mutex_t * mmio_xscom_mutex() // Ensure task is pinned. crit_assert(task->affinity_pinned); - + // Return mutex from cpu structure. return &task->cpu->xscom_mutex; } |