[Skiboot] [RFC PATCH 0/3] WIP VMM for OPAL boot
Stewart Smith
stewart at linux.ibm.com
Fri Jun 7 07:56:54 AEST 2019
Stewart Smith <stewart at linux.ibm.com> writes:
> Nicholas Piggin <npiggin at gmail.com> writes:
>> This is my current work in progress, I've gradually been adding bits
>> and fixing bugs so time for another rebase. It's been booting pretty
>> reliably on my P9, I've next been trying to bring VMM mode back up
>> when we fast-reboot which is still a bit buggy but almost works.
>
> Cool. I'm chasing the secure boot problems, which has now become "get
> all the genuine secure "rom" stuff running in Mambo".
>
> This is the most obivous "Something is going to go wrong without it" bit
> I have, but that doesn't magically fix things, nor explain why
> everything stops suddenly.
As mentioned on slack, I found the problem was that we had a "li %r2,0"
in the mix.
The Container Verification Code is a blob that we get passed in from
hostboot (well, all the way from the hostboot bootloader actually) that
has two entry points: one for validating a secureboot header and the
other for computing sha512 checksum of a blob.
In skiboot, the libstb/cvc.c code finds it, which on P9 is from a
reserved memory region, and on P8 it's by copying it from an actual ROM
that's on chip that needs to be accessed with cache inhibited reads.
The asm/cvc_entry.S wrapper, as part of calling the CVC function, sets
%r2 to zero. Thus, when we take the ISI for the page of text, we end up
in vm_isi() without %r2 set to anything sane, and we end up hitting the
assert(!_dw0) in htab_install because we're poking around where we're
not meant to. Naturally, all the (soon multiple levels) of
exception_entry() and abort() without a sane %r2 goes about as well as
you'd expect and we eventually xstop.
For at least a quick hack (I haven't thought about it beyond "hey, we're
not using that register") I stashed the skiboot TOC in HSPRG0 and pulled
it in in _exception.
So, the below patch is on top of this series that (at least in Mambo, I
haven't tested on hardware yet), will run the CVC code and boot a
kernel.
I'm not sure what's up with my mambo tcl to ensure I get the
references/size right for the CVC code in the device tree, so have
quickly hacked around it with a if (size==0) size = 64*1024 in cvc.c
(maybe the Masters of Mambo can enlighten me).
I'm almost interested to try and pull out the CVC code and use that
rather than the "softrom" hack I put in a couple of years ago.
diff --git a/asm/head.S b/asm/head.S
index 18a9c12cfb06..ae9a73b1fd7b 100644
--- a/asm/head.S
+++ b/asm/head.S
@@ -238,6 +238,7 @@ _exception:
mr %r3,%r1
LOAD_IMM64(%r4, SKIBOOT_BASE)
LOAD_IMM32(%r5, exception_entry_foo - __head)
+ mfspr %r2, SPR_HSPRG0
add %r4,%r4,%r5
mtctr %r4
bctr
@@ -367,6 +368,7 @@ boot_entry:
LOAD_IMM32(%r2,__toc_start - __head)
LOAD_IMM64(%r29, SKIBOOT_BASE)
add %r2,%r2,%r29
+ mtspr SPR_HSPRG0, %r2
/* Fixup our MSR (remove TA) */
LOAD_IMM64(%r3, (MSR_HV | MSR_SF))
diff --git a/core/flash.c b/core/flash.c
index 420ae3244ae9..5555856e681a 100644
--- a/core/flash.c
+++ b/core/flash.c
@@ -762,11 +762,10 @@ done_reading:
* Verify and measure the retrieved PNOR partition as part of the
* secure boot and trusted boot requirements
*/
-#if 0
-// XXX: this chekstops
+
secureboot_verify(id, buf, *len);
trustedboot_measure(id, buf, *len);
-#endif
+
/* Find subpartition */
if (subid != RESOURCE_SUBID_NONE) {
memmove(buf, bufp, content_size);
diff --git a/core/init.c b/core/init.c
index 0fad02f67550..2f620c17b6c9 100644
--- a/core/init.c
+++ b/core/init.c
@@ -81,7 +81,7 @@ struct debug_descriptor debug_descriptor = {
#ifdef DEBUG
.console_log_levels = (PR_TRACE << 4) | PR_DEBUG,
#else
- .console_log_levels = (PR_DEBUG << 4) | PR_NOTICE,
+ .console_log_levels = (PR_DEBUG << 4) | PR_DEBUG,
#endif
};
diff --git a/core/mem_region.c b/core/mem_region.c
index fe89cedb6e79..d33093c61e97 100644
--- a/core/mem_region.c
+++ b/core/mem_region.c
@@ -154,7 +154,7 @@ static struct alloc_hdr *next_hdr(const struct mem_region *region,
}
#if POISON_MEM_REGION == 1
-static void mem_poison(struct free_hdr *f)
+static void mem_poison(struct free_hdr *f __unused)
{
}
#endif
diff --git a/core/vm.c b/core/vm.c
index 1bf5e4bd81a8..c741c3e55a8f 100644
--- a/core/vm.c
+++ b/core/vm.c
@@ -360,7 +360,7 @@ void vm_map_global(const char *name, unsigned long addr, unsigned long len, bool
__vm_map(name, addr, len, addr, true, rw, false, ci, false);
}
-static void vm_map_global_text(const char *name, unsigned long addr, unsigned long len)
+void vm_map_global_text(const char *name, unsigned long addr, unsigned long len)
{
__vm_map(name, addr, len, addr, true, false, true, false, false);
}
@@ -611,15 +611,26 @@ bool __nomcount vm_isi(uint64_t nia)
{
struct cpu_thread *c = this_cpu();
bool vm_setup = c->vm_setup;
+ struct vm_map *vmm;
assert(vm_setup);
- if (nia < (unsigned long)_stext)
- return false;
- if (nia >= (unsigned long)_etext)
- return false;
+ lock(&vm_maps_lock);
+ list_for_each(&vm_maps, vmm, list) {
+ assert(vmm->pa == vmm->address);
+ if (nia >= vmm->address && nia < vmm->address + vmm->length) {
+ if (!vmm->executable)
+ printf("Page fault at NIA:0x%016llx NX mapping!\n", nia);
+ goto found;
+ }
+ }
- c->vm_setup = false;
+ prerror("Page fault, no mapping for NIA:0x%016llx !\n", nia);
+
+found:
+ unlock(&vm_maps_lock);
+ c->vm_setup = false;
+ printf("Page fault, mapping NIA:0x%016llx !\n", nia);
htab_install(nia, nia, 0, 1, 0, false);
c->vm_setup = true;
diff --git a/external/mambo/skiboot.tcl b/external/mambo/skiboot.tcl
index 9f424dd9af23..f7014aed1658 100644
--- a/external/mambo/skiboot.tcl
+++ b/external/mambo/skiboot.tcl
@@ -306,6 +306,19 @@ if { [info exists env(SKIBOOT_NVRAM)] } {
mysim mcm 0 memory fread $fake_nvram_start $fake_nvram_size $fake_nvram_file
}
+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]
+}
+
+
# 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
@@ -322,6 +335,18 @@ 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 hb [mysim of addchild $root_node "ibm,hostboot" ""]
+set hb_reserved_memory [mysim of addchild $hb "reserved-memory" ""]
+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 opal_node [mysim of addchild $root_node "ibm,opal" ""]
# Allow P9 to use all idle states
@@ -546,10 +571,12 @@ 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" "" ]
- mysim of addprop $stb_node string "compatible" "ibm,secureboot-v1-softrom"
+# mysim of addprop $stb_node string "compatible" "ibm,secureboot-v1-softrom"
+ 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
@@ -568,6 +595,22 @@ if { [info exists env(SKIBOOT_ENABLE_MAMBO_STB)] } {
lappend hw_key_hash 0xfb708535
lappend hw_key_hash 0x1d01d6d1
mysim of addprop $stb_node array "hw-key-hash" hw_key_hash
+
+ 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
+
+ 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
diff --git a/include/skiboot.h b/include/skiboot.h
index 98a69ef1d68c..32f6307a2f45 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -352,6 +352,7 @@ extern int fake_nvram_write(uint32_t offset, void *src, uint32_t size);
bool vm_realmode(void);
void vm_map_global(const char *name, unsigned long addr, unsigned long len, bool rw, bool ci);
+void vm_map_global_text(const char *name, unsigned long addr, unsigned long len);
void vm_unmap_global(unsigned long addr, unsigned long len);
void *vm_map(unsigned long addr, unsigned long len, bool rw);
void vm_unmap(unsigned long addr, unsigned long len);
diff --git a/libstb/cvc.c b/libstb/cvc.c
index d46617b29070..4a3a08f5f4f5 100644
--- a/libstb/cvc.c
+++ b/libstb/cvc.c
@@ -167,6 +167,9 @@ static int cvc_reserved_mem_init(struct dt_node *parent) {
return -1;
}
addr = dt_get_address(cvc_resv_mem, 0, &size);
+ if (size == 0) // MAMBO HACK
+ size = 64*1024;
+ vm_map_global_text("STB-CVC", addr, size);
cvc_register(addr, addr + size-1);
/*
diff --git a/libstb/secureboot.c b/libstb/secureboot.c
index 1578f52ecdfc..2f0f3298e5bc 100644
--- a/libstb/secureboot.c
+++ b/libstb/secureboot.c
@@ -176,6 +176,7 @@ void secureboot_init(void)
int secureboot_verify(enum resource_id id, void *buf, size_t len)
{
const char *name;
+ void *vbuf;
uint64_t log;
int rc = -1;
@@ -194,7 +195,9 @@ int secureboot_verify(enum resource_id id, void *buf, size_t len)
return -1;
}
- rc = call_cvc_verify(buf, len, hw_key_hash, hw_key_hash_size, &log);
+ vbuf = vm_map((unsigned long)buf, len, false);
+ rc = call_cvc_verify(vbuf, len, hw_key_hash, hw_key_hash_size, &log);
+ vm_unmap((unsigned long)buf, len);
if (rc == OPAL_SUCCESS) {
prlog(PR_NOTICE, "%s verified\n", name);
diff --git a/libstb/trustedboot.c b/libstb/trustedboot.c
index f431e338acd4..ba922bb67862 100644
--- a/libstb/trustedboot.c
+++ b/libstb/trustedboot.c
@@ -174,7 +174,7 @@ out_free:
int trustedboot_measure(enum resource_id id, void *buf, size_t len)
{
uint8_t digest[SHA512_DIGEST_LENGTH];
- void *buf_aux;
+ void *buf_aux, *vbuf;
size_t len_aux;
const char *name;
TPM_Pcr pcr;
@@ -232,7 +232,9 @@ int trustedboot_measure(enum resource_id id, void *buf, size_t len)
len_aux = len;
}
- rc = call_cvc_sha512(buf_aux, len_aux, digest, SHA512_DIGEST_LENGTH);
+ vbuf = vm_map((unsigned long)buf_aux, len_aux, false);
+ rc = call_cvc_sha512(vbuf, len_aux, digest, SHA512_DIGEST_LENGTH);
+ vm_unmap((unsigned long)buf_aux, len_aux);
if (rc == OPAL_SUCCESS) {
prlog(PR_NOTICE, "%s hash calculated\n", name);
--
Stewart Smith
OPAL Architect, IBM.
More information about the Skiboot
mailing list