vpd 0 24 декабря, 2013 Опубликовано 24 декабря, 2013 · Жалоба В некоторых процессорах, с которыми приходится иметь дело, память уровня L1 может не полностью превращаться в кэш первого уровня. Память L1 намного быстрее обычной пользовательской памяти Linux. в моем случае memcpy, выполненный в обычной памяти (DDR2 SDRAM через кэши L2 и L1) дает скорость около 100 МБ/с. Тот же вызов с указателями в памяти L1 дает скорость более 6 ГБ/c, то есть в 60 раз быстрее. Многие счетные приложения могли бы существенно выиграть, если бы использовали эту память напрямую, а не через кэш. Тем более, что в нашем случае более половины этой памяти (48К из 80К) именно только памятью и являются. Возникла следующая идея - доработать ядро линукс так, чтобы при загрузке процесса в память, оно все секции, начинающиеся с префикса, скажем, ".l1_" (например, ".l1_text"), при возможности (наличии места) переносило само в память L1, и динамически перелинковывало все указатели на новое место. В этом случае программист получает возможность писать приложение как обычно, и только отдельным данным и коду назначать атрибут размещения в секции с другим именем. Собственно, именно так и делается при обычном программировании без Linux. Но загрузчик ELF мог бы сам выделять место в L1, чем гарантировать совместное использование общей памяти разными процессами. Причем, если память L1 в достаточном объеме отсутствует, то ничего страшного не происходило бы, просто в журнал ядро записывало бы предупреждение о невозможности загрузить процесс оптимально. Однако пока я копался в деталях загрузки ELF, уперся в простую проблему. При сборке линкер обычно не делает никаких relocation таблиц, а кладет секции друг за другом в виртуальном адресном пространстве процесса по мере того, как у него проясняется расклад по всем объектным модулям. То есть, перенести отдельную секцию неявно не очень то и получается, надо как-то линкер предупредить, что секция будет динамически линковаться потом, и что нужно составить для нее таблицу символов и поместить в объектный модуль. Так вот, вопрос уперся в то, можно ли такое сделать, и если можно, то как? Еще раз повторю свое видение процесса загрузки такого процесса. 1) Загрузить процесс стандартным образом. 2) Для каждой секции с именем, начинающимся на заданный префикс, выполнить попытку переноса в L1. 3) ... для этого попытаться выделить место в L1, проверить наличие таблицы и при успехе скопировать секцию в L1, перенести все ссылки процесса в новое место. 4) если попытка переноса не удастся, то написать сообщение в журнал ядра. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Harbour 0 24 декабря, 2013 Опубликовано 24 декабря, 2013 · Жалоба Всего-то придется переписать Linux memory manager, добавив свою зону (cat /proc/pagetypeinfo). Ну и скорей всего ld придется патчить, хотя теретически можно использовать и статически привязанные секции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vpd 0 24 декабря, 2013 Опубликовано 24 декабря, 2013 · Жалоба Не понял про ld, зачем его патчить? Смысл как раз в том, чтобы динамически перелинковывать часть секций. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Harbour 0 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба Ну и как тогда предполагается стандартному загрузчику сообщить что этот sysbrk нужно вызывать с параметром для зоны L-cache ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vpd 0 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба ну, а что, просто секцию сделать relocatable нельзя? Ну или как крайний вариант - сделать отдельный объектный модуль, который скомпилировать отдельно как so, и его потом встроить (влинковать) в исполнимый файл. Или стандартно ld может делать либо исполнимый неперемещаемый, либо исполнимый перемещаемый как целое, либо целиком .so? В моем случае патчить ld затруднительно, так как для выбранной архитектуры есть только готовые пресобранные кросс binutils + gcc от CodeSourcery. Исходников нет. Хочется проверить идею где-то на уровне ld command file. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sasamy 9 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба В моем случае патчить ld затруднительно, так как для выбранной архитектуры есть только готовые пресобранные кросс binutils + gcc от CodeSourcery. Исходников нет. Ну это неправда, учитывая что TI и Mentor Graphics это не китайщина беспредельная и законы соблюдают http://sourcery.mentor.com/public/gnu_toolchain/ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vpd 0 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба За ссылку спасибо! Но это все же вариант не самый удобный, хотелось бы уложиться в стандартные возможности. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sasamy 9 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба хотелось бы уложиться в стандартные возможности. Стандартно SRAM отдают на уровне ядра драйверам быстрой периферии (HS USB например или например в i.mx5/6 для видеопроцессора). Код все равно в кеше исполняется а для данных элементарно смапить эту память на пользовательском уровне, тем более в вашем случае и мапить ничего не надо - MMU нет - лезь куда хочешь. Только я на вашем месте проверил для начала - не используется ли эта SRAM в драйверах. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vpd 0 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба Ну вот идея как раз в том и состояла, чтобы не городить драйвер для предоставления L1 прикладным программам, и не делать никакого сложного mmap, а просто написать в объявлении данных что-то типа /* <asm/memory.h> */ #define __L1_data __section(.l1_data) /* user program */ char __L1_data buffer_in_L1[4096]; и все. Собственно, обычная программа под DSP у TI в CCS так и выглядит: - переменная закидывается в специальную секцию - на уровне командного файла линкера секция размещается в определенном блоке памяти. Все что хочется добавить, чтобы ядро могло администрировать выделение этой памяти. по поводу "лезь куда хочешь" есть такие возражения: 1) Если процессов, требующих быстрой памяти, несколько, то кто-то должен быть арбитром. 2) Если такая память выделена своим доморощенным арбитром, то остается проблема передачи указателей на эту память в ядро. В нынешнем виде в ядре c6x функции copy_to_user и copy_from_user, ccылаются на функцию _access_ok, которая проверяет правильность пользовательского указателя. И вот эта функция знает только о внешней памяти L3 (DDR2), поэтому программы будут спотыкаться при попытке передать в ядро данные через L1. Чтобы решить эту проблему, хорошо бы ядру явно обозначить наличие L1. Ну или выключить проверку access_ok, но это породит проблему устойчивости системы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sasamy 9 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба Ну вот идея как раз в том и состояла, чтобы не городить драйвер для предоставления L1 прикладным программам Ну вот идея mmap (man mem) как раз в том чтобы не городить драйверы по поводу "лезь куда хочешь" есть такие возражения: Вам в любом случае придется решить эти же самые "возражения" - независимо от реализации. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vpd 0 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба И все же я пока не получил ответа на вопрос, можно ли слинковать ELF с помощью обычного так, чтобы одна секция была перемещаемой? То есть для всех символов из этой секции имелась бы таблица символов, а для всех ссылок на эти символы имелась таблица relocation-ов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sasamy 9 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба И все же я пока не получил ответа на вопрос Я вам нагуглил вместо вас http://blackfin.uclinux.org/doku.php?id=uc...st:on-chip_sram http://elinux.org/Memory_Type_Based_Allocation Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Harbour 0 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба И все же я пока не получил ответа на вопрос, можно ли слинковать ELF с помощью обычного так, чтобы одна секция была перемещаемой? То есть для всех символов из этой секции имелась бы таблица символов, а для всех ссылок на эти символы имелась таблица relocation-ов. -fPIC делает это для всех .text* секций Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vpd 0 25 декабря, 2013 Опубликовано 25 декабря, 2013 · Жалоба К сожалению, в этих материалах тоже нет ответа на вопрос о перемещении секций и их сочетании с секциями в обычных данных. никаких совпадений на 'reloc' я там не нашел. Ну вот допустим пример такой: char __L1_data some_string[] = "Example string"; int main() { printf("%s\n", some_string); return 0; } Очевидно, перед вызовом printf компилятор захочет загрузить в регистр адрес строки. Если секция в процессе загрузки процесса переедет, то и адрес строки изменится. То есть, нужно будет не только секцию .l1_data передвинуть, но и в секции .text подправить непосредственные операнды в командах загрузки адреса строки. В архитектуре c6x еще 32-битные данные нельзя загрузить в регистр одной командой, они грузятся двумя половинками по 16 бит. Поэтому и фиксапы будут весьма специфические. Насколько я представляю, они где-то в .rel.dyn должны попасть. Но вот при обычном связывании секция .l1_data будет размещена где-нибудь рядом с .data, вычислены реальные смещения относительно начала процесса, половинки которого будут подправлены при передаче аргументов в printf и в таблицы динамического связывание ничего не попадет. Поэтому секцию то я перенести могу, но работать оно будет по старым адресам. Ни в одном из найденных Вами документов вообще ничего про это не написано. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sasamy 9 26 декабря, 2013 Опубликовано 26 декабря, 2013 (изменено) · Жалоба -fPIC делает это для всех .text* секций PIC - это прямой и рекомендуемый метод, но существует еще динамическая релокация. То есть, нужно будет не только секцию .l1_data передвинуть, но и в секции .text подправить непосредственные операнды в командах загрузки адреса строки. Не совсем так по крайней мере на архитектурах которые поддерживают динамическую релокацию. Вот наглядная статья, правда на примере x86 и динамических библиотек http://eli.thegreenplace.net/2011/08/25/lo...ared-libraries/ У блэкфинов в ядре есть (или был ?) свой специальный парсер elf который определял что секцию надо помещать в sram, в ванильном ядре этого нет - sram используется для буферов в драйверах. http://lkml.indiana.edu/hypermail/linux/ke...06.2/00159.html правда я не понял - почему они genalloc не используют в качестве аллокатора http://lxr.free-electrons.com/source/lib/genalloc.c Изменено 26 декабря, 2013 пользователем sasamy Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться