OSDev

для всех
Текущее время: 25 авг 2025, 12:47

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




Начать новую тему Ответить на тему  [ Сообщений: 160 ]  На страницу Пред.  1 ... 6, 7, 8, 9, 10, 11, 12 ... 16  След.
Автор Сообщение
СообщениеДобавлено: 20 авг 2013, 14:46 
Аватара пользователя

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
Это происходит именно в переключалке
Код:
void switch_task(void)
{
   if (multi_task)
   {
      /* Disable all interrupts */
      asm volatile ("pushf; cli");

      /* Remember current thread state */
      asm volatile ("mov %%esp, %0":"=a"(current_thread->esp));

      /* Get next task, find next task while it is not suspended */
      do
      {
         current_thread = (thread_t*) current_thread->list_item.next;
         current_proc = (process_t*) current_proc->list_item.next;

      }   while ( (current_thread->suspend) || (current_proc->suspend) );

      /* Set current page directory */
      asm volatile ("mov %0, %%cr3"::"a"(current_proc->page_dir));
      /* Set stack */
      asm volatile ("mov %0, %%esp"::"a"(current_thread->esp));

      set_kernel_stack_in_tss((u32int) current_thread->stack + current_thread->stack_size);

      /* Enable interrupts */
      asm volatile ("popf");
   }
}

Если set_kernel_stack_in_tss() вызвать в любом другом месте - всё ок

Сама виновница
Код:
/*------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------*/
void set_kernel_stack_in_tss(u32int stack)
{
   tss.esp0 = stack;
}


Дескриптор TSS
Код:
struct tss_descriptor
{
   u16int   limit_15_0;
   u16int   base_15_0;
   u8int   base_23_16;
   u8int   type:4;
   u8int   sys:1;
   u8int   DPL:2;
   u8int   present:1;
   u8int   limit_19_16:4;
   u8int   AVL:1;
   u8int   allways_zero:2;
   u8int   gran:1;
   u8int   base_31_24;

}__attribute__((packed));

typedef   struct   tss_descriptor   tss_descriptor_t;

Так он инициализируется
Код:
/*------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------*/
void write_tss(s32int num, u32int ss0, u32int esp0)
{
   u32int base = (u32int) &tss;
   u32int limit = sizeof(tss);

   debug_msg("Size of TSS: ", sizeof(tss));
   debug_msg("Size of tss descriptor: ", sizeof(tss_descriptor_t));

   tss_descriptor_t* tss_d = (tss_descriptor_t*) &gdt_entries[num];

   tss_d->base_15_0 = base & 0xFFFF;
   tss_d->base_23_16 = (base >> 16) & 0xFF;
   tss_d->base_31_24 = (base >> 8) & 0xFF;

   tss_d->limit_15_0 = limit & 0xFFFF;
   tss_d->limit_19_16 = (limit >> 16) & 0xFF;

   tss_d->present = 1;
   tss_d->sys = 0;
   tss_d->DPL = 3;
   tss_d->type = 9;

   tss_d->AVL = 0;
   tss_d->allways_zero = 0;
   tss_d->gran = 0;

   memset(&tss, 0, sizeof(tss_entry_t));

   tss.ss0 = ss0;
   tss.esp0 = esp0;

   tss.cs = 0x0b;

   tss.ss = tss.ds = tss.es = tss.fs = tss.gs = 0x13;
}

Так формируется таблица GDT
Код:
/*------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------*/
void init_gdt(void)
{
  gdt_ptr.limit = (sizeof(gdt_entry_t)*6);
  gdt_ptr.base = (u32int) &gdt_entries;
 
  gdt_set_gate(0, 0, 0, 0, 0);   /* Null segment */
  gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); /* Code segment */
  gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); /* Data segment */
  gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); /* User mode code segment */
  gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); /* User mode code segment */
  write_tss(5, 0x10, init_esp); /* TSS */
 
  gdt_flush( (u32int) &gdt_ptr);

  print_dump((u32int*) gdt_entries, 48);
  print_text("\n");
}


Последний раз редактировалось maisvendoo 20 авг 2013, 15:06, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 20 авг 2013, 15:03 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1209
Это просто запись в память. Откуда берется #TS? Ты точно не пытался переключаться в user mode?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 20 авг 2013, 15:07 
Аватара пользователя

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
phantom-84 писал(а):
Это просто запись в память. Откуда берется #TS? Ты точно не пытался переключаться в user mode?

Нет, в user mode не переключаюсь. Сначала с этим разбираюсь ибо странно
После того как я привел формат дескриптора в соотвествие с Intel-документацией #TS исчезло, вместо него #PF по причине отсутствия страницы по совершенно левому адресу

Ааааа, стоп, есть косяк!
Код:
tss_d->base_31_24 = (base >> 8) & 0xFF;
24 а не 8 надо

Испаривил и теперь всё ок - снова #TS :D


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 20 авг 2013, 15:15 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1209
TSS покажи. LTR уже пробовал выполнять?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 20 авг 2013, 15:19 
Аватара пользователя

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
phantom-84 писал(а):
TSS покажи. LTR уже пробовал выполнять?

