aboutsummaryrefslogtreecommitdiffstats
path: root/roms/skiboot/external/mambo
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/skiboot/external/mambo
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/skiboot/external/mambo')
-rw-r--r--roms/skiboot/external/mambo/Makefile10
-rw-r--r--roms/skiboot/external/mambo/README.md73
-rw-r--r--roms/skiboot/external/mambo/cvc.binbin0 -> 9984 bytes
-rw-r--r--roms/skiboot/external/mambo/mambo-socket-proxy.c347
-rw-r--r--roms/skiboot/external/mambo/mambo_utils.tcl794
-rw-r--r--roms/skiboot/external/mambo/qtrace_utils.tcl16
-rw-r--r--roms/skiboot/external/mambo/skiboot.tcl732
7 files changed, 1972 insertions, 0 deletions
diff --git a/roms/skiboot/external/mambo/Makefile b/roms/skiboot/external/mambo/Makefile
new file mode 100644
index 000000000..942ebf20e
--- /dev/null
+++ b/roms/skiboot/external/mambo/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+CFLAGS=-O2 -m64 -pthread -Werror -Wall
+
+CC=$(CROSS)gcc
+
+all: mambo-socket-proxy
+
+clean:
+ rm -rf mambo-socket-proxy
diff --git a/roms/skiboot/external/mambo/README.md b/roms/skiboot/external/mambo/README.md
new file mode 100644
index 000000000..06a0f3185
--- /dev/null
+++ b/roms/skiboot/external/mambo/README.md
@@ -0,0 +1,73 @@
+# Running skiboot and Linux in Mambo
+
+The POWER8 Functional Simulator (aka Mambo) is free to use but not
+open source and is only supported on limited platforms. This is a
+guide to getting started guide with it with skiboot and linux.
+
+## Getting Started
+
+From a bare x86_64 Ubuntu 16.04 install, to running skiboot and linux
+in the simulator, you can do do the following:
+
+### Steps to get Running on Ubuntu
+xterm is needed by the simulator.
+```
+apt-get install xterm
+```
+
+### Download mambo from IBM
+Download systemsim-p8..deb from:
+http://www-304.ibm.com/support/customercare/sas/f/pwrfs/home.html
+```
+dpkg -i systemsim-p8*deb
+```
+
+### Grab your skiboot, linux and initramfs images
+How to build a skiboot.lid is in the top level README file.
+
+Use a 64 bit powerpc kernel here. If compiling yourself, we suggest
+using powernv_defconfig.
+
+If you use op-build to build a full set of OpenPower images, you’ll
+likely be able to extract skiboot, zImage.epapr (or vmlinux and
+rootfs.cpio.xz) from output/images. We suggest using the
+opal_defconfig.
+
+### Setup environment variables
+Setup environment variables to point to your images
+```
+export SKIBOOT_ZIMAGE=$HOME/src/op-build/output/images/zImage.epapr
+export SKIBOOT=$HOME/src/op-build/output/images/skiboot.lid
+export SKIBOOT_AUTORUN=1
+```
+If you want Mambo to autmatically run *AND* exit when the system is
+shutdown (or has a HW crash) use this:
+```
+export SKIBOOT_AUTORUN=2
+```
+If you want a vmlinux and separate initramfs you can also do this:
+```
+export SKIBOOT_ZIMAGE=$HOME/src/op-build/output/images/vmlinux
+export SKIBOOT_INITRD=$HOME/src/op-build/output/images/rootfs.cpio.xz
+export SKIBOOT=$HOME/src/skiboot/skiboot.lid
+export SKIBOOT_AUTORUN=1
+```
+
+### Using Real Container Verification Code for Secure Boot
+
+The CVC code dump is from a real machine, and the code is from the Hostboot
+project (see src/securerom). We just include the dump here for testing
+purposes.
+
+```
+export SKIBOOT_CVC_CODE=$HOME/src/skiboot/external/mambo/cvc.bin
+export SKIBOOT_ENABLE_MAMBO_STB=1
+```
+
+### Run the simulator
+```
+/opt/ibm/systemsim-p8/run/pegasus/power8 -f $HOME/src/skiboot/external/mambo/skiboot.tcl
+```
+
+This should open an xterm and start booting. It should take around
+20sec to get to a petitboot console.
diff --git a/roms/skiboot/external/mambo/cvc.bin b/roms/skiboot/external/mambo/cvc.bin
new file mode 100644
index 000000000..8d4c7e704
--- /dev/null
+++ b/roms/skiboot/external/mambo/cvc.bin
Binary files differ
diff --git a/roms/skiboot/external/mambo/mambo-socket-proxy.c b/roms/skiboot/external/mambo/mambo-socket-proxy.c
new file mode 100644
index 000000000..64b677045
--- /dev/null
+++ b/roms/skiboot/external/mambo/mambo-socket-proxy.c
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/*
+ * Compile with:
+ * gcc -static -O2 mambo-socket-proxy.c -o mambo-socket-proxy -pthread
+ * Run inside the simulator:
+ * - to forward host ssh connections to sim ssh server
+ * ./mambo-socket-proxy -h 10022 -s 22
+ * Then connect to port 10022 on your host
+ * ssh -p 10022 localhost
+ * - to allow http proxy access from inside the sim to local http proxy
+ * ./mambo-socket-proxy -b proxy.mynetwork -h 3128 -s 3128
+ *
+ * Copyright (C) 2017 Michael Neuling <mikey@neuling.org>, IBM
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <getopt.h>
+
+#define CALL_TCL 86
+#define BOGUS_SOCKET_CONN_PROBE_CODE 224
+#define BOGUS_SOCKET_CONN_SEND_CODE 225
+#define BOGUS_SOCKET_CONN_RECV_CODE 226
+
+static inline int callthru2(int command, unsigned long arg1, unsigned long arg2)
+{
+ register int c asm("r3") = command;
+ register unsigned long a1 asm("r4") = arg1;
+ register unsigned long a2 asm("r5") = arg2;
+ asm volatile (".long 0x000eaeb0":"=r" (c):"r"(c), "r"(a1), "r"(a2));
+ return (c);
+}
+
+static inline int callthru3(int command, unsigned long arg1, unsigned long arg2,
+ unsigned long arg3)
+{
+ register int c asm("r3") = command;
+ register unsigned long a1 asm("r4") = arg1;
+ register unsigned long a2 asm("r5") = arg2;
+ register unsigned long a3 asm("r6") = arg3;
+ asm volatile (".long 0x000eaeb0":"=r" (c):"r"(c), "r"(a1), "r"(a2),
+ "r"(a3));
+ return (c);
+}
+
+static inline int callthru4(int command, unsigned long arg1, unsigned long arg2,
+ unsigned long arg3, unsigned long arg4)
+{
+ register int c asm("r3") = command;
+ register unsigned long a1 asm("r4") = arg1;
+ register unsigned long a2 asm("r5") = arg2;
+ register unsigned long a3 asm("r6") = arg3;
+ register unsigned long a4 asm("r7") = arg4;
+ asm volatile (".long 0x000eaeb0":"=r" (c):"r"(c), "r"(a1), "r"(a2),
+ "r"(a3), "r"(a4));
+ return (c);
+}
+
+static inline int callthru5(int command, unsigned long arg1, unsigned long arg2,
+ unsigned long arg3, unsigned long arg4, unsigned long arg5)
+{
+ register int c asm("r3") = command;
+ register unsigned long a1 asm("r4") = arg1;
+ register unsigned long a2 asm("r5") = arg2;
+ register unsigned long a3 asm("r6") = arg3;
+ register unsigned long a4 asm("r7") = arg4;
+ register unsigned long a5 asm("r8") = arg5;
+ asm volatile (".long 0x000eaeb0":"=r" (c):"r"(c), "r"(a1), "r"(a2),
+ "r"(a3), "r"(a4), "r"(a5));
+ return (c);
+}
+
+unsigned long callthru_tcl(const char *str, int strlen)
+{
+ return callthru2(CALL_TCL, (unsigned long)str,
+ (unsigned long)strlen);
+}
+
+unsigned long bogus_socket_conn_probe(int dev, void *addr, int conn)
+{
+ return callthru3(BOGUS_SOCKET_CONN_PROBE_CODE,
+ (unsigned long)dev,
+ (unsigned long)addr,
+ (unsigned long)conn);
+}
+
+unsigned long bogus_socket_conn_recv(int dev, void *addr, int maxlen, int conn)
+{
+ return callthru4(BOGUS_SOCKET_CONN_RECV_CODE,
+ (unsigned long)dev,
+ (unsigned long)addr,
+ (unsigned long)maxlen,
+ (unsigned long)conn);
+}
+
+unsigned long bogus_socket_conn_send(int dev, void *addr, int maxlen, int conn)
+{
+ return callthru5(BOGUS_SOCKET_CONN_SEND_CODE,
+ (unsigned long)dev,
+ (unsigned long)addr,
+ (unsigned long)maxlen,
+ 0,
+ (unsigned long)conn);
+}
+
+#define BUF_MAX 1024
+
+struct sock_info {
+ char *host;
+ int sock;
+ int dev;
+ int open;
+ int conn;
+};
+
+void *recv_thread(void *ptr)
+{
+ struct timeval timeout;
+ struct sock_info *si = ptr;
+ char buf[BUF_MAX];
+ int len;
+ fd_set set;
+
+ /* 1 sec */
+
+
+ while(1) {
+ FD_ZERO(&set);
+ FD_SET(si->sock, &set);
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+ /* Set timeout to 1 second */
+ len = select(si->sock+1, &set, NULL, NULL, &timeout);
+ if (len <= 0) /* timeout */
+ len = -1;
+ else /* Receive from mambo tcp server */
+ len = recv(si->sock, &buf, BUF_MAX, 0);
+ if (len == 0) {
+ si->open = 0;
+ return NULL; /* closed */
+ }
+ if (len != -1) {
+ bogus_socket_conn_send(si->dev, &buf, len, si->conn);
+ }
+ if (!si->open)
+ return NULL;
+ }
+}
+
+#define POLL_MAX_NS 10000000
+
+void *send_thread(void *ptr)
+{
+ struct sock_info *si = ptr;
+ char buf[BUF_MAX];
+ int len;
+ struct timespec t;
+ int fault_retry = 16;
+
+ t.tv_sec = 0;
+ t.tv_nsec = POLL_MAX_NS;
+
+ while(1) {
+ /* Send to mambo tcp server */
+ len = bogus_socket_conn_recv(si->dev, &buf, BUF_MAX, si->conn);
+ if (len == -3 && fault_retry--) {
+ /* Page fault. Touch the buf and try again */
+ memset(buf, 0, BUF_MAX);
+ continue;
+ }
+ fault_retry = 16;
+
+ if (len == -1) /* EAGAIN */
+ nanosleep(&t , NULL);
+ else if (len > 0)
+ send(si->sock, &buf, len, 0);
+ else {
+ si->open = 0;
+ return NULL; /* closed */
+ }
+ if (!si->open)
+ return NULL;
+ }
+
+}
+
+void *connect_sockets(void *ptr)
+{
+ struct sock_info *si = ptr;
+ pthread_t recv, send;
+ unsigned long rc = 0;
+
+ if (pthread_create(&recv, NULL, recv_thread, si) ||
+ pthread_create(&send, NULL, send_thread, si)) {
+ rc = -1;
+ goto out;
+ }
+
+ if (pthread_join(recv, NULL) || pthread_join(send, NULL)) {
+ rc = -1;
+ goto out;
+ }
+
+out:
+ /* FIXME: Do shutdown better */
+ shutdown(si->sock, SHUT_WR);
+ si->open = 0;
+ free(si);
+ return (void *)rc;
+}
+
+void print_usage() {
+ printf("Usage:\n");
+ printf(" mambo-socket-proxy [-b <host>] -h <host port> -s <sim port>\n");
+ printf("\n");
+ printf(" -h <host port> : Port on the host to forward\n");
+ printf(" -s <host port> : Port in the sim to forward\n");
+ printf(" -b <host machine> : Connect sim port to host network\n");
+ printf("\n");
+}
+
+int main (int argc, char *argv[])
+{
+ char cmd[128];
+ struct sockaddr_in ser, client;
+ pthread_t sockets_thread;
+ struct sock_info *si;
+ int sock, conn, rc = 0, option = 0, one_shot = 0, c, sock_desc = 0;
+ char *host = NULL;
+ int host_port = -1, sim_port = -1;
+ int dev = 1; /* backwards starts at 1 so forwards can use 0 */
+
+ while ((option = getopt(argc, argv,"rb:h:s:")) != -1) {
+ switch (option) {
+ case 'b' :
+ host = optarg;
+ break;
+ case 'h' :
+ host_port = atoi(optarg);
+ break;
+ case 's' :
+ sim_port = atoi(optarg);
+ break;
+ default:
+ print_usage();
+ exit(1);
+ }
+ }
+
+ if (host_port == -1 || sim_port ==-1) {
+ print_usage();
+ exit(EXIT_FAILURE);
+ }
+
+ /*
+ * A host/backwards connection will use dev=0 and conn >= 0.
+ * The forwards connection will use dev >= 1 and conn=0
+ */
+ if (host) {
+ sock_desc = socket(PF_INET, SOCK_STREAM, 0);
+ ser.sin_family = AF_INET;
+ ser.sin_addr.s_addr = INADDR_ANY;
+ ser.sin_port = htons(sim_port);
+
+ if (bind(sock_desc, (struct sockaddr *) &ser, sizeof(ser)) < 0) {
+ perror("Can't connect to sim port");
+ rc = -1;
+ goto out;
+ }
+
+ listen(sock_desc, 3);
+ } else {
+ /*
+ * Cleaning up old bogus socket.
+ */
+ sprintf(cmd, "mysim bogus socket cleanup");
+ callthru_tcl(cmd, strlen(cmd));
+ sleep(1); /* Cleanup takes a while */
+ sprintf(cmd, "mysim bogus socket init 0 server "
+ "127.0.0.1 %i poll 0 nonblock", host_port);
+ callthru_tcl(cmd, strlen(cmd));
+ }
+
+ while (1) {
+
+ if (host) {
+ sock = accept(sock_desc, (struct sockaddr *)&client, (socklen_t*)&c);
+ if (sock < 0) {
+ perror("accept failed");
+ rc = -1;
+ goto out;
+ }
+
+ sprintf(cmd, "mysim bogus socket init %i client %s %i poll 0",
+ dev, host, host_port);
+ callthru_tcl(cmd, strlen(cmd));
+ while (bogus_socket_conn_probe(dev, NULL, 0) == -1)
+ sleep(1);
+ } else {
+ struct timespec t;
+ t.tv_sec = 0;
+ t.tv_nsec = 10000000;
+ do {
+ conn = bogus_socket_conn_probe(0, NULL, -1);
+ nanosleep(&t , NULL);
+ } while (conn == -1);
+
+ sock = socket(PF_INET, SOCK_STREAM, 0);
+ ser.sin_family = AF_INET;
+ ser.sin_port = htons(sim_port);
+ ser.sin_addr.s_addr = inet_addr("127.0.0.1");
+ memset(ser.sin_zero, '\0', sizeof ser.sin_zero);
+
+ if (connect(sock, (struct sockaddr *) &ser, sizeof(ser))) {
+ perror("Can't connect to sim port");
+ rc = -1;
+ goto out;
+ }
+ }
+
+ si = malloc(sizeof(struct sock_info));
+ si->host = host;
+ si->sock = sock;
+ si->dev = host?dev:0;
+ si->open = 1;
+ si->conn = host?0:conn;
+
+ if (pthread_create(&sockets_thread, NULL, connect_sockets, si)) {
+ rc = -1;
+ goto out;
+ }
+
+ if (one_shot)
+ break;
+ ++dev; // FIXME: do a real allocator
+ }
+out:
+ exit(rc);
+}
diff --git a/roms/skiboot/external/mambo/mambo_utils.tcl b/roms/skiboot/external/mambo/mambo_utils.tcl
new file mode 100644
index 000000000..96f8971ab
--- /dev/null
+++ b/roms/skiboot/external/mambo/mambo_utils.tcl
@@ -0,0 +1,794 @@
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+#
+# Make Mambo behave a bit more like gdb
+#
+set target_t 0
+set target_c 0
+set target_p 0
+
+proc target { { t 0 } { c 0 } { p 0 } } {
+ global target_t
+ global target_c
+ global target_p
+
+ set target_t $t
+ set target_c $c
+ set target_p $p
+
+ return "targeting cpu $p:$c:$t"
+}
+
+proc p { reg { t -1 } { c -1 } { p -1 } } {
+ global target_t
+ global target_c
+ global target_p
+
+ if { $t == -1 } { set t $target_t }
+ if { $c == -1 } { set c $target_c }
+ if { $p == -1 } { set p $target_p }
+
+ switch -regexp $reg {
+ ^r$ {
+ set val [mysim cpu $p:$c:$t display gprs]
+ }
+ ^r[0-9]+$ {
+ regexp "r(\[0-9\]*)" $reg dummy num
+ set val [mysim cpu $p:$c:$t display gpr $num]
+ }
+ ^f[0-9]+$ {
+ regexp "f(\[0-9\]*)" $reg dummy num
+ set val [mysim cpu $p:$c:$t display fpr $num]
+ }
+ ^v[0-9]+$ {
+ regexp "v(\[0-9\]*)" $reg dummy num
+ set val [mysim cpu $p:$c:$t display vmxr $num]
+ }
+ default {
+ set val [mysim cpu $p:$c:$t display spr $reg]
+ }
+ }
+
+ return "$val"
+}
+
+#
+# behave like gdb
+#
+proc sr { reg val { t -1} { c -1 } { p -1 } } {
+ global target_t
+ global target_c
+ global target_p
+
+ if { $t == -1 } { set t $target_t }
+ if { $c == -1 } { set c $target_c }
+ if { $p == -1 } { set p $target_p }
+
+ switch -regexp $reg {
+ ^r[0-9]+$ {
+ regexp "r(\[0-9\]*)" $reg dummy num
+ mysim cpu $p:$c:$t set gpr $num $val
+ }
+ ^f[0-9]+$ {
+ regexp "f(\[0-9\]*)" $reg dummy num
+ mysim cpu $p:$c:$t set fpr $num $val
+ }
+ ^v[0-9]+$ {
+ regexp "v(\[0-9\]*)" $reg dummy num
+ mysim cpu $p:$c:$t set vmxr $num $val
+ }
+ default {
+ mysim cpu $p:$c:$t set spr $reg $val
+ }
+ }
+ p $reg $t
+}
+
+proc b { addr } {
+ mysim trigger set pc $addr "just_stop"
+ set at [i $addr]
+ puts "breakpoint set at $at"
+}
+
+# Run until $console_string appears on the Linux console
+#
+# eg.
+# break_on_console "Freeing unused kernel memory:"
+# break_on_console "buildroot login:"
+
+proc break_on_console { console_string } {
+ mysim trigger set console "$console_string" "just_stop"
+}
+
+proc clear_console_break { console_string } {
+ mysim trigger clear console "$console_string"
+}
+
+proc wr { start stop } {
+ mysim trigger set memory system w $start $stop 0 "just_stop"
+}
+
+proc c { } {
+ mysim go
+}
+
+proc i { pc { t -1 } { c -1 } { p -1 } } {
+ global target_t
+ global target_c
+ global target_p
+
+ if { $t == -1 } { set t $target_t }
+ if { $c == -1 } { set c $target_c }
+ if { $p == -1 } { set p $target_p }
+
+ set pc_laddr [mysim cpu $p:$c:$t util itranslate $pc]
+ set inst [mysim cpu $p:$c:$t memory display $pc_laddr 4]
+ set disasm [mysim cpu $p:$c:$t util ppc_disasm $inst $pc]
+ return "\[$p:$c:$t\]: $pc ($pc_laddr) Enc:$inst : $disasm"
+}
+
+proc ipc { { t -1 } { c -1 } { p -1 } } {
+ global target_t
+ global target_c
+ global target_p
+
+ if { $t == -1 } { set t $target_t }
+ if { $c == -1 } { set c $target_c }
+ if { $p == -1 } { set p $target_p }
+
+ set pc [mysim cpu $p:$c:$t display spr pc]
+ i $pc $t $c $p
+}
+
+proc ipca { } {
+ set cpus [myconf query cpus]
+ set threads [myconf query processor/number_of_threads]
+
+ for { set i 0 } { $i < $cpus } { incr i 1 } {
+ for { set j 0 } { $j < $threads } { incr j 1 } {
+ puts [ipc $j $i]
+ }
+ }
+}
+
+proc pa { spr } {
+ set cpus [myconf query cpus]
+ set threads [myconf query processor/number_of_threads]
+
+ for { set i 0 } { $i < $cpus } { incr i 1 } {
+ for { set j 0 } { $j < $threads } { incr j 1 } {
+ set val [mysim cpu $i thread $j display spr $spr]
+ puts "CPU: $i THREAD: $j SPR $spr = $val"
+ }
+ }
+}
+
+proc s { {nr 1} } {
+ for { set i 0 } { $i < $nr } { incr i 1 } {
+ mysim step 1
+ ipca
+ }
+}
+
+proc S { {nr 1} } {
+ upvar #0 target_t t
+ upvar #0 target_c c
+ upvar #0 target_p p
+
+ for { set i 0 } { $i < $nr } { incr i 1 } {
+ mysim cpu $p:$c:$t step 1
+ puts [ipc]
+ }
+}
+
+proc z { count } {
+ while { $count > 0 } {
+ s
+ incr count -1
+ }
+}
+
+proc sample_pc { sample count } {
+ while { $count > 0 } {
+ mysim cycle $sample
+ ipc
+ incr count -1
+ }
+}
+
+proc e2p { ea } {
+ upvar #0 target_t t
+ upvar #0 target_c c
+ upvar #0 target_p p
+
+ set pa [ mysim cpu $p:$c:$t util dtranslate $ea ]
+ puts "$pa"
+}
+
+proc x { pa { size 8 } } {
+ set val [ mysim memory display $pa $size ]
+ puts "$pa : $val"
+}
+
+proc it { ea } {
+ upvar #0 target_t t
+ upvar #0 target_c c
+ upvar #0 target_p p
+
+ mysim cpu $p:$c:$t util itranslate $ea
+}
+proc dt { ea } {
+ upvar #0 target_t t
+ upvar #0 target_c c
+ upvar #0 target_p p
+
+ mysim cpu $p:$c:$t util dtranslate $ea
+}
+
+proc ex { ea { size 8 } } {
+ upvar #0 target_t t
+ upvar #0 target_c c
+ upvar #0 target_p p
+
+ set pa [ mysim cpu $p:$c:$t util dtranslate $ea ]
+ set val [ mysim memory display $pa $size ]
+ puts "$pa : $val"
+}
+
+proc di { location { count 16 } } {
+ set addr [expr $location & 0xfffffffffffffff0]
+ disasm_mem mysim $addr $count
+}
+
+proc hexdump { location count } {
+ set addr [expr $location & 0xfffffffffffffff0]
+ set top [expr $addr + ($count * 15)]
+ for { set i $addr } { $i < $top } { incr i 16 } {
+ set val [expr $i + (4 * 0)]
+ set val0 [format "%08x" [mysim memory display $val 4]]
+ set val [expr $i + (4 * 1)]
+ set val1 [format "%08x" [mysim memory display $val 4]]
+ set val [expr $i + (4 * 2)]
+ set val2 [format "%08x" [mysim memory display $val 4]]
+ set val [expr $i + (4 * 3)]
+ set val3 [format "%08x" [mysim memory display $val 4]]
+
+ set ascii ""
+ for { set j 0 } { $j < 16 } { incr j } {
+ set byte [get_char [expr $i + $j]]
+ if { $byte < 0x20 || $byte >= 127} {
+ set c "."
+ } else {
+ set c [format %c $byte]
+ }
+ set ascii [string cat "$ascii" "$c"]
+ }
+
+ set loc [format "0x%016x" $i]
+ puts "$loc: $val0 $val1 $val2 $val3 $ascii"
+ }
+}
+
+proc get_char { addr } {
+ return [expr [mysim memory display "$addr" 1]]
+}
+
+proc p_str { addr { limit 0 } } {
+ set addr_limit 0xfffffffffffffffff
+ if { $limit > 0 } { set addr_limit [expr $limit + $addr] }
+ set s ""
+
+ for {} { [get_char "$addr"] != 0} { incr addr 1 } {
+ # memory display returns hex values with a leading 0x
+ set c [format %c [get_char "$addr"]]
+ set s [string cat "$s" "$c"]
+ if { $addr == $addr_limit } { break }
+ }
+
+ puts "$s"
+}
+
+proc slbv {} {
+ upvar #0 target_t t
+ upvar #0 target_c c
+ upvar #0 target_p p
+
+ puts [mysim cpu $p:$c:$t display slb valid]
+}
+
+proc regs { { t -1 } { c -1 } { p -1 }} {
+ global target_t
+ global target_c
+ global target_p
+
+ if { $t == -1 } { set t $target_t }
+ if { $c == -1 } { set c $target_c }
+ if { $p == -1 } { set p $target_p }
+
+ puts "GPRS:"
+ puts [mysim cpu $p:$c:$t display gprs]
+}
+
+proc tlbv {} {
+ upvar #0 target_t t
+ upvar #0 target_c c
+ upvar #0 target_p p
+
+ puts "$p:$c:$t:TLB: ----------------------"
+ puts [mysim cpu $p:$c:$t display tlb valid]
+}
+
+proc exc { { i SystemReset } } {
+ upvar #0 target_t t
+ upvar #0 target_c c
+ upvar #0 target_p p
+
+ puts "$p:$c:$t:EXCEPTION:$i"
+ puts [mysim cpu $p:$c:$t interrupt $i]
+}
+
+proc just_stop { args } {
+ simstop
+ ipca
+}
+
+proc st { count } {
+ upvar #0 target_t t
+ upvar #0 target_c c
+ upvar #0 target_p p
+
+ set sp [mysim cpu $p:$c:$t display gpr 1]
+ puts "SP: $sp"
+ ipc
+ set lr [mysim cpu $p:$c:$t display spr lr]
+ i $lr
+ while { $count > 0 } {
+ set sp [mysim cpu $p:$c:$t util itranslate $sp]
+ set lr [mysim memory display [expr $sp++16] 8]
+ i $lr
+ set sp [mysim memory display $sp 8]
+
+ incr count -1
+ }
+}
+
+proc mywatch { } {
+ while { [mysim memory display 0x700 8] != 0 } {
+ mysim cycle 1
+ }
+ puts "condition occurred "
+ ipc
+}
+
+#
+# force gdb to attach
+#
+proc gdb { { timeout 0 } } {
+ mysim set fast off
+ mysim debugger wait $timeout
+}
+
+proc egdb { { timeout 0 }} {
+ upvar #0 target_t t
+ upvar #0 target_c c
+ upvar #0 target_p p
+
+ set srr0 [mysim cpu $p:$c:$t display spr srr0]
+ set srr1 [mysim cpu $p:$c:$t display spr srr1]
+ mysim cpu $p:$c:$t set spr pc $srr0
+ mysim cpu $p:$c:$t set spr msr $srr1
+ gdb $timeout
+}
+
+proc mem_display_64_le { addr } {
+ set data 0
+ for {set i 0} {$i < 8} {incr i} {
+ set data [ expr $data << 8 ]
+ set l [ mysim memory display [ expr $addr+7-$i ] 1 ]
+ set data [ expr $data | $l ]
+ }
+ return [format 0x%X $data]
+}
+
+proc mem_display_64 { addr le } {
+ if { $le } {
+ return [ mem_display_64_le $addr ]
+ }
+ # mysim memory display is big endian
+ return [ mysim memory display $addr 8 ]
+}
+
+proc bt { {sp 0} } {
+ upvar #0 target_t t
+ upvar #0 target_c c
+ upvar #0 target_p p
+
+ set lr [mysim cpu $p:$c:$t display spr pc]
+ set sym [addr2func $lr]
+ puts "pc:\t\t\t\t$lr\t$sym"
+ if { $sp == 0 } {
+ set sp [mysim cpu $p:$c:$t display gpr 1]
+ }
+ set lr [mysim cpu $p:$c:$t display spr lr]
+ set sym [addr2func $lr]
+ puts "lr:\t\t\t\t$lr\t$sym"
+
+ set msr [mysim cpu $p:$c:$t display spr msr]
+ set le [ expr $msr & 1 ]
+
+ # Limit to 200 in case of an infinite loop
+ for {set i 0} {$i < 200} {incr i} {
+ set pa [ mysim cpu $p:$c:$t util dtranslate $sp ]
+ set bc [ mem_display_64 $pa $le ]
+ set lr [ mem_display_64 [ expr $pa + 16 ] $le ]
+ set sym [addr2func $lr]
+ puts "stack:$pa \t$lr\t$sym"
+ if { $bc == 0 } { break }
+ set sp $bc
+ }
+ puts ""
+}
+
+proc ton { } {mysim mode turbo }
+proc toff { } {mysim mode simple }
+
+proc don { opt } {
+ simdebug set $opt 1
+}
+
+proc doff { opt } {
+ simdebug set $opt 0
+}
+
+# skisym and linsym return the address of a symbol, looked up from
+# the relevant System.map or skiboot.map file.
+proc linsym { name } {
+ global linux_symbol_map
+
+ # create a regexp that matches the symbol name
+ set base {([[:xdigit:]]*) (.)}
+ set exp [concat $base " $name\$"]
+ set ret ""
+
+ foreach {line addr type} [regexp -line -inline $exp $linux_symbol_map] {
+ set ret "0x$addr"
+ }
+
+ return $ret
+}
+
+# skisym factors in skiboot's load address
+proc skisym { name } {
+ global skiboot_symbol_map
+ global mconf
+
+ set base {([[:xdigit:]]*) (.)}
+ set exp [concat $base " $name\$"]
+ set ret ""
+
+ foreach {line addr type} [regexp -line -inline $exp $skiboot_symbol_map] {
+ set actual_addr [expr "0x$addr" + $mconf(boot_load)]
+ set ret [format "0x%.16x" $actual_addr]
+ }
+
+ return $ret
+}
+
+proc addr2func { addr } {
+ global skiboot_symbol_list
+ global linux_symbol_list
+ global user_symbol_list
+ global mconf
+
+ set prevname ""
+ set preva "0"
+
+ if { [ info exists linux_symbol_list ] && "$addr" >= 0xc000000000000000} {
+ foreach line $linux_symbol_list {
+ lassign $line a type name
+ if { "0x$a" > $addr } {
+ set o [format "0x%x" [expr $addr - "0x$preva"]]
+ return "$prevname+$o"
+ }
+ set prevname $name
+ set preva $a
+ }
+ }
+ # Assume skiboot is less that 4MB big
+ if { [ info exists skiboot_symbol_list ] &&
+ "$addr" > $mconf(boot_load) && "$addr" < [expr $mconf(boot_load) + 4194304] } {
+ set mapaddr [expr $addr - $mconf(boot_load)]
+
+ foreach line $skiboot_symbol_list {
+ lassign $line a type name
+ if { "0x$a" > $mapaddr } {
+ set o [format "0x%x" [expr $mapaddr - "0x$preva"]]
+ return "$prevname+$o"
+ }
+ set prevname $name
+ set preva $a
+ }
+ }
+ if { [ info exists user_symbol_list ] } {
+ foreach line $user_symbol_list {
+ lassign $line a type name
+ if { "0x$a" > $addr } {
+ set o [format "0x%x" [expr $addr - "0x$preva"]]
+ return "$prevname+$o"
+ }
+ set prevname $name
+ set preva $a
+ }
+ }
+ return "+$addr"
+}
+
+proc current_insn { { t -1 } { c -1 } { p -1 }} {
+ global target_t
+ global target_c
+ global target_p
+
+ if { $t == -1 } { set t $target_t }
+ if { $c == -1 } { set c $target_c }
+ if { $p == -1 } { set p $target_p }
+
+ set pc [mysim cpu $p:$c:$t display spr pc]
+ set pc_laddr [mysim cpu $p:$c:$t util itranslate $pc]
+ set inst [mysim cpu $p:$c:$t memory display $pc_laddr 4]
+ set disasm [mysim cpu $p:$c:$t util ppc_disasm $inst $pc]
+ return $disasm
+}
+
+set SRR1 0
+set DSISR 0
+set DAR 0
+
+proc sreset_trigger { args } {
+ global SRR1
+ upvar #0 target_t t
+ upvar #0 target_c c
+ upvar #0 target_p p
+
+ mysim trigger clear pc 0x100
+ mysim trigger clear pc 0x104
+ set s [expr [mysim cpu $p:$c:$t display spr srr1] & ~0x00000000003c0002]
+ set SRR1 [expr $SRR1 | $s]
+ mysim cpu $p:$c:$t set spr srr1 $SRR1
+}
+
+proc exc_sreset { } {
+ global SRR1
+ global DSISR
+ global DAR
+ upvar #0 target_t t
+ upvar #0 target_c c
+ upvar #0 target_p p
+
+ # In case of recoverable MCE, idle wakeup always sets RI, others get
+ # RI from current environment. For unrecoverable, RI would always be
+ # clear by hardware.
+ if { [current_insn] in { "stop" "nap" "sleep" "winkle" } } {
+ set msr_ri 0x2
+ set SRR1_powersave [expr (0x2 << (63-47))]
+ } else {
+ set msr_ri [expr [mysim cpu $p:$c:$t display spr msr] & 0x2]
+ set SRR1_powersave 0
+ }
+
+ # reason system reset
+ set SRR1_reason 0x4
+
+ set SRR1 [expr 0x0 | $msr_ri | $SRR1_powersave]
+ set SRR1 [expr $SRR1 | ((($SRR1_reason >> 3) & 0x1) << (63-42))]
+ set SRR1 [expr $SRR1 | ((($SRR1_reason >> 2) & 0x1) << (63-43))]
+ set SRR1 [expr $SRR1 | ((($SRR1_reason >> 1) & 0x1) << (63-44))]
+ set SRR1 [expr $SRR1 | ((($SRR1_reason >> 0) & 0x1) << (63-45))]
+
+ if { [current_insn] in { "stop" "nap" "sleep" "winkle" } } {
+ # mambo has a quirk that interrupts from idle wake immediately
+ # and go over current instruction.
+ mysim trigger set pc 0x100 "sreset_trigger"
+ mysim trigger set pc 0x104 "sreset_trigger"
+ mysim cpu $p:$c:$t interrupt SystemReset
+ } else {
+ mysim trigger set pc 0x100 "sreset_trigger"
+ mysim trigger set pc 0x104 "sreset_trigger"
+ mysim cpu $p:$c:$t interrupt SystemReset
+ }
+
+ # sleep and sometimes other types of interrupts do not trigger 0x100
+ if { [expr [mysim cpu $p:$c:$t display spr pc] == 0x100 ] } {
+ sreset_trigger
+ }
+ if { [expr [mysim cpu $p:$c:$t display spr pc] == 0x104 ] } {
+ sreset_trigger
+ }
+}
+
+proc mce_trigger { args } {
+ global SRR1
+ global DSISR
+ global DAR
+ upvar #0 target_t t
+ upvar #0 target_c c
+ upvar #0 target_p p
+
+ mysim trigger clear pc 0x200
+ mysim trigger clear pc 0x204
+
+ set s [expr [mysim cpu 0 display spr srr1] & ~0x00000000801f0002]
+ set SRR1 [expr $SRR1 | $s]
+ mysim cpu $p:$c:$t set spr srr1 $SRR1
+ mysim cpu $p:$c:$t set spr dsisr $DSISR
+ mysim cpu $p:$c:$t set spr dar $DAR ; list
+}
+
+#
+# Inject a machine check. Recoverable MCE types can be forced to unrecoverable
+# by clearing MSR_RI bit from SRR1 (which hardware may do).
+# If d_side is 0, then cause goes into SRR1. Otherwise it gets put into DSISR.
+# DAR is hardcoded to always 0xdeadbeefdeadbeef
+#
+# Default with no arguments is a recoverable i-side TLB multi-hit
+# Other options:
+# d_side=1 dsisr=0x80 - recoverable d-side SLB multi-hit
+# d_side=1 dsisr=0x8000 - ue error on instruction fetch
+# d_side=0 cause=0xd - unrecoverable i-side async store timeout (POWER9 only)
+# d_side=0 cause=0x1 - unrecoverable i-side ifetch
+#
+proc exc_mce { { d_side 0 } { cause 0x5 } { recoverable 1 } } {
+ global SRR1
+ global DSISR
+ global DAR
+ upvar #0 target_t t
+ upvar #0 target_c c
+ upvar #0 target_p p
+
+# puts "INJECTING MCE"
+
+ # In case of recoverable MCE, idle wakeup always sets RI, others get
+ # RI from current environment. For unrecoverable, RI would always be
+ # clear by hardware.
+ if { [current_insn] in { "stop" "nap" "sleep" "winkle" } } {
+ set msr_ri 0x2
+ set SRR1_powersave [expr (0x2 << (63-47))]
+ } else {
+ set msr_ri [expr [mysim cpu $p:$c:$t display spr msr] & 0x2]
+ set SRR1_powersave 0
+ }
+
+ if { !$recoverable } {
+ set msr_ri 0x0
+ }
+
+ if { $d_side } {
+ set is_dside 1
+ set SRR1_mc_cause 0x0
+ set DSISR $cause
+ set DAR 0xdeadbeefdeadbeef
+ } else {
+ set is_dside 0
+ set SRR1_mc_cause $cause
+ set DSISR 0x0
+ set DAR 0x0
+ }
+
+ set SRR1 [expr 0x0 | $msr_ri | $SRR1_powersave]
+
+ set SRR1 [expr $SRR1 | ($is_dside << (63-42))]
+ set SRR1 [expr $SRR1 | ((($SRR1_mc_cause >> 3) & 0x1) << (63-36))]
+ set SRR1 [expr $SRR1 | ((($SRR1_mc_cause >> 2) & 0x1) << (63-43))]
+ set SRR1 [expr $SRR1 | ((($SRR1_mc_cause >> 1) & 0x1) << (63-44))]
+ set SRR1 [expr $SRR1 | ((($SRR1_mc_cause >> 0) & 0x1) << (63-45))]
+
+ if { [current_insn] in { "stop" "nap" "sleep" "winkle" } } {
+ # mambo has a quirk that interrupts from idle wake immediately
+ # and go over current instruction.
+ mysim trigger set pc 0x200 "mce_trigger"
+ mysim trigger set pc 0x204 "mce_trigger"
+ mysim cpu $p:$c:$t interrupt MachineCheck
+ } else {
+ mysim trigger set pc 0x200 "mce_trigger"
+ mysim trigger set pc 0x204 "mce_trigger"
+ mysim cpu $p:$c:$t interrupt MachineCheck
+ }
+
+ # sleep and sometimes other types of interrupts do not trigger 0x200
+ if { [expr [mysim cpu $p:$c:$t display spr pc] == 0x200 ] } {
+ mce_trigger
+ }
+ if { [expr [mysim cpu $p:$c:$t display spr pc] == 0x204 ] } {
+ mce_trigger
+ }
+}
+
+set R1 0
+
+# Avoid stopping if we re-enter the same code. Wait until r1 matches.
+# This helps stepping over exceptions or function calls etc.
+proc stop_stack_match { args } {
+ global R1
+ upvar #0 target_t t
+ upvar #0 target_c c
+ upvar #0 target_p p
+
+ set r1 [mysim cpu $p:$c:$t display gpr 1]
+ if { $R1 == $r1 } {
+ simstop
+ ipca
+ }
+}
+
+# inject default recoverable MCE and step over it. Useful for testing whether
+# code copes with taking an interleaving MCE.
+proc inject_mce { } {
+ global R1
+ upvar #0 target_t t
+ upvar #0 target_c c
+ upvar #0 target_p p
+
+ set R1 [mysim cpu $p:$c:$t display gpr 1]
+ set pc [mysim cpu $p:$c:$t display spr pc]
+ mysim trigger set pc $pc "stop_stack_match"
+ exc_mce
+ c
+ mysim trigger clear pc $pc ; list
+}
+
+#
+# We've stopped at addr and we need to inject the mce and continue
+#
+proc trigger_mce_ue_addr {args} {
+ set addr [lindex [lindex $args 0] 1]
+ mysim trigger clear memory system rw $addr $addr
+ exc_mce 0x1 0x8000 0x1
+}
+
+proc inject_mce_ue_on_addr {addr} {
+ mysim trigger set memory system rw $addr $addr 1 "trigger_mce_ue_addr"
+}
+
+# inject and step over one instruction, and repeat.
+proc inject_mce_step { {nr 1} } {
+ for { set i 0 } { $i < $nr } { incr i 1 } {
+ inject_mce
+ s
+ }
+}
+
+# inject if RI is set and step over one instruction, and repeat.
+proc inject_mce_step_ri { {nr 1} } {
+ upvar #0 target_t t
+ upvar #0 target_c c
+ upvar #0 target_p p
+
+ set reserve_inject 1
+ set reserve_inject_skip 0
+ set reserve_counter 0
+
+ for { set i 0 } { $i < $nr } { incr i 1 } {
+ if { [expr [mysim cpu $p:$c:$t display spr msr] & 0x2] } {
+ # inject_mce
+ if { [mysim cpu $p:$c:$t display reservation] in { "none" } } {
+ inject_mce
+ mysim cpu $p:$c:$t set reservation none
+ if { $reserve_inject_skip } {
+ set reserve_inject 1
+ set reserve_inject_skip 0
+ }
+ } else {
+ if { $reserve_inject } {
+ inject_mce
+ mysim cpu $p:$c:$t set reservation none
+ set reserve_inject 0
+ } else {
+ set reserve_inject_skip 1
+ set reserve_counter [ expr $reserve_counter + 1 ]
+ if { $reserve_counter > 30 } {
+ mysim cpu $p:$c:$t set reservation none
+ }
+ }
+ }
+ }
+ s
+ }
+}
diff --git a/roms/skiboot/external/mambo/qtrace_utils.tcl b/roms/skiboot/external/mambo/qtrace_utils.tcl
new file mode 100644
index 000000000..bb20b31d3
--- /dev/null
+++ b/roms/skiboot/external/mambo/qtrace_utils.tcl
@@ -0,0 +1,16 @@
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+if { [file exists $env(LIB_DIR)/perf/qtrace.tcl] == 1} {
+ if { [catch {source $env(LIB_DIR)/perf/qtrace.tcl} issue ] } {
+ puts "QTrace not available: $issue"
+ }
+
+ proc start_qtrace { { qtfile qtrace.qt } } {
+ QTrace::Initialize p9 mysim
+ QTrace::Start $qtfile mysim
+ }
+
+ proc stop_qtrace { } {
+ QTrace::Stop mysim
+ }
+}
diff --git a/roms/skiboot/external/mambo/skiboot.tcl b/roms/skiboot/external/mambo/skiboot.tcl
new file mode 100644
index 000000000..0ecb55a77
--- /dev/null
+++ b/roms/skiboot/external/mambo/skiboot.tcl
@@ -0,0 +1,732 @@
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+#
+# scripts to run skiboot (and a payload) with Mambo (otherwise known as the
+# POWER[89] Functional Simulator)
+#
+# Copyright 2014-2019 IBM Corp.
+
+# need to get images path defined early
+source $env(LIB_DIR)/ppc/util.tcl
+if { [file exists qtrace_utils.tcl] } then {
+ source qtrace_utils.tcl
+}
+
+#
+# Call tclreadline's Loop to move to friendlier
+# commandline if one exists
+#
+proc readline { } {
+ set readline [catch { package require tclreadline }]
+ if { $readline == 0 } {
+ ::tclreadline::Loop
+ }
+}
+
+proc mconfig { name env_name def } {
+ global mconf
+ global env
+
+ if { [info exists env($env_name)] } { set mconf($name) $env($env_name) }
+ if { ![info exists mconf($name)] } { set mconf($name) $def }
+}
+
+mconfig cpus CPUS 1
+mconfig threads THREADS 1
+mconfig memory MEM_SIZE 4G
+
+# Create multiple memory nodes? This will create a MEM_SIZE region
+# on each chip (CPUS above).
+mconfig numa MAMBO_NUMA 0
+
+# Should we stop on an illeagal instruction
+mconfig stop_on_ill MAMBO_STOP_ON_ILL false
+
+# Location of application binary to load
+mconfig boot_image SKIBOOT ../../skiboot.lid
+
+# Boot: Memory location to load boot_image, for binary or vmlinux
+mconfig boot_load MAMBO_BOOT_LOAD 0x30000000
+
+# Boot: Value of PC after loading, for binary or vmlinux
+mconfig boot_pc MAMBO_BOOT_PC 0x30000010
+
+# Payload: Allow for a Linux style ramdisk/initrd
+if { ![info exists env(SKIBOOT_ZIMAGE)] } {
+ error "Please set SKIBOOT_ZIMAGE to the path of your zImage.epapr"
+}
+mconfig payload PAYLOAD $env(SKIBOOT_ZIMAGE)
+
+mconfig linux_cmdline LINUX_CMDLINE ""
+
+# Paylod: Memory location for a Linux style ramdisk/initrd
+mconfig payload_addr PAYLOAD_ADDR 0x20000000;
+
+# FW: Where should ePAPR Flat Devtree Binary be loaded
+mconfig epapr_dt_addr EPAPR_DT_ADDR 0x1f00000;# place at 31M
+
+# Disk: Location of file to use a bogus disk 0
+mconfig rootdisk ROOTDISK none
+
+# Disk: File to use for re COW file: none or <file>
+mconfig rootdisk_cow MAMBO_ROOTDISK_COW none
+
+# Disk: COW method to use
+mconfig rootdisk_cow_method MAMBO_ROOTDISK_COW_METHOD newcow
+
+# Disk: COW hash size
+mconfig rootdisk_cow_hash MAMBO_ROOTDISK_COW_HASH 1024
+
+# Net: What type of networking: none, phea, bogus
+mconfig net MAMBO_NET none
+
+# Net: What MAC address to use
+mconfig net_mac MAMBO_NET_MAC 00:11:22:33:44:55
+
+# Net: What is the name of the tap device
+mconfig net_tapdev MAMBO_NET_TAPDEV "tap0"
+
+# Enable (default) or disable the "speculation-policy-favor-security" setting,
+# set to 0 to disable. When enabled it causes Linux's RFI flush to be enabled.
+mconfig speculation_policy_favor_security MAMBO_SPECULATION_POLICY_FAVOR_SECURITY 1
+
+# These values ~= P9N DD2.3, except for fw_count_cache_flush_assist=0 because it
+# exercises more kernel code.
+# See https://github.com/open-power/hostboot/blob/7ce2a9daac0ccf759376929b2ec40bbbc7ca3398/src/usr/hdat/hdatiplparms.H#L520
+mconfig needs_l1d_flush_msr_hv MAMBO_NEEDS_L1D_FLUSH_MSR_HV 1
+mconfig needs_l1d_flush_msr_pr MAMBO_NEEDS_L1D_FLUSH_MSR_PR 1
+mconfig fw_l1d_thread_split MAMBO_FW_L1D_THREAD_SPLIT 1
+mconfig needs_spec_barrier MAMBO_NEEDS_SPEC_BARRIER 1
+mconfig fw_bcctrl_serialized MAMBO_FW_BCCTRL_SERIALIZED 0
+mconfig fw_count_cache_disabled MAMBO_FW_COUNT_CACHE_DISABLED 0
+mconfig needs_count_cache_flush MAMBO_NEEDS_COUNT_CACHE_FLUSH 1
+mconfig fw_count_cache_flush_assist MAMBO_COUNT_CACHE_FLUSH_ASSIST 0
+mconfig inst_spec_barrier_ori31 MAMBO_INST_SPEC_BARRIER_ORI31 1
+mconfig inst_l1d_flush_trig2 MAMBO_INST_L1D_FLUSH_TRIG2 1
+mconfig inst_l1d_flush_ori30 MAMBO_INST_L1D_FLUSH_ORI30 0
+
+#
+# Create machine config
+#
+set default_config [display default_configure]
+define dup $default_config myconf
+myconf config cpus $mconf(cpus)
+myconf config processor/number_of_threads $mconf(threads)
+myconf config memory_size $mconf(memory)
+myconf config processor_option/ATTN_STOP true
+myconf config processor_option/stop_on_illegal_instruction $mconf(stop_on_ill)
+myconf config UART/0/enabled false
+myconf config SimpleUART/enabled false
+myconf config enable_rtas_support false
+myconf config processor/cpu_frequency 512M
+myconf config processor/timebase_frequency 1/1
+myconf config enable_pseries_nvram false
+myconf config machine_option/NO_RAM TRUE
+myconf config machine_option/NO_ROM TRUE
+myconf config machine_option/MEMORY_OVERFLOW FALSE
+
+if { $default_config == "PEGASUS" } {
+ # We need to be DD2 or greater on p8 for the HILE HID bit.
+ myconf config processor/initial/PVR 0x4b0201
+
+ if { $mconf(numa) } {
+ myconf config memory_region_id_shift 35
+ }
+}
+
+if { $default_config == "P9" } {
+ # PVR configured for POWER9 DD2.3 Scale out 24 Core (ie SMT4)
+ myconf config processor/initial/PVR 0x4e1203
+ myconf config processor/initial/SIM_CTRL1 0x4228301710000000
+
+ if { $mconf(numa) } {
+ myconf config memory_region_id_shift 45
+ }
+}
+
+if { $default_config == "P10" } {
+ # PVR configured for POWER10 DD1.0
+ myconf config processor/initial/PVR 0x800100
+ myconf config processor/initial/SIM_CTRL1 0xc228100400000000
+
+ if { $mconf(numa) } {
+ myconf config memory_region_id_shift 44
+ }
+}
+
+
+if { $mconf(numa) } {
+ myconf config memory_regions $mconf(cpus)
+}
+
+if { [info exists env(SKIBOOT_SIMCONF)] } {
+ source $env(SKIBOOT_SIMCONF)
+}
+
+define machine myconf mysim
+
+#
+# Include various utilities
+#
+
+source $env(LIB_DIR)/common/epapr.tcl
+if {![info exists of::encode_compat]} {
+ source $env(LIB_DIR)/common/openfirmware_utils.tcl
+}
+
+# Only source mambo_utils.tcl if it exists in the current directory. That
+# allows running mambo in another directory to the one skiboot.tcl is in.
+if { [file exists mambo_utils.tcl] } then {
+ source mambo_utils.tcl
+
+ if { [info exists env(USER_MAP)] } {
+ global user_symbol_map user_symbol_list
+
+ set fp [open $env(USER_MAP) r]
+ set user_symbol_map [read $fp]
+ set user_symbol_list [split $user_symbol_map "\n"]
+ close $fp
+ }
+
+ if { [info exists env(VMLINUX_MAP)] } {
+ global linux_symbol_map linux_symbol_list
+
+ set fp [open $env(VMLINUX_MAP) r]
+ set linux_symbol_map [read $fp]
+ set linux_symbol_list [split $linux_symbol_map "\n"]
+ close $fp
+ }
+
+ if { [info exists env(SKIBOOT_MAP)] } {
+ global skiboot_symbol_map skiboot_symbol_list
+
+ set fp [open $env(SKIBOOT_MAP) r]
+ set skiboot_symbol_map [read $fp]
+ set skiboot_symbol_list [split $skiboot_symbol_map "\n"]
+ close $fp
+ }
+}
+
+#
+# Instanciate xscom
+#
+
+set xscom_base 0x1A0000000000
+mysim xscom create $xscom_base
+
+# Setup bogus IO
+
+if { $mconf(rootdisk) != "none" } {
+ # Now load the bogus disk image
+ switch $mconf(rootdisk_cow) {
+ none {
+ mysim bogus disk init 0 $mconf(rootdisk) rw
+ puts "bogusdisk initialized for $mconf(rootdisk)"
+ }
+ default {
+ mysim bogus disk init 0 $mconf(rootdisk) \
+ $mconf(rootdisk_cow_method) \
+ $mconf(rootdisk_cow) $mconf(rootdisk_cow_hash)
+ }
+ }
+}
+switch $mconf(net) {
+ none {
+ puts "No network support selected"
+ }
+ bogus - bogusnet {
+ mysim bogus net init 0 $mconf(net_mac) $mconf(net_tapdev)
+ }
+ default {
+ error "Bad net \[none | bogus]: $mconf(net)"
+ }
+}
+
+# Device tree fixups
+
+set root_node [mysim of find_device "/"]
+
+mysim of addprop $root_node string "epapr-version" "ePAPR-1.0"
+mysim of setprop $root_node "compatible" "ibm,powernv"
+
+set cpus_node [mysim of find_device "/cpus"]
+mysim of addprop $cpus_node int "#address-cells" 1
+mysim of addprop $cpus_node int "#size-cells" 0
+
+set mem0_node [mysim of find_device "/memory@0"]
+mysim of addprop $mem0_node int "ibm,chip-id" 0
+
+set xscom_node [ mysim of addchild $root_node xscom [format %x $xscom_base]]
+set reg [list $xscom_base 0x10000000]
+mysim of addprop $xscom_node array64 "reg" reg
+mysim of addprop $xscom_node empty "scom-controller" ""
+mysim of addprop $xscom_node int "ibm,chip-id" 0
+mysim of addprop $xscom_node int "#address-cells" 1
+mysim of addprop $xscom_node int "#size-cells" 1
+set compat [list]
+lappend compat "ibm,xscom"
+lappend compat "ibm,power8-xscom"
+set compat [of::encode_compat $compat]
+mysim of addprop $xscom_node byte_array "compatible" $compat
+
+set chosen_node [mysim of find_device /chosen]
+set base_addr [list $mconf(payload_addr)]
+mysim of addprop $chosen_node array64 "kernel-base-address" base_addr
+
+# Load any initramfs
+set cpio_start 0x80000000
+set cpio_end $cpio_start
+set cpio_size 0
+if { [info exists env(SKIBOOT_INITRD)] } {
+
+ set cpios [split $env(SKIBOOT_INITRD) ","]
+
+ foreach cpio_file $cpios {
+ set cpio_file [string trim $cpio_file]
+ set cpio_size [file size $cpio_file]
+ mysim mcm 0 memory fread $cpio_end $cpio_size $cpio_file
+ set cpio_end [expr $cpio_end + $cpio_size]
+ # Linux requires cpios are 4 byte aligned
+ set cpio_end [expr $cpio_end + 3 & 0xfffffffffffffffc]
+ }
+
+ mysim of addprop $chosen_node int "linux,initrd-start" $cpio_start
+ mysim of addprop $chosen_node int "linux,initrd-end" $cpio_end
+}
+
+# Map persistent memory disks
+proc pmem_node_add { root start size } {
+ set start_hex [format %x $start]
+ set node [mysim of addchild $root "pmem@$start_hex" ""]
+ set reg [list [expr $start >> 32] [expr $start & 0xffffffff] [expr $size >> 32] [expr $size & 0xffffffff] ]
+ mysim of addprop $node array "reg" reg
+ mysim of addprop $node string "compatible" "pmem-region"
+ mysim of addprop $node empty "volatile" "1"
+ mysim of addprop $node int "ibm,chip-id" 0
+ return [expr $start + $size]
+}
+
+set pmem_files ""
+if { [info exists env(PMEM_DISK)] } {
+ set pmem_files [split $env(PMEM_DISK) ","]
+}
+set pmem_sizes ""
+if { [info exists env(PMEM_VOLATILE)] } {
+ set pmem_sizes [split $env(PMEM_VOLATILE) ","]
+}
+set pmem_modes ""
+if { [info exists env(PMEM_MODE)] } {
+ set pmem_modes [split $env(PMEM_MODE) ","]
+}
+set pmem_root [mysim of addchild $root_node "pmem" ""]
+mysim of addprop $pmem_root int "#address-cells" 2
+mysim of addprop $pmem_root int "#size-cells" 2
+mysim of addprop $pmem_root empty "ranges" ""
+# Start above where XICS normally is at 0x1A0000000000
+set pmem_start [expr 0x20000000000]
+set pmem_file_ix 0
+foreach pmem_file $pmem_files { # PMEM_DISK
+ set pmem_file [string trim $pmem_file]
+ set pmem_size [file size $pmem_file]
+ if { [expr [llength $pmem_modes] > $pmem_file_ix] } {
+ set pmem_mode [lindex $pmem_modes $pmem_file_ix]
+ } else {
+ set pmem_mode "rw"
+ }
+ if {[catch {mysim memory mmap $pmem_start $pmem_size $pmem_file $pmem_mode}]} {
+ puts "ERROR: pmem: 'mysim mmap' command needs newer mambo"
+ exit
+ }
+ set pmem_start [pmem_node_add $pmem_root $pmem_start $pmem_size]
+ set pmem_file_ix [expr $pmem_file_ix + 1]
+}
+foreach pmem_size $pmem_sizes { # PMEM_VOLATILE
+ set pmem_start [pmem_node_add $pmem_root $pmem_start $pmem_size]
+}
+
+
+# Default NVRAM is blank and will be formatted by Skiboot if no file is provided
+set fake_nvram_start $cpio_end
+set fake_nvram_size 0x40000
+# Load any fake NVRAM file if provided
+if { [info exists env(SKIBOOT_NVRAM)] } {
+ # Set up and write NVRAM file
+ set fake_nvram_file $env(SKIBOOT_NVRAM)
+ set fake_nvram_size [file size $fake_nvram_file]
+ mysim mcm 0 memory fread $fake_nvram_start $fake_nvram_size $fake_nvram_file
+}
+
+# Add device tree entry for NVRAM
+set reserved_memory [mysim of addchild $root_node "reserved-memory" ""]
+mysim of addprop $reserved_memory int "#size-cells" 2
+mysim of addprop $reserved_memory int "#address-cells" 2
+mysim of addprop $reserved_memory empty "ranges" ""
+
+set cvc_code_start [expr $fake_nvram_start + $fake_nvram_size]
+set cvc_code_end $cvc_code_start
+set cvc_code_size 0
+
+if { [info exists env(SKIBOOT_CVC_CODE)] } {
+ set cvc_file $env(SKIBOOT_CVC_CODE)
+
+ set cvc_code_size [file size $cvc_file]
+ mysim mcm 0 memory fread $cvc_code_start $cvc_code_size $cvc_file
+ set cvc_code_end [expr $cvc_code_start + $cvc_code_size]
+
+ # Set up Device Tree for Container Verification Code
+ set hb [mysim of addchild $root_node "ibm,hostboot" ""]
+ set hb_reserved_memory [mysim of addchild $hb "reserved-memory" ""]
+ mysim of addprop $hb_reserved_memory int "#address-cells" 2
+ mysim of addprop $hb_reserved_memory int "#size-cells" 2
+
+ set hb_cvc_code_node [mysim of addchild $hb_reserved_memory "ibm,secure-crypt-algo-code" [format %x $cvc_code_start]]
+ set reg [list $cvc_code_start $cvc_code_size]
+ mysim of addprop $hb_cvc_code_node array64 "reg" reg
+ mysim of addprop $hb_cvc_code_node empty "name" "ibm,secure-crypt-algo-code"
+
+ set cvc_code_node [mysim of addchild $reserved_memory "ibm,secure-crypt-algo-code" [format %x $cvc_code_start]]
+ set reg [list $cvc_code_start $cvc_code_size]
+ mysim of addprop $cvc_code_node array64 "reg" reg
+ mysim of addprop $cvc_code_node empty "name" "ibm,secure-crypt-algo-code"
+}
+
+set initramfs_res [mysim of addchild $reserved_memory "initramfs" ""]
+set reg [list $cpio_start $cpio_size ]
+mysim of addprop $initramfs_res array64 "reg" reg
+mysim of addprop $initramfs_res empty "name" "initramfs"
+
+set fake_nvram_node [mysim of addchild $reserved_memory "ibm,fake-nvram" ""]
+set reg [list $fake_nvram_start $fake_nvram_size ]
+mysim of addprop $fake_nvram_node array64 "reg" reg
+mysim of addprop $fake_nvram_node empty "name" "ibm,fake-nvram"
+
+set opal_node [mysim of addchild $root_node "ibm,opal" ""]
+
+# Allow P9/P10 to use all idle states
+if { $default_config == "P9" || $default_config == "P10" } {
+ set power_mgt_node [mysim of addchild $opal_node "power-mgt" ""]
+ mysim of addprop $power_mgt_node int "ibm,enabled-stop-levels" 0xffffffff
+}
+
+proc add_feature_node { parent name { value 1 } } {
+ if { $value != 1 } {
+ set value "disabled"
+ } else {
+ set value "enabled"
+ }
+ set np [mysim of addchild $parent $name ""]
+ mysim of addprop $np empty $value ""
+}
+
+set np [mysim of addchild $opal_node "fw-features" ""]
+add_feature_node $np "speculation-policy-favor-security" $mconf(speculation_policy_favor_security)
+add_feature_node $np "needs-l1d-flush-msr-hv-1-to-0" $mconf(needs_l1d_flush_msr_hv)
+add_feature_node $np "needs-l1d-flush-msr-pr-0-to-1" $mconf(needs_l1d_flush_msr_pr)
+add_feature_node $np "fw-l1d-thread-split" $mconf(fw_l1d_thread_split)
+add_feature_node $np "needs-spec-barrier-for-bound-checks" $mconf(needs_spec_barrier)
+add_feature_node $np "fw-bcctrl-serialized" $mconf(fw_bcctrl_serialized)
+add_feature_node $np "fw-count-cache-disabled" $mconf(fw_count_cache_disabled)
+add_feature_node $np "needs-count-cache-flush-on-context-switch" $mconf(needs_count_cache_flush)
+add_feature_node $np "fw-count-cache-flush-bcctr2,0,0" $mconf(fw_count_cache_flush_assist)
+add_feature_node $np "inst-spec-barrier-ori31,31,0" $mconf(inst_spec_barrier_ori31)
+add_feature_node $np "inst-l1d-flush-trig2" $mconf(inst_l1d_flush_trig2)
+add_feature_node $np "inst-l1d-flush-ori30,30,0" $mconf(inst_l1d_flush_ori30)
+
+
+# Init CPUs
+set pir 0
+for { set c 0 } { $c < $mconf(cpus) } { incr c } {
+ set cpu_node [mysim of find_device "/cpus/PowerPC@$pir"]
+ mysim of addprop $cpu_node int "ibm,pir" $pir
+ set reg [list 0x0000001c00000028 0xffffffffffffffff]
+ mysim of addprop $cpu_node array64 "ibm,processor-segment-sizes" reg
+
+ mysim of addprop $cpu_node int "ibm,chip-id" $c
+
+ # Create a chip node to tell skiboot to create another chip for this CPU.
+ # This bubbles up to Linux which will then see a new chip (aka nid).
+ # For chip 0 the xscom node above has already definied chip 0, so skip it.
+ if { $c > 0 } {
+ set node [mysim of addchild $root_node "mambo-chip" [format %x $c]]
+ mysim of addprop $node int "ibm,chip-id" $c
+ mysim of addprop $node string "compatible" "ibm,mambo-chip"
+
+ if { $mconf(numa) } {
+ set shift [myconf query memory_region_id_shift]
+ set addr [format %lx [expr (1 << $shift) * $c]]
+ set node [mysim of find_device "/memory@$addr"]
+ mysim of addprop $node int "ibm,chip-id" $c
+ }
+ }
+
+ set reg {}
+ lappend reg 0x0000000c 0x00000010 0x00000018 0x00000022
+ mysim of addprop $cpu_node array "ibm,processor-page-sizes" reg
+
+ set reg {}
+ lappend reg 0x0c 0x000 3 0x0c 0x0000 ;# 4K seg 4k pages
+ lappend reg 0x10 0x0007 ;# 4K seg 64k pages
+ lappend reg 0x18 0x0038 ;# 4K seg 16M pages
+ lappend reg 0x10 0x110 2 0x10 0x0001 ;# 64K seg 64k pages
+ lappend reg 0x18 0x0008 ;# 64K seg 16M pages
+ lappend reg 0x18 0x100 1 0x18 0x0000 ;# 16M seg 16M pages
+ lappend reg 0x22 0x120 1 0x22 0x0003 ;# 16G seg 16G pages
+ mysim of addprop $cpu_node array "ibm,segment-page-sizes" reg
+
+ if { $default_config == "P9" || $default_config == "P10" } {
+ # Set actual page size encodings
+ set reg {}
+ # 4K pages
+ lappend reg 0x0000000c
+ # 64K pages
+ lappend reg 0xa0000010
+ # 2M pages
+ lappend reg 0x20000015
+ # 1G pages
+ lappend reg 0x4000001e
+ mysim of addprop $cpu_node array "ibm,processor-radix-AP-encodings" reg
+
+ set reg {}
+ # POWER9 PAPR defines upto bytes 62-63
+ # POWER10 PAPR defines upto byte 64-65
+ # header + bytes 0-5
+ if { $default_config == "P9" } {
+ lappend reg 0x4000f63fc70080c0
+ } else {
+ lappend reg 0x4200f63fc70080c0
+ }
+ # bytes 6-13
+ lappend reg 0x8000000000000000
+ # bytes 14-21
+ lappend reg 0x0000800080008000
+ # bytes 22-29 22/23=TM
+ lappend reg 0x0000800080008000
+ # bytes 30-37
+ lappend reg 0x80008000C0008000
+ # bytes 38-45 40/41=radix
+ lappend reg 0x8000800080008000
+ # bytes 46-55
+ lappend reg 0x8000800080008000
+ # bytes 54-61 58/59=seg tbl
+ lappend reg 0x8000800080008000
+ # bytes 62-69 64/65=DAWR1(P10 only)
+ if { $default_config == "P9" } {
+ lappend reg 0x8000000000000000
+ } else {
+ lappend reg 0x8000800000000000
+ }
+ mysim of addprop $cpu_node array64 "ibm,pa-features" reg
+ } else {
+ set reg {}
+ lappend reg 0x6000f63fc70080c0
+ mysim of addprop $cpu_node array64 "ibm,pa-features" reg
+ }
+
+ set irqreg [list]
+ for { set t 0 } { $t < $mconf(threads) } { incr t } {
+ mysim mcm 0 cpu $c thread $t set spr pc $mconf(boot_pc)
+ mysim mcm 0 cpu $c thread $t set gpr 3 $mconf(epapr_dt_addr)
+ mysim mcm 0 cpu $c thread $t config_on
+ mysim mcm 0 cpu $c thread $t set spr pir $pir
+ lappend irqreg $pir
+ incr pir
+ }
+ mysim of addprop $cpu_node array "ibm,ppc-interrupt-server#s" irqreg
+}
+
+#Add In-Memory Collection Counter nodes
+if { $default_config == "P9" || $default_config == "P10" } {
+ #Add the base node "imc-counters"
+ set imc_c [mysim of addchild $root_node "imc-counters" ""]
+ mysim of addprop $imc_c string "compatible" "ibm,opal-in-memory-counters"
+ mysim of addprop $imc_c int "#address-cells" 1
+ mysim of addprop $imc_c int "#size-cells" 1
+ mysim of addprop $imc_c int "version-id" 1
+
+ #Add a common mcs event node
+ set mcs_et [mysim of addchild $imc_c "nest-mcs-events" ""]
+ mysim of addprop $mcs_et int "#address-cells" 1
+ mysim of addprop $mcs_et int "#size-cells" 1
+
+ #Add a event
+ set et [mysim of addchild $mcs_et event [format %x 0]]
+ mysim of addprop $et string "event-name" "64B_RD_OR_WR_DISP_PORT01"
+ mysim of addprop $et string "unit" "MiB/s"
+ mysim of addprop $et string "scale" "4"
+ mysim of addprop $et int "reg" 0
+
+ #Add a event
+ set et [mysim of addchild $mcs_et event [format %x 1]]
+ mysim of addprop $et string "event-name" "64B_WR_DISP_PORT01"
+ mysim of addprop $et string "unit" "MiB/s"
+ mysim of addprop $et int "reg" 40
+
+ #Add a event
+ set et [mysim of addchild $mcs_et event [format %x 2]]
+ mysim of addprop $et string "event-name" "64B_RD_DISP_PORT01"
+ mysim of addprop $et string "scale" "100"
+ mysim of addprop $et int "reg" 64
+
+ #Add a event
+ set et [mysim of addchild $mcs_et event [format %x 3]]
+ mysim of addprop $et string "event-name" "64B_XX_DISP_PORT01"
+ mysim of addprop $et int "reg" 32
+
+ #Add a mcs device node
+ set mcs_01 [mysim of addchild $imc_c "mcs01" ""]
+ mysim of addprop $mcs_01 string "compatible" "ibm,imc-counters"
+ mysim of addprop $mcs_01 string "events-prefix" "PM_MCS01_"
+ mysim of addprop $mcs_01 int "reg" 65536
+ mysim of addprop $mcs_01 int "size" 262144
+ mysim of addprop $mcs_01 int "offset" 1572864
+ mysim of addprop $mcs_01 int "events" $mcs_et
+ mysim of addprop $mcs_01 int "type" 16
+ mysim of addprop $mcs_01 string "unit" "KiB/s"
+ mysim of addprop $mcs_01 string "scale" "8"
+
+ #Add a common core event node
+ set ct_et [mysim of addchild $imc_c "core-thread-events" ""]
+ mysim of addprop $ct_et int "#address-cells" 1
+ mysim of addprop $ct_et int "#size-cells" 1
+
+ #Add a event
+ set cet [mysim of addchild $ct_et event [format %x 200]]
+ mysim of addprop $cet string "event-name" "0THRD_NON_IDLE_PCYC"
+ mysim of addprop $cet string "desc" "The number of processor cycles when all threads are idle"
+ mysim of addprop $cet int "reg" 200
+
+ #Add a core device node
+ set core [mysim of addchild $imc_c "core" ""]
+ mysim of addprop $core string "compatible" "ibm,imc-counters"
+ mysim of addprop $core string "events-prefix" "CPM_"
+ mysim of addprop $core int "reg" 24
+ mysim of addprop $core int "size" 8192
+ mysim of addprop $core string "scale" "512"
+ mysim of addprop $core int "events" $ct_et
+ mysim of addprop $core int "type" 4
+
+ #Add a thread device node
+ set thread [mysim of addchild $imc_c "thread" ""]
+ mysim of addprop $thread string "compatible" "ibm,imc-counters"
+ mysim of addprop $thread string "events-prefix" "CPM_"
+ mysim of addprop $thread int "reg" 24
+ mysim of addprop $thread int "size" 8192
+ mysim of addprop $thread string "scale" "512"
+ mysim of addprop $thread int "events" $ct_et
+ mysim of addprop $thread int "type" 1
+
+ #Add a common trace event node
+ set tr_et [mysim of addchild $imc_c "trace-events" ""]
+ mysim of addprop $tr_et int "#address-cells" 1
+ mysim of addprop $tr_et int "#size-cells" 1
+
+ #Add an event
+ set tr [mysim of addchild $tr_et event [format 10200000]]
+ mysim of addprop $tr string "event-name" "cycles"
+ mysim of addprop $tr string "desc" "Reference cycles"
+ mysim of addprop $tr int "reg" 0x10200000
+
+ #Add a trace device node
+ set trace [mysim of addchild $imc_c "trace" ""]
+ mysim of addprop $trace string "compatible" "ibm,imc-counters"
+ mysim of addprop $trace string "events-prefix" "trace_"
+ mysim of addprop $trace int "reg" 0
+ mysim of addprop $trace int "size" 262144
+ mysim of addprop $trace int "events" $tr_et
+ mysim of addprop $trace int "type" 2
+
+}
+
+mconfig enable_stb SKIBOOT_ENABLE_MAMBO_STB 0
+
+if { [info exists env(SKIBOOT_ENABLE_MAMBO_STB)] } {
+ set stb_node [ mysim of addchild $root_node "ibm,secureboot" "" ]
+
+ # For P8 we still use the softrom emulation
+ if { $default_config == "PEGASUS" || ! [info exists env(SKIBOOT_CVC_CODE)] } {
+ mysim of addprop $stb_node string "compatible" "ibm,secureboot-v1-softrom"
+ } else {
+ # on P9 we can use the real CVC
+ mysim of addprop $stb_node string "compatible" "ibm,secureboot-v2"
+ }
+# mysim of addprop $stb_node string "secure-enabled" ""
+ mysim of addprop $stb_node string "trusted-enabled" ""
+ mysim of addprop $stb_node string "hash-algo" "sha512"
+ mysim of addprop $stb_node int "hw-key-hash-size" 64
+ set hw_key_hash {}
+ lappend hw_key_hash 0x40d487ff
+ lappend hw_key_hash 0x7380ed6a
+ lappend hw_key_hash 0xd54775d5
+ lappend hw_key_hash 0x795fea0d
+ lappend hw_key_hash 0xe2f541fe
+ lappend hw_key_hash 0xa9db06b8
+ lappend hw_key_hash 0x466a42a3
+ lappend hw_key_hash 0x20e65f75
+ lappend hw_key_hash 0xb4866546
+ lappend hw_key_hash 0x0017d907
+ lappend hw_key_hash 0x515dc2a5
+ lappend hw_key_hash 0xf9fc5095
+ lappend hw_key_hash 0x4d6ee0c9
+ lappend hw_key_hash 0xb67d219d
+ lappend hw_key_hash 0xfb708535
+ lappend hw_key_hash 0x1d01d6d1
+ mysim of addprop $stb_node array "hw-key-hash" hw_key_hash
+
+ if { $default_config != "PEGASUS" && [info exists env(SKIBOOT_CVC_CODE)] } {
+ set cvc_node [ mysim of addchild $stb_node "ibm,cvc" "" ]
+ mysim of addprop $cvc_node string "compatible" "ibm,container-verification-code"
+ mysim of addprop $cvc_node int "memory-region" $hb_cvc_code_node
+
+ # I'm sure hardcoding these addresses will *never* cause us a problem...
+ set sha_node [ mysim of addchild $cvc_node "ibm,cvc-service" [format %x 0x40]]
+ mysim of addprop $sha_node string "name" "ibm,cvc-service"
+ mysim of addprop $sha_node string "compatible" "ibm,cvc-sha512"
+ mysim of addprop $sha_node int "reg" 0x40
+ mysim of addprop $sha_node int "version" 1
+
+ set verify_node [ mysim of addchild $cvc_node "ibm,cvc-service" [format %x 0x50]]
+ mysim of addprop $verify_node string "name" "ibm,cvc-service"
+ mysim of addprop $verify_node string "compatible" "ibm,cvc-verify"
+ mysim of addprop $verify_node int "reg" 0x50
+ mysim of addprop $verify_node int "version" 1
+ }
+}
+
+# Kernel command line args, appended to any from the device tree
+# e.g.: of::set_bootargs "xmon"
+#
+# Can be set from the environment by setting LINUX_CMDLINE.
+of::set_bootargs $mconf(linux_cmdline)
+
+# Load images
+
+set boot_size [file size $mconf(boot_image)]
+mysim memory fread $mconf(boot_load) $boot_size $mconf(boot_image)
+
+set payload_size [file size $mconf(payload)]
+mysim memory fread $mconf(payload_addr) $payload_size $mconf(payload)
+
+if { $payload_size > [expr $mconf(boot_load) - $mconf(payload_addr)] } {
+ error "vmlinux is too large, consider adjusting PAYLOAD_ADDR"
+}
+
+# Flatten it
+epapr::of2dtb mysim $mconf(epapr_dt_addr)
+
+# Set run speed
+mysim mode fastest
+
+if { [info exists env(GDB_SERVER)] } {
+ mysim debugger wait $env(GDB_SERVER)
+}
+
+if { [info exists env(SKIBOOT_AUTORUN)] } {
+ if [catch { mysim go }] {
+ readline
+ }
+} else {
+ readline
+}
+
+if { [info exists env(SKIBOOT_AUTORUN)] && $env(SKIBOOT_AUTORUN) == 2 } {
+ quit
+}