This patchset is a result of my work to get the *BSD kernels to boot under QEMU SPARC64, and should be applied on top of the timer patchset previously posted.
With these patches applied we now get the following:
- NetBSD kernels start and enumerate PCI devices but panic due to missing device properties
- Old OpenBSD kernels start and enumerate PCI devices but panic due to missing device properties
- New OpenBSD kernels trap soon after trap table takeover (possible window fill/spill issue?)
- FreeBSD kernels start and die during PCI device enumeration similar to above but seem to stop console output after trap table takeover?
The first four patches fix bugs which enable us to unmap page zero on SPARC64 to catch NULL dereferences (in line with all other architectures) and helped further reveal the bugs fixed by the subsequent patches.
Mark Cave-Ayland (7): pc_serial.c: fix up missing address property pc_kbd.c: fix up reg property and missing address property SPARC64: fix NULL pointer reference when attempting kernel boot SPARC64: Remove zero page mapping from MMU to enable detection of NULL pointer dereferences SPARC64: fix up translation property mode to make it a valid TTE ciface.fs: handle buggy callers to test-method SPARC64: only map 8MB RAM on startup
openbios-devel/arch/sparc64/boot.c | 40 ++++++++++++++------------- openbios-devel/arch/sparc64/ofmem_sparc64.c | 6 ++-- openbios-devel/drivers/pc_kbd.c | 15 +++++++++- openbios-devel/drivers/pc_serial.c | 6 ++++ openbios-devel/forth/system/ciface.fs | 25 +++++++++++++---- 5 files changed, 64 insertions(+), 28 deletions(-)
Create the missing address property for the PC serial port, otherwise pc_serial_open() will dereference a NULL pointer when opening the serial port device.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- openbios-devel/drivers/pc_serial.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/openbios-devel/drivers/pc_serial.c b/openbios-devel/drivers/pc_serial.c index 6192f18..f63fcaa 100644 --- a/openbios-devel/drivers/pc_serial.c +++ b/openbios-devel/drivers/pc_serial.c @@ -190,6 +190,12 @@ ob_pc_serial_init(const char *path, const char *dev_name, uint64_t base, fword("encode+"); push_str("reg"); fword("property"); + + PUSH(offset); + fword("encode-int"); + push_str("address"); + fword("property"); + #if defined(CONFIG_SPARC64) set_int_property(get_cur_dev(), "interrupts", 1); #endif
Create the missing address property for the PC serial keyboard, otherwise pc_kbd_open() will dereference a NULL pointer when opening the serial keyboard device.
Similarly fix up the reg property to match the PC serial port which appears to give values matching those found in SPARC64 device trees.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- openbios-devel/drivers/pc_kbd.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/openbios-devel/drivers/pc_kbd.c b/openbios-devel/drivers/pc_kbd.c index 0f1ee70..49218f8 100644 --- a/openbios-devel/drivers/pc_kbd.c +++ b/openbios-devel/drivers/pc_kbd.c @@ -15,6 +15,8 @@ * simple polling video/keyboard console functions * ****************************************************************** */
+#define SER_SIZE 8 + /* * keyboard driver */ @@ -206,10 +208,21 @@ ob_pc_kbd_init(const char *path, const char *dev_name, uint64_t base, push_str("keyboard"); fword("property");
- PUSH(0); + PUSH((base + offset) >> 32); + fword("encode-int"); + PUSH((base + offset) & 0xffffffff); + fword("encode-int"); + fword("encode+"); + PUSH(SER_SIZE); fword("encode-int"); + fword("encode+"); push_str("reg"); fword("property"); + + PUSH(offset); + fword("encode-int"); + push_str("address"); + fword("property");
chosen = find_dev("/chosen"); push_str(nodebuff);
When checking to determine whether to boot a standalone kernel, we would inadvertently reference a NULL pointer if no path was found. Make sure subsequent path processing is ignored when not booting a standalone kernel so we fall through to normal Forth boot.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- openbios-devel/arch/sparc64/boot.c | 40 +++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 19 deletions(-)
diff --git a/openbios-devel/arch/sparc64/boot.c b/openbios-devel/arch/sparc64/boot.c index c4e40b0..5107be6 100644 --- a/openbios-devel/arch/sparc64/boot.c +++ b/openbios-devel/arch/sparc64/boot.c @@ -105,24 +105,26 @@ void boot(void) path = pop_fstr_copy(); }
- param = strchr(path, ' '); - if(param) { - *param = '\0'; - param++; - } else if (cmdline_size) { - param = (char *)qemu_cmdline; - } else { - push_str("boot-args"); - push_str("/options"); - fword("(find-dev)"); - POP(); - fword("get-package-property"); - POP(); - param = pop_fstr_copy(); + if (path) { + param = strchr(path, ' '); + if(param) { + *param = '\0'; + param++; + } else if (cmdline_size) { + param = (char *)qemu_cmdline; + } else { + push_str("boot-args"); + push_str("/options"); + fword("(find-dev)"); + POP(); + fword("get-package-property"); + POP(); + param = pop_fstr_copy(); + } + + /* Invoke platform-specific Linux loader */ + linux_load(&sys_info, path, param); + + free(path); } - - /* Invoke platform-specific Linux loader */ - linux_load(&sys_info, path, param); - - free(path); }
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- openbios-devel/arch/sparc64/ofmem_sparc64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/openbios-devel/arch/sparc64/ofmem_sparc64.c b/openbios-devel/arch/sparc64/ofmem_sparc64.c index d0a7d88..005d774 100644 --- a/openbios-devel/arch/sparc64/ofmem_sparc64.c +++ b/openbios-devel/arch/sparc64/ofmem_sparc64.c @@ -366,7 +366,7 @@ void ofmem_init( void ) ofmem_walk_boot_map(remap_page_range);
/* Map the memory */ - ofmem_map_page_range(0, 0, qemu_mem_size, 0x36); + ofmem_map_page_range(PAGE_SIZE, PAGE_SIZE, qemu_mem_size, 0x36);
if (!(retained->magic == RETAIN_MAGIC)) { OFMEM_TRACE("ofmem_init: no retained magic found, creating\n");
NetBSD attempts to parse the translation property in order to set up the virtual to physical translations for kernel. Alter the mode cell to include the physical address and valid bit so that it represents a real TTE entry for the given start adddress.
This is confirmed by checking real dumps from prtconf examples, plus the NetBSD kernel now starts to boot.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- openbios-devel/arch/sparc64/ofmem_sparc64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/openbios-devel/arch/sparc64/ofmem_sparc64.c b/openbios-devel/arch/sparc64/ofmem_sparc64.c index 005d774..5758a5d 100644 --- a/openbios-devel/arch/sparc64/ofmem_sparc64.c +++ b/openbios-devel/arch/sparc64/ofmem_sparc64.c @@ -103,12 +103,12 @@ void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t)
virtual address length - mode + mode (valid TTE for start of translation region) */
transentry[0] = t->virt; transentry[1] = t->size; - transentry[2] = t->mode; + transentry[2] = t->phys | t->mode | SPITFIRE_TTE_VALID; }
/* Return the size of a memory available entry given the phandle in cells */
SPARC64 *BSDs accidentally call test-method with an ihandle rather than a phandle which causes OpenBIOS to crash. Work around this by checking to ensure that the phandle exists within the tree before trying to use it.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- openbios-devel/forth/system/ciface.fs | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-)
diff --git a/openbios-devel/forth/system/ciface.fs b/openbios-devel/forth/system/ciface.fs index 727f0a3..fc40cff 100644 --- a/openbios-devel/forth/system/ciface.fs +++ b/openbios-devel/forth/system/ciface.fs @@ -55,6 +55,17 @@ variable callback-function ." <" dup cstrlen dup 20 < if type else 2drop ." BAD" then ." >" ;
+: phandle-exists? ( phandle -- found? ) + false swap 0 + begin iterate-tree ?dup while + ( found? find-ph current-ph ) + over over = if + rot drop true -rot + then + repeat + drop +; + \ ------------------------------------------------------------- \ public interface \ ------------------------------------------------------------- @@ -317,11 +328,15 @@ external outer-interpreter ;
-( cstring-method phandle -- missing ) - -: test-method - swap dup cstrlen rot - find-method 0= if -1 else drop 0 then +: test-method ( cstring-method phandle -- missing? ) + swap dup cstrlen rot + + \ Check for incorrect phandle + dup phandle-exists? false = if + -1 throw + then + + find-method 0= if -1 else drop 0 then ;
finish-device
Due to a (bug?) in OpenBSD's pmap_bootstrap(), the kernel attempts to locate its text segment and size by searching the translations property for continuous regions in use starting from the kernel load address.
Unfortunately if we have already mapped memory above the kernel load address of 0x1000000 then the kernel extends the text region way beyond the text segement causing an exception when eventually trying to set non-existent mappings in the TLB.
Fix this by only mapping 8MB of RAM so that we guarantee that the region above 0x1000000 will always be free, and hence the text/data regions will be discrete so that the sizing algorithms return the correct answer.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- openbios-devel/arch/sparc64/ofmem_sparc64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/openbios-devel/arch/sparc64/ofmem_sparc64.c b/openbios-devel/arch/sparc64/ofmem_sparc64.c index 5758a5d..16f9247 100644 --- a/openbios-devel/arch/sparc64/ofmem_sparc64.c +++ b/openbios-devel/arch/sparc64/ofmem_sparc64.c @@ -366,7 +366,7 @@ void ofmem_init( void ) ofmem_walk_boot_map(remap_page_range);
/* Map the memory */ - ofmem_map_page_range(PAGE_SIZE, PAGE_SIZE, qemu_mem_size, 0x36); + ofmem_map_page_range(PAGE_SIZE, PAGE_SIZE, 0x800000, 0x36);
if (!(retained->magic == RETAIN_MAGIC)) { OFMEM_TRACE("ofmem_init: no retained magic found, creating\n");