Messages in this thread Patch in this message | | | Date | Mon, 20 Dec 2004 08:12:24 -0700 (MST) | From | Zwane Mwaikambo <> | Subject | Re: [PATCH] Boottime allocated GDTs and doublefault handler |
| |
On Mon, 20 Dec 2004, Zwane Mwaikambo wrote:
> Ok =), i've added the page table walker and some basic code to fish out > 'current' and dump a few words of its stack. Sorry about the noise in the > patch but the nested if()s were beginning to go too far.
William Irwin pointed out my faulty highmem page check;
arch/i386/kernel/doublefault.c | 89 +++++++++++++++++++++++++++++++---------- arch/i386/kernel/traps.c | 6 -- include/asm-i386/thread_info.h | 6 ++ 3 files changed, 75 insertions(+), 26 deletions(-)
===== arch/i386/kernel/doublefault.c 1.4 vs edited ===== --- 1.4/arch/i386/kernel/doublefault.c 2004-08-24 03:08:41 -06:00 +++ edited/arch/i386/kernel/doublefault.c 2004-12-20 08:08:40 -07:00 @@ -3,6 +3,7 @@ #include <linux/init.h> #include <linux/init_task.h> #include <linux/fs.h> +#include <linux/highmem.h> #include <asm/uaccess.h> #include <asm/pgtable.h> @@ -13,37 +14,85 @@ static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE]; #define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE) -#define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + 0x1000000) +static int ptr_ok(unsigned long vaddr) +{ + pgd_t *pgd; + pmd_t *pmd; + pte_t pte; + + __asm__ __volatile__("movl %%cr3, %0" : "=r"(pgd)); + pgd = __va(pgd); + pgd += pgd_index(vaddr); + pmd = pmd_offset(pgd, vaddr); + if (pmd_none(*pmd)) + return 0; + else if (pmd_large(*pmd)) + return 1; +#ifdef CONFIG_HIGHMEM + else if ((pmd_val(*pmd) >> PAGE_SHIFT) > page_to_pfn(highmem_start_page)) + return 0; +#endif + pte = *pte_offset_kernel(pmd, vaddr); + if (!pte_present(pte)) + return 0; + + return 1; +} static void doublefault_fn(void) { struct Xgt_desc_struct gdt_desc = {0, 0}; - unsigned long gdt, tss; + struct tss_struct *t; + struct thread_info *ti; + struct task_struct *tsk; + unsigned long gdt, tss, *esp; + int r = 0; __asm__ __volatile__("sgdt %0": "=m" (gdt_desc): :"memory"); gdt = gdt_desc.address; printk("double fault, gdt at %08lx [%d bytes]\n", gdt, gdt_desc.size); - if (ptr_ok(gdt)) { - gdt += GDT_ENTRY_TSS << 3; - tss = *(u16 *)(gdt+2); - tss += *(u8 *)(gdt+4) << 16; - tss += *(u8 *)(gdt+7) << 24; - printk("double fault, tss at %08lx\n", tss); - - if (ptr_ok(tss)) { - struct tss_struct *t = (struct tss_struct *)tss; - - printk("eip = %08lx, esp = %08lx\n", t->eip, t->esp); - - printk("eax = %08lx, ebx = %08lx, ecx = %08lx, edx = %08lx\n", - t->eax, t->ebx, t->ecx, t->edx); - printk("esi = %08lx, edi = %08lx\n", - t->esi, t->edi); - } - } + if (!ptr_ok(gdt)) + goto done; + + gdt += GDT_ENTRY_TSS << 3; + tss = *(u16 *)(gdt+2); + tss += *(u8 *)(gdt+4) << 16; + tss += *(u8 *)(gdt+7) << 24; + printk("double fault, tss at %08lx\n", tss); + + if (!ptr_ok(tss)) + goto done; + + t = (struct tss_struct *)tss; + printk("eip = %08lx, esp = %08lx\n", t->eip, t->esp); + printk("eax = %08lx, ebx = %08lx, ecx = %08lx, edx = %08lx\n", + t->eax, t->ebx, t->ecx, t->edx); + printk("esi = %08lx, edi = %08lx\n", + t->esi, t->edi); + + if (!ptr_ok(t->esp)) + goto done; + + ti = (struct thread_info *)(t->esp & ~(THREAD_SIZE - 1)); + tsk = ti->task; + if (!ptr_ok((unsigned long)tsk)) + goto done; + + esp = (unsigned long *)t->esp; + printk("task: %p (%s) stack:\n", tsk, tsk->comm); +#if 0 + show_stack(tsk, esp); +#else + while (ptr_ok((unsigned long)esp) && valid_stack_ptr(ti, esp)) { + printk("%08lx ", *esp++); + if (!(++r % 8)) + printk("\n"); + } +#endif +done: for (;;) /* nothing */; } ===== arch/i386/kernel/traps.c 1.91 vs edited ===== --- 1.91/arch/i386/kernel/traps.c 2004-11-23 17:47:27 -07:00 +++ edited/arch/i386/kernel/traps.c 2004-12-20 00:04:38 -07:00 @@ -105,12 +105,6 @@ int register_die_notifier(struct notifie return err; } -static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) -{ - return p > (void *)tinfo && - p < (void *)tinfo + THREAD_SIZE - 3; -} - static inline unsigned long print_context_stack(struct thread_info *tinfo, unsigned long *stack, unsigned long ebp) { ===== include/asm-i386/thread_info.h 1.23 vs edited ===== --- 1.23/include/asm-i386/thread_info.h 2004-11-19 00:03:11 -07:00 +++ edited/include/asm-i386/thread_info.h 2004-12-20 00:09:19 -07:00 @@ -95,6 +95,12 @@ static inline struct thread_info *curren /* how to get the current stack pointer from C */ register unsigned long current_stack_pointer asm("esp") __attribute_used__; +static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) +{ + return p > (void *)tinfo && + p < (void *)tinfo + THREAD_SIZE - 3; +} + /* thread information allocation */ #ifdef CONFIG_DEBUG_STACK_USAGE #define alloc_thread_info(tsk) \ - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |