aboutsummaryrefslogtreecommitdiff
path: root/src/stacks.c
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2010-05-23 10:24:22 -0400
committerKevin O'Connor <kevin@koconnor.net>2010-05-23 10:24:22 -0400
commit9c447c3a6d94b4e43e0b55a1d0cf0f9731472aa2 (patch)
tree2cb21e691276a923a0e2e4252c673b0ca16a62c2 /src/stacks.c
parent49cc72ba1e59e552754217225d66c7ef0feaf84f (diff)
downloadseabios-hppa-9c447c3a6d94b4e43e0b55a1d0cf0f9731472aa2.zip
seabios-hppa-9c447c3a6d94b4e43e0b55a1d0cf0f9731472aa2.tar.gz
seabios-hppa-9c447c3a6d94b4e43e0b55a1d0cf0f9731472aa2.tar.bz2
Allow wait_irq to be called in 32bit code.
If wait_irq() is called from 32bit code, then jump to 16bit mode for the wait. Have wait_irq check for threads, and have it use yield if threads are pending. This ensures threads aren't delayed if anything calls wait_irq. Use wait_irq() in 32bit mode during a failed boot.
Diffstat (limited to 'src/stacks.c')
-rw-r--r--src/stacks.c83
1 files changed, 73 insertions, 10 deletions
diff --git a/src/stacks.c b/src/stacks.c
index 859de3f..f5feeeb 100644
--- a/src/stacks.c
+++ b/src/stacks.c
@@ -8,6 +8,20 @@
#include "util.h" // dprintf
#include "bregs.h" // CR0_PE
+// Thread info - stored at bottom of each thread stack - don't change
+// without also updating the inline assembler below.
+struct thread_info {
+ struct thread_info *next;
+ void *stackpos;
+ struct thread_info **pprev;
+};
+struct thread_info VAR16VISIBLE MainThread;
+
+
+/****************************************************************
+ * Low level helpers
+ ****************************************************************/
+
static inline u32 getcr0(void) {
u32 cr0;
asm("movl %%cr0, %0" : "=r"(cr0));
@@ -77,6 +91,65 @@ call32(void *func)
return 0;
}
+// 16bit trampoline for enabling irqs from 32bit mode.
+ASM16(
+ " .global trampoline_checkirqs\n"
+ "trampoline_checkirqs:\n"
+ " rep ; nop\n"
+ " lretw"
+ );
+
+static void
+check_irqs(void)
+{
+ if (MODESEGMENT) {
+ asm volatile(
+ "sti\n"
+ "nop\n"
+ "rep ; nop\n"
+ "cli\n"
+ "cld\n"
+ : : :"memory");
+ return;
+ }
+ extern void trampoline_checkirqs();
+ struct bregs br;
+ br.flags = F_IF;
+ br.code.seg = SEG_BIOS;
+ br.code.offset = (u32)&trampoline_checkirqs;
+ call16big(&br);
+}
+
+// 16bit trampoline for waiting for an irq from 32bit mode.
+ASM16(
+ " .global trampoline_waitirq\n"
+ "trampoline_waitirq:\n"
+ " sti\n"
+ " hlt\n"
+ " lretw"
+ );
+
+// Wait for next irq to occur.
+void
+wait_irq(void)
+{
+ if (MODESEGMENT) {
+ asm volatile("sti ; hlt ; cli ; cld": : :"memory");
+ return;
+ }
+ if (CONFIG_THREADS && MainThread.next != &MainThread) {
+ // Threads still active - do a yield instead.
+ yield();
+ return;
+ }
+ extern void trampoline_waitirq();
+ struct bregs br;
+ br.flags = 0;
+ br.code.seg = SEG_BIOS;
+ br.code.offset = (u32)&trampoline_waitirq;
+ call16big(&br);
+}
+
/****************************************************************
* Stack in EBDA
@@ -115,16 +188,6 @@ stack_hop(u32 eax, u32 edx, void *func)
****************************************************************/
#define THREADSTACKSIZE 4096
-
-// Thread info - stored at bottom of each thread stack - don't change
-// without also updating the inline assembler below.
-struct thread_info {
- struct thread_info *next;
- void *stackpos;
- struct thread_info **pprev;
-};
-
-struct thread_info VAR16VISIBLE MainThread;
int VAR16VISIBLE CanPreempt;
void