From e89e72d2f8a2efe86acad95ed0769aa7a8fe64ae Mon Sep 17 00:00:00 2001 From: Patrick Williams Date: Tue, 26 Mar 2013 11:23:47 -0500 Subject: Secureboot memory layout support. * Start kernel in 1/4 cache mode per Secureboot. * Copy Secureboot header for base image for later use. * Blind-purge bottom half of cache. * Add bottom of cache into memory maps for 1/2 cache mode. RTC: 64762 Change-Id: I1b45f30a2d45c9709d4fd486cfe0ca2ce86b051c Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/3773 Reviewed-by: Michael Baiocchi Tested-by: Jenkins Server Reviewed-by: ADAM R. MUHLE Reviewed-by: Daniel M. Crowell Reviewed-by: A. Patrick Williams III --- src/build/citest/etc/patches/p8_ex_l3purge.act | 9 ++ src/build/citest/etc/patches/patchlist.txt | 7 +- src/build/citest/etc/workarounds.postsimsetup | 8 ++ src/include/kernel/misc.H | 11 +- src/include/kernel/pagemgr.H | 6 +- src/include/kernel/vmmmgr.H | 22 ++-- src/include/sys/mm.h | 1 + src/include/usr/hbotcompid.H | 8 ++ src/include/usr/secureboot/secure_reasoncodes.H | 43 ++++++++ src/include/usr/secureboot/service.H | 41 +++++++ src/include/util/align.H | 51 +++++---- src/kernel/basesegment.C | 18 +-- src/kernel/misc.C | 47 ++++++++ src/kernel/pagemgr.C | 113 ++++++++++++++----- src/kernel/syscall.C | 4 + src/makefile | 4 +- src/usr/initservice/baseinitsvc/initservice.C | 8 +- src/usr/initservice/baseinitsvc/initsvctasks.H | 57 ++++++---- src/usr/makefile | 2 +- src/usr/secureboot/base/header.C | 57 ++++++++++ src/usr/secureboot/base/makefile | 30 +++++ src/usr/secureboot/base/purge.C | 140 ++++++++++++++++++++++++ src/usr/secureboot/base/purge.H | 35 ++++++ src/usr/secureboot/base/service.C | 68 ++++++++++++ src/usr/secureboot/base/settings.C | 52 +++++++++ src/usr/secureboot/ext/makefile | 30 +++++ src/usr/secureboot/header.H | 53 +++++++++ src/usr/secureboot/makefile | 27 +++++ src/usr/secureboot/settings.H | 56 ++++++++++ 29 files changed, 905 insertions(+), 103 deletions(-) create mode 100644 src/build/citest/etc/patches/p8_ex_l3purge.act create mode 100644 src/include/usr/secureboot/secure_reasoncodes.H create mode 100644 src/include/usr/secureboot/service.H create mode 100644 src/usr/secureboot/base/header.C create mode 100644 src/usr/secureboot/base/makefile create mode 100644 src/usr/secureboot/base/purge.C create mode 100644 src/usr/secureboot/base/purge.H create mode 100644 src/usr/secureboot/base/service.C create mode 100644 src/usr/secureboot/base/settings.C create mode 100644 src/usr/secureboot/ext/makefile create mode 100644 src/usr/secureboot/header.H create mode 100644 src/usr/secureboot/makefile create mode 100644 src/usr/secureboot/settings.H (limited to 'src') diff --git a/src/build/citest/etc/patches/p8_ex_l3purge.act b/src/build/citest/etc/patches/p8_ex_l3purge.act new file mode 100644 index 000000000..3d540b662 --- /dev/null +++ b/src/build/citest/etc/patches/p8_ex_l3purge.act @@ -0,0 +1,9 @@ + +# Indicate purge complete whenever a purge operation is requested. +CAUSE_EFFECT CHIPLETS ex{ + LABEL=[L3 PURGE REGISTER] + WATCH=[REG(MYCHIPLET,0x0001080e)] + + CAUSE: TARGET=[REG(MYCHIPLET,0x0001080e)] OP=[BIT,ON] BIT=[0] + EFFECT: TARGET=[REG(MYCHIPLET,0x0001080e)] OP=[BIT,OFF] BIT=[0] +} diff --git a/src/build/citest/etc/patches/patchlist.txt b/src/build/citest/etc/patches/patchlist.txt index afccedee0..c605c55de 100644 --- a/src/build/citest/etc/patches/patchlist.txt +++ b/src/build/citest/etc/patches/patchlist.txt @@ -14,5 +14,8 @@ New version of proc_a_x_pll HW procedure requires additional actions src/build/citest/etc/patches/s1.act_proc_a_x_pll_patch - CoReq: N/A - - +Add action for L3 purge register. +-RTC: 67762 +-CMVC: 876083 +-Files: p8_ex_l3purge.act +-Coreq: None diff --git a/src/build/citest/etc/workarounds.postsimsetup b/src/build/citest/etc/workarounds.postsimsetup index d335f723b..54a80b8a5 100755 --- a/src/build/citest/etc/workarounds.postsimsetup +++ b/src/build/citest/etc/workarounds.postsimsetup @@ -32,3 +32,11 @@ #cp $BACKING_BUILD/src/simu/data/cec-chip/base_cec_chip_file $sb/simu/data/cec-chip #patch -p0 $sb/simu/data/cec-chip/base_cec_chip_file $HOSTBOOTROOT/src/build/citest/etc/patches/my_patch_File +echo "+++ Updating actions for Blind Purge (CMVC 876083)" +mkdir -p $sb/simu/data/cec-chip +cp $BACKING_BUILD/src/simu/data/cec-chip/p8_ex.act $sb/simu/data/cec-chip +cp $BACKING_BUILD/src/simu/data/cec-chip/s1_ex.act $sb/simu/data/cec-chip +cat $HOSTBOOTROOT/src/build/citest/etc/patches/p8_ex_l3purge.act >> \ + $sb/simu/data/cec-chip/p8_ex.act +cat $HOSTBOOTROOT/src/build/citest/etc/patches/p8_ex_l3purge.act >> \ + $sb/simu/data/cec-chip/s1_ex.act diff --git a/src/include/kernel/misc.H b/src/include/kernel/misc.H index f0fe0ffd0..544df7c88 100644 --- a/src/include/kernel/misc.H +++ b/src/include/kernel/misc.H @@ -121,6 +121,15 @@ namespace KernelMisc }; + /** @fn expand_half_cache + * + * @brief Expands the image footprint from a quarter-cache (top 512k of + * each cache column) to a half-cache (full 1mb of each column). + * + * @return 0 or -errno + */ + int expand_half_cache(); + /** @fn expand_full_cache * * @brief Expands the image footprint from a half-cache to full-cache @@ -155,7 +164,7 @@ namespace KernelMisc * NOTE: This function is a wrapper function for writeScratchReg that * takes care of modifying the scratch register address value depending * on the getCPUType. The writeScratchReg takes the scratch address - * passed in and puts that date in that register using assembly code + * passed in and puts that data in that register using assembly code * * @param[in] uint64_t - scratch_addr * @param[in] uint64_t - Data diff --git a/src/include/kernel/pagemgr.H b/src/include/kernel/pagemgr.H index 65da0de66..b05e0b237 100644 --- a/src/include/kernel/pagemgr.H +++ b/src/include/kernel/pagemgr.H @@ -5,7 +5,7 @@ /* */ /* IBM CONFIDENTIAL */ /* */ -/* COPYRIGHT International Business Machines Corp. 2010,2012 */ +/* COPYRIGHT International Business Machines Corp. 2010,2013 */ /* */ /* p1 */ /* */ @@ -176,8 +176,7 @@ class PageManager enum { - MEMLEN = VmmManager::FIRST_RESERVED_PAGE, - RESERVED_PAGES = 4, + KERNEL_HEAP_RESERVED_PAGES = 4, LOWMEM_NORM_LIMIT = 16, LOWMEM_CRIT_LIMIT = 5, @@ -192,6 +191,7 @@ class PageManager ~PageManager() {}; private: + void _initialize(); void* _allocatePage(size_t,bool); //!< see allocatePage() void _freePage(void*, size_t); //!< see freePage() diff --git a/src/include/kernel/vmmmgr.H b/src/include/kernel/vmmmgr.H index b740d03e1..dae3c387d 100644 --- a/src/include/kernel/vmmmgr.H +++ b/src/include/kernel/vmmmgr.H @@ -42,18 +42,22 @@ class VmmManager { INITIAL_MEM_SIZE = 4*MEGABYTE, - // put the Page Table at the end of our memory space - PTSIZE = (1 << 18), - HTABORG_OFFSET = (INITIAL_MEM_SIZE - PTSIZE), + // Place the page table at the top side of the cache, 256k in size. + INITIAL_PT_OFFSET = INITIAL_MEM_SIZE - 1*MEGABYTE, + PTSIZE = 256*KILOBYTE, + HTABORG_OFFSET = INITIAL_PT_OFFSET, - // Put the DMA Pages just under the Page Table + // Put the DMA Pages just after the Page Table MBOX_DMA_PAGES = 64, // must be <= 64 MBOX_DMA_PAGESIZE = (1 * KILOBYTE), - MBOX_DMA_ADDR = (HTABORG_OFFSET - - (MBOX_DMA_PAGES * MBOX_DMA_PAGESIZE)), - - /** The base image and heap must be below this address. */ - FIRST_RESERVED_PAGE = MBOX_DMA_ADDR, + MBOX_DMA_ADDR = INITIAL_PT_OFFSET + PTSIZE, + MBOX_DMA_SIZE = MBOX_DMA_PAGES * MBOX_DMA_PAGESIZE, + + /** We need to reserve a hole in heap memory for the page table, + * etc. Use these constants to define the hole. */ + FIRST_RESERVED_PAGE = INITIAL_PT_OFFSET, + END_RESERVED_PAGE = INITIAL_PT_OFFSET + + PTSIZE + MBOX_DMA_SIZE, // Tells processor to ignore HRMOR FORCE_PHYS_ADDR = 0x8000000000000000, diff --git a/src/include/sys/mm.h b/src/include/sys/mm.h index 959c2fa57..38272c684 100644 --- a/src/include/sys/mm.h +++ b/src/include/sys/mm.h @@ -99,6 +99,7 @@ int mm_set_permission(void* va, uint64_t size, uint64_t access_type); enum MM_EXTEND_SIZE { + MM_EXTEND_POST_SECUREBOOT, //< Extend memory to include bottom of cache. MM_EXTEND_FULL_CACHE, //< Extend memory to include full cache (8mb). MM_EXTEND_REAL_MEMORY, //< Extend memory into real mainstore. }; diff --git a/src/include/usr/hbotcompid.H b/src/include/usr/hbotcompid.H index ce725012d..382cbd685 100644 --- a/src/include/usr/hbotcompid.H +++ b/src/include/usr/hbotcompid.H @@ -275,6 +275,14 @@ const compId_t VPD_COMP_ID = 0x1D00; const char VPD_COMP_NAME[] = "vpd"; //@} +/** @name SECURE + * Secureboot Support component + */ +//@{ +const compId_t SECURE_COMP_ID = 0x1E00; +const char SECURE_COMP_NAME[] = "secure"; +//@} + /** @name HSVC * Host Services component diff --git a/src/include/usr/secureboot/secure_reasoncodes.H b/src/include/usr/secureboot/secure_reasoncodes.H new file mode 100644 index 000000000..eac9dfda9 --- /dev/null +++ b/src/include/usr/secureboot/secure_reasoncodes.H @@ -0,0 +1,43 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/usr/secureboot/secure_reasoncodes.H $ */ +/* */ +/* 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 */ +#ifndef __SECUREBOOT_REASONCODES_H +#define __SECUREBOOT_REASONCODES_H + +#include + +namespace SECUREBOOT +{ + enum SECUREModuleId + { + MOD_SECURE_INVALID = 0x00, + MOD_SECURE_BLINDPURGE = 0x01, + }; + + enum SECUREReasonCode + { + RC_PURGEOP_PENDING = SECURE_COMP_ID | 0x01, + RC_PURGEOP_FAIL_COMPLETE = SECURE_COMP_ID | 0x02, + }; +} + +#endif diff --git a/src/include/usr/secureboot/service.H b/src/include/usr/secureboot/service.H new file mode 100644 index 000000000..a83d5d510 --- /dev/null +++ b/src/include/usr/secureboot/service.H @@ -0,0 +1,41 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/usr/secureboot/service.H $ */ +/* */ +/* 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 */ +#ifndef __SECUREBOOT_SERVICE_H +#define __SECUREBOOT_SERVICE_H + +namespace SECUREBOOT +{ + /** @brief Perform initialization of Secureboot for the Base image. + * + * - Copy secure header from original location. + * - Perform blind-purge of bottom-half of cache. + * - Add bottom-half of cache to available memory. + */ + void* initializeBase(void* unused); + + /** @brief Determines if Secureboot is enabled. + */ + bool enabled(); +} + +#endif diff --git a/src/include/util/align.H b/src/include/util/align.H index 8ba0e06b9..f951b7ce9 100644 --- a/src/include/util/align.H +++ b/src/include/util/align.H @@ -1,25 +1,25 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/include/util/align.H $ -// -// 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/include/util/align.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2011,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 */ #ifndef __UTIL_ALIGN_H #define __UTIL_ALIGN_H @@ -43,4 +43,11 @@ // Return a number <= input that is aligned on a page boundary #define ALIGN_PAGE_DOWN(u) ((u) - (u)%PAGESIZE) +// Return a number >= input that is aligned up to the next MB boundary +#define ALIGN_MEGABYTE(u) (((u) + (MEGABYTE-1)) & ~(MEGABYTE-1)) + +// Return a number <= input that is aligned on a MB boundary +#define ALIGN_MEGABYTE_DOWN(u) ((u) - (u)%MEGABYTE) + + #endif diff --git a/src/kernel/basesegment.C b/src/kernel/basesegment.C index 5317d2a25..e9f966433 100644 --- a/src/kernel/basesegment.C +++ b/src/kernel/basesegment.C @@ -62,8 +62,6 @@ void BaseSegment::_init() iv_block = new Block(0x0, iv_physMemSize); iv_block->setParent(this); - // TODO iv_physMemSize needs to be recalculated when DIMM memory is avail. - // Set default page permissions on block. for (uint64_t i = 0; i < VMM_BASE_BLOCK_SIZE; i += PAGESIZE) { @@ -246,9 +244,9 @@ int BaseSegment::_mmExtend(void) // Call to allocate a block passing in the requested address of where the // SPTEs should be created - int rc = _mmAllocBlock(NULL, reinterpret_cast(l_vaddr), l_size, false, - /*(uint64_t *)*/reinterpret_cast(l_vaddr)); - + int rc = _mmAllocBlock(NULL, reinterpret_cast(l_vaddr), l_size, + false, reinterpret_cast(l_vaddr)); + if (rc) { printk("Got an error in mmAllocBlock\n"); @@ -264,7 +262,8 @@ int BaseSegment::_mmExtend(void) // Now need to take the pages past the SPTE and add them to the heap. //get the number of pages needed to hold the SPTE entries. - uint64_t spte_pages = (ALIGN_PAGE(l_size)/PAGESIZE * sizeof(ShadowPTE))/PAGESIZE; + uint64_t spte_pages = (ALIGN_PAGE(l_size)/PAGESIZE * + sizeof(ShadowPTE))/PAGESIZE; printkd("Number of SPTE pages %ld\n", spte_pages); @@ -273,7 +272,8 @@ int BaseSegment::_mmExtend(void) // used for the SPTE. // Call Add Memory with the starting address , size.. it will put the pages - // on the heap call this with the address being the first page past the SPTE. + // on the heap call this with the address being the first page past the + // SPTE. PageManager::addMemory(l_vaddr + (spte_pages*PAGESIZE), l_size/PAGESIZE - spte_pages); @@ -291,7 +291,7 @@ int BaseSegment::_mmExtend(void) /** * Allocates a block of virtual memory of the given size - * to at a specified physical address. + * to at a specified physical address. */ int BaseSegment::mmLinearMap(void *i_paddr, uint64_t i_size) { @@ -300,7 +300,7 @@ int BaseSegment::mmLinearMap(void *i_paddr, uint64_t i_size) /** * Allocates a block of virtual memory of the given size - * to at a specified physical address + * to at a specified physical address */ int BaseSegment::_mmLinearMap(void *i_paddr, uint64_t i_size) { diff --git a/src/kernel/misc.C b/src/kernel/misc.C index e280a1527..6d7e866f6 100644 --- a/src/kernel/misc.C +++ b/src/kernel/misc.C @@ -314,6 +314,51 @@ namespace KernelMisc kassert(false); } + int expand_half_cache() + { + static bool executed = false; + + if (executed) // Why are we being called a second time? + { + return -EFAULT; + } + + uint64_t startAddr = 512*KILOBYTE; + uint64_t endAddr = 1*MEGABYTE; + + size_t cache_columns = 0; + + switch(CpuID::getCpuType()) + { + case CORE_POWER8_MURANO: + case CORE_POWER8_VENICE: + cache_columns = 4; + break; + + default: + kassert(false); + break; + } + + for (size_t i = 0; i < cache_columns; i++) + { + size_t offset = i * MEGABYTE; + populate_cache_lines( + reinterpret_cast(startAddr + offset), + reinterpret_cast(endAddr + offset)); + + PageManager::addMemory(startAddr + offset, + (512*KILOBYTE)/PAGESIZE); + } + + executed = true; + + KernelMemState::setMemScratchReg(KernelMemState::MEM_CONTAINED_L3, + KernelMemState::HALF_CACHE); + + return 0; + } + int expand_full_cache() { static bool executed = false; @@ -334,8 +379,10 @@ namespace KernelMisc ( VmmManager::INITIAL_MEM_SIZE ) ; endAddr = reinterpret_cast(8 * MEGABYTE); + break; default: + kassert(false); break; } diff --git a/src/kernel/pagemgr.C b/src/kernel/pagemgr.C index f1e74c695..c402c51bb 100644 --- a/src/kernel/pagemgr.C +++ b/src/kernel/pagemgr.C @@ -187,44 +187,98 @@ uint64_t PageManager::availPages() PageManager::PageManager() : iv_pagesAvail(0), iv_pagesTotal(0), iv_lock(0) { - // Determine first page of un-allocated memory - // and number of pages available. - uint64_t addr = firstPageAddr(); - size_t length = (MEMLEN - addr) / PAGESIZE; + this->_initialize(); +} +void PageManager::_initialize() +{ + typedef PageManagerCore::page_t page_t; + uint64_t totalPages = 0; - // Display. - printk("Initializing PageManager with %zd pages starting at %lx...", - length, - addr); + page_t* startAddr = reinterpret_cast(firstPageAddr()); + page_t* endAddr = reinterpret_cast(VmmManager::INITIAL_MEM_SIZE); + printk("Initializing PageManager starting at %p...", startAddr); - // Populate L3 cache lines. - uint64_t* cache_line = reinterpret_cast(addr); - uint64_t* end_cache_line = (uint64_t*) VmmManager::INITIAL_MEM_SIZE; - KernelMisc::populate_cache_lines(cache_line, end_cache_line); + // Calculate chunks along the top half of the L3 and erase them. + uint64_t currentBlock = reinterpret_cast(startAddr); + do + { + if (currentBlock % (1*MEGABYTE) >= (512*KILOBYTE)) + { + currentBlock = ALIGN_MEGABYTE(currentBlock); + continue; + } + uint64_t endBlock = ALIGN_MEGABYTE_DOWN(currentBlock) + 512*KILOBYTE; - // Allocate pages - iv_heapKernel.addMemory( addr, RESERVED_PAGES ); - addr += RESERVED_PAGES * PAGESIZE; - length -= RESERVED_PAGES; + // Populate L3 cache lines for this chunk. + KernelMisc::populate_cache_lines( + reinterpret_cast(currentBlock), + reinterpret_cast(endBlock)); - iv_heap.addMemory( addr, length ); + // Adjust address to compensate for reserved hole and add to + // heap... - KernelMemState::setMemScratchReg(KernelMemState::MEM_CONTAINED_L3, - KernelMemState::HALF_CACHE); + // Check if this block starts in the hole. + if ((currentBlock >= VmmManager::FIRST_RESERVED_PAGE) && + (currentBlock < VmmManager::END_RESERVED_PAGE)) + { + // End of the block is in the hole, skip. + if (endBlock < VmmManager::END_RESERVED_PAGE) + { + currentBlock = ALIGN_MEGABYTE(endBlock); + continue; + } - // Statistics - iv_pagesTotal = length; - iv_pagesAvail = length; - cv_low_page_count = length; + // Advance the current block past the hole. + currentBlock = VmmManager::END_RESERVED_PAGE; + } + // Check if the block is has the hole in it. + if ((endBlock >= VmmManager::FIRST_RESERVED_PAGE) && + (currentBlock < VmmManager::FIRST_RESERVED_PAGE)) + { + // Hole is at the end of the block, shrink it down. + if (endBlock < VmmManager::END_RESERVED_PAGE) + { + endBlock = VmmManager::FIRST_RESERVED_PAGE; + } + // Hole is in the middle... yuck. + else + { + uint64_t pages = + (VmmManager::FIRST_RESERVED_PAGE - currentBlock) / PAGESIZE; + + iv_heap.addMemory(currentBlock, pages); + totalPages += pages; + + currentBlock = VmmManager::END_RESERVED_PAGE; + } + } + + uint64_t pages = (endBlock - currentBlock) / PAGESIZE; + + iv_heap.addMemory(currentBlock, pages); + totalPages += pages; - // @TODO: Venice: Clear 3-8MB region and add to free memory pool. - // Can't do this now due to fake-PNOR driver. - // iv_heap.addMemory(...); + currentBlock = ALIGN_MEGABYTE(endBlock); - printk("done\n"); + } while (reinterpret_cast(currentBlock) != endAddr); + + printk("%ld pages.\n", totalPages); + + // Reserve pages for the kernel. + iv_heapKernel.addMemory(reinterpret_cast( + iv_heap.allocatePage(KERNEL_HEAP_RESERVED_PAGES)), + KERNEL_HEAP_RESERVED_PAGES); + + // Statistics + iv_pagesTotal = totalPages; + iv_pagesAvail = totalPages; + cv_low_page_count = totalPages; + + KernelMemState::setMemScratchReg(KernelMemState::MEM_CONTAINED_L3, + KernelMemState::PRE_SECURE_BOOT); } void* PageManager::_allocatePage(size_t n, bool userspace) @@ -271,11 +325,10 @@ void PageManager::_freePage(void* p, size_t n) __sync_add_and_fetch(&iv_pagesAvail, n); // Keep the reserved page count for the kernel full - // Should it be continuous RESERVED_PAGES?? size_t ks = iv_heapKernel.getFreePageCount(); - if(ks < RESERVED_PAGES) + if(ks < KERNEL_HEAP_RESERVED_PAGES) { - ks = RESERVED_PAGES - ks; + ks = KERNEL_HEAP_RESERVED_PAGES - ks; PageManagerCore::page_t * page = iv_heap.allocatePage(ks); if(page) { diff --git a/src/kernel/syscall.C b/src/kernel/syscall.C index 610f36d26..1c9b62ab6 100644 --- a/src/kernel/syscall.C +++ b/src/kernel/syscall.C @@ -865,6 +865,10 @@ namespace Systemcalls switch (size) { + case MM_EXTEND_POST_SECUREBOOT: + TASK_SETRTN(t, KernelMisc::expand_half_cache()); + break; + case MM_EXTEND_FULL_CACHE: TASK_SETRTN(t, KernelMisc::expand_full_cache()); break; diff --git a/src/makefile b/src/makefile index 7b99eb510..df5c82d0e 100644 --- a/src/makefile +++ b/src/makefile @@ -46,7 +46,7 @@ DIRECT_BOOT_OBJECTS = start.o kernel.o taskmgr.o cpumgr.o syscall.o \ shutdown.o forceattn_p8.o terminate.o ipc.o machchk.o BASE_MODULES = trace errl devicefw scom xscom initservice \ - pnor vfs + secureboot_base pnor vfs EXTENDED_MODULES = targeting ecmddatabuffer fapi hwp plat \ extinitsvc istepdisp hwas fsi fsiscom i2c intr scan \ @@ -57,7 +57,7 @@ EXTENDED_MODULES = targeting ecmddatabuffer fapi hwp plat \ core_activate dram_initialization edi_ei_initialization \ establish_system_smp occ\ nest_chiplets start_payload thread_activate slave_sbe \ - attn runtime ibscom dump tod_init + attn runtime ibscom dump tod_init secureboot_ext TESTCASE_MODULES = cxxtest testtrace testerrl testdevicefw testsyslib \ testscom testxscom testtargeting testinitservice testkernel \ diff --git a/src/usr/initservice/baseinitsvc/initservice.C b/src/usr/initservice/baseinitsvc/initservice.C index b0ee9730a..4e8dd8aa9 100644 --- a/src/usr/initservice/baseinitsvc/initservice.C +++ b/src/usr/initservice/baseinitsvc/initservice.C @@ -307,8 +307,12 @@ errlHndl_t InitService::executeFn( do { - // - l_errl = checkNLoadModule( i_ptask ); + // If the module is not in the base image, then we must ensure that + // the module has been loaded already. + if (BASE_IMAGE != i_ptask->taskflags.module_type) + { + l_errl = checkNLoadModule( i_ptask ); + } if ( l_errl ) { TRACFCOMP(g_trac_initsvc, diff --git a/src/usr/initservice/baseinitsvc/initsvctasks.H b/src/usr/initservice/baseinitsvc/initsvctasks.H index eed58f592..92111e40d 100644 --- a/src/usr/initservice/baseinitsvc/initsvctasks.H +++ b/src/usr/initservice/baseinitsvc/initsvctasks.H @@ -1,25 +1,25 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/usr/initservice/baseinitsvc/initsvctasks.H $ -// -// 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/usr/initservice/baseinitsvc/initsvctasks.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2011,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 */ #ifndef __INIT_SVC_TASKS_H #define __INIT_SVC_TASKS_H @@ -33,6 +33,7 @@ #include #include "initservice.H" +#include namespace INITSERVICE { @@ -40,6 +41,18 @@ namespace INITSERVICE const TaskInfo g_taskinfolist[] = { + /** + * @brief Secureboot Base Initialization + */ + { + "libsecureboot_base.so", + &SECUREBOOT::initializeBase, + { + START_FN, + BASE_IMAGE, + } + }, + /** * @brief PNOR Driver Task */ diff --git a/src/usr/makefile b/src/usr/makefile index 49a7a5e05..1bad2ebe7 100644 --- a/src/usr/makefile +++ b/src/usr/makefile @@ -30,6 +30,6 @@ SUBDIRS = example.d trace.d cxxtest.d testcore.d errl.d devicefw.d \ scom.d xscom.d targeting.d initservice.d hwpf.d \ ecmddatabuffer.d pnor.d i2c.d vfs.d fsi.d hwas.d fsiscom.d \ intr.d pore.d util.d mbox.d diag.d vpd.d scan.d \ - runtime.d ibscom.d dump.d + runtime.d ibscom.d dump.d secureboot.d include ${ROOTPATH}/config.mk diff --git a/src/usr/secureboot/base/header.C b/src/usr/secureboot/base/header.C new file mode 100644 index 000000000..00f808e1b --- /dev/null +++ b/src/usr/secureboot/base/header.C @@ -0,0 +1,57 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/secureboot/base/header.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 "header.H" +#include +#include +#include + +namespace SECUREBOOT +{ + void Header::loadBaseHeader() + { + // Calculate original address of the secureboot header. + // Zero is purposefully not mapped into the VMM tables, so we + // can't use that for the virtual-to-real translation. Since + // this object is in the base image, EA = HRMOR | PA, so we can + // use PA - EA to find the HRMOR. + uint64_t addr = mm_virt_to_phys(this) - + reinterpret_cast(this); + addr -= PAGESIZE; + + // Map in the header. + void* origHeader = mm_block_map(reinterpret_cast(addr), + PAGESIZE); + + // Copy header to a save area. + // In the future we might want to just extract pieces of the + // header. The header is important when we start updating + // the TPM PCRs. + iv_data = malloc(PAGESIZE); + memcpy(iv_data, origHeader, PAGESIZE); + + // Unmap the header. + mm_block_unmap(origHeader); + + return; + } +} diff --git a/src/usr/secureboot/base/makefile b/src/usr/secureboot/base/makefile new file mode 100644 index 000000000..8a63e1537 --- /dev/null +++ b/src/usr/secureboot/base/makefile @@ -0,0 +1,30 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/secureboot/base/makefile $ +# +# 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 +ROOTPATH = ../../../.. +MODULE = secureboot_base +SUBDIRS = + +OBJS = service.o settings.o header.o purge.o + +CFLAGS += -iquote ../ +include ${ROOTPATH}/config.mk 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 +#include +#include +#include +#include + +#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; + } + +} diff --git a/src/usr/secureboot/base/purge.H b/src/usr/secureboot/base/purge.H new file mode 100644 index 000000000..f10edf0aa --- /dev/null +++ b/src/usr/secureboot/base/purge.H @@ -0,0 +1,35 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/secureboot/base/purge.H $ */ +/* */ +/* 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 */ +#ifndef __SECUREBOOT_PURGE_H +#define __SECUREBOOT_PURGE_H + +#include + +namespace SECUREBOOT +{ + /** @brief Issues the SCOMs to the master EX's L3 to perform a blind purge. + */ + errlHndl_t issueBlindPurge(); +} + +#endif diff --git a/src/usr/secureboot/base/service.C b/src/usr/secureboot/base/service.C new file mode 100644 index 000000000..bb18bef9f --- /dev/null +++ b/src/usr/secureboot/base/service.C @@ -0,0 +1,68 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/secureboot/base/service.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 +#include +#include +#include +#include + +#include "settings.H" +#include "header.H" +#include "purge.H" + +namespace SECUREBOOT +{ + void* initializeBase(void* unused) + { + errlHndl_t l_errl = NULL; + + do + { + // Load original secureboot header. + if (enabled()) + { + Singleton
::instance().loadBaseHeader(); + } + + // Blind-purge lower portion of cache. + l_errl = issueBlindPurge(); + if (l_errl) + { + break; + } + + // Extend memory footprint into lower portion of cache. + // This can only fail is someone has already called to extend + // to post-secureboot state. Major coding bug, so just assert. + assert(0 == mm_extend(MM_EXTEND_POST_SECUREBOOT)); + + } while(0); + + return l_errl; + } + + bool enabled() + { + return Singleton::instance().getEnabled(); + } +} diff --git a/src/usr/secureboot/base/settings.C b/src/usr/secureboot/base/settings.C new file mode 100644 index 000000000..dfacf46e7 --- /dev/null +++ b/src/usr/secureboot/base/settings.C @@ -0,0 +1,52 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/secureboot/base/settings.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 +#include + +#include "settings.H" + +namespace SECUREBOOT +{ + const uint64_t Settings::SECURITY_SWITCH_REGISTER = 0x00010005; + const uint64_t + Settings::SECURITY_SWITCH_TRUSTED_BOOT = 0x4000000000000000ull; + + void Settings::_init() + { + errlHndl_t l_errl = NULL; + size_t size = sizeof(iv_regValue); + + // Read / cache security switch setting from processor. + l_errl = deviceRead(TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL, + &iv_regValue, size, + DEVICE_SCOM_ADDRESS(SECURITY_SWITCH_REGISTER)); + + // If this errors, we're in bad shape and shouldn't trust anything. + assert(NULL == l_errl); + } + + bool Settings::getEnabled() + { + return 0 != (iv_regValue & SECURITY_SWITCH_TRUSTED_BOOT); + } +} diff --git a/src/usr/secureboot/ext/makefile b/src/usr/secureboot/ext/makefile new file mode 100644 index 000000000..dd62accc2 --- /dev/null +++ b/src/usr/secureboot/ext/makefile @@ -0,0 +1,30 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/secureboot/ext/makefile $ +# +# 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 +ROOTPATH = ../../../.. +MODULE = secureboot_ext +SUBDIRS = + +OBJS = + +CFLAGS += -iquote ../ +include ${ROOTPATH}/config.mk diff --git a/src/usr/secureboot/header.H b/src/usr/secureboot/header.H new file mode 100644 index 000000000..4b905044a --- /dev/null +++ b/src/usr/secureboot/header.H @@ -0,0 +1,53 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/secureboot/header.H $ */ +/* */ +/* 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 */ +#ifndef __SECUREBOOT_HEADER_H +#define __SECUREBOOT_HEADER_H + +#include + +/** @file header.H + * + * @brief Classes for manipulating Secureboot headers. + */ + +namespace SECUREBOOT +{ + /** @class Header + * @brief Class for storing the original Secureboot header for later use. + */ + class Header + { + public: + Header() : iv_data(NULL) {}; + ~Header() {}; + + /** @brief Extract header from original HRMOR - 1 page address. */ + void loadBaseHeader(); + + private: + /** Copy of the original secureboot header for the base image. */ + void* iv_data; + }; +}; + +#endif diff --git a/src/usr/secureboot/makefile b/src/usr/secureboot/makefile new file mode 100644 index 000000000..d406bb620 --- /dev/null +++ b/src/usr/secureboot/makefile @@ -0,0 +1,27 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/secureboot/makefile $ +# +# 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 +ROOTPATH = ../../.. + +SUBDIRS = base.d ext.d + +include ${ROOTPATH}/config.mk diff --git a/src/usr/secureboot/settings.H b/src/usr/secureboot/settings.H new file mode 100644 index 000000000..ee5485027 --- /dev/null +++ b/src/usr/secureboot/settings.H @@ -0,0 +1,56 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/secureboot/settings.H $ */ +/* */ +/* 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 */ +#ifndef __SECUREBOOT_SETTINGS_H +#define __SECUREBOOT_SETTINGS_H + +#include + +namespace SECUREBOOT +{ + /** @class Settings + * + * @brief Caches and parses the hardware settings for Secureboot. + */ + class Settings + { + public: + Settings() : iv_regValue(0) { _init(); }; + ~Settings() {}; + + /** @brief Determine if Secureboot is enabled. */ + bool getEnabled(); + + private: + void _init(); + + /** Cached register value. */ + uint64_t iv_regValue; + + /** SCOM address for security settings. */ + static const uint64_t SECURITY_SWITCH_REGISTER; + /** Bitfield mask for Secureboot enable flag. */ + static const uint64_t SECURITY_SWITCH_TRUSTED_BOOT; + }; +} + +#endif -- cgit v1.2.1