OSDev

для всех
Текущее время: 17 ноя 2018, 13:36

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 13 ]  На страницу 1, 2  След.
Автор Сообщение
 Заголовок сообщения: Проблемы user mode
СообщениеДобавлено: 23 ноя 2012, 13:13 

Зарегистрирован: 23 ноя 2012, 13:02
Сообщения: 27
Здравствуйте, я не давно начал разбираться с написанием операционных систем и столкнулся с такой проблемой:
Когда я решил перейти из режима ядра в режим пользователя (для этого воспользовался туториалом http://wiki.osdev.org/Getting_to_Ring_3), все вроде заработало, но при попытки таймера переключить задачи выскакивает ошибка: Page fault! (Present)
Я понимаю, что это связанно скорее всего с тем, что я пытаюсь вызвать функцию ядра из пользовательского режима... Но, если попытаться вызвать функцию переключения задач через системный вызов - система падает, VirtualBox - просто виснет, Qemu - перезапускается.
Подскажите, пожалуйста, как можно решить данную проблему? :oops:


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Проблемы user mode
СообщениеДобавлено: 23 ноя 2012, 14:00 
Заблокирован

Зарегистрирован: 28 окт 2011, 12:14
Сообщения: 555
Откуда: Новосибирск
Если проблема в доступе то переключение cs (code selector) с 0 на 3 может быть только дальним прыжком и с 3 на 0 вызовом прерывания у которого cs с 0 кольцом (в idt на векторе ставится) или syscall/sysenter, нужно смотреть gdt правильно ли она заполнена.
Если проблема в ВАП, то надо смотреть как настраиваются адресные пространства.
Об этих ошибках процессора сообщают свои прерывания процессора, можно снимать при выходе номер прерывания, если 13 то ругается на неправильный доступ к памяти.
А вообще не понятно, в какой системе работаеш?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Проблемы user mode
СообщениеДобавлено: 23 ноя 2012, 14:22 

Зарегистрирован: 23 ноя 2012, 13:02
Сообщения: 27
Ладно... Сейчас попробую посмотреть, что там происходит...
Цитата:
А вообще не понятно, в какой системе работаеш?

Под линуксом работаю.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Проблемы user mode
СообщениеДобавлено: 23 ноя 2012, 14:56 

Зарегистрирован: 23 ноя 2012, 13:02
Сообщения: 27
Ну в общем, что выяснилось... Ошибка теперь есть даже тогда когда я не перехожу в юзер мод...
То есть при попытки переключить процессы теперь и в режиме ядра выдается Page fault! (Present)
Это ошибка может быть связанна только с настраиванием адресного пространства?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Проблемы user mode
СообщениеДобавлено: 23 ноя 2012, 18:43 

Зарегистрирован: 19 май 2011, 14:54
Сообщения: 73
Цитата:
Ну в общем, что выяснилось... Ошибка теперь есть даже тогда когда я не перехожу в юзер мод..


Слишком мало информации чтобы что-то советовать. Если где-то можно посмотреть исходники ваших тестов, было бы слегка проще. :?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Проблемы user mode
СообщениеДобавлено: 25 ноя 2012, 11:17 

Зарегистрирован: 23 ноя 2012, 13:02
Сообщения: 27
Да, конечно... Вот часть исходников:
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:               \
               ");
     
}


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Проблемы user mode
СообщениеДобавлено: 25 ноя 2012, 11:34 

Зарегистрирован: 23 ноя 2012, 13:02
Сообщения: 27
Если нужны еще какие-то файлы - могу выложить, не проблема...
В принципе тут вроде все примитивно, переключение идет по таймеру...
До того, как прикрутил переход в юзер мод все работало отлично, сейчас же все виснит сразу после инициализации задач при попытки переключить задачу. Специально в переключение задач добавил строку с выводом информации eip, esp, ebp, ... Теперь выводит следующее:


Вложения:
Screenshot.png
Screenshot.png [ 15.82 КБ | Просмотров: 5915 ]
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Проблемы user mode
СообщениеДобавлено: 25 ноя 2012, 12:38 
Аватара пользователя

Зарегистрирован: 16 май 2007, 23:46
Сообщения: 1092
Цитата:
IlyaChur
Никто за вас разбираться не будет.
При компиляции создайте map файл и посмотрите в какой строчке происходит исключение.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Проблемы user mode
СообщениеДобавлено: 25 ноя 2012, 13:15 

Зарегистрирован: 23 ноя 2012, 13:02
Сообщения: 27
Цитата:
pavia

Я не прошу за меня разбираться, просто хотелось узнать, может кто-нибудь сталкивался с подобной проблемой.
Хорошо, попробую с помощью мап файла посмотреть, что там происходит, спасибо)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Проблемы user mode
СообщениеДобавлено: 25 ноя 2012, 14:31 

Зарегистрирован: 19 май 2011, 14:54
Сообщения: 73
Судя по фрагменту исходников, код делается по руководству James Molloy. Проблема совсем не в переключении задач, а в paging-е. Такими кусочками проблемы обсуждать - только время терять. :roll:


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 13 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB