Skip to content

Commit

Permalink
Merge pull request #1984 from ghaerr/tstack
Browse files Browse the repository at this point in the history
[kernel] Use early temp stack to avoid irqit stack overruns on faults during startup
  • Loading branch information
ghaerr authored Sep 3, 2024
2 parents b9cc06c + f44fe9a commit 1474364
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 23 deletions.
4 changes: 2 additions & 2 deletions elks/arch/i86/boot/crt0.S
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ _start:

mov %ds,%ax
mov %ax,%ss // SS=ES=DS
mov $istack,%sp
mov $tstack,%sp // can't use kernel interrupt stack, must have temp stack

call start_kernel // fall through into breakpoint if returns

Expand Down Expand Up @@ -80,7 +80,7 @@ early_putchar:
.global _endbss
.extern kernel_cs
.extern kernel_ds
.extern istack
.extern tstack

_endtext:
.word 0
Expand Down
10 changes: 5 additions & 5 deletions elks/arch/i86/boot/setup.S
Original file line number Diff line number Diff line change
Expand Up @@ -666,10 +666,10 @@ data_reloc:
jmp data_reloc
3:

mov $'\r',%ax
call putc
mov $'\n',%ax
call putc
// mov $'\r',%ax
// call putc
// mov $'\n',%ax
// call putc

// Load registers as kernel expects

Expand All @@ -688,7 +688,7 @@ data_reloc:
push %ax
push %cx

.hex4sp %ss,"Done SS:"
.hex4sp %ss,"\nDone SS:"
.hex4sp %ds,"DS/ES:"
.hex4sp %bx,".text size:"
.hex4sp %di,".fartext size:"
Expand Down
2 changes: 1 addition & 1 deletion elks/arch/i86/drivers/char/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ int kmem_ioctl(struct inode *inode, struct file *file, int cmd, char *arg)
retword = kernel_ds;
break;
case MEM_GETFARTEXT:
retword = (unsigned)((long)kernel_init >> 16);
retword = (unsigned)((long)buffer_init >> 16);
break;
case MEM_GETUSAGE:
mm_get_usage (&(mu.free_memory), &(mu.used_memory));
Expand Down
3 changes: 2 additions & 1 deletion elks/arch/i86/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ OBJS = strace.o system.o irq.o irqtab.o process.o \
entry.o signal.o timer.o

ifeq ($(CONFIG_ARCH_IBMPC), y)
OBJS += irq-8259.o timer-8254.o divzero.o
OBJS += irq-8259.o timer-8254.o
#OBJS += divzero.o
endif

ifeq ($(CONFIG_ARCH_PC98), y)
Expand Down
10 changes: 7 additions & 3 deletions elks/arch/i86/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,13 @@ void INITPROC irq_init(void)
int_handler_add(IDX_SYSCALL, 0x80, _irqit);

#ifdef CONFIG_ARCH_IBMPC
/* catch INT 0x00h divide by zero trap */
irq_action[IDX_DIVZERO] = div0_handler;
int_handler_add(IDX_DIVZERO, 0x00, _irqit);
/* catch INT 0 divide by zero/divide overflow hardware fault */
/*irq_action[IDX_DIVZERO] = div0_handler;
int_handler_add(IDX_DIVZERO, 0x00, _irqit);*/
/* install direct panic-only DIV fault handler until known that
* the _irqit version doesn't overwrite the stack
*/
int_handler_add(IDX_DIVZERO, 0x00, div0_handler_panic);
#endif

#if defined(CONFIG_TIMER_INT0F) || defined(CONFIG_TIMER_INT1C)
Expand Down
38 changes: 36 additions & 2 deletions elks/arch/i86/kernel/irqtab.S
Original file line number Diff line number Diff line change
Expand Up @@ -392,10 +392,40 @@ idle_halt:
hlt
ret

.global div0_handler_panic
// Divide Fault hander - just panic for now
div0_handler_panic:
push %ax // save regs, uses 4+4+10 bytes of current stack
push %bx
push %cx
push %dx
push %ds

// Recover kernel data segment
// Was pushed by the CALLF of the dynamic handler
mov %sp,%bx
mov %ss:12(%bx),%ds

mov $dmsg,%ax
push %ax
call panic
pop %ax
1: hlt
jmp 1b

// pop %ds // restore regs
// pop %dx
// pop %cx
// pop %bx
// pop %ax
// add $4,%sp // skip the trampoline lcall
// iret

.data
.global _gint_count
.global endistack
.global istack
.global tstack
.extern current
.extern previous

Expand All @@ -406,10 +436,14 @@ org_irq0: // original BIOS IRQ 0 vector
_gint_count: // General interrupts count. Start with 1
.word 1 // because init_task() is in kernel mode
#ifdef CHECK_SS
pmsg: .ascii "Running unknown code"
.byte 0
pmsg: .ascii "Running unknown code\0"
#endif
dmsg: .ascii "DIVIDE FAULT\0"

.p2align 1
endistack:
.skip ISTACK_BYTES,0 // interrupt stack
istack:

.skip 256,0 // startup temp stack
tstack:
3 changes: 2 additions & 1 deletion elks/include/arch/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ int request_irq(int,irq_handler,int hflag);
int free_irq(int irq);

/* irqtab.S */
void int_vector_set (int vect, word_t proc, word_t seg);
void _irqit (void);
void int_vector_set (int vect, word_t proc, word_t seg);
void div0_handler_panic(void);

/* irq-8259.c, irq-8018x.c*/
void initialize_irq(void);
Expand Down
1 change: 0 additions & 1 deletion elks/include/linuxmt/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ struct gendisk;
struct drive_infot;

/* kernel init routines*/
extern void INITPROC kernel_init(void);
extern int INITPROC buffer_init(void);
extern void INITPROC console_init(void);
extern void INITPROC fs_init(void);
Expand Down
14 changes: 7 additions & 7 deletions elks/init/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ static char * INITPROC option(char *s);
#endif

static void init_task(void);
static void INITPROC kernel_banner(seg_t start, seg_t end, seg_t init, seg_t extra);
static void INITPROC early_kernel_init(void);
static void INITPROC kernel_init(void);
static void INITPROC kernel_banner(seg_t start, seg_t end, seg_t init, seg_t extra);

#if TIMER_TEST
void testloop(unsigned timer)
Expand Down Expand Up @@ -118,10 +119,12 @@ void testloop(unsigned timer)
/* this procedure called using temp stack then switched, no local vars allowed */
void start_kernel(void)
{
printk("START\n");
early_kernel_init(); /* read bootopts using kernel interrupt stack */
task = heap_alloc(max_tasks * sizeof(struct task_struct),
HEAP_TAG_TASK|HEAP_TAG_CLEAR);
if (!task) panic("No task mem");
sched_init(); /* set us (the current stack) to be idle task #0*/
setsp(&task->t_regs.ax); /* change to idle task stack */
kernel_init(); /* continue init running on idle task stack */

Expand Down Expand Up @@ -168,17 +171,14 @@ static void INITPROC early_kernel_init(void)
#endif
}

void INITPROC kernel_init(void)
static void INITPROC kernel_init(void)
{
/* set us (the current stack) to be idle task #0*/
sched_init();
irq_init();
irq_init(); /* installs timer and div fault handlers */

/* set console from /bootopts console= or 0=default*/
set_console(boot_console);

/* init direct, bios or headless console*/
console_init();
console_init(); /* init direct, bios or headless console*/

#ifdef CONFIG_CHAR_DEV_RS
serial_init();
Expand Down

0 comments on commit 1474364

Please sign in to comment.