summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-03-05 16:04:24 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-03-05 16:04:24 +0000
commit8a818deb60c19ee90d47b99cf12ed079f36d51b3 (patch)
treeb3832a80b6ae8bb4a5dffca7d78c2001c008e8a1
parentd1e4881ac3b65fb9486ebc8bc5508ca7ad668eb9 (diff)
downloadnuttx-8a818deb60c19ee90d47b99cf12ed079f36d51b3.tar.gz
nuttx-8a818deb60c19ee90d47b99cf12ed079f36d51b3.tar.bz2
nuttx-8a818deb60c19ee90d47b99cf12ed079f36d51b3.zip
Add QEMU interrupt handling (incomplete)
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3339 42af7a65-404d-4744-a932-0658087f49c3
-rwxr-xr-xnuttx/arch/x86/include/i486/arch.h36
-rwxr-xr-xnuttx/arch/x86/include/qemu/irq.h52
-rw-r--r--nuttx/arch/x86/src/i486/up_assert.c2
-rwxr-xr-xnuttx/arch/x86/src/qemu/Make.defs2
-rwxr-xr-xnuttx/arch/x86/src/qemu/qemu_head.S125
-rw-r--r--nuttx/arch/x86/src/qemu/qemu_lowputc.c8
-rw-r--r--nuttx/arch/x86/src/qemu/qemu_lowsetup.c51
-rwxr-xr-xnuttx/arch/x86/src/qemu/qemu_vectors.S395
-rwxr-xr-xnuttx/configs/qemu-i486/ostest/ld.script4
9 files changed, 649 insertions, 26 deletions
diff --git a/nuttx/arch/x86/include/i486/arch.h b/nuttx/arch/x86/include/i486/arch.h
index fcce94fa4..f2c270067 100755
--- a/nuttx/arch/x86/include/i486/arch.h
+++ b/nuttx/arch/x86/include/i486/arch.h
@@ -82,6 +82,42 @@
#define X86_EFLAGS_ID (1 << 21) /* Bit 21: CPUID detection flag (Pentium+) */
/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* GDT data structures
+ *
+ * The Global Descriptor Table or GDT is a data structure used by Intel x86-
+ * family processors starting with the 80286 in order to define the
+ * characteristics of the various memory areas used during program execution,
+ * for example the base address, the size and access privileges like
+ * executability and writability. These memory areas are called segments in
+ * Intel terminology.
+ */
+
+/* This structure defines one segment */
+
+struct gdt_entry_s
+{
+ uint16_t lowlimit; /* The lower 16 bits of the limit */
+ uint16_t lowbase; /* The lower 16 bits of the base */
+ uint8_t midbase; /* The next 8 bits of the base */
+ uint8_t access; /* Access flags, determine ring segment can be used in */
+ uint8_t granularity;
+ uint8_t hibase; /* The last 8 bits of the base */
+} __attribute__((packed));
+
+/* This structure refers to the array of GDT entries, and is in the format
+ * required by the lgdt instruction.
+ */
+
+struct gdt_ptr_s
+{
+ uint16_t limit; /* The upper 16 bits of all selector limits */
+ uint32_t base; /* The address of the first gdt_entry_t struct */
+} __attribute__((packed));
+
+/****************************************************************************
* Inline functions
****************************************************************************/
diff --git a/nuttx/arch/x86/include/qemu/irq.h b/nuttx/arch/x86/include/qemu/irq.h
index a39876bc6..ef834b271 100755
--- a/nuttx/arch/x86/include/qemu/irq.h
+++ b/nuttx/arch/x86/include/qemu/irq.h
@@ -48,7 +48,57 @@
* Definitions
****************************************************************************/
-#define NR_IRQS 0
+#define ISR0 0
+#define ISR1 1
+#define ISR2 2
+#define ISR3 3
+#define ISR4 4
+#define ISR5 5
+#define ISR6 6
+#define ISR7 7
+#define ISR8 8
+#define ISR9 9
+#define ISR10 10
+#define ISR11 11
+#define ISR12 12
+#define ISR13 13
+#define ISR14 14
+#define ISR15 15
+#define ISR16 16
+#define ISR17 17
+#define ISR18 18
+#define ISR19 19
+#define ISR20 20
+#define ISR21 21
+#define ISR22 22
+#define ISR23 23
+#define ISR24 24
+#define ISR25 25
+#define ISR26 26
+#define ISR27 27
+#define ISR28 28
+#define ISR29 29
+#define ISR30 30
+#define ISR31 31
+
+#define IRQ0 32
+#define IRQ1 33
+#define IRQ2 34
+#define IRQ3 35
+#define IRQ4 36
+#define IRQ5 37
+#define IRQ6 38
+#define IRQ7 39
+#define IRQ8 40
+#define IRQ9 41
+#define IRQ10 42
+#define IRQ11 43
+#define IRQ12 44
+#define IRQ13 45
+#define IRQ14 46
+#define IRQ15 47
+
+#define NR_IRQS 48
/****************************************************************************
* Public Types
diff --git a/nuttx/arch/x86/src/i486/up_assert.c b/nuttx/arch/x86/src/i486/up_assert.c
index 77d6ca3ba..e9be9bcfc 100644
--- a/nuttx/arch/x86/src/i486/up_assert.c
+++ b/nuttx/arch/x86/src/i486/up_assert.c
@@ -1,7 +1,7 @@
/****************************************************************************
* arch/x86/src/i486/up_assert.c
*
- * Copyright (C) 2010 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Redistribution and use in source and binary forms, with or without
diff --git a/nuttx/arch/x86/src/qemu/Make.defs b/nuttx/arch/x86/src/qemu/Make.defs
index 5793ecd09..0010f3f3e 100755
--- a/nuttx/arch/x86/src/qemu/Make.defs
+++ b/nuttx/arch/x86/src/qemu/Make.defs
@@ -50,7 +50,7 @@ CMN_CSRCS = up_allocateheap.c up_assert.c up_blocktask.c up_copystate.c \
# Required QEMU files
-CHIP_ASRCS = qemu_saveusercontext.S qemu_fullcontextrestore.S
+CHIP_ASRCS = qemu_saveusercontext.S qemu_fullcontextrestore.S qemu_vectors.S
CHIP_CSRCS = qemu_idle.c qemu_irq.c qemu_lowputc.c qemu_lowsetup.c \
qemu_timerisr.c
diff --git a/nuttx/arch/x86/src/qemu/qemu_head.S b/nuttx/arch/x86/src/qemu/qemu_head.S
index 9d436b4fd..cf754408f 100755
--- a/nuttx/arch/x86/src/qemu/qemu_head.S
+++ b/nuttx/arch/x86/src/qemu/qemu_head.S
@@ -40,20 +40,37 @@
#include <nuttx/config.h>
/****************************************************************************
- * .text
+ * Pre-processor definitions
+ ****************************************************************************/
+
+/* Memory Map: _sbss is the start of the BSS region (see ld.script) _ebss is
+ * the end of the BSS regsion (see ld.script). The idle task stack starts at
+ * the end of BSS and is of size CONFIG_IDLETHREAD_STACKSIZE. The IDLE thread
+ * is the thread that the system boots on and, eventually, becomes the idle,
+ * do nothing task that runs only when there is nothing else to run. The
+ * heap continues from there until the end of memory. See g_heapbase below.
+ */
+
+#define STACKBASE ((_ebss + 0x1f) & 0xffffffe0)
+#define IDLE_STACK (STACKBASE+CONFIG_IDLETHREAD_STACKSIZE)
+#define HEAP_BASE (STACKBASE+CONFIG_IDLETHREAD_STACKSIZE)
+
+/****************************************************************************
+ * Nasm .text
****************************************************************************/
#ifdef CONFIG_X86_NASM
global __start /* Making entry point visible to linker */
-extern os_start /* os_start is defined elsewhere */
-extern up_lowsetup /* up_lowsetup is defined elsewhere */
+global _g_heapbase /* The start of the heap */
+extern _os_start /* os_start is defined elsewhere */
+extern _up_lowsetup /* up_lowsetup is defined elsewhere */
/* Setting up the Multiboot header - see GRUB docs for details */
MODULEALIGN equ 1<<0 /* Align loaded modules on page boundaries */
MEMINFO equ 1<<1 /* Provide memory map */
FLAGS equ MODULEALIGN | MEMINFO /* This is the Multiboot 'flag' field */
-MAGIC equ 0x1BADB002 /* 'magic number' lets bootloader find the header */
+MAGIC equ 0x1badb002 /* 'magic number' lets bootloader find the header */
CHECKSUM equ -(MAGIC + FLAGS) /* Checksum required */
section .text
@@ -63,63 +80,129 @@ MultiBootHeader:
dd FLAGS
dd CHECKSUM
-/* Reserve initial kernel stack space */
-
-STACKSIZE equ 0x4000 /* That's 16k */
-
__start:
- mov esp, stack+STACKSIZE /* Set up the stack */
+ /* Set up the stack */
+
+ mov esp, idle_stack + CONFIG_IDLETHREAD_STACKSIZE
+
+ /* Multiboot setup */
+
push eax /* Pass Multiboot magic number */
push ebx /* Pass Multiboot info structure */
+
+ /* Initialize and start NuttX */
+
+ call _up_lowsetup /* Low-level, pre-OS initialization */
+ call _os_start /* Start NuttX */
- call up_lowsetup /* Low-level, pre-OS initialization */
- call os_start /* Start NuttX */
-
+ /* NuttX will not return */
+
cli
hang:
hlt /* Halt machine should NuttX return */
jmp hang
+/****************************************************************************
+ * .bss
+ ****************************************************************************/
+
+/* The stack for the IDLE task thread is declared in .bss. NuttX boots and
+ * initializes on the IDLE thread, then at the completion of OS startup, this
+ * thread becomes the thread that executes when there is nothing else to
+ * do in the system (see up_idle()).
+ */
+
section .bss
align 4
-stack:
- resb STACKSIZE /* Reserve 16k stack on a doubleword boundary */
+idle_stack:
+ resb CONFIG_IDLETHREAD_STACKSIZE
+
+/****************************************************************************
+ * .rodata
+ ****************************************************************************/
+
+section .rodata
+
+/* HEAP BASE: _sbss is the start of the BSS region (see ld.script) _ebss is
+ * the end of the BSS region (see ld.script). The heap continues from there
+ * until the end of memory.
+ */
+
+align 4
+g_heapbase:
+ dd _ebss
#else /* !CONFIG_X86_NASM (GAS) */
+/****************************************************************************
+ * GAS .text
+ ****************************************************************************/
+
.global __start /* Making entry point visible to linker */
.global _os_start /* os_start is defined elsewhere */
.global _up_lowsetup /* up_lowsetup is defined elsewhere */
+ .global _g_heapbase /* The start of the heap */
-/* Setting up the Multiboot header - see GRUB docs for details */
+ /* Setting up the Multiboot header - see GRUB docs for details */
.set ALIGN, 1<<0 /* Align loaded modules on page boundaries */
.set MEMINFO, 1<<1 /* Provide memory map */
.set FLAGS, ALIGN | MEMINFO /* This is the Multiboot 'flag' field */
- .set MAGIC, 0x1BADB002 /* 'magic number' lets bootloader find the header */
+ .set MAGIC, 0x1badb002 /* 'magic number' lets bootloader find the header */
.set CHECKSUM, -(MAGIC + FLAGS) /* Checksum required */
+ .text
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
-/* Reserve initial kernel stack space */
+__start:
+ /* Set up the stack */
- .set STACKSIZE, 0x4000 /* That is, 16k */
- .comm stack, STACKSIZE, 32 /* Reserve 16k stack on a quadword boundary */
+ mov $(idle_stack + CONFIG_IDLETHREAD_STACKSIZE), %esp
+
+ /* Multiboot setup */
-__start:
- mov $(stack + STACKSIZE), %esp /* Set up the stack */
push %eax /* Multiboot magic number */
push %ebx /* Multiboot data structure */
+ /* Initialize and start NuttX */
+
call _up_lowsetup /* Low-level, pre-OS initialization */
call _os_start /* Start NuttX */
+ /* NuttX will not return */
+
cli
hang:
hlt /* Halt machine should NuttX return */
jmp hang
+
+/****************************************************************************
+ * .bss
+ ****************************************************************************/
+
+/* The stack for the IDLE task thread is declared in .bss. NuttX boots and
+ * initializes on the IDLE thread, then at the completion of OS startup, this
+ * thread becomes the thread that executes when there is nothing else to
+ * do in the system (see up_idle()).
+ */
+
+ .comm idle_stack, CONFIG_IDLETHREAD_STACKSIZE, 32
+
+/****************************************************************************
+ * .rodata
+ ****************************************************************************/
+
+ .section .rodata, "a"
+
+/* HEAP BASE: _sbss is the start of the BSS region (see ld.script) _ebss is
+ * the end of the BSS region (see ld.script). The heap continues from there
+ * until the end of memory.
+ */
+
+_g_heapbase:
+ .word _ebss
.end
#endif /* CONFIG_X86_NASM */ \ No newline at end of file
diff --git a/nuttx/arch/x86/src/qemu/qemu_lowputc.c b/nuttx/arch/x86/src/qemu/qemu_lowputc.c
index 16d4425cc..4e3471e60 100644
--- a/nuttx/arch/x86/src/qemu/qemu_lowputc.c
+++ b/nuttx/arch/x86/src/qemu/qemu_lowputc.c
@@ -67,6 +67,14 @@
void up_lowputc(char ch)
{
+ /* Wait until the BIOS can accept another character (so that the OS will
+ * continue to run.
+ */
+
+ while ((inb(0x3f8+5) & (1 << 5)) == 0);
+
+ /* Then output the character */
+
outb(ch, 0x3f8);
}
diff --git a/nuttx/arch/x86/src/qemu/qemu_lowsetup.c b/nuttx/arch/x86/src/qemu/qemu_lowsetup.c
index ef48f0e7b..aac19042d 100644
--- a/nuttx/arch/x86/src/qemu/qemu_lowsetup.c
+++ b/nuttx/arch/x86/src/qemu/qemu_lowsetup.c
@@ -57,6 +57,57 @@
****************************************************************************/
/****************************************************************************
+ * Name: up_gdtentry
+ *
+ * Description:
+ * Set the value of one GDT entry.
+ *
+ ****************************************************************************/
+
+static void up_gdtentry(struct gdt_entry_s *entry, uint32_t base,
+ uint32_t limit, uint8_t access, uint8_t gran)
+{
+ entry->lowbase = (base & 0xffff);
+ entry->midbase = (base >> 16) & 0xff;
+ entry->hibase = (base >> 24) & 0xff;
+
+ entry->lowlimit = (limit & 0xffff);
+ entry->granularity = (limit >> 16) & 0x0f;
+
+ entry->granularity |= gran & 0xf0;
+ entry->access = access;
+}
+
+/****************************************************************************
+ * Name: up_gdtinit
+ *
+ * Description:
+ * Initialize the GDT. The Global Descriptor Table or GDT is a data
+ * structure used by Intel x86-family processors starting with the 80286
+ * in order to define the characteristics of the various memory areas used
+ * during program execution, for example the base address, the size and
+ * access privileges like executability and writability. These memory areas
+ * are called segments in Intel terminology.
+ *
+ ****************************************************************************/
+
+static void up_gdtinit(void)
+{
+ struct gdt_entry_s gdt_entries[5];
+ struct gdt_ptr_s gdt_ptr;
+
+ up_gdtentry(0, 0, 0, 0, 0); /* Null segment */
+ up_gdtentry(1, 0, 0xffffffff, 0x9a, 0xcf); /* Code segment */
+ up_gdtentry(2, 0, 0xffffffff, 0x92, 0xcf); /* Data segment */
+ up_gdtentry(3, 0, 0xffffffff, 0xfa, 0xcf); /* User mode code segment */
+ up_gdtentry(4, 0, 0xffffffff, 0xf2, 0xcf); /* User mode data segment */
+
+ gdt_ptr.limit = (sizeof(struct gdt_entry_s) * 5) - 1;
+ gdt_ptr.base = (uint32_t)gdt_entries;
+ gdt_flush((uint32_t )&gdt_ptr);
+}
+
+/****************************************************************************
* Public Functions
****************************************************************************/
diff --git a/nuttx/arch/x86/src/qemu/qemu_vectors.S b/nuttx/arch/x86/src/qemu/qemu_vectors.S
new file mode 100755
index 000000000..93cac4b3d
--- /dev/null
+++ b/nuttx/arch/x86/src/qemu/qemu_vectors.S
@@ -0,0 +1,395 @@
+/****************************************************************************
+ * arch/x86/src/qemu/qemu_head.S
+ *
+ * Copyright (C) 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Based on Bran's kernel development tutorials. Rewritten for JamesM's
+ * kernel development tutorials.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <arch/irq.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define KSEG 0x10
+
+/****************************************************************************
+ * Nasm .text
+ ****************************************************************************/
+
+#ifdef CONFIG_X86_NASM
+extern _irq_handler
+extern _isr_handler
+
+/* Trace macros, use like trace 'i' to print char to serial port. */
+
+%macro io_outb 2
+ mov dx, %1 /* param1 = address, param2 = data. */
+ mov al, %2
+ out dx, al
+%endmacro
+
+%macro trace 1
+ io_outb 0x3f8, %1 /* diagnostic character */
+%endmacro
+
+/* This macro creates a stub for an ISR which does NOT pass it's own
+ * error code (adds a dummy errcode byte).
+ */
+
+%macro ISR_NOERRCODE 1
+ global vector_isr%1
+ vector_isr%1:
+ cli /* Disable interrupts firstly. */
+ push byte 0 /* Push a dummy error code. */
+ push byte %1 /* Push the interrupt number. */
+ jmp isr_common /* Go to our common handler code. */
+%endmacro
+
+/* This macro creates a stub for an ISR which passes it's own
+ * error code.
+ */
+
+%macro ISR_ERRCODE 1
+ global vector_isr%1
+ vector_isr%1:
+ cli /* Disable interrupts. */
+ push byte %1 /* Push the interrupt number */
+ jmp isr_common
+%endmacro
+
+/* This macro creates a stub for an IRQ - the first parameter is
+ * the IRQ number, the second is the ISR number it is remapped to.
+ */
+
+%macro IRQ 2
+ global vector_irq%1
+ vector_irq%1:
+ cli
+ push byte 0
+ push byte %2
+ jmp irq_common
+%endmacro
+
+/* The following will be the vector address programmed into the IDT */
+
+ISR_NOERRCODE ISR0
+ISR_NOERRCODE ISR1
+ISR_NOERRCODE ISR2
+ISR_NOERRCODE ISR3
+ISR_NOERRCODE ISR4
+ISR_NOERRCODE ISR5
+ISR_NOERRCODE ISR6
+ISR_NOERRCODE ISR7
+ISR_ERRCODE ISR8
+ISR_NOERRCODE ISR9
+ISR_ERRCODE ISR10
+ISR_ERRCODE ISR11
+ISR_ERRCODE ISR12
+ISR_ERRCODE ISR13
+ISR_ERRCODE ISR14
+ISR_NOERRCODE ISR15
+ISR_NOERRCODE ISR16
+ISR_NOERRCODE ISR17
+ISR_NOERRCODE ISR18
+ISR_NOERRCODE ISR19
+ISR_NOERRCODE ISR20
+ISR_NOERRCODE ISR21
+ISR_NOERRCODE ISR22
+ISR_NOERRCODE ISR23
+ISR_NOERRCODE ISR24
+ISR_NOERRCODE ISR25
+ISR_NOERRCODE ISR26
+ISR_NOERRCODE ISR27
+ISR_NOERRCODE ISR28
+ISR_NOERRCODE ISR29
+ISR_NOERRCODE ISR30
+ISR_NOERRCODE ISR31
+IRQ 0, IRQ0
+IRQ 1, IRQ1
+IRQ 2, IRQ2
+IRQ 3, IRQ3
+IRQ 4, IRQ4
+IRQ 5, IRQ5
+IRQ 6, IRQ6
+IRQ 7, IRQ7
+IRQ 8, IRQ8
+IRQ 9, IRQ9
+IRQ 10, IRQ10
+IRQ 11, IRQ11
+IRQ 12, IRQ12
+IRQ 13, IRQ13
+IRQ 14, IRQ14
+IRQ 15, IRQ15
+
+/* This is our common ISR stub. It saves the processor state, sets up for
+ * kernel mode segments, calls the C-level fault handler, and finally restores
+ * the stack frame.
+ */
+
+isr_common:
+/* trace 'S' */
+ pusha /* Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax */
+
+ mov ax, ds /* Lower 16-bits of eax = ds. */
+ push eax /* Save the data segment descriptor */
+
+ mov ax, KSEG /* Load the kernel data segment descriptor */
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+
+ call _isr_handler
+
+ pop ebx /* Reload the original data segment descriptor */
+ mov ds, bx
+ mov es, bx
+ mov fs, bx
+ mov gs, bx
+
+ popa /* Pops edi,esi,ebp... */
+ add esp, 8 /* Cleans up the pushed error code and pushed ISR number */
+ sti
+ iret /* Pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP */
+
+/* This is our common IRQ stub. It saves the processor state, sets up for
+ * kernel mode segments, calls the C-level fault handler, and finally restores
+ * the stack frame.
+ */
+
+irq_common:
+/* trace 'R' */
+ pusha /* Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax */
+
+ mov ax, ds /* Lower 16-bits of eax = ds. */
+ push eax /* Save the data segment descriptor */
+
+ mov ax, KSEG /* Load the kernel data segment descriptor */
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+
+ call _irq_handler
+
+ pop ebx /* Reload the original data segment descriptor */
+ mov ds, bx
+ mov es, bx
+ mov fs, bx
+ mov gs, bx
+
+ popa /* Pops edi,esi,ebp... */
+ add esp, 8 /* Cleans up the pushed error code and pushed ISR number */
+ sti
+ iret /* Pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP */
+
+#else /* !CONFIG_X86_NASM (GAS) */
+
+/****************************************************************************
+ * GAS .text
+ ****************************************************************************/
+
+ .globl _irq_handler
+ .globl _isr_handler
+
+/* Trace macros, use like trace 'i' to print char to serial port. */
+
+ .macro io_outb, addr, data
+ mov dx, $\addr
+ mov al, $\data
+ out dx, al
+ .endm
+
+ .macro trace, ch
+ io_outb 0x3f8, \ch
+ .endm
+
+/* This macro creates a stub for an ISR which does NOT pass it's own
+ * error code (adds a dummy errcode byte).
+ */
+
+ .macro ISR_NOERRCODE, intno
+ .globl vector_isr\intno
+vector_isr\intno:
+ cli /* Disable interrupts firstly. */
+ push $0 /* Push a dummy error code. */
+ push $\intno /* Push the interrupt number. */
+ jmp isr_common /* Go to the common handler code. */
+ .endm
+
+/* This macro creates a stub for an ISR which passes it's own
+ * error code.
+ */
+
+ .macro ISR_ERRCODE, intno
+ .globl vector_isr\intno
+vector_isr\intno:
+ cli /* Disable interrupts firstly. */
+ push $\intno /* Push the interrupt number. */
+ jmp isr_common /* Go to the common handler code. */
+ .endm
+
+/* This macro creates a stub for an IRQ - the first parameter is
+ * the IRQ number, the second is the ISR number it is remapped to.
+ */
+
+ .macro IRQ, irqno, intno
+ .globl vector_irq\irqno
+vector_irq\irqno:
+ cli /* Disable interrupts firstly. */
+ push $0 /* Push a dummy error code. */
+ push $\intno /* Push the interrupt number. */
+ jmp isr_common /* Go to the common handler code. */
+ .endm
+
+ /* The following will be the vector address programmed into the IDT */
+
+ ISR_NOERRCODE ISR0
+ ISR_NOERRCODE ISR1
+ ISR_NOERRCODE ISR2
+ ISR_NOERRCODE ISR3
+ ISR_NOERRCODE ISR4
+ ISR_NOERRCODE ISR5
+ ISR_NOERRCODE ISR6
+ ISR_NOERRCODE ISR7
+ ISR_ERRCODE ISR8
+ ISR_NOERRCODE ISR9
+ ISR_ERRCODE ISR10
+ ISR_ERRCODE ISR11
+ ISR_ERRCODE ISR12
+ ISR_ERRCODE ISR13
+ ISR_ERRCODE ISR14
+ ISR_NOERRCODE ISR15
+ ISR_NOERRCODE ISR16
+ ISR_NOERRCODE ISR17
+ ISR_NOERRCODE ISR18
+ ISR_NOERRCODE ISR19
+ ISR_NOERRCODE ISR20
+ ISR_NOERRCODE ISR21
+ ISR_NOERRCODE ISR22
+ ISR_NOERRCODE ISR23
+ ISR_NOERRCODE ISR24
+ ISR_NOERRCODE ISR25
+ ISR_NOERRCODE ISR26
+ ISR_NOERRCODE ISR27
+ ISR_NOERRCODE ISR28
+ ISR_NOERRCODE ISR29
+ ISR_NOERRCODE ISR30
+ ISR_NOERRCODE ISR31
+ IRQ 0, IRQ0
+ IRQ 1, IRQ1
+ IRQ 2, IRQ2
+ IRQ 3, IRQ3
+ IRQ 4, IRQ4
+ IRQ 5, IRQ5
+ IRQ 6, IRQ6
+ IRQ 7, IRQ7
+ IRQ 8, IRQ8
+ IRQ 9, IRQ9
+ IRQ 10, IRQ10
+ IRQ 11, IRQ11
+ IRQ 12, IRQ12
+ IRQ 13, IRQ13
+ IRQ 14, IRQ14
+ IRQ 15, IRQ15
+
+/* This is our common ISR stub. It saves the processor state, sets up for
+ * kernel mode segments, calls the C-level fault handler, and finally restores
+ * the stack frame.
+ */
+
+isr_common:
+/* trace 'S' */
+ pusha /* Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax */
+
+ mov %ax, ds /* Lower 16-bits of eax = ds. */
+ pushl %eax /* Save the data segment descriptor */
+
+ mov %ax, KSEG /* Load the kernel data segment descriptor */
+ mov ds, %ax
+ mov es, %ax
+ mov fs, %ax
+ mov gs, %ax
+
+ call _isr_handler
+
+ pop ebx /* Reload the original data segment descriptor */
+ mov ds, %bx
+ mov es, %bx
+ mov fs, %bx
+ mov gs, %bx
+
+ popa /* Pops edi,esi,ebp... */
+ add %esp, 8 /* Cleans up the pushed error code and pushed ISR number */
+ sti
+ iret /* Pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP */
+
+/* This is our common IRQ stub. It saves the processor state, sets up for
+ * kernel mode segments, calls the C-level fault handler, and finally restores
+ * the stack frame.
+ */
+
+irq_common:
+/* trace 'R' */
+ pusha /* Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax */
+
+ mov %ax, ds /* Lower 16-bits of eax = ds. */
+ push %eax /* Save the data segment descriptor */
+
+ mov %ax, KSEG /* Load the kernel data segment descriptor */
+ mov ds, %ax
+ mov es, %ax
+ mov fs, %ax
+ mov gs, %ax
+
+ call _irq_handler
+
+ pop %ebx /* Reload the original data segment descriptor */
+ mov ds, %bx
+ mov es, %bx
+ mov fs, %bx
+ mov gs, %bx
+
+ popa /* Pops edi,esi,ebp... */
+ add %esp, 8 /* Cleans up the pushed error code and pushed ISR number */
+ sti
+ iret /* Pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP */
+ .end
+#endif /* CONFIG_X86_NASM */
diff --git a/nuttx/configs/qemu-i486/ostest/ld.script b/nuttx/configs/qemu-i486/ostest/ld.script
index 0996f5310..209a0089a 100755
--- a/nuttx/configs/qemu-i486/ostest/ld.script
+++ b/nuttx/configs/qemu-i486/ostest/ld.script
@@ -41,6 +41,7 @@ SECTIONS
.text : {
_stext = ABSOLUTE(.);
*(.text .text.*)
+ *(.gnu.linkonce.t.*)
_etext = ABSOLUTE(.);
}
@@ -49,7 +50,6 @@ SECTIONS
*(.rodata .rodata.*)
*(.fixup)
*(.gnu.warning)
- *(.gnu.linkonce.t.*)
*(.glue_7)
*(.glue_7t)
*(.got)
@@ -74,7 +74,7 @@ SECTIONS
_ebss = ABSOLUTE(.);
}
- /* Stabs debugging sections. */
+ /* Stabs debugging sections */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }