OSDev http://osdev.su/ |
|
Проблемы user mode http://osdev.su/viewtopic.php?f=6&t=653 |
Страница 1 из 2 |
Автор: | IlyaChur [ 23 ноя 2012, 13:13 ] |
Заголовок сообщения: | Проблемы user mode |
Здравствуйте, я не давно начал разбираться с написанием операционных систем и столкнулся с такой проблемой: Когда я решил перейти из режима ядра в режим пользователя (для этого воспользовался туториалом http://wiki.osdev.org/Getting_to_Ring_3), все вроде заработало, но при попытки таймера переключить задачи выскакивает ошибка: Page fault! (Present) Я понимаю, что это связанно скорее всего с тем, что я пытаюсь вызвать функцию ядра из пользовательского режима... Но, если попытаться вызвать функцию переключения задач через системный вызов - система падает, VirtualBox - просто виснет, Qemu - перезапускается. Подскажите, пожалуйста, как можно решить данную проблему? |
Автор: | Станислав [ 23 ноя 2012, 14:00 ] |
Заголовок сообщения: | Re: Проблемы user mode |
Если проблема в доступе то переключение cs (code selector) с 0 на 3 может быть только дальним прыжком и с 3 на 0 вызовом прерывания у которого cs с 0 кольцом (в idt на векторе ставится) или syscall/sysenter, нужно смотреть gdt правильно ли она заполнена. Если проблема в ВАП, то надо смотреть как настраиваются адресные пространства. Об этих ошибках процессора сообщают свои прерывания процессора, можно снимать при выходе номер прерывания, если 13 то ругается на неправильный доступ к памяти. А вообще не понятно, в какой системе работаеш? |
Автор: | IlyaChur [ 23 ноя 2012, 14:22 ] |
Заголовок сообщения: | Re: Проблемы user mode |
Ладно... Сейчас попробую посмотреть, что там происходит... Цитата: А вообще не понятно, в какой системе работаеш? Под линуксом работаю. |
Автор: | IlyaChur [ 23 ноя 2012, 14:56 ] |
Заголовок сообщения: | Re: Проблемы user mode |
Ну в общем, что выяснилось... Ошибка теперь есть даже тогда когда я не перехожу в юзер мод... То есть при попытки переключить процессы теперь и в режиме ядра выдается Page fault! (Present) Это ошибка может быть связанна только с настраиванием адресного пространства? |
Автор: | achesnokov [ 23 ноя 2012, 18:43 ] |
Заголовок сообщения: | Re: Проблемы user mode |
Цитата: Ну в общем, что выяснилось... Ошибка теперь есть даже тогда когда я не перехожу в юзер мод.. Слишком мало информации чтобы что-то советовать. Если где-то можно посмотреть исходники ваших тестов, было бы слегка проще. |
Автор: | IlyaChur [ 25 ноя 2012, 11:17 ] |
Заголовок сообщения: | Re: Проблемы user mode |
Да, конечно... Вот часть исходников: task.h Код: #ifndef _TASK_H #define _TASK_H #include <types.h> #include <paging.h> #define KERNEL_STACK_SIZE 2048 // Use a 2kb kernel stack. typedef struct task { int id; uint32 esp, ebp; uint32 eip; page_directory_t *page_directory; uint32 kernel_stack; // Kernel stack location. struct task *next; } task_t; void init_tasking(); void switch_task(); int fork(); void move_stack(void *new_stack_start, uint32 size); int getpid(); #endif task.c Код: #include <task.h>
#include <paging.h> volatile task_t *current_task; volatile task_t *ready_queue; extern page_directory_t *kernel_directory; extern page_directory_t *current_directory; extern void alloc_frame(page_t*,int,int); extern uint32 initial_esp; extern uint32 read_eip(); uint32 next_pid = 1; void initialise_tasking() { asm volatile("cli"); move_stack((void*)0xE0000000, 0x2000); current_task = ready_queue = (task_t*)kmalloc(sizeof(task_t)); current_task->id = next_pid++; current_task->esp = current_task->ebp = 0; current_task->eip = 0; current_task->page_directory = current_directory; current_task->next = 0; current_task->kernel_stack = kmalloc/*_a*/(KERNEL_STACK_SIZE); asm volatile("sti"); } void move_stack(void *new_stack_start, uint32 size) { uint32 i; // Выделяем немного места для нового стека. for( i = (uint32)new_stack_start; i >= ((uint32)new_stack_start-size); i -= 0x1000) { alloc_frame( get_page(i, 1, current_directory), 0 /* User mode */, 1 /* Is writable */ ); } uint32 pd_addr; asm volatile("mov %%cr3, %0" : "=r" (pd_addr)); asm volatile("mov %0, %%cr3" : : "r" (pd_addr)); uint32 old_stack_pointer; asm volatile("mov %%esp, %0" : "=r" (old_stack_pointer)); uint32 old_base_pointer; asm volatile("mov %%ebp, %0" : "=r" (old_base_pointer)); uint32 offset = (uint32)new_stack_start - initial_esp; uint32 new_stack_pointer = old_stack_pointer + offset; uint32 new_base_pointer = old_base_pointer + offset; memcpy((void*)new_stack_pointer, (void*)old_stack_pointer, initial_esp-old_stack_pointer); for(i = (uint32)new_stack_start; i > (uint32)new_stack_start-size; i -= 4) { uint32 tmp = * (uint32*)i; if (( old_stack_pointer < tmp) && (tmp < initial_esp)) { tmp = tmp + offset; uint32 *tmp2 = (uint32*)i; *tmp2 = tmp; } } asm volatile("mov %0, %%esp" : : "r" (new_stack_pointer)); asm volatile("mov %0, %%ebp" : : "r" (new_base_pointer)); } void switch_task() { if (!current_task) return; uint32 esp, ebp, eip; asm volatile("mov %%esp, %0" : "=r"(esp)); asm volatile("mov %%ebp, %0" : "=r"(ebp)); eip = read_eip(); if (eip == 0x12345) return; current_task->eip = eip; current_task->esp = esp; current_task->ebp = ebp; current_task = current_task->next; if (!current_task) current_task = ready_queue; eip = current_task->eip; esp = current_task->esp; ebp = current_task->ebp; current_directory = current_task->page_directory; kprintf ("eip = 0x%x, esp = 0x%x, ebp = 0x%x, cda = 0x%x\n",eip,esp,ebp,current_directory->physicalAddr); // Change our kernel stack over. set_kernel_stack(current_task->kernel_stack+KERNEL_STACK_SIZE); asm volatile(" \ cli; \ mov %0, %%ecx; \ mov %1, %%esp; \ mov %2, %%ebp; \ mov %3, %%cr3; \ mov $0x12345, %%eax; \ sti; \ jmp *%%ecx " : : "r"(eip), "r"(esp), "r"(ebp), "r"(current_directory->physicalAddr)); } int fork() { asm volatile("cli"); task_t *parent_task = (task_t*)current_task; page_directory_t *directory = clone_directory(current_directory); task_t *new_task = (task_t*)kmalloc(sizeof(task_t)); new_task->id = next_pid++; new_task->esp = new_task->ebp = 0; new_task->eip = 0; new_task->page_directory = directory; current_task->kernel_stack = kmalloc_a(KERNEL_STACK_SIZE); new_task->next = 0; task_t *tmp_task = (task_t*)ready_queue; while (tmp_task->next) tmp_task = tmp_task->next; tmp_task->next = new_task; uint32 eip = read_eip(); if (current_task == parent_task) { uint32 esp; asm volatile("mov %%esp, %0" : "=r"(esp)); uint32 ebp; asm volatile("mov %%ebp, %0" : "=r"(ebp)); new_task->esp = esp; new_task->ebp = ebp; new_task->eip = eip; asm volatile("sti"); return new_task->id; } else { return 0; } } ... void switch_to_user_mode() { // Set up our kernel stack. set_kernel_stack(current_task->kernel_stack+KERNEL_STACK_SIZE); asm volatile(" \ cli; \ mov $0x23, %ax; \ mov %ax, %ds; \ mov %ax, %es; \ mov %ax, %fs; \ mov %ax, %gs; \ \ mov %esp, %eax; \ pushl $0x23; \ pushl %esp; \ pushf; \ \ pop %eax; \ or $0x200, %eax; \ push %eax; \ \ pushl $0x1B; \ push $1f; \ iret; \ 1: \ "); } |
Автор: | IlyaChur [ 25 ноя 2012, 11:34 ] | ||
Заголовок сообщения: | Re: Проблемы user mode | ||
Если нужны еще какие-то файлы - могу выложить, не проблема... В принципе тут вроде все примитивно, переключение идет по таймеру... До того, как прикрутил переход в юзер мод все работало отлично, сейчас же все виснит сразу после инициализации задач при попытки переключить задачу. Специально в переключение задач добавил строку с выводом информации eip, esp, ebp, ... Теперь выводит следующее:
|
Автор: | pavia [ 25 ноя 2012, 12:38 ] |
Заголовок сообщения: | Re: Проблемы user mode |
Цитата: IlyaChur Никто за вас разбираться не будет.При компиляции создайте map файл и посмотрите в какой строчке происходит исключение. |
Автор: | IlyaChur [ 25 ноя 2012, 13:15 ] |
Заголовок сообщения: | Re: Проблемы user mode |
Цитата: pavia Я не прошу за меня разбираться, просто хотелось узнать, может кто-нибудь сталкивался с подобной проблемой. Хорошо, попробую с помощью мап файла посмотреть, что там происходит, спасибо) |
Автор: | achesnokov [ 25 ноя 2012, 14:31 ] |
Заголовок сообщения: | Re: Проблемы user mode |
Судя по фрагменту исходников, код делается по руководству James Molloy. Проблема совсем не в переключении задач, а в paging-е. Такими кусочками проблемы обсуждать - только время терять. |
Страница 1 из 2 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |