OSDev

для всех
Текущее время: 28 апр 2024, 15:29

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




Начать новую тему Ответить на тему  [ Сообщений: 32 ]  На страницу Пред.  1, 2, 3, 4  След.
Автор Сообщение
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 11 сен 2013, 19:20 
Аватара пользователя

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
Вот так это выглядит
Код:
/*-----------------------------------------------------------------------------
 *
 *---------------------------------------------------------------------------*/
void kthread_suspend(thread_t* thread, bool suspend)
{
   stop(); /* Тормозим планировщик */

   if (suspend) /* Если надо усыпить поток */
   {
      remove_thread(thread);         /* Удаляем его из очереди выполнения */
      thread->list_item.list = NULL;  /* Метим его не принадлежащим никакому списку */
      thread->suspend = true;       /* Ставим флаг что поток спит */
      add_wait(thread);                /* Заносим в список спящих потоков */
   }
   else /* если поток надо разбудить */
   {
       remove_wait(thread);                    /* Убираем его из списка спящих */
      thread->wait_list_item.list = NULL;   
      thread->suspend = false;
      add_thread(thread);                     /* Снова ставим в очередь выполнения */
   }

   start(); /* Пускаем планировщик */
}

Эта функция завернута в системный вызов thread_suspend(...)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 12 сен 2013, 10:29 
Аватара пользователя

Зарегистрирован: 14 мар 2011, 12:31
Сообщения: 970
Откуда: Дагоба
maisvendoo писал(а):
Nable писал(а):
Их не "воткнули", а, скорее, "не убрали".

Это результат какого-то промежуточного прохода компилятора?

Это результат полного отсутствия какой бы то ни было оптимизации, т.к. после её применения может полностью потеряться связь между сгенерированным кодом и исходным текстом программы. Это делается специально, чтобы можно было трассировать программу по шагам на высоком уровне и отслеживать содержимое каждой переменной в любой момент времени.

_________________
Yet Other Developer of Architecture.
The mistery of Yoda’s speech uncovered is:
Just an old Forth programmer Yoda was.

<<< OS Boot Tools. >>>


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 12 сен 2013, 11:14 
Аватара пользователя

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
Yoda писал(а):
отслеживать содержимое каждой переменной в любой момент времени

То есть появление любой промежуточной переменной порождает серию пересылок из памяти в регистры и обратно!
Действительно, мне следовало бы догадаться самому. Спасибо за объяснение :)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 12 сен 2013, 13:30 

Зарегистрирован: 21 сен 2007, 17:24
Сообщения: 1088
Откуда: Балаково
maisvendoo писал(а):
лучше написать нормальную ассемблерную функцию (это код из мануала JM).

Если это редко вызываемая функция, тогда можно. Ассемблерные функции не встраиваемые, поэтому их вызов не оптимален.
И ещё совет. Когда описываешь параметры ассемблерной вставки, задавай не явные имена регистров, а тип "r", "g" или "p". Это даёт возможность оптимизатору манипулировать регистрами. Например
Код:
asm volatile ("xchg (,%1,), %0" : "+r"(old_value): "r"(mutex));


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 12 сен 2013, 21:59 
Аватара пользователя

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
Чтобы разобраться с APIC timer даже разобрался с Bochs - теперь он у меня работает с отладчиком gdb и отлаживается через eclipse
Только вот APIC как не живой. Bochs собирал с опцией --enable-apic, вот конфиг
Код:
#------------------------------------------------------------------------------
#
#   Bochs configuration file
#   (c) maisvendoo, 01.07.2013
#
#-------------------------------------------------------------------------------

#-------------------------------------------------------------------------------
#   BIOS
#-------------------------------------------------------------------------------
romimage: file=$BXSHARE/BIOS-bochs-latest

#-------------------------------------------------------------------------------
#   CPU
#-------------------------------------------------------------------------------
cpu: model=p2_klamath,count=1,ips=50000000,reset_on_triple_fault=1,ignore_bad_msrs=1,msrs="msrs.def"
cpu: cpuid_limit_winnt=0
cpuid: level=6, mmx=1, sep=1, sse=sse4_2, apic=xapic, aes=1, movbe=1, xsave=1

