{"id":4532,"date":"2019-12-31T16:50:17","date_gmt":"2020-01-01T00:50:17","guid":{"rendered":"https:\/\/www.flamingspork.com\/blog\/?p=4532"},"modified":"2019-12-31T16:50:17","modified_gmt":"2020-01-01T00:50:17","slug":"speeding-up-blackbird-boot-the-sbe","status":"publish","type":"post","link":"https:\/\/www.flamingspork.com\/blog\/2019\/12\/31\/speeding-up-blackbird-boot-the-sbe\/","title":{"rendered":"Speeding up Blackbird boot: the SBE"},"content":{"rendered":"\n<p>The Self Boot Engine (SBE) is a small embedded PPE42 core inside the POWER9 CPU which has the unenvious job of getting a single POWER9 core ready enough to start executing instructions out of L3 cache, and poking some instructions into said cache for the core to start executing.<\/p>\n\n\n\n<p>It&#8217;s called the &#8220;Self Boot Engine&#8221; as in generations prior to POWER8, it was the job of the FSP (Service Processor) to do all of the booting for the CPU. On POWER8, there was still an SBE, but it was a custom instruction set (this was the Power On Reset Engine &#8211; PORE), while the PPE42 is basically a 32bit powerpc core cut straight down the middle (just the way to make it awkward for toolchains).<\/p>\n\n\n\n<p>One of the things I noted in my post on <a href=\"https:\/\/www.flamingspork.com\/blog\/2019\/12\/14\/booting-temporary-firmware-on-the-raptor-blackbird\/\">Booting temporary firmware on the Raptor Blackbird<\/a> is that we got serial console output from the SBE. It turns out one of thing things explicitly <strong>not<\/strong> enabled by Raptor in their build was this output as &#8220;it made the SBE boot much slower&#8221;. I&#8217;d actually long suspected this, but hadn&#8217;t really had the time to delve into it.<\/p>\n\n\n\n<p>Since for POWER9, the <a href=\"https:\/\/github.com\/open-power\/sbe\/\">firmware for the SBE is now open source<\/a> code, as is the <a href=\"https:\/\/github.com\/open-power\/ppe42-binutils\">ppe42-binutils<\/a> and <a href=\"https:\/\/github.com\/open-power\/ppe42-gcc\">ppe42-gcc<\/a> toolchain for it. This means we can hack on it!<\/p>\n\n\n\n<p><strong>WARNING:<\/strong> hacking on your SBE firmware can be <em>relatively<\/em> dangerous, as it&#8217;s literally the first thing that needs to work in order to boot the system, and there isn&#8217;t (AFAIK) publicly documented easy way to re-flash your SBE firmware if you mess it up.<\/p>\n\n\n\n<p>Seeing as we saw a regression in boot time with the UART output enabled, we need to look at the <a href=\"https:\/\/github.com\/open-power\/sbe\/blob\/245b9cef8f3cb4a537689b024a05088a0df6c15a\/src\/sbefw\/core\/sbeConsole.C#L164\">uartPutChar() function in sbeConsole.C<\/a> (error paths removed for clarity):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>static void uartPutChar(char c)\n{\n    #define SBE_FUNC \"uartPutChar\"\n    uint32_t rc = SBE_SEC_OPERATION_SUCCESSFUL;\n    do {\n        static const uint64_t DELAY_NS = 100;\n        static const uint64_t DELAY_LOOPS = 100000000;\n\n        uint64_t loops = 0;\n        uint8_t data = 0;\n        do {\n            rc = readReg(LSR, data);\n...\n            if(data == LSR_BAD || (data &amp; LSR_THRE))\n            {\n                break;\n            }\n            delay(DELAY_NS, 1000000);\n        } while(++loops &lt; DELAY_LOOPS);\n\n...\n        rc = writeReg(THR, c);\n...\n    } while(0);\n\n    #undef SBE_FUNC\n}<\/code><\/pre>\n\n\n\n<p>One thing you may notice if you&#8217;ve spent some time around serial ports is that it&#8217;s not using the transmit FIFO! While <a href=\"https:\/\/en.wikipedia.org\/wiki\/16550_UART\">according to Wikipedia<\/a> the original 16550 had a broken FIFO, but we&#8217;re certainly not going to be hooked up to an original rev of that silicon.<\/p>\n\n\n\n<p>To compare, let&#8217;s look at the skiboot code, which is all in <a href=\"https:\/\/github.com\/open-power\/skiboot\/blob\/v6.5\/hw\/lpc-uart.c#L98\">hw\/lpc-uart.c<\/a>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>static void uart_check_tx_room(void)\n{\n\tif (uart_read(REG_LSR) &amp; LSR_THRE) {\n\t\t\/* FIFO is 16 entries *\/\n\t\ttx_room = 16;\n\t\ttx_full = false;\n\t}\n}<\/code><\/pre>\n\n\n\n<p>The <a href=\"https:\/\/github.com\/open-power\/skiboot\/blob\/v6.5\/hw\/lpc-uart.c#L98\">uart_check_tx_room()<\/a> function is pretty simple, it checks if there&#8217;s room in the FIFO and knows that there&#8217;s 16 entries. Next, we have a busy loop that waits until there&#8217;s room again in the FIFO:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>static void uart_wait_tx_room(void)\n{\n\twhile (!tx_room) {\n\t\tuart_check_tx_room();\n\t\tif (!tx_room) {\n\t\t\tsmt_lowest();\n\t\t\tdo {\n\t\t\t\tbarrier();\n\t\t\t\tuart_check_tx_room();\n\t\t\t} while (!tx_room);\n\t\t\tsmt_medium();\n\t\t}\n\t}\n}<\/code><\/pre>\n\n\n\n<p>Finally, the bit of code that writes the (internal) log buffer out to a serial port:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/*\n * Internal console driver (output only)\n *\/\nstatic size_t uart_con_write(const char *buf, size_t len)\n{\n\tsize_t written = 0;\n\n\t\/* If LPC bus is bad, we just swallow data *\/\n\tif (!lpc_ok() &amp;&amp; !mmio_uart_base)\n\t\treturn written;\n\n\tlock(&amp;uart_lock);\n\twhile(written &lt; len) {\n\t\tif (tx_room == 0) {\n\t\t\tuart_wait_tx_room();\n\t\t\tif (tx_room == 0)\n\t\t\t\tgoto bail;\n\t\t} else {\n\t\t\tuart_write(REG_THR, buf&#91;written++]);\n\t\t\ttx_room--;\n\t\t}\n\t}\n bail:\n\tunlock(&amp;uart_lock);\n\treturn written;\n}<\/code><\/pre>\n\n\n\n<p>The skiboot code ends up being a bit more complicated thanks to a number of reasons, but the basic algorithm could be applied to the SBE code, and rather than busy waiting for each character to be written out before sending the other into the FIFO, we could just splat things down there and continue with life. So, I <a href=\"https:\/\/github.com\/open-power\/sbe\/pull\/18\/commits\/8522639f495c02ee0a6eb0a34313d7d8971636dc\">put together a patch to try out<\/a>.<\/p>\n\n\n\n<p>Before (i.e. upstream SBE code): it took about 15 seconds from &#8220;Welcome to SBE&#8221; to &#8220;Booting Hostboot&#8221;.<\/p>\n\n\n\n<p>Now (with my patch): Around 10 seconds.<\/p>\n\n\n\n<p>It&#8217;s a full five seconds (33%) faster to get through the SBE stage of booting. Wow.<\/p>\n\n\n\n<p>Hopefully somebody <a href=\"https:\/\/github.com\/open-power\/sbe\/pull\/18\">looks at the pull request<\/a> sometime soon, as it&#8217;s probably useful to a lot of people doing firmware and Operating System development.<\/p>\n\n\n\n<p>So, Happy New Year for Blackbird owners (I&#8217;ll publish a build with this and other misc improvements &#8220;soon&#8221;).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Self Boot Engine (SBE) is a small embedded PPE42 core inside the POWER9 CPU which has the unenvious job of getting a single POWER9 core ready enough to start executing instructions out of L3 cache, and poking some instructions &hellip; <a href=\"https:\/\/www.flamingspork.com\/blog\/2019\/12\/31\/speeding-up-blackbird-boot-the-sbe\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[76,5,615],"tags":[740,586,587,743],"class_list":["post-4532","post","type-post","status-publish","format-standard","hentry","category-code","category-cool-gadgets","category-powerpc","tag-blackbird","tag-firmware","tag-openpower","tag-sbe"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p5a6n8-1b6","jetpack-related-posts":[{"id":4495,"url":"https:\/\/www.flamingspork.com\/blog\/2019\/12\/10\/blackbird-singing-in-the-dead-of-night\/","url_meta":{"origin":4532,"position":0},"title":"Blackbird (singing in the dead of night..)","author":"Stewart Smith","date":"2019-12-10","format":false,"excerpt":"Way back when Raptor Computer Systems was doing pre-orders for the microATX Blackboard POWER9 system, I put in a pre-order. Since then, I've had a few life changes (such as moving to the US and starting to work for Amazon rather than IBM), but I've finally gone and done (most\u2026","rel":"","context":"In &quot;cool gadgets&quot;","block_context":{"text":"cool gadgets","link":"https:\/\/www.flamingspork.com\/blog\/category\/cool-gadgets\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2019\/12\/IMG_4007-scaled.jpg?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2019\/12\/IMG_4007-scaled.jpg?resize=350%2C200 1x, https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2019\/12\/IMG_4007-scaled.jpg?resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2019\/12\/IMG_4007-scaled.jpg?resize=700%2C400 2x, https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2019\/12\/IMG_4007-scaled.jpg?resize=1050%2C600 3x, https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2019\/12\/IMG_4007-scaled.jpg?resize=1400%2C800 4x"},"classes":[]},{"id":4544,"url":"https:\/\/www.flamingspork.com\/blog\/2020\/02\/01\/another-close-to-upstream-blackbird-firmware-build\/","url_meta":{"origin":4532,"position":1},"title":"Another close-to-upstream Blackbird Firmware Build","author":"Stewart Smith","date":"2020-02-01","format":false,"excerpt":"A few weeks ago (okay, close to six), I put up a firmware build for the Raptor Blackbird with close-to-upstream firmware (see here). Well, I've done another build! It's current op-build (as of this morning), but my branch with patches for the Raptor Blackbird. The skiboot patch is there, as\u2026","rel":"","context":"In &quot;OPAL&quot;","block_context":{"text":"OPAL","link":"https:\/\/www.flamingspork.com\/blog\/category\/opal\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":4522,"url":"https:\/\/www.flamingspork.com\/blog\/2019\/12\/14\/booting-temporary-firmware-on-the-raptor-blackbird\/","url_meta":{"origin":4532,"position":2},"title":"Booting temporary firmware on the Raptor Blackbird","author":"Stewart Smith","date":"2019-12-14","format":false,"excerpt":"In a future post, I'll detail how to build my ported-to-upstream Blackbird firmware. Here though, we'll explore booting some firmware temporarily to experiment. Step 1: Copy your new PNOR image over to the BMC.Step 2: ...Step 3: Profit! Okay, not really, once you've copied over your image, ensure the computer\u2026","rel":"","context":"In &quot;cool gadgets&quot;","block_context":{"text":"cool gadgets","link":"https:\/\/www.flamingspork.com\/blog\/category\/cool-gadgets\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2019\/12\/Screenshot-from-2019-12-14-09-59-38.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2019\/12\/Screenshot-from-2019-12-14-09-59-38.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2019\/12\/Screenshot-from-2019-12-14-09-59-38.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":4561,"url":"https:\/\/www.flamingspork.com\/blog\/2020\/03\/08\/yet-another-near-upstream-raptor-blackbird-firmware-build\/","url_meta":{"origin":4532,"position":3},"title":"Yet another near-upstream Raptor Blackbird firmware build","author":"Stewart Smith","date":"2020-03-08","format":false,"excerpt":"In what is coming a month occurance, I've put up yet another firmware build for the Raptor Blackbird with close-to-upstream firmware (see here and here for previous ones). Well, I\u00e2\u20ac\u2122ve done another build! It\u00e2\u20ac\u2122s current op-build (as of yesterday), but my branch with patches for the Raptor Blackbird. The skiboot\u2026","rel":"","context":"In &quot;General&quot;","block_context":{"text":"General","link":"https:\/\/www.flamingspork.com\/blog\/category\/general\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":4510,"url":"https:\/\/www.flamingspork.com\/blog\/2019\/12\/12\/blackbird-boots\/","url_meta":{"origin":4532,"position":4},"title":"Black(bird) boots!","author":"Stewart Smith","date":"2019-12-12","format":false,"excerpt":"Well, after the half false start of not having RAM so really not being able to do much (yeah yeah, I hear you - I'm weak for not just running Linux in L3), my RAM arrived today. Putting the sticks in was easy (of course), although does not make for\u2026","rel":"","context":"In &quot;cool gadgets&quot;","block_context":{"text":"cool gadgets","link":"https:\/\/www.flamingspork.com\/blog\/category\/cool-gadgets\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2019\/12\/Screenshot-from-2019-12-12-19-40-34-1.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2019\/12\/Screenshot-from-2019-12-12-19-40-34-1.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.flamingspork.com\/blog\/wp-content\/uploads\/2019\/12\/Screenshot-from-2019-12-12-19-40-34-1.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":4520,"url":"https:\/\/www.flamingspork.com\/blog\/2019\/12\/14\/building-openpower-firmware-on-fedora-31\/","url_meta":{"origin":4532,"position":5},"title":"Building OpenPOWER firmware on Fedora 31","author":"Stewart Smith","date":"2019-12-14","format":false,"excerpt":"One of the challenges with Fedora 31 is that \/usr\/bin\/python is now Python 3 rather than Python 2. Just about every python script in existence relies on \/usr\/bin\/python being Python 2 and not anything else. I can't really recall, but this probably happened with the 1.5 to 2 transition as\u2026","rel":"","context":"In &quot;General&quot;","block_context":{"text":"General","link":"https:\/\/www.flamingspork.com\/blog\/category\/general\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/posts\/4532","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/comments?post=4532"}],"version-history":[{"count":1,"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/posts\/4532\/revisions"}],"predecessor-version":[{"id":4533,"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/posts\/4532\/revisions\/4533"}],"wp:attachment":[{"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/media?parent=4532"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/categories?post=4532"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.flamingspork.com\/blog\/wp-json\/wp\/v2\/tags?post=4532"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}