html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

Пишу игрушечную ОС (о прерываниях)


Данная статья написана в форме поста для блога. Если она окажется вам интересной, то будет продолжение.

Последние четыре месяца посвящаю свободное от работы время написанию игрушечной ОС для x86_64. Исходный код лежит здесь.

Общая задумка (пока весьма далёкая от реализации) следующая: единое 64-битное адресное пространство с вечно живущими нитями (как у Phantom OS); виртуальная машина, обеспечивающая безопасность исполнения кода. На данный момент реализованы:

1. загрузка ядра при помощи multiboot-загрузчика (GRUB);
2. текстовый VGA-режим (16-цветов, kprintf);
3. простой интерфейс настройки отображения страниц;
4. возможность обработки прерываний на C;
5. идентификация топологии процессоров (сокеты, ядра, потоки) и их запуск;
6. работающий прототип вытесняющего SMP-планировщика с поддержкой приоритетов;

Пропустим описание multiboot-загрузки и работы с VGA-режимом (об этом не писал, разве что, ленивый). Про отображение страниц тоже не хочу писать, боюсь это будет скучно (может, в другой раз). Давайте лучше поговорим об обработке прерываний.

Обычно обработчики прерываний, как любой другой критичный код, пишутся на ассемблере. Не очень люблю ассемблер, предпочитая как можно больше кода писать на C. Поэтому я сделал несколько макросов, позволяющих удобно писать обработчики прерываний на С. Конечно же, такое решение негативно сказывается на производительности, но мощность современных компьютеров позволяет такую роскошь (выносим за скобки системы реального времени).

В момент прерывания в long mode процессор формирует в стеке обработчика (это может быть как пользовательский, так и отдельно выделенный стек) фрейм, содержащий сохранённые регистры:



Вообще-то, это картинка соответствует protected mode (не нашёл качественную картинку для long mode), но, не считая мелких деталей, принцип абсолютно тот же. Остальные регистры пользовательского потока остаются нетронутыми, поэтому обработчик должен их сохранить в стеке. Поскольку наш обработчик написан на C, то приходится сохранять полный комплект регистров, включая 512 байт FPU/MMX/SSE. Конечно, можно запретить компилятору генерировать SIMD-код для всего ядра или только для функций, работающих внутри прерываний. В первом случае мы лишимся многих оптимизаций, во втором – вообще нивелируем пользу от написания обработчиков на С, так как не сможем пользоваться никакими стандартными функциями. Итак, пользуемся инструкциями fxsave и fxrstor для быстрого сохранения/восстановления регистров FPU/MMX/SSE.

Вот структура нашего стекового фрейма:

struct int_stack_frame {
  uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
  uint64_t rdi, rsi, rbp, rdx, rcx, rbx, rax;
  uint8_t fxdata[512];
  uint32_t error_code;
  uint64_t rip;
  uint16_t cs;
  uint64_t rflags, rsp;
  uint16_t ss;
};

Первая часть полей до error_code – вручную сохранённые регистры, вторая – регистры, автоматически сохранённые процессором. Обратный порядок обусловлен тем, что стек растёт сверху вниз. Теперь определим макросы для удобного написания обработчиков.

#define DEFINE_INT_HANDLER(name)                                        \
  static NOINLINE                                                       \
  void handle_##name##_int(UNUSED struct int_stack_frame *stack_frame,  \
                           UNUSED uint64_t data)

#define DEFINE_ISR_WRAPPER(name, handler_name, data)                 \
  static NOINLINE void *get_##name##_isr(void) {                     \
    ASMV("jmp 2f\n.align 16\n1: andq $(~0xF), %rsp");                \
    ASMV("subq $512, %rsp\nfxsave (%rsp)");                          \
    ASMV("push %rax\npush %rbx\npush %rcx\npush %rdx\npush %rbp\n"); \
    ASMV("push %rsi\npush %rdi\npush %r8\npush %r9\npush %r10");     \
    ASMV("push %r11\npush %r12\npush %r13\npush %r14\npush %r15");   \
    ASMV("movq %%rsp, %%rdi\nmovabsq $%P0, %%rsi" : : "i"(data));    \
    ASMV("callq %P0" : : "i"(handle_##handler_name##_int));          \
    ASMV("pop %r15\npop %r14\npop %r13\npop %r12\npop %r11");        \
    ASMV("pop %r10\npop %r9\npop %r8\npop %rdi\npop %rsi");          \
    ASMV("pop %rbp\npop %rdx\npop %rcx\npop %rbx\npop %rax");        \
    ASMV("fxrstor (%rsp)\naddq $(512 + 8), %rsp");                   \
    void *isr;                                                       \
    ASMV("iretq\n2: movq $1b, %0" : "=m"(isr));                      \
    return isr;                                                      \
  }

#define DEFINE_ISR(name, data)             \
  DEFINE_INT_HANDLER(name);                \
  DEFINE_ISR_WRAPPER(name, name, data)     \
  DEFINE_INT_HANDLER(name)

Первый макрос определяет сигнатуру функции обработчика. Второй – обёртка сохраняющая и восстанавливающая регистры. Подобная схема позволяет вызывать одну функцию-обработчик на несколько прерываний. Я это использую для стандартных ошибок, когда несколько прерываний делают дамп стекового фрейма. Как видно из кода, обработчик принимает дополнительный аргумент data, соответственно, разные прерывания могут передавать свои данные в один обработчик. Наконец, последний макрос для сокращённого написания пары: обработчик + обёртка, когда обработчик заточен под одно единственное прерывание.

Обёртка представляет собой функцию, возвращающую указатель на начало обрабатывающего кода, расположенного в её же теле. Подробнее об этом трюке можно почитать здесь.

В результате написать обработчик и привязать его к прерыванию становится тривиальной задачей:

DEFINE_ISR(foo) {
// обычный C-код обработки прерывания
// доступны struct int_stack_frame *stack_frame и uint64_t data
}

set_isr(INT_FOO_VECTOR, get_foo_isr());

Вот и всё что я хотел рассказать о Вьетнаме обработке прерываний.
Продолжать?

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Проголосовало 1287 человек. Воздержалось 280 человек.

Читать дальше
Twitter
Одноклассники
Мой Мир

материал с habrahabr.ru

0

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • habrahabr.ru
          • домен habrahabr.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции