diff options
| author | Patrick Williams <iawillia@us.ibm.com> | 2012-07-17 21:57:58 -0500 |
|---|---|---|
| committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2012-07-28 13:04:48 -0500 |
| commit | b866f4173f605d8dcdf83b3239dd7fb9a5a8768b (patch) | |
| tree | abb7ddef100518198c44202293d9042b8922ae50 /src | |
| parent | ac9ad22f261cd391c0d5163e82ff02ae4929f820 (diff) | |
| download | blackbird-hostboot-b866f4173f605d8dcdf83b3239dd7fb9a5a8768b.tar.gz blackbird-hostboot-b866f4173f605d8dcdf83b3239dd7fb9a5a8768b.zip | |
Execute 'doze' in idle loop.
Change-Id: Ifd611129c2d7173b5e0dec36c870e06a4d851009
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/1384
Tested-by: Jenkins Server
Reviewed-by: Douglas R. Gilbert <dgilbert@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src')
| -rwxr-xr-x | src/build/debug/Hostboot/Ps.pm | 7 | ||||
| -rw-r--r-- | src/include/kernel/cpumgr.H | 3 | ||||
| -rw-r--r-- | src/include/kernel/ppcconsts.S | 23 | ||||
| -rw-r--r-- | src/include/kernel/syscalls.H | 2 | ||||
| -rw-r--r-- | src/include/kernel/task.H | 46 | ||||
| -rw-r--r-- | src/kernel/exception.C | 91 | ||||
| -rw-r--r-- | src/kernel/misc.C | 48 | ||||
| -rw-r--r-- | src/kernel/start.S | 79 | ||||
| -rw-r--r-- | src/kernel/syscall.C | 30 | ||||
| -rw-r--r-- | src/sys/prof/idletask.C | 59 |
10 files changed, 256 insertions, 132 deletions
diff --git a/src/build/debug/Hostboot/Ps.pm b/src/build/debug/Hostboot/Ps.pm index a5a56ba02..e8a238c11 100755 --- a/src/build/debug/Hostboot/Ps.pm +++ b/src/build/debug/Hostboot/Ps.pm @@ -6,7 +6,7 @@ # # IBM CONFIDENTIAL # -# COPYRIGHT International Business Machines Corp. 2011 +# COPYRIGHT International Business Machines Corp. 2011-2012 # # p1 # @@ -20,8 +20,7 @@ # # Origin: 30 # -# IBM_PROLOG_END - +# IBM_PROLOG_END_TAG use strict; package Hostboot::Ps; @@ -47,7 +46,7 @@ use constant PS_TRACKER_RETVAL_OFFSET => 8 + PS_TRACKER_STATUS_OFFSET; use constant PS_TRACKER_WAITINFO_OFFSET => 8 + PS_TRACKER_RETVAL_OFFSET; use constant PS_TRACKER_ENTRYPOINT_OFFSET => 8 + PS_TRACKER_WAITINFO_OFFSET; -use constant PS_TASK_STATE_OFFSET => 8*42; +use constant PS_TASK_STATE_OFFSET => 8*43; use constant PS_TASK_STATEEXTRA_OFFSET => 8 + PS_TASK_STATE_OFFSET; sub main diff --git a/src/include/kernel/cpumgr.H b/src/include/kernel/cpumgr.H index bbd16fcd8..8cf6d0fc3 100644 --- a/src/include/kernel/cpumgr.H +++ b/src/include/kernel/cpumgr.H @@ -111,10 +111,11 @@ class CpuManager /** Desired value for LPCR after wakeup. * * bit 49 - Wake-up from external interrupt. + * bit 50 - Wake-up from decrementer. * bit 51 - Wake-up from machine check. * bit 60, 61 - LPES(0,1) = 1 (see ISA). */ - static const uint64_t WAKEUP_LPCR_VALUE = 0x000000000000500C; + static const uint64_t WAKEUP_LPCR_VALUE = 0x000000000000700C; protected: CpuManager(); diff --git a/src/include/kernel/ppcconsts.S b/src/include/kernel/ppcconsts.S index 89a52a008..1568bb911 100644 --- a/src/include/kernel/ppcconsts.S +++ b/src/include/kernel/ppcconsts.S @@ -1,25 +1,25 @@ # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. -# +# # $Source: src/include/kernel/ppcconsts.S $ -# +# # IBM CONFIDENTIAL -# -# COPYRIGHT International Business Machines Corp. 2010 - 2011 -# +# +# COPYRIGHT International Business Machines Corp. 2010-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 +# +# IBM_PROLOG_END_TAG #*--------------------------------------------------------------------*# #* Register Constants *# #*--------------------------------------------------------------------*# @@ -206,8 +206,9 @@ .set TASK_CR, TASK_LR+8 .set TASK_CTR, TASK_CR+8 .set TASK_XER, TASK_CTR+8 +.set TASK_MSR_MASK, TASK_XER+8 -.set TASK_FP_CONTEXT, TASK_XER+8 +.set TASK_FP_CONTEXT, TASK_MSR_MASK+8 .set TASK_FPR_0, 0 .set TASK_FPR_1, TASK_FPR_0+8 .set TASK_FPR_2, TASK_FPR_1+8 diff --git a/src/include/kernel/syscalls.H b/src/include/kernel/syscalls.H index 28e13628c..5523fc158 100644 --- a/src/include/kernel/syscalls.H +++ b/src/include/kernel/syscalls.H @@ -92,6 +92,8 @@ namespace Systemcalls MISC_CPUSTARTCORE, /** cpu_spr_value() */ MISC_CPUSPRVALUE, + /** cpu_doze() - Hidden syscall */ + MISC_CPUDOZE, /** mm_alloc_block() */ MM_ALLOC_BLOCK, diff --git a/src/include/kernel/task.H b/src/include/kernel/task.H index 9ff0401ba..f9ceab994 100644 --- a/src/include/kernel/task.H +++ b/src/include/kernel/task.H @@ -1,25 +1,26 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/include/kernel/task.H $ -// -// IBM CONFIDENTIAL -// -// COPYRIGHT International Business Machines Corp. 2010 - 2011 -// -// 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 +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/include/kernel/task.H $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2010-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 + */ /** @file task.H * @brief Defines kernel information about tasks. */ @@ -42,6 +43,7 @@ struct context_t uint64_t cr; uint64_t ctr; uint64_t xer; + uint64_t msr_mask; // XOR mask applied to MSR. }; /** @struct context_fp_t diff --git a/src/kernel/exception.C b/src/kernel/exception.C index 6115b5bd8..0d63d0a73 100644 --- a/src/kernel/exception.C +++ b/src/kernel/exception.C @@ -1,25 +1,26 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/kernel/exception.C $ -// -// IBM CONFIDENTIAL -// -// COPYRIGHT International Business Machines Corp. 2010 - 2011 -// -// 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 +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/kernel/exception.C $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2010-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 <assert.h> #include <kernel/types.h> #include <kernel/console.H> @@ -29,14 +30,16 @@ #include <kernel/vmmmgr.H> #include <kernel/cpuid.H> #include <kernel/intmsghandler.H> +#include <errno.h> +#include <kernel/vmmmgr.H> namespace ExceptionHandles { - bool HvEmulation(task_t*); + bool PrivInstr(task_t*); } const uint64_t EXCEPTION_SRR1_MASK = 0x00000000783F0000; -const uint64_t EXCEPTION_SRR1_HVEMUL = 0x0000000000080000; +const uint64_t EXCEPTION_SRR1_PRIVINS = 0x0000000000040000; extern "C" void kernel_execute_prog_ex() @@ -47,9 +50,9 @@ void kernel_execute_prog_ex() bool handled = false; switch(exception) { - case EXCEPTION_SRR1_HVEMUL: - handled = ExceptionHandles::HvEmulation(t); - break; + case EXCEPTION_SRR1_PRIVINS: + handled = ExceptionHandles::PrivInstr(t); + break; } if (!handled) { @@ -157,22 +160,26 @@ void kernel_execute_hype_emu_assist() namespace ExceptionHandles { - bool HvEmulation(task_t* t) + bool PrivInstr(task_t* t) { - /*printk("NIP = %lx : Inst = %x\n", - t->context.nip, - (*(uint32_t*)t->context.nip));*/ - - uint32_t instruction = *(uint32_t*)t->context.nip; - - // check for mfsprg3 - if ((instruction & 0xfc1fffff) == 0x7c1342a6) - { - t->context.gprs[(instruction & 0x03E00000) >> 21] = - (uint64_t) t; - t->context.nip = (void*) (((uint64_t)t->context.nip)+4); - return true; - } + uint64_t phys_addr = VmmManager::findPhysicalAddress( + reinterpret_cast<uint64_t>(t->context.nip)); + + if (-EFAULT != static_cast<int64_t>(phys_addr)) + { + uint32_t* instruction = reinterpret_cast<uint32_t*>(phys_addr); + + // Check for 'doze' and skip over. This avoids a task-crash + // if for some reason we entered back into the task without + // priviledge raised. + if (*instruction == 0x4c000324) + { + printk("Error: Doze executed with lowered permissions on %d\n", + t->tid); + t->context.nip = static_cast<void*>(instruction + 1); + return true; + } + } return false; } diff --git a/src/kernel/misc.C b/src/kernel/misc.C index 74be12de1..a29aaea21 100644 --- a/src/kernel/misc.C +++ b/src/kernel/misc.C @@ -1,25 +1,26 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/kernel/misc.C $ -// -// IBM CONFIDENTIAL -// -// COPYRIGHT International Business Machines Corp. 2011 -// -// 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 +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/kernel/misc.C $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2011-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/misc.H> #include <kernel/cpumgr.H> #include <kernel/cpuid.H> @@ -84,6 +85,9 @@ namespace KernelMisc printk("No payload... doze'ing all threads.\n"); } + // Clear LPCR values that wakes up from doze. LPCR[49, 50, 51] + setLPCR(getLPCR() & (~0x0000000000007000)); + while(1) { doze(); diff --git a/src/kernel/start.S b/src/kernel/start.S index 2e4cd1784..7d2d77845 100644 --- a/src/kernel/start.S +++ b/src/kernel/start.S @@ -146,11 +146,41 @@ finished_relocate: .org _start + 0x100 intvect_system_reset: - b _start + /* TODO: Add handling for SRESET from winkle for master. */ + ;// Need to identify reason for SRESET and then perform appropriate + ;// action. + ;// Current support: + ;// - Decrementer wake-up from doze. + ;// - External interrupt (also wake-up from doze). + ;// - IPI wake-up from winkle of slave core. + + ;// Free up two registers temporarily. + mtsprg0 r1 + mtsprg1 r2 + + ;// Save CR. + mfcr r1 + + ;// Find bit 42:44 of SRR1 (reason for SRESET). + mfsrr1 r2 + extrdi r2, r2, 3, 42 + ;// Check for decrementer (bits = 011). + cmpi cr0, r2, 0x3 + beq+ intvect_system_reset_decrementer + ;// Check for external interrupt (bits = 010). + cmpi cr0, r2, 0x4 + beq+ intvect_system_reset_external + ;// Check for HMI (bits = 101). + cmpi cr0, r2, 0x5 + beq+ _start + ;// Check for bits 000, which is probably a Simics bug right now. + cmpi cr0, r2, 0x0 + beq+ _start +1: ;// Unknown reason. + b 1b -.org _start + 0x17C -hbi_pre_phyp_breakpoint: - attn; /* TODO: Add actual breakpoint attention. */ +.org _start + 0x180 +intvect_inst_start: b _start /* TODO: Eventually we likely need specific code for machine check @@ -436,10 +466,10 @@ kernel_dispatch_task: mfmsr r2 ;// Get current MSR ori r2,r2, 0xC030 ;// Enable MSR[EE,PR,IR,DR]. - rldicl r2,r2,1,1 ;// Clear ... - rotldi r2,r2,63 ;// MSR[TA] rldicl r2,r2,50,1 ;// Clear ... rotldi r2,r2,14 ;// MSR[FP] + ld r3, TASK_MSR_MASK(r1) ;// Load MSR mask. + xor r2, r2, r3 ;// Apply MSR mask (XOR). mtsrr1 r2 ;// Set task MSR (SRR1) ld r2, TASK_NIP(r1) ;// Load NIP from context. @@ -544,7 +574,44 @@ kernel_dispatch_task: b 2b + ;// @fn intvect_system_reset_decrementer + ;// Handle SRESET due to decrementer wake-up. + ;// This is a wake-up from 'doze'. Clear priviledge escalation and + ;// perform decrementer. +intvect_system_reset_decrementer: + ;// Restore CR. + mtcr r1 + + ;// Clear MSR mask, since privilaged instruction was now executed (doze). + mfsprg3 r1 ;// Load task structure to r1. + li r2, 0 ;// Zero r2. + std r2, TASK_MSR_MASK(r1) ;// Zero msr_mask. + + ;// Advance saved NIA (past doze). + mfsrr0 r1 + addi r1, r1, 4 + mtsrr0 r1 + + ;// Restore save registers. + mfsprg0 r1 + mfsprg1 r2 + + b intvect_decrementer + + ;// @fn intvect_system_reset_external + ;// Handle SRESET due to wake-up from external interrupt. + ;// This is a wake-up from 'doze', but not due to the decrementer + ;// itself firing. Therefore, leave 'doze' process state alone + ;// including NIA and handle the external interrupt. +intvect_system_reset_external: + ;// Restore CR. + mtcr r1 + + ;// Restore save registers. + mfsprg0 r1 + mfsprg1 r2 + b intvect_external ;// @fn system_call_fast_path ;// Handle fast path system calls. diff --git a/src/kernel/syscall.C b/src/kernel/syscall.C index 061971f96..6dcbe0c25 100644 --- a/src/kernel/syscall.C +++ b/src/kernel/syscall.C @@ -98,6 +98,7 @@ namespace Systemcalls void CpuDDLevel(task_t *t); void CpuStartCore(task_t *t); void CpuSprValue(task_t *t); + void CpuDoze(task_t *t); void MmAllocBlock(task_t *t); void MmRemovePages(task_t *t); void MmSetPermission(task_t *t); @@ -133,6 +134,7 @@ namespace Systemcalls &CpuDDLevel, // MISC_CPUDDLEVEL &CpuStartCore, // MISC_CPUSTARTCORE &CpuSprValue, // MISC_CPUSPRVALUE + &CpuDoze, // MISC_CPUDOZE &MmAllocBlock, // MM_ALLOC_BLOCK &MmRemovePages, // MM_REMOVE_PAGES @@ -668,6 +670,34 @@ namespace Systemcalls }; /** + * Allow a task to request priviledge escalation to execute the 'doze' + * instruction. + * + * Verifies the instruction to execute is, in fact, doze and then sets + * an MSR mask in the task structure to allow escalation on next + * execution. + * + * When 'doze' is executed the processor will eventually issue an + * SRESET exception with flags in srr1 to indication that the + * decrementer caused the wake-up. The kernel will then need to + * advance the task to the instruction after the doze and remove + * priviledge escalation. + * + */ + void CpuDoze(task_t *t) + { + + uint32_t* instruction = static_cast<uint32_t*>(t->context.nip); + if (0x4c000324 == (*instruction)) // Verify 'doze' instruction, + // otherwise just return. + { + // Disable PR, IR, DR so 'doze' can be executed. + // (which means to stay in HV state) + t->context.msr_mask = 0x4030; + } + }; + + /** * Allocate a block of virtual memory within the base segment * @param[in] t: The task used to allocate a block in the base segment */ diff --git a/src/sys/prof/idletask.C b/src/sys/prof/idletask.C index 843f26628..da568f955 100644 --- a/src/sys/prof/idletask.C +++ b/src/sys/prof/idletask.C @@ -1,26 +1,26 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/sys/prof/idletask.C $ -// -// 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 - +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/sys/prof/idletask.C $ + * + * 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 + */ /** @file idletask.C * @brief Code for the kernel idle-loop. * @@ -31,11 +31,22 @@ #include <kernel/taskmgr.H> #include <arch/ppc.H> +#include <sys/syscall.h> + +using namespace Systemcalls; void TaskManager::idleTaskLoop(void* unused) { while(1) { - setThreadPriorityLow(); + // Lower priority (and yield simics thread). + setThreadPriorityLow(); + + // Request privilege escalation for doze. + register uint64_t syscall = MISC_CPUDOZE; + asm volatile("or 3, %0, %0; sc" :: "r" (syscall) : "r3"); + + // Execute doze. + doze(); } } |

