Sfoglia il codice sorgente

!298 在x86版本中,应用程序执行错误时内核的容错机制
Merge pull request !298 from 胡自成/rt-smart-x86

bernard 4 anni fa
parent
commit
bd8ccd4590

+ 1 - 1
bsp/qemu-vexpress-a9/applications/mnt.c

@@ -13,7 +13,7 @@ int mnt_init(void)
     }
 
     rt_thread_mdelay(200);
-    if (dfs_mount("sd0", "/mnt", "elm", 0, NULL) != 0)
+    if (dfs_mount("sd", "/mnt", "elm", 0, NULL) != 0)
     {
         rt_kprintf("Dir /mnt mount failed!\n");
         return -1;

+ 2 - 1
bsp/x86/drivers/board.c

@@ -67,7 +67,8 @@ void rt_hw_board_init(void)
     init_page_region.start = (size_t)HW_PAGE_START;
     init_page_region.end = page_region_init();
     /* init no mapped area in kernel table, must in kernel space */
-    RT_ASSERT(!rt_hw_mmu_map_init(&mmu_info, (void *)HW_KERNEL_DELAY_MAP_START, HW_KERNEL_DELAY_MAP_SIZE, (rt_size_t *)g_mmu_table, 0))
+    RT_ASSERT(!rt_hw_mmu_map_init(&mmu_info, (void *)HW_KERNEL_DELAY_MAP_START, 
+              HW_KERNEL_DELAY_MAP_SIZE, (rt_size_t *)g_mmu_table, 0))
 
     rt_page_init(init_page_region);
     /* map kernel space, then can read/write this area directly. */

+ 3 - 3
bsp/x86/drivers/drv_uart.c

@@ -41,8 +41,8 @@ struct hw_uart_device
 #define SERIAL0_IRQ    4
 #define SERIAL1_IRQ    3
 
-#define MAX_BAUD_VALUE  11520
-#define DEFAULT_BAUD_VALUE  11520
+#define MAX_BAUD_VALUE  115200
+#define DEFAULT_BAUD_VALUE  115200
 #define DEFAULT_DIVISOR_VALUE (MAX_BAUD_VALUE / DEFAULT_BAUD_VALUE)
 
 enum uart_fifo_control_register_bits
@@ -281,7 +281,7 @@ static void do_uart_init(char *name, struct hw_uart_device *uart, struct rt_seri
 
     /* register device */
     rt_hw_serial_register(serial, name,
-                          RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
+                          RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM,
                           uart);
     rt_hw_interrupt_install(uart->irqno, rt_hw_uart_isr, serial, name);
     rt_hw_interrupt_umask(uart->irqno);

+ 19 - 5
bsp/x86/rtconfig.py

@@ -31,23 +31,37 @@ if os.getenv('RTT_EXEC_PATH'):
 	EXEC_PATH = os.getenv('RTT_EXEC_PATH')
 
 BUILD = 'debug'
+LIBC_MODE = 'release' # 'debug' or 'release', if debug, use libc in components, or not use libc with toolchain
 
 if PLATFORM == 'gcc':
     # toolchains
     PREFIX = 'i386-unknown-linux-musl-'
-    CC = PREFIX + 'gcc -fno-builtin -fno-stack-protector -nostdinc -nostdlib'
-    AS = PREFIX + 'gcc -nostdinc -nostdlib'
+ 
+    CC = PREFIX + 'gcc'
+    AS = PREFIX + 'gcc'
     AR = PREFIX + 'ar'
-    LINK = PREFIX + 'ld'
+    LINK = PREFIX + 'gcc'
     TARGET_EXT = 'elf'
     SIZE = PREFIX + 'size'
     OBJDUMP = PREFIX + 'objdump'
     OBJCPY = PREFIX + 'objcopy'
 
     DEVICE = ''
-    CFLAGS = DEVICE + ' -Wall'
+
+    if LIBC_MODE == 'debug':
+        EXT_CFLAGS = ' -nostdinc -nostdlib -fno-builtin -fno-stack-protector'
+    else:
+        EXT_CFLAGS = ''
+
+    CFLAGS = DEVICE + ' -Wall'  + EXT_CFLAGS
     AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp'
-    LFLAGS = DEVICE + ' -Map rtthread-i386.map -nostdlib -n -T link.lds'
+
+    if LIBC_MODE == 'debug':
+        EXT_LFLAGS = ' -nostdlib'
+    else:
+        EXT_LFLAGS = ''
+        
+    LFLAGS = DEVICE + ' -static -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref -n -T link.lds' + EXT_LFLAGS
 
     CPATH = ''
     LPATH = ''

+ 21 - 1
components/lwp/arch/x86/i386/lwp_arch.c

@@ -11,6 +11,7 @@
 #include <rthw.h>
 #include <stddef.h>
 #include <rtconfig.h>
+#include <rtdbg.h>
 
 #ifdef RT_USING_USERSPACE
 
@@ -23,7 +24,10 @@
 #include <lwp_mm_area.h>
 #include <lwp_user_mm.h>
 #include <lwp_arch.h>
+
+#ifdef RT_USING_SIGNALS
 #include <lwp_signal.h>
+#endif /* RT_USING_SIGNALS */
 
 extern size_t g_mmu_table[];
 
@@ -39,8 +43,24 @@ int arch_expand_user_stack(void *addr)
 
         if (map || lwp_user_accessable(addr, 1))
         {
-            ret = 1;
+            ret = 1;    /* map success */
         }
+        else /* map failed, send signal SIGSEGV */
+        {
+#ifdef RT_USING_SIGNALS
+            dbg_log(DBG_ERROR, "[fault] thread %s mapped addr %p failed!\n", rt_thread_self()->name, addr);
+            lwp_thread_kill(rt_thread_self(), SIGSEGV);
+            ret = 1;    /* return 1, will return back to intr, then check exit */
+#endif
+        }
+    }
+    else    /* not stack, send signal SIGSEGV */
+    {
+#ifdef RT_USING_SIGNALS
+        dbg_log(DBG_ERROR, "[fault] thread %s access unmapped addr %p!\n", rt_thread_self()->name, addr);
+        lwp_thread_kill(rt_thread_self(), SIGSEGV);
+        ret = 1;    /* return 1, will return back to intr, then check exit */
+#endif
     }
     return ret;
 }

+ 80 - 6
libcpu/x86/i386/interrupt.c

@@ -11,6 +11,7 @@
 #include <rtthread.h>
 #include <rthw.h>
 #include <rtdbg.h>
+#include <rtconfig.h>
 
 #include <interrupt.h>
 #include <stackframe.h>
@@ -18,6 +19,35 @@
 #include <pic.h>
 #include <lwp_arch.h>
 
+#ifdef RT_USING_SIGNALS
+#include <lwp_signal.h>
+#endif /* RT_USING_SIGNALS */
+
+enum HW_EXCEPTION_TYPE
+{
+    HW_EXCEPT_DIVIDE = 0,                          /* Division error: DIV and IDIV instructions */
+    HW_EXCEPT_DEBUG,                               /* Debugging exceptions: access to any code and data */
+    HW_EXCEPT_INTERRUPT,                           /* Unshielded interrupt: Unshielded external interrupt */
+    HW_EXCEPT_BREAKPOINT,                          /* Debug breakpoint: instruction INT3 */
+    HW_EXCEPT_OVERFLOW,                            /* Overflow: instruction INTO */
+    HW_EXCEPT_BOUND_RANGE,                         /* Out of bounds: command BOUND */
+    HW_EXCEPT_INVALID_OPCODE,                      /* Invalid (undefined) opcode: instruction UD2 or invalid instruction */
+    HW_EXCEPT_DEVICE_NOT_AVAILABLE,                /* Device unavailable (no math processor): floating point or WAIT/FWAIT instructions */
+    HW_EXCEPT_DOUBLE_FAULT,                        /* Double error: all instructions that can generate an exception or NMI or INTR */
+    HW_EXCEPT_COPROCESSOR_SEGMENT_OVERRUN,         /* Assist the processor segment to cross the boundary: floating-point instructions 
+                                                      (IA32 processors after 386 no longer generate such exceptions) */
+    HW_EXCEPT_INVALID_TSS,                         /* Invalid TSS: When switching tasks or accessing TSS */
+    HW_EXCEPT_SEGMENT_NOT_PRESENT,                 /* Segment does not exist: when loading segment registers or accessing system segments */
+    HW_EXCEPT_STACK_FAULT,                         /* Stack segmentation error: stack operation or loading SS */
+    HW_EXCEPT_GENERAL_PROTECTION,                  /* General protection error: memory or other protection check */
+    HW_EXCEPT_PAGE_FAULT,                          /* Page fault: memory access */
+    HW_EXCEPT_RESERVED,                            /* INTEL reserved, not used */
+    HW_EXCEPT_X87_FLOAT_POINT,                     /* X87FPU floating point error (math error): X87FPU floating point instruction or WAIT/FWAIIT instruction */
+    HW_EXCEPT_ALIGNMENT_CHECK,                     /* Alignment check: data access in memory (supported from 486) */
+    HW_EXCEPT_MACHINE_CHECK,                       /* Machine Check: The error code (if any) and source depend on the specific mode (Pentium CPU starts to support) */
+    HW_EXCEPT_SIMD_FLOAT_POINT,                    /* SIMD floating-point exceptions: SSE and SSE2 floating-point instructions (supported by Pentium III) */
+};
+
 typedef void (*rt_hw_intr_handler_t)(rt_hw_stack_frame_t *);
 
 static rt_hw_intr_handler_t interrupt_handlers[MAX_INTR_NR] = {0};
