Add QEMU interrupt handling (incomplete)
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3339 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
1135ccf5a0
commit
758b944c8a
@ -81,6 +81,42 @@
|
||||
#define X86_EFLAGS_VIP (1 << 20) /* Bit 20: Virtual Interrupt Pending (Pentium+) */
|
||||
#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
|
||||
****************************************************************************/
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
call up_lowsetup /* Low-level, pre-OS initialization */
|
||||
call os_start /* Start NuttX */
|
||||
/* 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()).
|
||||
*/
|
||||
|
||||
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 */
|
||||
|
||||
.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 */
|
||||
|
||||
.set STACKSIZE, 0x4000 /* That is, 16k */
|
||||
.comm stack, STACKSIZE, 32 /* Reserve 16k stack on a quadword boundary */
|
||||
|
||||
__start:
|
||||
mov $(stack + STACKSIZE), %esp /* Set up the stack */
|
||||
/* Set up the stack */
|
||||
|
||||
mov $(idle_stack + CONFIG_IDLETHREAD_STACKSIZE), %esp
|
||||
|
||||
/* Multiboot setup */
|
||||
|
||||
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 */
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,57 @@
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* 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
|
||||
****************************************************************************/
|
||||
|
395
arch/x86/src/qemu/qemu_vectors.S
Executable file
395
arch/x86/src/qemu/qemu_vectors.S
Executable file
@ -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 */
|
Loading…
Reference in New Issue
Block a user