CPU сбрасывает выполнение собственного ядра C при обращении к глобальной переменной - PullRequest
1 голос
/ 13 апреля 2020

Надеюсь, у вас все хорошо во время конфайнмента.

В качестве краткого вступления: я пишу этот вопрос не как Tretorn, а как член ASO C, ассоциации студентов-информатиков из Испании. Мы пытаемся узнать, как работают ядра, самостоятельно разрабатывая их. У нас есть весь код (связанный с вопросом), опубликованный в https://github.com/TretornESP/ASOC2

Поскольку у нас около 30 учеников, мы разделили работу на: файловую систему, память, программное обеспечение пользовательского пространства (просто оболочка), Управление процессами и Bootloader.

Когда мы один месяц в разработке, мы столкнулись с некоторыми реальными проблемами в этой последней части, поэтому здесь я прошу вас о некоторой помощи по этому вопросу.

Шаги, которые мы выполняем с того момента, как B IOS настраивает нас на 0x7c00:

  • Установите CS, выполнив прыжок в длину (Спасибо, мистер Петч!)
  • Сохранить основной диск
  • Установить 16-битный стек
  • Загрузить 8 секторов с диска (2-й этап)
  • Загрузить 32-битный GDT
  • Загрузить IDT
  • Включить защищенный режим (CR0)
  • Выполнить дальний переход к конвейеру flu sh и установить CS
  • Установить все сегменты одинаково (Плоская сегментация)
  • Установить новый стек в 0x90000
  • Обнаружить присутствие LM через CPUID
  • Отключить старый пейджинг (мы не делали настроить подкачку в PM)
  • настроить таблицы страниц
  • активировать PAE
  • активировать LM
  • включить подкачку
  • загрузить GDT (аналогично как в 32 битах, может быть в режиме сжатия?)
  • Дальний переход по тем же причинам, что и выше
  • Обновление сегментов
  • Сброс стека
  • Вызов C kmain via extern kmain call kmain

Наш скрипт компоновщика:

OUTPUT_FORMAT("binary");
ENTRY(boot);
SECTIONS
{
    . = 0x7C00;
    .text : {
        *(.boot);
        *(.text);
    }

    .rodata : SUBALIGN(4) {
        *(.rodata);
    }

    .data : SUBALIGN(4) {
        *(.data);
    }

    .bss : SUBALIGN(4) {
        *(.bss)
    }

    /DISCARD/ : {
        *(.eh_frame);
        *(.comment);
        *(.note.gnu.build-id);
    }
}

, который мы компилируем с:

nasm -f elf64 boot.asm -o boot.o 
gcc -ffreestanding -nostdlib -mno-red-zone -fno-exceptions -m64 kernel.c boot.o -o kernel.bin -T link.ld

и тестируем с помощью:

qemu-system-x86_64 -fda kernel.bin

Наш kmain вроде пишет в VGA, если мы устанавливаем функцию следующим образом:

void kmain() {

    char * vga_ptr = (char*)0xb8000;
    *(vga_ptr++) = 0x0f;
    *(vga_ptr++) = 'H';

    while (1){}
}

Но если вместо этого я объявляю vga_ptr за пределами kmain границ, процессор сбрасывает выполнение.

Предположение, которое я здесь делаю, состоит в том, что ЦП имеет тройной отказ, учитывая тот факт, что IDT неполна (любая помощь в этом тоже будет признательна). Вопрос больше в том, что вызывает исключение, которое вызывает двойной отказ, тройной отказ, сброс салазок в первую очередь. Я просто догадываюсь, но, возможно, это связано с неправильным подкачкой или процессом сборки (друг link.ld доставил нам много проблем в прошлом).

Любой свет залил эту проблему или указал на любой беспорядок обнаружен в нашем коде будет принята с благодарностью. И мне жаль, если вопрос был слишком длинным или неточным. Помните, что мы действительно студенты (;

Хорошего дня и будьте в безопасности!

PS Полный код загрузчика приведен выше в github, в ветке BootTest. Я пытался сделайте вопрос как можно короче, но по запросу я могу отредактировать текст, включив в него любой фрагмент кода, который вам нужен.

[РЕДАКТИРОВАТЬ] Еще одна ошибка, возможно, не связанная с тем, что, когда я разбираю файл .bin, он показывает все в разделе .data.

...