Как раз собирался показать
Код:
struct   tss_entry
{
   u32int   prev_tss;
   u32int   esp0;
   u32int   ss0;
   u32int   esp1;
   u32int   ss1;
   u32int   esp2;
   u32int   ss2;
   u32int   cr3;
   u32int   eip;
   u32int   eflags;
   u32int   eax;
   u32int   ecx;
   u32int   edx;
   u32int   ebx;
   u32int   esp;
   u32int   ebp;
   u32int   esi;
   u32int   edi;
   u32int   es;
   u32int   cs;
   u32int   ss;
   u32int   ds;
   u32int   fs;
   u32int   gs;
   u32int   ldtr;
   u16int   task_flags;
   u16int   iomap;

} __attribute__((packed));

typedef struct tss_entry tss_entry_t;

Так тут кроме ss0 и esp0 ничего не нужно же
Сверялся тут
Изображение
phantom-84 писал(а):
LTR уже пробовал выполнять?

Да, срабатывает нормально, при инициализации планировщика
Код:
set_kernel_stack_in_tss(esp);

tss_flush(0x2B);

u32int TR = get_tr(); /* Для контроля что там загрузилось */

Код загрузки и чтения
Код:
/*-----------------------------------------------------------------------------
 *      Load TR
 *---------------------------------------------------------------------------*/   
.global tss_flush

tss_flush:

    mov    4(%esp), %eax
   ltr      %ax
   ret

/*-----------------------------------------------------------------------------
 *      Read TR
 *---------------------------------------------------------------------------*/   
 .global get_tr
 
 get_tr:
 
    xor      %eax, %eax
    str      %eax
    ret


P.S.: при загрузке TR исправил селектор с 0x28 (40) на 0x2B (43). Та же фигня


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 20 авг 2013, 16:08 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1209
Код:
   u32int limit = sizeof(tss);
Лимиты на 1 меньше, чем размеры. Это относится и к дескрипторным таблицам. Это для информации. Твой вариант приемлем, хотя при задании лимита TSS нужно быть особенно осторожным (почему, см. ниже).

Код:
   tss_d->limit_19_16 = (limit >> 16) & 0xFF;
&0xF

Код:
   tss_d->DPL = 3;
=0. Незачем приложениям прыгать на TSS.

Код:
   tss.cs = 0x0b;

   tss.ss = tss.ds = tss.es = tss.fs = tss.gs = 0x13;
В основном TSS это лишнее. В служебном TSS нужно прописывать ядерный контекст начала выполнения обработчика, но тебе это пока не надо. Конец TSS должен быть таким:
Код:
iomap dw $+2
db 0FFh
Т.е. в конце TSS должен находиться терминатор 0FFh. Размер TSS должен его охватывать, лимит - нет. Иными словами, в дескриптор TSS ты должен записать значение лимита, равное значению поля iomap. Кстати limit_19_16 можешь смело обнулять.

Цитата:
P.S.: при загрузке TR исправил селектор с 0x28 (40) на 0x2B (43). Та же фигня
Было правильно, 0x28.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 20 авг 2013, 16:30 
Аватара пользователя

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
Код:
iomap dw $+2

Насколько я помню $ - это адрес текущей точки?
То есть у меня
Код:
tss.iomap = (u16int) &tss.iomap + 2

так адрес-то 32 битный...
У Intel написано что iomap - I/O map base - то есть базовый адрес карты ввода вывода. У Зубкова - что это 16-битное смещение от начала TSS до этой самой карты ввода/вывода.

0x0FF - имитирует наличие этой карты?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 20 авг 2013, 16:47 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1209
Да, я написал немного неточно. Под $ я подразумевал смещение iomap от начала TSS.


Цитата:
0x0FF - имитирует наличие этой карты?
Видимо, да. Вероятно это шаманство связано с какими-то багами проца или семантическими ошибками в описании архитектуры проца. Однако не следует считать этот терминатор описанием портов. Если к примеру тебе нужно описать 8 портов, то нужно сначала разместить байт-описатель, а потом байт-терминатор.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 20 авг 2013, 17:04 
Аватара пользователя

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
Запилил
Код:
   u32int ds;
   u32int fs;
   u32int gs;
   u32int ldtr;
   u16int task_flags;
   u16int iomap_offset;
   u8int   iomap;

} __attribute__((packed));

Код:
tss.iomap = 0xFF;
tss.iomap_offset = (u16int) ( (u32int) &tss.iomap - (u32int) &tss );

Внес и прочие исправления. Один фиг - #TS. Причем возникает он однинаково при наличии tss_flush(0x28) и без выполнения этого вызова. Аккурат при перезаписи поля esp0 в переключалке. При вызове в другом месте просто перезаписывает и никакого вывала.

При трассировке по шагам значение tss.esp0 номально модифицируется, а исключение возникает при выходе из обработчика прерывания IRQ0. В коде ошибки - нулевой селектор
Изображение


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 20 авг 2013, 17:25 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1209
Это исправление сделал?
Код:
   u32int limit = sizeof(tss)-1;


Еще меня немного смущает команда загрузки cr3 в переключалке. Попробуй сделать загрузку через регистр общего назначения явно.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 160 ]  На страницу Пред.  1 ... 6, 7, 8, 9, 10, 11, 12 ... 16  След.

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


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

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


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

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