Есть некий код который правит код в памяти. Для этого временно сбрасывается WP-bit. Код выполняется в DriverEntry. Я так понимаю, что если в это время моя процедура потеряет управление, а потом возобновится на другом ядре/процессоре, то возникнут проблемы. Поможет ли конструкция cli/sti ?
Поможет. (при CLI IRQL становится IRQL_HIGH, а стало быть выше чем IRQL прерываний и IRQL_DISPATCH - а стало быть контекст переключать будет некому и никто не прервёт)
2sl0n а как тут DPC прикрутить ? Вообще-то дело вот в чём. Есть некий драйвер, который сам по себе успешно работает. Для защиты от копирования был добавлен код который раскодирует на лету некий участок кода затем считает его контрольную сумму и сравнивает с эталоном. В зависимости от результата драйвер или работает или отвергает некоторые комманды. Ключ для раскодировки зависит от параметров HDD. Вся эта штука нормаьлно работала. Но стали покупать новое железо и на нём стали возникать проблемы. Причём не всегда. При загрузке BSOD. Причём багчеки разные: 0x7e(0xc000005, ...), 0x8e(0xc000005, ...), 0x7f(0x0d, ...). Возможно дело в том что теперь используется SATA-винты.
Делаем cli, сбрасываем WP бит, пишем куда надо, ставим WP бит обратно и делаем sti. Все будет работать зашибись на любом процессоре. И никакие DPC нахрен не нужны.
2Agent666 Я вот тоже так думал. Ведь если нет прерываний, то некому будет проц переключить. Хотя могу ошибаться. А вот товарищи говорят, что всё сложнее. Давайте выясним в чём тут дело
Ошибаются эти товарищи. cli/sti - единственно правильное решение. З.Ы. спинлок здесь нахрен ненужен, и его юзать будет неправильно.
2ECk что-то не понял про спинлок напоминаю, что дело происходит в Driver Entry: Код (Text): NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { ... __asm { cli push eax mov eax, cr0 mov CR0Reg,eax and eax,0xFFFEFFFF // сбросить WP bit mov cr0, eax pop eax } Decod(StartAddr, Len, Key); __asm { push eax mov eax, CR0Reg mov cr0, eax // востановить содержимое CR0 pop eax sti } ... }
Maveric Ну ты своей головой чуток подумай, и потом сделай вывод самостоятельно, а не слушай левые советы всяких личностей. И так, что мы имеем: Нам надо сбросить wp бит, записать данные и поставить обратно, и сделать это так, чтобы нас никто не прервал, и желательно никакой посторонний код с сброшеным WP битом не исполнился. Если мы запретили прерывания, то прервать работу нашего кода могут только два события: #nmi и #smi. Первый используется при обработке всяких железных ошибок и при нормальной работе не встречается. Второй используется биосом для управления питанием (в основном на ноутах) и эмуляции устройств (но это нас не должно волновать, т.к. никак не связано с ОС). Все, никакие таймерные прерывания и IPI в этом момент передаваться не могут, а значит никакое переключение потоков не возможно. Сколько процессоров - дело десятое, это тоже неколышит так как работаем мы в данный момент только с одним. Ну а если по совету некоторых товарищей использовать спинлок, то мы получим программную блокировку переключения потоков, ну а прерывания по прежнему будут вызываться, таймер будет работать, IPI приходить. Т.е. с сброшеным WP битом может исполниться черт знает сколько ядерного кода, чего нам бы не хотелось. Некоторые товарищи еще советовали юзать DPC. Нахрена это вобще нужно я так и не понял, DPC тут примерно как мартышке очки. З.Ы. если после того, как я тебе разжевал всю эту хрень, ты по прежнему будешь слушать глупые советы, то лучше не берись писать дрова, всеравно не получиться.
2Agent666 Мощно. А нет случаем литературки по поводу того как в многоядерных системах обрабатываются прерывания и как там планировщик работает ?
ECk Не надо меня отсылать к тем сорцам, которые я знаю чуть ли не наизусть. К твоему сведению, переключение потоков может просходить в двух случаях: 1 - переключение по исчерпанию выделеного кванта времени (вызывается из KiDispatchInterrupt) 2 - переключение по вхождению потока в ожидание какого-либо события (происходит при вызову ждущих апи) KiDispatchInterrupt на нашем процессоре при запрещенных прерываниях вызываться не будет, ну а апи вызывать нам здесь нахрен не нужно.
З.Ы. добавлю сраведливости ради, что спинлок может понадобиться в том случае, если аффтар может из нескольких потоков работать с одной и той же областью данных. Но необходимость cli/sti это не отменяет. Но понадобиться он или нет - зависит от того, где и каким образом аффтар работает с данными.
Остальным процессорам ультрафиолетово CLI на твоем процессоре, к тому же, никаких действий с контроллером/контроллерами прерываний ты не производишь. А стало быть прерывание возникнет при приходе прерывания на APIC - и будет обработано без переключения контекста (для твоего сведения) на другом процессоре. А что выполненная ISR делать будет - это ее дело.
А мне ультрафиолетово на другие процессоры. Задача то в том, чтобы код на текущем процессоре не был прерван. И пускай обрабатывается, мне не жалко. Главное что на другом процессоре.