#-------------------------------------------------------------------------------
#   Memory
#-------------------------------------------------------------------------------
memory: guest=512, host=256

#-------------------------------------------------------------------------------
#   ATA
#-------------------------------------------------------------------------------
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11
ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9

ata0-master: type=disk, mode=flat, path="/home/maisvendoo/PhantomEx/hdd/hdd.img"

#-------------------------------------------------------------------------------
#   Boot
#-------------------------------------------------------------------------------
boot: disk

floppy_bootsig_check: disabled=1
#-------------------------------------------------------------------------------
#   Bochs log
#-------------------------------------------------------------------------------
log: /home/maisvendoo/phantom/logs/bochsout.txt

panic: action=ask
error: action=report
info: action=report
#debug: action=1, pci=report # report BX_DEBUG from module 'pci'

megs: 128
#-------------------------------------------------------------------------------
#   GDB interface
#-------------------------------------------------------------------------------
gdbstub: enabled=1, port=1234, text_base=0, data_base=0, bss_base=0

Да ладно борщ, та же беда с QEMU и VMware - везде память по адресу 0xFEE00000 заполняется я а счетчик apic-таймера не идет. Базу APIC определял как полагается через MSR 0x1B
Код инициализации. Под это дело отобразил в ВАП ядра страницу
Код:
/*------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------*/
void init_apic_timer(u32int quatum)
{
   cpu_ver_ext_t   ver_ext;
   u64int         msr_0x1B = 0;
   u32int         tmp = 0;
   u32int         cpu_bus_freq = 0;

   get_cpu_ver_ext(&ver_ext);

   if (ver_ext.apic == 0)
   {
      print_text("APIC is not supported by this processor...FAIL");
      return;
   }

   /* Get APIC base address */
   apic = get_apic_base() & 0xFFFFF000;

   /* Set interrupt handler */
   register_interrupt_handler(IRQ7, &apic_spurios_callback);
   register_interrupt_handler(IRQ0, &apic_timer_callback);

   /* Initialize LAPIC in known state */
   apic_set_register(APIC_DFR, 0xFFFFFFFF);

   tmp = apic_get_register(APIC_LDR);
   tmp &= 0x00FFFFFF;
   tmp |= 1;

   apic_set_register(APIC_LDR, tmp);
   apic_set_register(APIC_LVT_TMR, APIC_DISABLE);
   apic_set_register(APIC_LVT_PERF, APIC_NMI);
   apic_set_register(APIC_LVT_LINT0, APIC_DISABLE);
   apic_set_register(APIC_LVT_LINT1, APIC_DISABLE);
   apic_set_register(APIC_TASKPRIOR, 0);

   /* Enable APIC global */
   set_apic_base(get_apic_base());
   apic_set_register(APIC_SPURIOS, IRQ7 | APIC_SW_ENABLE);
   apic_set_register(APIC_LVT_TMR, IRQ0);
   apic_set_register(APIC_TMRDIV, 0x03);

   /* Initialize PIT channel 2 in one-shot mode */
   u8int tmp_port = inb(0x61);
   tmp_port &= 0xFD;
   tmp_port |= 1;

   outb(0x61, tmp_port);
   outb(0x43, 0xB2);
   outb(0x42, 0x9B);
   inb(0x60);
   outb(0x42, 0x2E);

   tmp_port = inb(0x61);
   tmp_port &= 0xFE;

   tmp_port |= 0x03;

   outb(0x61, tmp_port);

   apic_set_register(APIC_TMRINITCNT, 0xFFFFFFFF);

   do
   {
      tmp_port = 0;
      tmp_port = inb(0x61);
      tmp_port &= 0x20;

   } while (!tmp_port);

   apic_set_register(APIC_LVT_TMR, APIC_DISABLE);

   tmp = apic_get_register(APIC_TMRCURRCNT);

   cpu_bus_freq = (0xFFFFFFFF - tmp + 1 )*16*100;

   tmp = cpu_bus_freq/quatum/16;

   apic_set_register(APIC_TMRINITCNT, (tmp < 16 ? 16 : tmp));
   apic_set_register(APIC_LVT_TMR, IRQ0 | TMR_PERIODIC);
   apic_set_register(APIC_TMRDIV, 0x03);
}

