Нужно обеспечить операцию атомарной модификации 4х байтов в случае SMP системы на базе x86 в режиме ядра. По терминологии Intel, это "Cross-Modifying Code". Смущает вот что: Т.е. получается, что LOCK префикс в случае модификации кода бесполезен?
7mm Не бесполезен, но модифицируемые инструкции, могут быть уже выбраны на исполнение. Поэтому блокировать или не блокировать шину — не важно, т.к. поздно уже. Аналогично с доступом к таблицам страниц, т.к. их данные грузятся в TLB. Собственно, как писать кросс-модифицируемый код, описано там же.
l_inc Вот поясните, если я ошибаюсь. Допустим, на одном процессоре я пишу 4 байта, которые лежат на границе линии кеша или страниц -- т.е. это получается будет однозначно не атомарная операция. А вот где-то в этот момент второй процессор делает предвыборку команд, и не получится ли так, что у него будут частично-обновлённые данные? И второй вопрос, если я модифицировал код, который лежит где-то в памяти и также закеширован некоторыми процессорами, будет ли осуществлена инвалидация их кешей после записи (после снятия LOCK) ?..
Кажется префикс lock блокирует шину на время выполнения всей инструкции, т.е. как бы не лежали 4 байта - вся разница будет во времени блокирования (в случае пересечения границы просто "надолго" память будет недоступна).
100gold Да, похоже так и будет. Но всё-таки, достаточно ли указать префикс LOCK перед операцией модификации 4х байтов для SMP, или же нужно делать что-то дополнительно?..
Вот так вопрос задам. В линуксе есть такой кодес: Код (Text): 14 /* 15 * Note: no "lock" prefix even on SMP: xchg always implies lock anyway. 16 * Since this is generally used to protect other memory information, we 17 * use "asm volatile" and "memory" clobbers to prevent gcc from moving 18 * information around. 19 */ 20 #define __xchg(x, ptr, size) \ 21 ({ \ 22 __typeof(*(ptr)) __x = (x); \ 23 switch (size) { \ 24 case 1: \ 25 { \ 26 volatile u8 *__ptr = (volatile u8 *)(ptr); \ 27 asm volatile("xchgb %0,%1" \ 28 : "=q" (__x), "+m" (*__ptr) \ 29 : "0" (__x) \ 30 : "memory"); \ 31 break; \ 32 } \ 33 case 2: \ 34 { \ 35 volatile u16 *__ptr = (volatile u16 *)(ptr); \ 36 asm volatile("xchgw %0,%1" \ 37 : "=r" (__x), "+m" (*__ptr) \ 38 : "0" (__x) \ 39 : "memory"); \ 40 break; \ 41 } \ 42 case 4: \ 43 { \ 44 volatile u32 *__ptr = (volatile u32 *)(ptr); \ 45 asm volatile("xchgl %0,%1" \ 46 : "=r" (__x), "+m" (*__ptr) \ 47 : "0" (__x) \ 48 : "memory"); \ 49 break; \ 50 } \ 51 case 8: \ 52 { \ 53 volatile u64 *__ptr = (volatile u64 *)(ptr); \ 54 asm volatile("xchgq %0,%1" \ 55 : "=r" (__x), "+m" (*__ptr) \ 56 : "0" (__x) \ 57 : "memory"); \ 58 break; \ 59 } \ 60 default: \ 61 __xchg_wrong_size(); \ 62 } \ 63 __x; \ 64 }) 65 66 #define xchg(ptr, v) \ 67 __xchg((v), (ptr), sizeof(*ptr)) Допустимо ли использовать вот этот самый xchg(ptr, v) в случае с SMP для модификации 4х байтов: Код (Text): typedef struct { u8 type; s32 imm32; } __attribute__((packed)) x86_call_t; int x86_fixup_call(x86_call_t * pcall, void * handler) { s32 imm32 = (...); ... xchg(&pcall->imm32, imm32); ... } Подскажите, кто знает?..
Насколько я понимаю, допустимо. Добавлю, что если будет необходимость сразу-же исполнить изменённый код в этом-же потоке, то можно выполнить команду cpuid, это сбросит уже загруженные на исполнение инструкции.
http://wasm.ru/forum/viewtopic.php?id=37370&p=2 #28 l_inc При записи в текущий сегмент кода очередь команд сбрасывается в современных камнях. Поэтому нельзя обмануть процессор модификацией следующей инструкции из текущей.
klzlk Возможно, Вы не заметили, но речь не о самомодифицирующемся коде, а о кроссмодифицируемом. Так что вполне можно обмануть процессор.
dinoweb Нет, речь о корректной работе других камней после модификации общего кода. 2All Итак, вердикт каков? Есть чем подтвердить/опровергнуть? Боюсь, отловить потенциальный баг будет ой-как не просто...
Кстати, как вариант, наверняка можно создать копию страницы, модифицировать её и затем изменить запись PTE... Единственное, что тут может быть не так, если целевые байты лежат на границе страниц -- тогда нужно будет менять сразу 2 записи PTE, а это уже будет никак не атомарно