From a702bf170b58a8be92fb66bae6c9f0bff23a4cce Mon Sep 17 00:00:00 2001 From: Dan Crowell Date: Fri, 22 Sep 2017 13:15:22 -0500 Subject: Use a VMM allocator for the giant WOFDATA lid The WOFDATA lid is now 12MB which is too big for our default malloc logic that requires contiguous memory. Instead we will use a custom VMM block to page in new pages dynamically as needed. Change-Id: I50360812328d6811716955b7a22c396566044a87 CQ: SW402766 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/46640 Tested-by: Jenkins Server Reviewed-by: Nicholas E. Bofferding Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Reviewed-by: Daniel M. Crowell Tested-by: Daniel M. Crowell --- src/usr/fapi2/plat_wof_access.C | 146 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 145 insertions(+), 1 deletion(-) (limited to 'src/usr/fapi2') diff --git a/src/usr/fapi2/plat_wof_access.C b/src/usr/fapi2/plat_wof_access.C index 66b2fb024..6db703d5e 100644 --- a/src/usr/fapi2/plat_wof_access.C +++ b/src/usr/fapi2/plat_wof_access.C @@ -37,6 +37,8 @@ #include #include #include +#include +#include namespace fapi2 { @@ -50,6 +52,12 @@ const uint32_t RES_VERSION_MASK = 0xFF; const uint32_t WOF_IMAGE_VERSION = 1; const uint32_t WOF_TABLES_VERSION = 1; +#ifndef __HOSTBOOT_RUNTIME +// Remember that we have already allocated the VMM space for +// the WOFDATA lid +static void* g_wofdataVMM = nullptr; +#endif + /* WOF Tables In PNOR @@ -170,9 +178,84 @@ fapi2::ReturnCode platParseWOFTables(uint8_t* o_wofData) break; } - // Allocate space, remember to free it later + FAPI_INF("WOFDATA lid is %d bytes", l_lidImageSize); + +#ifdef __HOSTBOOT_RUNTIME + // Locally allocate space for the lid l_pWofImage = static_cast(malloc(l_lidImageSize)); +#else + // Use a special VMM block to avoid the requirement for + // contiguous memory + int l_mm_rc = 0; + if( !g_wofdataVMM ) + { + l_mm_rc = mm_alloc_block( nullptr, + reinterpret_cast(VMM_VADDR_WOFDATA_LID), + VMM_SIZE_WOFDATA_LID ); + if(l_mm_rc != 0) + { + FAPI_INF("Fail from mm_alloc_block for WOFDATA, rc=%d", l_mm_rc); + /*@ + * @errortype + * @moduleid fapi2::MOD_FAPI2_PLAT_PARSE_WOF_TABLES + * @reasoncode fapi2::RC_MM_ALLOC_BLOCK_FAILED + * @userdata1 Address being allocated + * @userdata2[00:31] Size of block allocation + * @userdata2[32:63] rc from mm_alloc_block + * @devdesc Error calling mm_alloc_block for WOFDATA + * @custdesc Firmware Error + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + fapi2::MOD_FAPI2_PLAT_PARSE_WOF_TABLES, + fapi2::RC_MM_ALLOC_BLOCK_FAILED, + VMM_VADDR_WOFDATA_LID, + TWO_UINT32_TO_UINT64(VMM_SIZE_WOFDATA_LID, + l_mm_rc), + true); //software callout + l_rc.setPlatDataPtr(reinterpret_cast(l_errl)); + break; + } + + g_wofdataVMM = reinterpret_cast(VMM_VADDR_WOFDATA_LID); + } + + l_mm_rc = mm_set_permission( + reinterpret_cast(VMM_VADDR_WOFDATA_LID), + l_lidImageSize, + WRITABLE | ALLOCATE_FROM_ZERO ); + if(l_mm_rc != 0) + { + FAPI_INF("Fail from mm_set_permission for WOFDATA, rc=%d", l_mm_rc); + /*@ + * @errortype + * @moduleid fapi2::MOD_FAPI2_PLAT_PARSE_WOF_TABLES + * @reasoncode fapi2::RC_MM_SET_PERMISSION_FAILED + * @userdata1 Address being changed + * @userdata2[00:31] Size of change + * @userdata2[32:63] rc from mm_set_permission + * @devdesc Error calling mm_set_permission for WOFDATA + * @custdesc Firmware Error + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + fapi2::MOD_FAPI2_PLAT_PARSE_WOF_TABLES, + fapi2::RC_MM_SET_PERMISSION_FAILED, + VMM_VADDR_WOFDATA_LID, + TWO_UINT32_TO_UINT64(VMM_SIZE_WOFDATA_LID, + l_mm_rc), + true); //software callout + l_rc.setPlatDataPtr(reinterpret_cast(l_errl)); + break; + } + + // Point my local pointer at the VMM space we allocated + l_pWofImage = g_wofdataVMM; + +#endif + + // Get the tables from pnor or lid l_errl = l_wofLidMgr.getLid(l_pWofImage, l_lidImageSize); if(l_errl) @@ -427,7 +510,68 @@ fapi2::ReturnCode platParseWOFTables(uint8_t* o_wofData) // Free the wof tables memory if(l_pWofImage != nullptr) { +#ifdef __HOSTBOOT_RUNTIME free(l_pWofImage); + l_pWofImage = nullptr; + +#else + errlHndl_t l_tmpErr = nullptr; + // Release the memory we may still have allocated and set the + // permissions to prevent further access to it + int l_mm_rc = mm_remove_pages(RELEASE, + l_pWofImage, + VMM_SIZE_WOFDATA_LID); + if( l_mm_rc ) + { + FAPI_INF("Fail from mm_remove_pages for WOFDATA, rc=%d", l_mm_rc); + /*@ + * @errortype + * @moduleid fapi2::MOD_FAPI2_PLAT_PARSE_WOF_TABLES + * @reasoncode fapi2::RC_MM_REMOVE_PAGES_FAILED + * @userdata1 Address being removed + * @userdata2[00:31] Size of removal + * @userdata2[32:63] rc from mm_remove_pages + * @devdesc Error calling mm_remove_pages for WOFDATA + * @custdesc Firmware Error + */ + l_tmpErr = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + fapi2::MOD_FAPI2_PLAT_PARSE_WOF_TABLES, + fapi2::RC_MM_REMOVE_PAGES_FAILED, + reinterpret_cast(l_pWofImage), + TWO_UINT32_TO_UINT64(VMM_SIZE_WOFDATA_LID, + l_mm_rc), + true); //software callout + errlCommit(l_tmpErr,FAPI2_COMP_ID); + } + l_mm_rc = mm_set_permission(l_pWofImage, + VMM_SIZE_WOFDATA_LID, + NO_ACCESS | ALLOCATE_FROM_ZERO ); + if( l_mm_rc ) + { + FAPI_INF("Fail from mm_set_permission reset for WOFDATA, rc=%d", l_mm_rc); + /*@ + * @errortype + * @moduleid fapi2::MOD_FAPI2_PLAT_PARSE_WOF_TABLES + * @reasoncode fapi2::RC_MM_SET_PERMISSION2_FAILED + * @userdata1 Address being changed + * @userdata2[00:31] Size of change + * @userdata2[32:63] rc from mm_set_permission + * @devdesc Error calling mm_set_permission for WOFDATA + * @custdesc Firmware Error + */ + l_tmpErr = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + fapi2::MOD_FAPI2_PLAT_PARSE_WOF_TABLES, + fapi2::RC_MM_SET_PERMISSION2_FAILED, + reinterpret_cast(l_pWofImage), + TWO_UINT32_TO_UINT64(VMM_SIZE_WOFDATA_LID, + l_mm_rc), + true); //software callout + errlCommit(l_tmpErr,FAPI2_COMP_ID); + } +#endif + } FAPI_DBG("Exiting platParseWOFTables ...."); -- cgit v1.2.1