Короче говоря мозги уже сломал...

P.S.: Поле APIC_APICVER содержит ноль, или какую-то чепуху, во всех ВМ


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 12 сен 2013, 23:03 

Зарегистрирован: 26 мар 2012, 17:32
Сообщения: 209
Не вижу реализаций apic_set_register/apic_get_register, а многие нередко в них ошибаются (например, позволяют компилятору заменить 32-bit write на что-то более короткое). Ещё можно в константах мог ляпнуть.
Ещё в
Код:
set_apic_base(get_apic_base());
не вижу OR с битом, который включает железку. А никто не обещает что BIOS его включит.

Хм, http://wiki.osdev.org/APIC утверждает что "The local APIC is enabled at boot-time and can be disabled by clearing bit 11 of the IA32_APIC_BASE", хотя сами в примере кода таки бит этот выставляют. Так-то.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 13 сен 2013, 08:29 
Аватара пользователя

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
Nable писал(а):
http://wiki.osdev.org/APIC

Тут и смотрел я.
Код - установка/чтение регистров APIC
Код:
/*------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------*/
u32int apic_get_register(u32int reg_idx)
{
   return *(u32int*) (apic + reg_idx);
}

/*------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------*/
void apic_set_register(u32int reg_idx, u32int value)
{
   *(u32int*) (apic + reg_idx) = value;
}

Установка/чтение базового адреса
Код:
/*------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------*/
u32int get_apic_base(void)
{
   u64int msr = 0;
   u32int apic_base = 0;

   read_msr(IA32_APIC_BASE_MSR, &msr);

   apic_base = (u32int) msr;
   apic_base &= 0xFFFFF100;

   return apic_base;
}

/*------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------*/
void set_apic_base(u32int apic)
{
   u64int   msr = 0;

   msr |= apic;
   msr &= 0xFFFFF100;
   msr |= IA32_APIC_BASE_MSR_ENABLE;

   write_msr(IA32_APIC_BASE_MSR, &msr);
}


Кстати, зачем в wiki делают вот это apic_base &= 0xFFFFF100 не понял, база же выровнена по странице и потом приходится делать ещё & 0xFFFFF000


Константы
Код:
/*------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------*/
#define   IA32_APIC_BASE_MSR         0x1B
#define   IA32_APIC_BASE_MSR_BSP      0x100
#define   IA32_APIC_BASE_MSR_ENABLE   0x800

/*------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------*/
#define      APIC_APICID         0x020
#define      APIC_APICVER      0x030
#define      APIC_TASKPRIOR      0x080
#define      APIC_EOI         0x0B0
#define      APIC_LDR         0x0D0
#define      APIC_DFR         0x0E0
#define      APIC_SPURIOS      0x0F0
#define      APIC_ESR         0x280
#define      APIC_ICRL         0x300
#define      APIC_ICRH         0x310
#define      APIC_LVT_TMR      0x320
#define      APIC_LVT_PERF      0x340
#define      APIC_LVT_LINT0      0x350
#define      APIC_LVT_LINT1      0x360
#define      APIC_LVT_ERR      0x370
#define      APIC_TMRINITCNT      0x380
#define      APIC_TMRCURRCNT      0x390
#define      APIC_TMRDIV         0x3E0
#define      APIC_LAST         0x38F
#define      APIC_DISABLE      0x10000
#define      APIC_SW_ENABLE      0x100
#define      APIC_CPUFOCUS      0x200
#define      APIC_NMI         (4 << 8)
#define      TMR_PERIODIC      0x20000
#define      TMR_BASEDIV         (1 << 20)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 13 сен 2013, 09:42 

