diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-03-05 16:04:24 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2011-03-05 16:04:24 +0000 |
commit | 8a818deb60c19ee90d47b99cf12ed079f36d51b3 (patch) | |
tree | b3832a80b6ae8bb4a5dffca7d78c2001c008e8a1 /nuttx/arch/x86/src/qemu | |
parent | d1e4881ac3b65fb9486ebc8bc5508ca7ad668eb9 (diff) | |
download | px4-nuttx-8a818deb60c19ee90d47b99cf12ed079f36d51b3.tar.gz px4-nuttx-8a818deb60c19ee90d47b99cf12ed079f36d51b3.tar.bz2 px4-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
Diffstat (limited to 'nuttx/arch/x86/src/qemu')
-rwxr-xr-x | nuttx/arch/x86/src/qemu/Make.defs | 2 | ||||
-rwxr-xr-x | nuttx/arch/x86/src/qemu/qemu_head.S | 125 | ||||
-rw-r--r-- | nuttx/arch/x86/src/qemu/qemu_lowputc.c | 8 | ||||
-rw-r--r-- | nuttx/arch/x86/src/qemu/qemu_lowsetup.c | 51 | ||||
-rwxr-xr-x | nuttx/arch/x86/src/qemu/qemu_vectors.S | 395 |
5 files changed, 559 insertions, 22 deletions
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 */ |