Обработчик ошибок страницы сборки не может быть вызван из-за неверного указателя стека - PullRequest
1 голос
/ 15 марта 2020

Когда вызывается прерывание обработчика ошибок моей страницы (предполагается, что система зависает), перед вызовом в стек помещаются некоторые переменные. У меня включена виртуальная память, и когда я устанавливаю неверный указатель стека (esp) и вызывается обработчик int14, он сразу же вызывает ошибку другой страницы и так далее, и так далее. Как мне разрешить эту ситуацию?

Мой код int14:

isr14:
    ; interrupt handler for isr14
    jmp $
    iretd

Код, вызывающий его разрыв:

mov esp, 0x1000 ; 0x1000 is not mapped in the VM directory
push dword 'A'
jmp $

Часть моей таблицы IDT:

irq14:
    dw isr14
    dw 0x0008
    db 0x00
    db 10101110b
    dw 0x0000

irq15:
........

1 Ответ

5 голосов
/ 15 марта 2020

Как мне разрешить эту ситуацию?

Я бы разрешил ситуацию, используя избегание - не позволяйте ядру иметь в начале хитрый указатель стека (и не не позволяйте стеку ядра отправляться в пространство подкачки, не используйте ошибку страницы для "автоматически растущего стека ядра" и т. д. c). Обратите внимание, что CPU автоматически переключится на стек ядра, если в пользовательском пространстве произойдет сбой страницы (при CPL = 3), поэтому не имеет значения, имеет ли пользовательское пространство хитрый указатель стека.

Альтернативы:

  • принудительное переключение стека ядра, когда код ядра (CPL = 0) вызывает ошибку страницы. Это можно сделать с помощью аппаратного переключателя задач (защищенный режим) или механизма IST (длинный режим) для обработчика исключений при сбое страницы. Это было бы лучшим вариантом для восстановления (например, чтобы было легче выяснить, в чем проблема, исправить ее, а затем вернуться).

  • принудительно переключать стек ядра при коде ядра (CPL = 0) вызывает двойную ошибку. Это можно сделать с помощью аппаратного переключателя задач (защищенный режим) или механизма IST (длинный режим) для обработчика исключений двойного сбоя. Это было бы лучшим вариантом для повышения производительности (без дополнительных накладных расходов для обычных сбоев страниц).

Примечание 1. Имейте в виду, что ни аппаратные переключатели задач / шлюзы задач, ни IST не являются повторными. При переключении аппаратных задач, если происходит сбой второй страницы, когда вы обрабатываете ошибку первой страницы, вы получите общую ошибку защиты (потому что «задача сбоя страницы» занята); и для IST, если ошибка второй страницы возникает во время обработки ошибки первой страницы, ошибка второй страницы уничтожит / перезапишет стек ошибки первой страницы и сделает невозможным восстановление. Теоретически, вы можете смягчить эти проблемы, переключившись на другую задачу или другой стек как можно скорее, но это сложно / грязно и может вызвать еще больше проблем.

Примечание 2: Вы, вероятно, в конечном итоге с комбинацией предотвращения и двойной ошибки с использованием аппаратного переключателя задач или IST; с помощью обработчика двойной ошибки, выполняющего «freeze system and dump info / pani c» в качестве обобщенного c запасного варианта для сбоев ядра catastrophi c (которые должны были быть предотвращены, но не были).

Примечание 3: если вы хотите поддерживать «автоматически растущие стеки ядра»; вместо этого вы можете использовать «пробники стека» - в основном, просто используйте фиктивные операции чтения / s (в эпилогах функций) из «будущего стека», прежде чем использовать память для стека, чтобы сбой страницы происходил, когда для страницы еще осталось достаточно стека ядра. обработчик ошибок.

...