kernel: tentative stack overflow panic, 14 kiB stack on G-III

I saw a crash with the 12 kB stack. Added an error message to diagnose
further similar issues, and bumbed the stack to 14 kB. That's a lot of
space just for BFile but stability is queen... :x
This commit is contained in:
Lephe 2021-12-11 16:36:51 +01:00
parent 8635880bbb
commit 321d6937e0
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
3 changed files with 30 additions and 6 deletions

View file

@ -50,6 +50,7 @@ GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
if(code == 0x1020) name = "DMA address error";
if(code == 0x1040) name = "Add-in too large";
if(code == 0x1060) name = "Memory init failed";
if(code == 0x1080) name = "Stack overflow";
if(name[0]) dtext(1, 9, name);
else dprint(1, 9, "%03x", code);
@ -82,6 +83,7 @@ GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
if(code == 0x1020) name = "DMA address error";
if(code == 0x1040) name = "Add-in not fully mapped (too large)";
if(code == 0x1060) name = "Memory initialization failed (heap)";
if(code == 0x1080) name = "Stack overflow during world switch";
dprint(6, 25, "%03x %s", code, name);

View file

@ -9,6 +9,7 @@
#include <gint/mpu/intc.h>
#include <gint/kmalloc.h>
#include <gint/cpu.h>
#include <gint/exc.h>
#include <string.h>
#include <stdlib.h>
@ -28,6 +29,9 @@ gint_world_t gint_world_addin = NULL;
/* Dynamic flags for all drivers */
uint8_t *gint_driver_flags = NULL;
/* Top of the stack */
void *gint_stack_top = NULL;
//---
// Initialization and unloading
//---
@ -45,9 +49,12 @@ void kinit(void)
expanded region. */
uint32_t uram_end = (uint32_t)mmu_uram() + mmu_uram_size();
/* Stack space on SH4. 12 kB is a lot, but BFile is known to overflow
from the previous 8 kB design */
if(isSH4()) uram_end -= 0x3000;
/* Stack space on SH4. 14 kB is a lot, but Fugue's BFile has been seen
overflowing both 8 kB and 12 kB */
if(isSH4()) {
uram_end -= (gint[HWFS] == HWFS_FUGUE) ? 0x3800 : 0x2000;
gint_stack_top = (void *)uram_end;
}
/* VBR is advanced 0x100 bytes because of an unused gap */
uram_end -= (isSH3() ? 0x600 : 0x1100);
@ -61,6 +68,7 @@ void kinit(void)
leave 16 kB. */
VBR = (uint32_t)mmu_uram();
uint32_t uram_end = (uint32_t)mmu_uram() + mmu_uram_size() - 0x4000;
gint_stack_top = (void *)uram_end;
#endif
/* Event handler entry points */
@ -93,10 +101,7 @@ void kinit(void)
gint_driver_flags = malloc(gint_driver_count());
if(!gint_world_os || !gint_world_addin || !gint_driver_flags)
{
extern void gint_panic(uint32_t code);
gint_panic(0x1060);
}
/* Initialize drivers */
for(int i = 0; i < gint_driver_count(); i++)

View file

@ -1,6 +1,7 @@
#include <gint/drivers.h>
#include <gint/cpu.h>
#include <gint/gint.h>
#include <gint/exc.h>
#include <gint/defs/call.h>
#include <stdlib.h>
@ -126,8 +127,24 @@ void gint_world_switch_out(gint_world_t world_addin, gint_world_t world_os)
int gint_world_switch(gint_call_t call)
{
extern void *gint_stack_top;
gint_world_switch_out(gint_world_addin, gint_world_os);
/* Watch out for stack overflows */
uint32_t *canary = gint_stack_top;
if(canary)
*canary = 0xb7c0ffee;
int rc = call.function ? gint_call(call) : 0;
/* The canary check needs to occur before switching in the gint world;
otherwise we just crash due to the overflow. gint_panic() isn't
really designed to work from the OS world, but it does fine on the
fx-9860G series and sometimes also on the fx-CG series; better crash
attempting to show a panic message than just crash */
if(canary && *canary != 0xb7c0ffee)
gint_panic(0x1080);
gint_world_switch_in(gint_world_os, gint_world_addin);
return rc;
}