Собственно, по сабжу. Народ, сил уже нету, просвятите немного. Значит, в данный момент нахожусь в стадии написания ядра (кто не знает - http://xskernel.org/). Всё бы хорошо, но недавно столкнулся с одной неприятной вещью. А именно: Есть три компа. Это: - 80486 DX2 66 MHz (MB х.з какая), 16 MB Ram. - Pentium 4 socket 478 2.00GHz (MB Gigabyte на чипсете i845), 256 MB Ram. - AMD Athlon X2 3800+ (MB Bisotar на чипсете NF-550), 1 GB Ram. Ядро грузится с дискеты (собственный бутлоадер, читающий FAT12 + вторичный загрузчик, распаковывающий ядро в память) сначала в ОЗУ ниже первого мегабайта, а затем копируется по физическому адресу 0x110000. Точка входа - 0x110000. При старте ядро: 0. Инициализирует память (распределитель динамической памяти + расположение таблиц дескрипторов). 1. загружает GDTR, IDTR, TR, CR3. 2. включает страничную адресацию. 3. создаёт процесс ядра и поток, прикреплённый к процессу передаёт управление планировщику (как отдельной задаче, в самом планировщике прерывания отключены). 4. планировщик передаёт управление потоку, инициализирующему драйверы. Далее работает один поток - создаёт виртуальные устройства для: - PIC (контроллера прерываний) - контроллер DMA - контроллер клавиатуры - создаёт Thread на периодическое копирование виртуального текстового буфера в видеобуфер (физ. адрес 0xb8000). - драйвер таймера, на который вешается sheduler и счётчик тиков + воспроизводитель звуков - виртуальное устройство, предоставляющее информацию о CPU (функция cpuid). После этого тред создаёт тестовый тред, который запускается и в цикле читает данные с клавиатуры и выводит сообщение на экран. При этом, тред видеобуфера работает параллельно с ним. В общем, всё бы хорошо, так как на P4 и 80486 всё работает прекрасно. НО на Athlon X2 система виснет после входа в тестовый тред, при чём в совершенно произвольном месте (вычислено посредством внедрения трапа в ядро). Кто может сказать, в чём может быть проблема? Я подозреваю, что для двух процессоров я что-то недоделал в инициализации ядра. Это может быть связано с APIC или ещё чем-нибудь? Код и образ могу привести, если будет нужно.
В данном случае моё ядро пока не рассчитано на MP. Я хочу пока запустить его на одном процессоре (в Protected Mode). Но оно почему-то виснет (при этом, несколько раз переключение задач успевает срабатывать).
На некоторых AMD64, и Win9x идет, а на некоторых нет.. Просто виснет, никаких исключений не срабатывает? Код (Text): Кто может сказать, в чём может быть проблема? Попробуй запустить загрузочную дискету SlackWare (там ее LoadLin.exe из DOS запускает), с какимнибудь реликтовым ядром (2.0.30 к примеру).
В принципе MP он может симулять... ток пересобирать его надо тщательно конфигуря (лично мне версия 2.3 покатила, 2.3.5 местами куда более лагает)... p.s Под винды можно заюзать "Free Visual C++ Command Line Tools". гм.. и сварить борщъх этим батником (разве что сорцы подправить придеться в паре мест) Код (Text): @set path=c:\msdev\bin ::http://bochs.sourceforge.net/ ::\BOCHS-2.3\bochs.bat - исходное размещение этого файла ::путь к компилеру и т.д @set include=c:\msdev\include :: @cl bx_debug\*.cpp bx_debug\*.c /Gr /O1 /G3 /MT /w /W0 /c /I $include /I "." /I "instrument\stubs" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"obj-release/" /Fd"obj-release/" cd obj-release @link -lib *.obj /out:bx_debug.lib del *.obj @cd ../ :: @cl cpu\*.cpp /Gr /O1 /G3 /MT /w /W0 /c /I $include /I "." /I "instrument\stubs" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"obj-release/" /Fd"obj-release/" cd obj-release @link -lib *.obj /out:cpu.lib del *.obj @cd ../ :: @cl disasm\*.cpp /Gr /G3 /MT /w /W0 /c /I $include /I "." /I "instrument\stubs" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"obj-release/" /Fd"obj-release/" cd obj-release @link -lib *.obj /out:disasm.lib del *.obj @cd ../ :: @cl fpu\*.cpp /Gr /O1 /G3 /MT /w /W0 /c /I $include /I "." /I "instrument\stubs" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"obj-release/" /Fd"obj-release/" cd obj-release @link -lib *.obj /out:fpu.lib del *.obj @cd ../ :: @cl gui\*.cpp /Gr /O1 /G3 /MT /w /W0 /c /I $include /I "." /I "./iodev" /I "instrument\stubs" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"obj-release/" /Fd"obj-release/" cd obj-release @link -lib *.obj /out:gui.lib del *.obj @cd ../ :: @cl iodev\*.cpp /Gr /O1 /G3 /MT /w /W0 /c /I $include /I "." /I "instrument\stubs" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"obj-release/" /Fd"obj-release/" cd obj-release @link -lib *.obj /out:iodev.lib del *.obj @cd ../ :: @cl memory\*.cpp /Gr /O1 /G3 /MT /w /W0 /c /I $include /I "." /I "instrument\stubs" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"obj-release/" /Fd"obj-release/" cd obj-release @link -lib *.obj /out:memory.lib del *.obj @cd ../ :: @cl *.cpp /Gr /O1 /G3 /MT /w /W0 /c /I $include /I "." /I "instrument\stubs" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fo"obj-release/" /Fd"obj-release/" cd obj-release @link -lib *.obj /out:bochs.lib del *.obj @cd ../ :: rc win32res.rc copy win32res.res obj-release :: @cd obj-release link *.lib win32res.res /out:bochs.exe /subsystem:console /libpath:c:\msdev\lib winmm.lib oldnames.lib wsock32.lib shell32.lib comctl32.lib comdlg32.lib user32.lib gdi32.lib kernel32.lib advapi32.lib libcmt.lib ::
Просто тупо виснет! Даже входа в обработчик таймера нет (по ходу, IRQ не приходит). Все исключения у меня ловятся и выводятся на экран (дескать, сработало исключение 0x0e, например). В данном случае на экран ничего не выводится. В ближайшее время постараюсь попробовать. Если тема интересна - могу выложить собранный образ дискеты. Сырцы можно из SVN взять - http://xskernel.svn.sf.net/ В принципе, если есть Watcom+FASM, то можно всё собрать прямо из SVN.
SadKo причина может быть вот в чем прерывание диспетчеризируется APIC'ом на "спящий" логический процессор а т. к он у тебя не инициализирован, то и IDTR у него не валиден из IDTR CPU берет адрес, который не соответствует IDT и пошло-поехало в итоге triple-fault если IF сброшен, тогда к таким последствиям может привести генерация NMI, SMI
rei3er, именно касательно этого у меня и есть подозрения. Хотя в драйвере PIC я уже делаю отрубание глобального APIC через MSR: Код (Text): if (sys_read(cpuid, &info, sizeof(TCPUIDInfo))==sizeof(TCPUIDInfo)) { if ((info.Extensions&CPUID_EXT_APIC)!=0) // Disable APIC if presented { QWORD apic = ReadMSR(IA32_APIC_BASE); apic &= (~(1<<11)); // Clear global enable/disable flag WriteMSR(IA32_APIC_BASE, apic); } }
Посмотрел материал тут: http://sasm.narod.ru/docs/pm/pm_int/chap_5.htm У меня, похоже, логика нарушена: сначала инициализирую PIC, потом вырубаю APIC. А надо наоборот, вроде. Вечером попробую, о результатах сообщу.
SadKo, тут задолбаешся гадать где глюк, лучше сперва пробить железо другими мультизадачными ОСями, минуетами/колибрями...
Народ, всем спасибо за помощь! Всё-таки это оказался APIC. Просто я его отрубал после того, как переназначал векторы прерываний. А блокировать APIC надо было до программирования PIC. Теперь всё работает. Буду возвращать на место всё, что временно отключил в ядре. P.S. Зато с пользой провёл отладку: переписал планировщик, упростив его структуру и добавив новые фичи.
Нет, похоже я поторопился с выводами. Баг опять вернулся. Я решил сделать простенький тестик. Заключается он в следующем: после отрубания APIC (прерывания выключены) вхожу в "вечный" цикл, в котором выводится строчка из нечётного количества букв (не менее трёх), чтобы видно было, что проц пашет. Гружусь. Проц пашет. Буквы выводятся, бегают. Нажимаю на клавишу клавиатуры. Прерывания отключены, система никак не должна реагировать. Вместо этого буквы побежали как-то по-другому. Это ладно. Повторяю действие. Где-то начиная с 5-го нажатия клавиши комп виснет наглухо (даже кнопка Power не отрубает).
Хм, похоже на приколы SMM/Supervisor-mode... Хотя, наврядли ВIOS передает управление 16bit -ому boot, будучи в таком невменяемом состоянии, да еще с включенным APIC... А так гадать неперегадать... В мультизадачке, самые "чудеса в решете" и начинаються как раз после LTR AX. Может описатели GDT/TSS чего мозги, или выравнивание данных.. Тут по идеи лучше с этим особо не мудрить, делать всё по накатаным еще в 386-ых DOS-расширителях стандартах.
SadKo посредством MSR ты выключаешь Local APIC причем скорее всего только один в этом может быть проблема второй логический процессор, я так понимаю, у тебя не инициализирован по-умолчанию после RESET# он включен и APIC (который на чипсете) может ему диспетчеризировать прерывания попробуй отключить все Local APIC'и
Ок, попробую сделать. Сейчас прикручиваю драйвер APIC к ядру. Заодно и разбираюсь, что этот зверь из себя представляет .
В общем, ситуация какая-то непонятная. Я Multiprocessor-структуру _MP_ нашёл в BIOS'е, но таблица, связанная с этой структурой на qemu, p4 и Athlon X2 пустая. По ходу, надо искать теперь проц через ACPI? И вообще, как можно получить доступ к APIC'ам других процов?