原始版本
This commit is contained in:
13
RT_Thread/libcpu/ia32/SConscript
Normal file
13
RT_Thread/libcpu/ia32/SConscript
Normal file
@ -0,0 +1,13 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp') + Glob('*_gcc.S')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
group = DefineGroup('libcpu', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
42
RT_Thread/libcpu/ia32/__udivsi3.c
Normal file
42
RT_Thread/libcpu/ia32/__udivsi3.c
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2006-10-09 Bernard the first version for i386
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t __udivsi3(uint32_t num, uint32_t den)
|
||||
{
|
||||
uint32_t quot = 0, qbit = 1;
|
||||
|
||||
if (den == 0)
|
||||
{
|
||||
asm volatile ("int $0");
|
||||
return 0; /* If trap returns... */
|
||||
}
|
||||
|
||||
/* Left-justify denominator and count shift */
|
||||
while ((int32_t) den >= 0)
|
||||
{
|
||||
den <<= 1;
|
||||
qbit <<= 1;
|
||||
}
|
||||
|
||||
while (qbit)
|
||||
{
|
||||
if (den <= num)
|
||||
{
|
||||
num -= den;
|
||||
quot += qbit;
|
||||
}
|
||||
den >>= 1;
|
||||
qbit >>= 1;
|
||||
}
|
||||
|
||||
return quot;
|
||||
}
|
||||
42
RT_Thread/libcpu/ia32/__umodsi3.c
Normal file
42
RT_Thread/libcpu/ia32/__umodsi3.c
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2006-10-09 Bernard the first version for i386
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t __umodsi3(uint32_t num, uint32_t den)
|
||||
{
|
||||
register uint32_t quot = 0, qbit = 1;
|
||||
|
||||
if (den == 0)
|
||||
{
|
||||
asm volatile ("int $0");
|
||||
return 0; /* if trap returns... */
|
||||
}
|
||||
|
||||
/* left-justify denominator and count shift */
|
||||
while ((int32_t) den >= 0)
|
||||
{
|
||||
den <<= 1;
|
||||
qbit <<= 1;
|
||||
}
|
||||
|
||||
while (qbit)
|
||||
{
|
||||
if (den <= num)
|
||||
{
|
||||
num -= den;
|
||||
quot += qbit;
|
||||
}
|
||||
den >>= 1;
|
||||
qbit >>= 1;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
81
RT_Thread/libcpu/ia32/context_gcc.S
Normal file
81
RT_Thread/libcpu/ia32/context_gcc.S
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2006-09-15 QiuYi The first version
|
||||
* 2006-10-09 Bernard add rt_hw_context_switch_to implementation
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup ia32
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
|
||||
*/
|
||||
.globl rt_hw_context_switch
|
||||
rt_hw_context_switch:
|
||||
pushfl /*pushed eflags*/
|
||||
/*
|
||||
* add by ssslady@gmail.com 2009-10-14
|
||||
* When we return again the esp should no be change.
|
||||
* The old code change the esp to esp-4 :-(.
|
||||
* A protection fault maybe occure for img created by some compiler,eg.gcc in the fedor-11
|
||||
* -------------------------------------------------------------------------
|
||||
* entry old code new code
|
||||
* EIP ->return esp EIP FLAGS ->return esp
|
||||
* ... FLAGS ->retern esp CS
|
||||
* CS EIP
|
||||
* EIP
|
||||
*/
|
||||
popl %eax /*get flags*/
|
||||
popl %ebx /*get eip*/
|
||||
pushl %eax /*push flags*/
|
||||
push %cs /*push cs*/
|
||||
pushl %ebx /*push eip*/
|
||||
|
||||
/*-------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*push %cs*/ /*push cs register*/
|
||||
/*pushl 0x8(%esp)*/ /*pushed eip register*/
|
||||
|
||||
pushl $0 /*fill irqno*/
|
||||
push %ds /*push ds register*/
|
||||
push %es /*push es register*/
|
||||
pushal /*push eax,ecx,edx,ebx,esp,ebp,esp,edi registers*/
|
||||
|
||||
/*movl 0x40(%esp), %eax*/ /*to thread TCB*/
|
||||
/*movl 0x3c(%esp), %ebx*/ /*from thread TCB*/
|
||||
movl 0x3c(%esp), %eax /*to thread TCB*/
|
||||
movl 0x38(%esp), %ebx /*from thread TCB*/
|
||||
|
||||
movl %esp, (%ebx) /*store esp in preempted tasks TCB*/
|
||||
movl (%eax), %esp /*get new task stack pointer*/
|
||||
|
||||
popal /*restore new task TCB*/
|
||||
pop %es
|
||||
pop %ds
|
||||
add $4,%esp /*skip irqno*/
|
||||
iret
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch_to(rt_uint32 to);
|
||||
*/
|
||||
.globl rt_hw_context_switch_to
|
||||
rt_hw_context_switch_to:
|
||||
push %ebp
|
||||
movl %esp, %ebp
|
||||
|
||||
movl 0x8(%ebp), %eax /* to thread TCB */
|
||||
movl (%eax), %esp /* get new task stack pointer */
|
||||
|
||||
popal /* restore new task TCB*/
|
||||
pop %es
|
||||
pop %ds
|
||||
add $4, %esp /* skip irqno */
|
||||
iret
|
||||
77
RT_Thread/libcpu/ia32/cpuport.c
Normal file
77
RT_Thread/libcpu/ia32/cpuport.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021/02/19 Bernard Implement rt_hw_context_switch_interrupt in C
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
volatile rt_ubase_t rt_interrupt_from_thread = 0;
|
||||
volatile rt_ubase_t rt_interrupt_to_thread = 0;
|
||||
volatile rt_uint32_t rt_thread_switch_interrupt_flag = 0;
|
||||
|
||||
rt_base_t rt_hw_interrupt_disable(void)
|
||||
{
|
||||
rt_base_t level;
|
||||
|
||||
__asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (level): :"memory");
|
||||
return level;
|
||||
}
|
||||
|
||||
void rt_hw_interrupt_enable(rt_base_t level)
|
||||
{
|
||||
__asm__ __volatile__("pushl %0 ; popfl": :"g" (level):"memory", "cc");
|
||||
}
|
||||
|
||||
void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to, rt_thread_t from_thread, rt_thread_t to_thread)
|
||||
{
|
||||
if (rt_thread_switch_interrupt_flag == 0)
|
||||
rt_interrupt_from_thread = from;
|
||||
|
||||
rt_interrupt_to_thread = to;
|
||||
rt_thread_switch_interrupt_flag = 1;
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will initialize thread stack
|
||||
*
|
||||
* @param tentry the entry of thread
|
||||
* @param parameter the parameter of entry
|
||||
* @param stack_addr the beginning stack address
|
||||
* @param texit the function will be called when thread exit
|
||||
*
|
||||
* @return stack address
|
||||
*/
|
||||
rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
|
||||
rt_uint8_t *stack_addr, void *texit)
|
||||
{
|
||||
unsigned long *stk;
|
||||
|
||||
stk = (unsigned long *)stack_addr;
|
||||
*(--stk) = (unsigned long)parameter;
|
||||
*(--stk) = (unsigned long)texit;
|
||||
*(--stk) = 0x200; /*flags*/
|
||||
*(--stk) = 0x08; /*cs*/
|
||||
*(--stk) = (unsigned long)tentry; /*eip*/
|
||||
*(--stk) = 0; /*irqno*/
|
||||
*(--stk) = 0x10; /*ds*/
|
||||
*(--stk) = 0x10; /*es*/
|
||||
*(--stk) = 0; /*eax*/
|
||||
*(--stk) = 0; /*ecx*/
|
||||
*(--stk) = 0; /*edx*/
|
||||
*(--stk) = 0; /*ebx*/
|
||||
*(--stk) = 0; /*esp*/
|
||||
*(--stk) = 0; /*ebp*/
|
||||
*(--stk) = 0; /*esi*/
|
||||
*(--stk) = 0; /*edi*/
|
||||
|
||||
/* return task's current stack address */
|
||||
return (rt_uint8_t *)stk;
|
||||
}
|
||||
118
RT_Thread/libcpu/ia32/hdisr_gcc.S
Normal file
118
RT_Thread/libcpu/ia32/hdisr_gcc.S
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2006-09-15 QiuYi The first version
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup I386
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
#define ENTRY(proc)\
|
||||
.align 2;\
|
||||
.globl proc;\
|
||||
.type proc,@function;\
|
||||
proc:
|
||||
#define HDINTERRUPTFNC(name,num) \
|
||||
ENTRY(name)\
|
||||
pushl $(num);\
|
||||
jmp _hdinterrupts;\
|
||||
.data;\
|
||||
.long name;\
|
||||
.text
|
||||
|
||||
.globl hdinterrupt_func
|
||||
.data
|
||||
.align 4
|
||||
.type hdinterrupt_func,@object
|
||||
hdinterrupt_func :
|
||||
.text
|
||||
|
||||
/* the external device interrupts */
|
||||
HDINTERRUPTFNC(irq0, 0)
|
||||
HDINTERRUPTFNC(irq1, 1)
|
||||
HDINTERRUPTFNC(irq2, 2)
|
||||
HDINTERRUPTFNC(irq3, 3)
|
||||
HDINTERRUPTFNC(irq4, 4)
|
||||
HDINTERRUPTFNC(irq5, 5)
|
||||
HDINTERRUPTFNC(irq6, 6)
|
||||
HDINTERRUPTFNC(irq7, 7)
|
||||
HDINTERRUPTFNC(irq8, 8)
|
||||
HDINTERRUPTFNC(irq9, 9)
|
||||
HDINTERRUPTFNC(irq10, 10)
|
||||
HDINTERRUPTFNC(irq11, 11)
|
||||
HDINTERRUPTFNC(irq12, 12)
|
||||
HDINTERRUPTFNC(irq13, 13)
|
||||
HDINTERRUPTFNC(irq14, 14)
|
||||
HDINTERRUPTFNC(irq15, 15)
|
||||
|
||||
.p2align 4,0x90
|
||||
.globl _hdinterrupts
|
||||
.type _hdinterrupts,@function
|
||||
.globl rt_interrupt_enter
|
||||
.globl rt_interrupt_leave
|
||||
.globl rt_hw_isr
|
||||
.globl rt_thread_switch_interrupt_flag
|
||||
.globl rt_interrupt_from_thread
|
||||
.globl rt_interrupt_to_thread
|
||||
|
||||
_hdinterrupts:
|
||||
push %ds
|
||||
push %es
|
||||
pushal
|
||||
movw $0x10, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %es
|
||||
pushl %esp
|
||||
|
||||
call rt_interrupt_enter
|
||||
|
||||
movl %esp, %eax /* copy esp to eax */
|
||||
addl $0x2c, %eax /* move to vector address */
|
||||
movl (%eax), %eax /* vector(eax) = *eax */
|
||||
|
||||
pushl %eax /* push argument : int vector */
|
||||
call rt_hw_isr
|
||||
add $4, %esp /* restore argument */
|
||||
|
||||
call rt_interrupt_leave
|
||||
|
||||
/* if rt_thread_switch_interrupt_flag set, jump to _interrupt_thread_switch and don't return */
|
||||
movl $rt_thread_switch_interrupt_flag, %eax
|
||||
movl (%eax), %ebx
|
||||
cmp $0x1, %ebx
|
||||
jz _interrupt_thread_switch
|
||||
|
||||
popl %esp
|
||||
popal
|
||||
pop %es
|
||||
pop %ds
|
||||
add $4,%esp
|
||||
iret
|
||||
|
||||
_interrupt_thread_switch:
|
||||
popl %esp
|
||||
|
||||
movl $0x0, %ebx
|
||||
movl %ebx, (%eax)
|
||||
|
||||
movl $rt_interrupt_from_thread, %eax
|
||||
movl (%eax), %ebx
|
||||
movl %esp, (%ebx)
|
||||
|
||||
movl $rt_interrupt_to_thread, %ecx
|
||||
movl (%ecx), %edx
|
||||
movl (%edx), %esp
|
||||
|
||||
popal
|
||||
pop %es
|
||||
pop %ds
|
||||
add $4,%esp
|
||||
iret
|
||||
|
||||
/*@}*/
|
||||
131
RT_Thread/libcpu/ia32/interrupt.c
Normal file
131
RT_Thread/libcpu/ia32/interrupt.c
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2015/9/15 Bernard Update to new interrupt framework.
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include <bsp.h>
|
||||
|
||||
extern void rt_hw_idt_init(void);
|
||||
|
||||
/* exception and interrupt handler table */
|
||||
struct rt_irq_desc irq_desc[MAX_HANDLERS];
|
||||
|
||||
rt_uint16_t irq_mask_8259A = 0xFFFF;
|
||||
|
||||
void rt_hw_interrupt_handle(int vector, void* param);
|
||||
|
||||
/**
|
||||
* @addtogroup I386
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
/**
|
||||
* This function initializes 8259 interrupt controller
|
||||
*/
|
||||
void rt_hw_pic_init()
|
||||
{
|
||||
outb(IO_PIC1, 0x11);
|
||||
outb(IO_PIC1+1, IRQ_OFFSET);
|
||||
outb(IO_PIC1+1, 1<<IRQ_SLAVE);
|
||||
outb(IO_PIC1+1, 0x3);
|
||||
outb(IO_PIC1+1, 0xff);
|
||||
outb(IO_PIC1, 0x68);
|
||||
outb(IO_PIC1, 0x0a);
|
||||
outb(IO_PIC2, 0x11);
|
||||
outb(IO_PIC2+1, IRQ_OFFSET + 8);
|
||||
outb(IO_PIC2+1, IRQ_SLAVE);
|
||||
outb(IO_PIC2+1, 0x3);
|
||||
outb(IO_PIC2+1, 0xff);
|
||||
outb(IO_PIC2, 0x68);
|
||||
outb(IO_PIC2, 0x0a);
|
||||
|
||||
if (irq_mask_8259A != 0xFFFF)
|
||||
{
|
||||
outb(IO_PIC1+1, (char)irq_mask_8259A);
|
||||
outb(IO_PIC2+1, (char)(irq_mask_8259A >> 8));
|
||||
}
|
||||
}
|
||||
|
||||
void rt_hw_interrupt_handle(int vector, void* param)
|
||||
{
|
||||
rt_kprintf("Unhandled interrupt %d occured!!!\n", vector);
|
||||
}
|
||||
|
||||
void rt_hw_isr(int vector)
|
||||
{
|
||||
if (vector < MAX_HANDLERS)
|
||||
{
|
||||
irq_desc[vector].handler(vector, irq_desc[vector].param);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function initializes interrupt descript table and 8259 interrupt controller
|
||||
*
|
||||
*/
|
||||
void rt_hw_interrupt_init(void)
|
||||
{
|
||||
int idx;
|
||||
|
||||
rt_hw_idt_init();
|
||||
rt_hw_pic_init();
|
||||
|
||||
/* init exceptions table */
|
||||
for(idx=0; idx < MAX_HANDLERS; idx++)
|
||||
{
|
||||
irq_desc[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle;
|
||||
irq_desc[idx].param = RT_NULL;
|
||||
#ifdef RT_USING_INTERRUPT_INFO
|
||||
rt_snprintf(irq_desc[idx].name, RT_NAME_MAX - 1, "default");
|
||||
irq_desc[idx].counter = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void rt_hw_interrupt_umask(int vector)
|
||||
{
|
||||
irq_mask_8259A = irq_mask_8259A&~(1<<vector);
|
||||
outb(IO_PIC1+1, (char)irq_mask_8259A);
|
||||
outb(IO_PIC2+1, (char)(irq_mask_8259A >> 8));
|
||||
}
|
||||
|
||||
void rt_hw_interrupt_mask(int vector)
|
||||
{
|
||||
irq_mask_8259A = irq_mask_8259A | (1<<vector);
|
||||
outb(IO_PIC1+1, (char)irq_mask_8259A);
|
||||
outb(IO_PIC2+1, (char)(irq_mask_8259A >> 8));
|
||||
}
|
||||
|
||||
rt_isr_handler_t rt_hw_interrupt_install(int vector,
|
||||
rt_isr_handler_t handler,
|
||||
void *param,
|
||||
const char *name)
|
||||
{
|
||||
rt_isr_handler_t old_handler = RT_NULL;
|
||||
|
||||
if(vector < MAX_HANDLERS)
|
||||
{
|
||||
old_handler = irq_desc[vector].handler;
|
||||
if (handler != RT_NULL)
|
||||
{
|
||||
irq_desc[vector].handler = (rt_isr_handler_t)handler;
|
||||
irq_desc[vector].param = param;
|
||||
#ifdef RT_USING_INTERRUPT_INFO
|
||||
rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name);
|
||||
irq_desc[vector].counter = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return old_handler;
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
93
RT_Thread/libcpu/ia32/start_gcc.S
Normal file
93
RT_Thread/libcpu/ia32/start_gcc.S
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2006-09-15 QiuYi The first version.
|
||||
* 2012-02-15 aozima update.
|
||||
*/
|
||||
|
||||
/* the magic number for the multiboot header. */
|
||||
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
|
||||
|
||||
/* the flags for the multiboot header. */
|
||||
#define MULTIBOOT_HEADER_FLAGS 0x00000003
|
||||
|
||||
#define CONFIG_STACKSIZE 8192
|
||||
|
||||
/**
|
||||
* @addtogroup I386
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
.section .init, "ax"
|
||||
|
||||
/* the system entry */
|
||||
.globl _start
|
||||
_start:
|
||||
jmp multiboot_entry
|
||||
|
||||
/* Align 32 bits boundary. */
|
||||
.align 4
|
||||
|
||||
/* multiboot header. */
|
||||
multiboot_header:
|
||||
/* magic */
|
||||
.long MULTIBOOT_HEADER_MAGIC
|
||||
/* flags */
|
||||
.long MULTIBOOT_HEADER_FLAGS
|
||||
/* checksum */
|
||||
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
|
||||
|
||||
multiboot_entry:
|
||||
movl $(_end + 0x1000),%esp
|
||||
|
||||
/* reset eflags. */
|
||||
pushl $0
|
||||
popf
|
||||
|
||||
/* rebuild globe describe table */
|
||||
lgdt __gdtdesc
|
||||
|
||||
movl $0x10,%eax
|
||||
movw %ax,%ds
|
||||
movw %ax,%es
|
||||
movw %ax,%ss
|
||||
ljmp $0x08, $relocated
|
||||
|
||||
relocated:
|
||||
/* push the pointer to the multiboot information structure. */
|
||||
pushl %ebx
|
||||
|
||||
/* push the magic value. */
|
||||
pushl %eax
|
||||
|
||||
call rtthread_startup
|
||||
|
||||
/* never get here */
|
||||
spin:
|
||||
hlt
|
||||
jmp spin
|
||||
|
||||
.data
|
||||
.p2align 2
|
||||
__gdt:
|
||||
.word 0,0,0,0
|
||||
|
||||
.word 0x07FF /* 8Mb - limit=2047 */
|
||||
.word 0x0000
|
||||
.word 0x9A00 /* code read/exec */
|
||||
.word 0x00C0
|
||||
|
||||
.word 0x07FF /* 8Mb - limit=2047 */
|
||||
.word 0x0000
|
||||
.word 0x9200 /* data read/write */
|
||||
.word 0x00C0
|
||||
|
||||
__gdtdesc:
|
||||
.word 0x17
|
||||
.long __gdt
|
||||
|
||||
/*@}*/
|
||||
100
RT_Thread/libcpu/ia32/trap.c
Normal file
100
RT_Thread/libcpu/ia32/trap.c
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include <bsp.h>
|
||||
|
||||
/* Interrupt descriptor table. (Must be built at run time because
|
||||
* shifted function addresses can't be represented in relocation records.)
|
||||
*/
|
||||
struct Gatedesc idt[256] = { {0}, };
|
||||
struct Pseudodesc idt_pd =
|
||||
{
|
||||
0, sizeof(idt) - 1, (unsigned long) idt,
|
||||
};
|
||||
|
||||
/* exception and interrupt handler table */
|
||||
extern rt_isr_handler_t isr_table[];
|
||||
extern rt_isr_handler_t trap_func[];
|
||||
extern rt_isr_handler_t hdinterrupt_func[];
|
||||
extern void rt_hw_interrupt_handle(int vector, void* param);
|
||||
|
||||
/**
|
||||
* @addtogroup I386
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
/**
|
||||
* this function initializes the interrupt descript table
|
||||
*
|
||||
*/
|
||||
void rt_hw_idt_init(void)
|
||||
{
|
||||
extern void Xdefault(void);
|
||||
int i, j, func;
|
||||
|
||||
// install a default handler
|
||||
for (i = 0; i < sizeof(idt)/sizeof(idt[0]); i++)
|
||||
SETGATE(idt[i], 0, GD_KT, &Xdefault, 0);
|
||||
|
||||
/*install trap handler*/
|
||||
for(i = 0; i < 16; i++)
|
||||
{
|
||||
func = (int)trap_func[i];
|
||||
SETGATE(idt[i], 0, GD_KT, func, 0);
|
||||
}
|
||||
|
||||
func = (int)trap_func[3];
|
||||
SETGATE(idt[3], 0, GD_KT, func, 3);
|
||||
|
||||
i = 0;
|
||||
|
||||
/*install exteral interrupt handler*/
|
||||
for(j = IRQ_OFFSET; j < IRQ_OFFSET + MAX_HANDLERS; j++)
|
||||
{
|
||||
func = (int)hdinterrupt_func[i];
|
||||
SETGATE(idt[j], 0, GD_KT, func, 0);
|
||||
i++;
|
||||
}
|
||||
|
||||
// Load the IDT
|
||||
asm volatile("lidt idt_pd + 2");
|
||||
}
|
||||
|
||||
/**
|
||||
* this function will deal with all kinds of kernel trap
|
||||
*
|
||||
*@param trapno the trap number
|
||||
*
|
||||
*/
|
||||
void rt_hw_trap_irq(int trapno)
|
||||
{
|
||||
switch(trapno)
|
||||
{
|
||||
case T_DIVIDE:
|
||||
rt_kprintf("Divide error interrupt\n");
|
||||
RT_ASSERT(0);
|
||||
case T_PGFLT:
|
||||
rt_kprintf("Page fault interrupt\n");
|
||||
RT_ASSERT(0);
|
||||
case T_GPFLT:
|
||||
rt_kprintf("General protection interrupt\n");
|
||||
RT_ASSERT(0);
|
||||
case T_DEFAULT:
|
||||
rt_hw_interrupt_handle(T_DEFAULT, RT_NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/*kernel bug if run here*/
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
96
RT_Thread/libcpu/ia32/trapisr_gcc.S
Normal file
96
RT_Thread/libcpu/ia32/trapisr_gcc.S
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2006-09-15 QiuYi The first version.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup I386
|
||||
*/
|
||||
/*@{*/
|
||||
|
||||
#define ENTRY(proc)\
|
||||
.align 2;\
|
||||
.globl proc;\
|
||||
.type proc,@function;\
|
||||
proc:
|
||||
|
||||
#define TRAPFNC(name,num)\
|
||||
ENTRY(name)\
|
||||
pushl $(num);\
|
||||
jmp _traps;\
|
||||
.data;\
|
||||
.long name;\
|
||||
.text
|
||||
|
||||
#define TRAPFNC_NOEC(name,num)\
|
||||
ENTRY(name)\
|
||||
pushl $0;\
|
||||
pushl $(num);\
|
||||
jmp _traps;\
|
||||
.data;\
|
||||
.long name;\
|
||||
.text
|
||||
|
||||
.globl trap_func
|
||||
.data
|
||||
.align 4
|
||||
.type trap_func,@object
|
||||
trap_func :
|
||||
.text
|
||||
|
||||
/* CPU traps */
|
||||
TRAPFNC_NOEC(Xdivide, 0)
|
||||
TRAPFNC_NOEC(Xdebug, 1)
|
||||
TRAPFNC_NOEC(Xnmi, 2)
|
||||
TRAPFNC_NOEC(Xbrkpt, 3)
|
||||
TRAPFNC_NOEC(Xoflow, 4)
|
||||
TRAPFNC_NOEC(Xbound, 5)
|
||||
TRAPFNC_NOEC(Xillop, 6)
|
||||
TRAPFNC_NOEC(Xdevice, 7)
|
||||
TRAPFNC (Xdblflt, 8)
|
||||
TRAPFNC (Xtss, 9)
|
||||
TRAPFNC (Xsegnp, 10)
|
||||
TRAPFNC (Xstack, 11)
|
||||
TRAPFNC (Xgpflt, 12)
|
||||
TRAPFNC (Xpgflt, 13)
|
||||
TRAPFNC_NOEC(Xfperr, 14)
|
||||
TRAPFNC (Xalign, 15)
|
||||
|
||||
/* default handler -- not for any specific trap */
|
||||
TRAPFNC (Xdefault, 500)
|
||||
|
||||
.p2align 4,0x90
|
||||
.globl _traps
|
||||
.type _traps,@function
|
||||
.globl rt_interrupt_enter
|
||||
.globl rt_interrupt_leave
|
||||
|
||||
_traps:
|
||||
push %ds
|
||||
push %es
|
||||
pushal
|
||||
movw $0x10,%ax
|
||||
movw %ax,%ds
|
||||
movw %ax,%es
|
||||
pushl %esp
|
||||
call rt_interrupt_enter
|
||||
movl %esp, %eax
|
||||
addl $0x2c,%eax /*get trapno*/
|
||||
movl (%eax),%eax
|
||||
pushl %eax /*push trapno*/
|
||||
call rt_hw_trap_irq
|
||||
addl $4,%esp
|
||||
call rt_interrupt_leave
|
||||
popl %esp
|
||||
popal
|
||||
pop %es
|
||||
pop %ds
|
||||
add $8,%esp
|
||||
iret
|
||||
|
||||
/*@}*/
|
||||
Reference in New Issue
Block a user