Зарегистрирован: 26 мар 2012, 17:32
Сообщения: 209
> Код - установка/чтение регистров APIC
Не вижу volatile, а это важно для железа. Даже если в асмовом выхлопе единожды получилось всё правильно, всё равно лучше раз и навсегда привыкнуть все MMIO объявлять как volatile.
Кстати, страницу отображаешь без кеширования (UC) ?

> get_apic_base
Стрёмная штука, функция ~не соответствует названию (ну да, в wiki так написано).
Ну т.е. если это base, то и возвращать надо базовый адрес (т.е. & ~0xFFF), а то вдруг какой-нибудь код, мапящий страницы для доступа к нему, фигню сделает. Хотя можно функцию переименовать в get_apic_base_msr.
Сбрасывают потенциально неведомые биты для уверенности (ибо производители железа иногда делают странное), кроме того, если почитать доки, то есть разные виды зарезервированных битов. Некоторые надо ставить принудительно в 0 (что чаще) или 1, если не знаешь, некоторые нужно оставлять такими, какими их прочёл. Наверное, тут тот случай когда MBZ (must be zero).

> Кстати, зачем в wiki делают вот это apic_base &= 0xFFFFF100 не понял, база же выровнена по странице и потом приходится делать ещё & 0xFFFFF000
Чтобы сохранить бит BSP и не плодить функции. Типа, для, эта функция возвращает не базовый адрес, а потенциально интересные биты из регистра (адрес и isBSP).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 13 сен 2013, 11:32 
Аватара пользователя

Зарегистрирован: 25 июл 2013, 08:45
Сообщения: 141
Откуда: Новочеркасск
Запрет кэширования не ставил, думаю это наиболее вероятная причина. Буду дома - исправлю.

Add: Поставил атрибуты страницы 0x13 вместо 0x03. Модифицировал функции чтения/записи регистров
Код:
/*------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------*/
u32int apic_get_register(u32int reg_idx)
{
   volatile u32int* reg = (u32int*) (apic + reg_idx);

   return *reg;
}

/*------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------*/
void apic_set_register(u32int reg_idx, u32int value)
{
   volatile u32int* reg = (u32int*) (apic + reg_idx);

   *reg = value;
}


Тишина.

Nable писал(а):
(ну да, в wiki так написано)

В вики, кстати, ошибка - упущен оператор разыменования указателя. Там так
Код:
(uint32*)(apic+APIC_DFR)=0xFFFFFFFF;

Тем не менее в примере на асме там
Код:
mov   dword [apic+APIC_DFR], 0FFFFFFFFh

Что соответствует
Код:
*(uint32*)(apic+APIC_DFR)=0xFFFFFFFF;

"звёздочку" посеяли


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Измерение времени в ОС
СообщениеДобавлено: 13 сен 2013, 23:07 

Зарегистрирован: 21 сен 2007, 17:24
Сообщения: 1088
Откуда: Балаково
Если ни чего не работает, пробуй методом "ad hoc" написать несколько чисто ассемблерных команд для работы с устройством, чтобы не разбираться с Си компилятором. Можешь использовать абсолютное значение адреса 0xFEE00000, он в Bochs и VMware именно такой.
Первым делом я записываю в регистр "версии" ноль и потом читаю из него значение. Регистр защищён от записи, поэтому если он есть, то будет "не ноль".
Может быть тебе этот код поможет чем-то
Код:
   //Enable Local APIC by "Spurious Interrupt Vector Register" and set spurious int vector to 0x4F
   *(volatile UINT*)0xFEE000F0 = (*(volatile UINT*)0xFEE000F0 & ~0x1FF) | 0x100 | 0x4F;
   //Test the presense of Local APIC, trying to zeroing a read-only port
   *(volatile UINT*)0xFEE00030 = 0;
   if(*(volatile UINT*)0xFEE00030 == 0) { ExitSystem(); }
   bLocalAPIC = true;
   LAPIC_Ver = *(volatile UINT*)0xFEE00030 & 0xFF;


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

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


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

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


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

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