@@ -71,7 +101,6 @@ static void hw_external_handler(rt_hw_stack_frame_t *frame)
     rt_hw_pic_ack(irqno);
 }
 
-
 #ifdef RT_USING_LWP
 static int check_user_stack(rt_hw_stack_frame_t *frame)
 {
@@ -109,6 +138,53 @@ static void hw_exception_handler(rt_hw_stack_frame_t *frame)
 
     exception_frame_dump(frame);
     rt_hw_print_backtrace();
+
+#ifdef RT_USING_SIGNALS
+    dbg_log(DBG_ERROR, "[exception] send signal to thread %s\n", rt_thread_self()->name);
+    /* send signal to thread */
+    switch (frame->vec_no)
+    {
+    case HW_EXCEPT_DIVIDE:
+    case HW_EXCEPT_INVALID_OPCODE:
+        lwp_thread_kill(rt_thread_self(), SIGILL);
+        return;
+    case HW_EXCEPT_DEVICE_NOT_AVAILABLE:
+        lwp_thread_kill(rt_thread_self(), SIGIO);
+        return;
+    case HW_EXCEPT_COPROCESSOR_SEGMENT_OVERRUN:
+    case HW_EXCEPT_X87_FLOAT_POINT:
+    case HW_EXCEPT_SIMD_FLOAT_POINT:
+        lwp_thread_kill(rt_thread_self(), SIGFPE);
+        return;
+    case HW_EXCEPT_OVERFLOW:
+    case HW_EXCEPT_BOUND_RANGE:
+    case HW_EXCEPT_INVALID_TSS:
+    case HW_EXCEPT_ALIGNMENT_CHECK:
+        lwp_thread_kill(rt_thread_self(), SIGBUS);
+        return;
+    case HW_EXCEPT_SEGMENT_NOT_PRESENT:
+    case HW_EXCEPT_GENERAL_PROTECTION:
+        lwp_thread_kill(rt_thread_self(), SIGSEGV);
+        return;
+    case HW_EXCEPT_STACK_FAULT:
+        lwp_thread_kill(rt_thread_self(), SIGSTKFLT);
+        return;
+    case HW_EXCEPT_MACHINE_CHECK:
+    case HW_EXCEPT_INTERRUPT:
+        lwp_thread_kill(rt_thread_self(), SIGINT);
+        return;
+    case HW_EXCEPT_DOUBLE_FAULT:
+        lwp_thread_kill(rt_thread_self(), SIGKILL);
+        return;
+    case HW_EXCEPT_DEBUG:
+    case HW_EXCEPT_BREAKPOINT:
+        lwp_thread_kill(rt_thread_self(), SIGTRAP);
+        return;
+    default:
+        break;
+    }
+#endif
+
     /* unhandled exception */
     rt_hw_interrupt_disable();
     for (;;)
@@ -140,19 +216,17 @@ void rt_hw_interrupt_dispatch(rt_hw_stack_frame_t *frame)
 
 void rt_hw_stack_frame_dump(rt_hw_stack_frame_t *frame)
 {
-    rt_kprintf("====stack frame dump====\n");
-    rt_kprintf("edi:%x esi:%x ebp:%x esp dummy:%x ebx:%x edx:%x ecx:%x eax:%x\n",
+    rt_kprintf("edi:%x\nesi:%x\nebp:%x\nesp dummy:%x\nebx:%x\nedx:%x\necx:%x\neax:%x\n",
         frame->edi, frame->esi, frame->ebp, frame->esp_dummy,
         frame->ebx, frame->edx, frame->ecx, frame->eax);
-    rt_kprintf("gs:%x fs:%x es:%x ds:%x error code:%x eip:%x cs:%x eflags:%x esp:%x ss:%x\n",
+    rt_kprintf("gs:%x\nfs:%x\nes:%x\nds:%x\nerror code:%x\neip:%x\ncs:%x\neflags:%x\nesp:%x\nss:%x\n",
         frame->gs, frame->fs, frame->es, frame->ds, frame->error_code,
         frame->eip, frame->cs, frame->eflags, frame->esp, frame->ss);
 }
 
 static void exception_frame_dump(rt_hw_stack_frame_t *frame)
 {
-    rt_kprintf("====exception frame dump====\n");
-    rt_kprintf("Stack frame: exception name %s\n", hw_exception_names[frame->vec_no]);
+    rt_kprintf("\n!!! Stack frame: exception name %s\n", hw_exception_names[frame->vec_no]);
     if (frame->vec_no == 14)
     {
         rt_kprintf("page fault addr: %p\n", read_cr2());

+ 23 - 6
libcpu/x86/i386/syscall_c.c

@@ -11,6 +11,7 @@
 
 #include <rthw.h>
 #include <rtthread.h>
+#include <rtconfig.h>
 
 //#define DBG_LEVEL DBG_WARNING
 //#define DBG_LEVEL DBG_INFO
@@ -27,6 +28,10 @@
 
 #include "stackframe.h"
 
+#ifdef RT_USING_SIGNALS
+#include <lwp_signal.h>
+#endif /* RT_USING_SIGNALS */
+
 typedef rt_size_t (*syscallfunc_t)(rt_size_t,rt_size_t,rt_size_t,rt_size_t,rt_size_t,rt_size_t,rt_size_t);
 syscallfunc_t lwp_get_sys_api(uint32_t);
 
@@ -34,14 +39,22 @@ void rt_hw_syscall_dispath(struct rt_hw_stack_frame *frame)
 {
     if(frame->eax == 0)
     {
-        rt_kprintf("syscall id = 0!\n");
-        while(1);   // TODO: raise signal
+        dbg_log(DBG_ERROR, "[syscall] thread %s called syscall id = 0!\n", rt_thread_self()->name);
+#ifdef RT_USING_SIGNALS
+        lwp_thread_kill(rt_thread_self(), SIGSYS);
+#else
+        while(1);
+#endif
     }
 
     if(frame->eax == 0xdeadbeef)
     {
-        rt_kprintf("syscall id = 0xdeadbeef\n");
-        while(1);   // TODO: raise signal
+        dbg_log(DBG_ERROR, "[syscall] thread %s called syscall id = 0xdeadbeef!\n", rt_thread_self()->name);
+#ifdef RT_USING_SIGNALS
+        lwp_thread_kill(rt_thread_self(), SIGSYS);
+#else
+        while(1);
+#endif
     }
 
 #ifdef RT_USING_SIGNALS
@@ -56,8 +69,12 @@ void rt_hw_syscall_dispath(struct rt_hw_stack_frame *frame)
 
     if(syscallfunc == RT_NULL)
     {
-        rt_kprintf("unsupported syscall %d!\n", frame->eax);
-        while(1);   // TODO: raise signal
+        dbg_log(DBG_ERROR, "[syscall] thread %s called unsupported syscall %d!\n", rt_thread_self()->name, frame->eax);
+#ifdef RT_USING_SIGNALS
+        lwp_thread_kill(rt_thread_self(), SIGSYS);
+#else
+        while(1);
+#endif
     }
     /* TODO: support arg6 */
     LOG_I("\033[36msyscall id = %d,arg0 = 0x%p,arg1 = 0x%p,arg2 = 0x%p,arg3 = 0x%p,arg4 = 0x%p,arg5 = 0x%p,arg6 = 0x%p(unsupport)\n\033[37m",