Commit diff
Commit 2082e133f48a97d4351ac46324b8032bd82fbb2
commit 2082e133f48a97d4351ac46324b8032bd82fbb25
Author: Greg Haerr <greg@censoft.com>
Date: Thu Feb 19 18:01:02 2026 -0700
[kernel] Prevent potential hang on 16550A UART by loop-reading FIFO each interrupt
---
elks/arch/i86/drivers/char/serfast.S | 19 ++++++++++++++-----
elks/arch/i86/drivers/char/serial-8250.c | 4 ++--
elks/arch/i86/mm/malloc.c | 3 +++
3 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/elks/arch/i86/drivers/char/serfast.S b/elks/arch/i86/drivers/char/serfast.S
index 94fefe2f..5600291a 100644
--- a/elks/arch/i86/drivers/char/serfast.S
+++ b/elks/arch/i86/drivers/char/serfast.S
@@ -27,6 +27,7 @@
// struct ch_queue *q = &sp->tty->inq;
// unsigned char c;
//
+// do {
// c = INB(sp->io + UART_RX); // Read received data
// if (q->len < q->size) {
// q->base[q->head] = c;
@@ -36,6 +37,7 @@
// }
// if (c == 03) // assumes VINTR = ^C and byte queued anyways
// sp->intrchar = c;
+// } while (INB(sp->io + UART_LSR) & UART_LSR_DR);
// }
//
@@ -62,7 +64,7 @@ common_entry:
mov %cx,%bx // bx = sp = &ports[n]
mov (%bx),%si // si = q = &sp->tty->inq
mov 0x4(%bx),%dx // dx = sp->io + UART_RX
- in (%dx),%al
+0: in (%dx),%al // do {
mov %al,%dl // dl = c = INB(sp->io+UART_RX)
mov (%si),%ax // ax = q->len
cmp 0x2(%si),%ax // if (ax >= q->size)
@@ -76,12 +78,19 @@ common_entry:
cmp 0x2(%si),%ax // if (q->size < q->head)
jl 1f
movw $0x0,0x4(%si) // q->head = 0
-1: incw (%si)
-2: cmp $0x3,%dl // if (c == 03)
+1: incw (%si) // q->len++
+2: mov %cx,%bx // bx = sp
+ cmp $0x3,%dl // if (c == 03)
jne 3f
- mov %cx,%bx // bx = sp
movw $0x3,2(%bx) // sp->intrchar = c
-3: pop %di
+3: mov 0x4(%bx),%dx // dx = sp->io
+ add $5,%dx // dx = sp->io + UART_LSR
+ in (%dx),%al // al = INB(sp->io + UART_LSR)
+ test $1,%al // while (al & UART_LSR_DR)
+ jz 4f
+ sub $5,%dx // dx = sp->io + UART_RX
+ jmp 0b
+4: pop %di
pop %si
mov $0x20,%al // EOI on primary controller
diff --git a/elks/arch/i86/drivers/char/serial-8250.c b/elks/arch/i86/drivers/char/serial-8250.c
index d8f42ee9..b6d41133 100644
--- a/elks/arch/i86/drivers/char/serial-8250.c
+++ b/elks/arch/i86/drivers/char/serial-8250.c
@@ -103,7 +103,7 @@ static void flush_input(register struct serial_info *sp)
#endif
}
-static int rs_probe(register struct serial_info *sp)
+static int INITPROC rs_probe(register struct serial_info *sp)
{
int status, type;
unsigned char scratch;
@@ -479,7 +479,7 @@ static int rs_ioctl(struct tty *tty, int cmd, char *arg)
return retval;
}
-static void rs_init(void)
+static void INITPROC rs_init(void)
{
register struct serial_info *sp = ports;
register struct tty *tty = ttys + NR_CONSOLES;
diff --git a/elks/arch/i86/mm/malloc.c b/elks/arch/i86/mm/malloc.c
index 09c51a7b..f08dd90e 100644
--- a/elks/arch/i86/mm/malloc.c
+++ b/elks/arch/i86/mm/malloc.c
@@ -291,6 +291,9 @@ static int set_brk(segoff_t brk, int increment)
stacklow = current->t_begstack - current->t_minstack;
if (newbrk > stacklow) {
printk("(%P)SBRK %d FAIL, OUT OF HEAP SPACE\n", increment);
+ /*printk("BEGSTK %x MINSTK %x LOWSTK %x NEWBRK %x CURBRK %x\n",
+ current->t_begstack, current->t_minstack, stacklow, newbrk,
+ current->t_endbrk);*/
return -ENOMEM;
}
if (newbrk > current->t_regs.sp) {