Форум программистов, компьютерный форум, киберфорум
ОС на Assembler
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.67/49: Рейтинг темы: голосов - 49, средняя оценка - 4.67
Эксперт Hardware
Эксперт Hardware
 Аватар для R71MT
6215 / 2449 / 403
Регистрация: 29.07.2014
Сообщений: 3,181
Записей в блоге: 4
13.12.2023, 14:26
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Teamur Посмотреть сообщение
значит уже в DRIVER FEATURES мне надо прописать 1, верно?
да.. а бит(23) сбрасываешь в нуль.
VIRTIO_NET_F_CTRL_MAC_ADDR = 23 ; Установите MAC-адрес через канал управления.

наиболее приемлемой для тебя будет сл.маска:

79 BF FF E7 = 0111 1001 1011 1111 1111 1111 1110 0111 - Device
00 2C EC E7 = 0000 0000 0010 1100 1110 1100 1110 0111 - Driver


Добавлено через 1 минуту
Цитата Сообщение от Teamur Посмотреть сообщение
Если оставить как есть,
нельзя оставлять необрабатываемые тобой биты, т.к. хост будет ждать на них реакцию.
2
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
13.12.2023, 14:26
Ответы с готовыми решениями:

Джаббер сервер для Win x64
В поисковиках смотрел, но так и не нашел ни чего подходящего. Нужен джаббер сервер на Windows server 2008 x64. Кто что посоветует?

Сервер Domino 8.5.3 X64 И Файл Подкачки (pagefile)
Ребята, проблема в следующем: Имеется сервер Domino x64 8.5.3 с последними фиксапами. Оперативы 16 Гбайт. В последнее время админы...

Как перенести веб-сервер со всеми конфигами с Windows 10 x64 на Debian (ARM)?
В составе веб-сервера: Apache2 (2.4), PHP 7.3, MySQL 5.7, а также веб-сайт WordPress с плагинами и конфигом под ip windows-ноутбука. ...

209
 Аватар для Teamur
29 / 29 / 5
Регистрация: 06.01.2015
Сообщений: 336
13.12.2023, 18:45  [ТС]
R71MT, сейчас код такой

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
; ----------------------------------------------- Queue(0) In
mov dx, [BAR0]       ; DX = С060h
add dx, 0Eh          ; PORT+0Eh= C06Eh, QUEUE_SELECT: 2 Б
xor ax, ax           ; AX=0, очистить 2 Б
out dx, ax           ; выбрать Очередь(0) In
 
mov dx, [BAR0]          ; DX = C060h
add dx, 08h             ; PORT+08h= C068h, QUEUE_ADDRESS: 4 Б
mov eax,[I_QUEUE_ADDR]  ; адрес очереди 4 Б
shr eax,12              ; сдвиг 12 бит = адрес/4096 (выравнивание)
out dx, eax             ; установить адрес очереди In
 
; ----------------------------------------------- Queue(1) Out
mov dx, [BAR0]       ; DX = С060h
add dx, 0Eh          ; PORT+0Eh= C06Eh, QUEUE_SELECT: 2 Б
mov ax, 0x1          ; AX=1
out dx, ax           ; выбрать Очередь(1) Out
 
mov dx, [BAR0]          ; DX = C060h
add dx, 08h             ; PORT+08h= C068h, QUEUE_ADDRESS: 4 Б
mov eax,[O_QUEUE_ADDR]  ; адрес очереди 4 Б
shr eax,12              ; сдвиг 12 бит = адрес/4096 (выравнивание)
out dx, eax             ; установить адрес очереди Out
 
; -------------------------------------------------------------------------
 
; Настроить в памяти цепочки кольцевых буферов Ring
 
 
 
 
; -------------------------------------------------------------------------
; 00 2C EC E7 = 0000 0000 0010 1100 1110 1100 1110 0111
; Указываем нужные нам возможности
mov dx, [BAR0]          ; dx=[PORT]
add dx,  0x04           ; dx+=04h
mov eax, 0x002CECE7     ; ( 4 байта в регистр DRIVER_FEATURES )
out dx,  eax            ; ввод
 
; Записать 0x07 в BAR0+12h - статус ACKNOWLEDGE + DRIVER + DRIVER_OK
mov dx, [BAR0]          ; dx=[PORT]
add dx, 0x12            ; dx+=12h
mov al, 0x07            ; al=7 ( 1 байт в регистр DEVICE_STATUS )
out dx, al              ; в порт -> драйвер в режиме ожидания
 
; Уведомить хост, что I_QUEUE была изменена драйвером
mov dx, [BAR0]          ; dx=[PORT]
add dx, 0x10            ; dx+=10h
xor ax, ax              ; ax=0 ( 2 байта в регистр QUEUE_NOTIFY )
out dx, ax              ; ввод
 
 
; --------------------------------------------------------------------------
I_QUEUE_ADDR   dd   0x00100000   ; Адрес In (Receive)  очереди
O_QUEUE_ADDR   dd   0x00120000   ; Адрес Out (Transmit) очереди
Настроить в памяти цепочки кольцевых буферов Ring.
Дескриптор согласно этому ?
https://wiki.osdev.org/Virtio#... Descriptor

Размер очереди задает хост, у меня это: 0100h ( 256 байт ) ?
0
Эксперт Hardware
Эксперт Hardware
 Аватар для R71MT
6215 / 2449 / 403
Регистрация: 29.07.2014
Сообщений: 3,181
Записей в блоге: 4
13.12.2023, 19:24
Цитата Сообщение от Teamur Посмотреть сообщение
Дескриптор согласно этому ?
не знаю точно.
по ссылке вики пишут одно, а в доках приводится другой формат.
поэтому нужно тестить.

Добавлено через 13 минут
..и статус подаёшь неверно.
сначала нужно отправить ACKNOWLEDGE + DRIVER, в результате чего хост будет ждать от тебя настроек. Далее определяешь функции, первый адрес, потом второй, и только в конце DRIVER_OK. Иначе хост проигнорирует твои настройки, т.к. не будет знать, где начало, а где конец.
2
 Аватар для Teamur
29 / 29 / 5
Регистрация: 06.01.2015
Сообщений: 336
13.12.2023, 20:45  [ТС]
R71MT, по поводу структуры дескриптора. Я собираюсь использовать спецификацию virtio 1.2

https://docs.oasis-open.org/vi... #x1-350007

ой, это вроде устаревший формат


Про акноледж, я в примере забыл указать, у меня перед выложенным кодом есть

Assembler
1
2
3
4
5
6
7
8
9
; Сообщаем о наличии драйвера NIC
mov  dx,[BAR0]   ; номер порта в DX = С060h
add  dx,12h      ; к регистру статуса = C072h
mov  al,0        ; Device_reset=0
out  dx,al       ; Reset!
inc  al          ; Acknowledge=1
out  dx,al       ; 
mov  al,3        ; Driver=2( ACKNOWLEDGE + DRIVER )
out  dx,al       ;
Добавлено через 49 минут
2.8.13 Формат дескриптора Virtqueue
AVAIL дескриптор относится к буферам, которые драйвер отправляет на устройство. addr - это физический адрес, а дескриптор идентифицируется с буфером с помощью поля id.
структура

C
1
2
3
4
5
6
virtq_desc {
    Адрес буфера: 64 бит
    Длина буфера: 32 бит
    Идентификатор буфера: 16 бит
    Флаги в зависимости от типа дескриптора: 16 бит
}
И как же я буду задавать 64 битный адрес? Но наверное это просто они привели максимальное значение

Какие-то цепочки, буфферы-подбуферы

Добавлено через 26 минут
R71MT, вот такая сказка на ночь
---------------------------------------------------------------------------
Есть 2 коробки: буфер отправки и буфер приёма
Известны места их нахождения ( адреса )

1) Отправка
ОС кладёт данные ( орешки = байты текста ) в коробку отправки

ОС говорит (уведомление) почтальону ( сетевой контролер ) : вон там (адрес) из коробки ( буфер отправки ) возьми орешки ( отправляемые байты ) и отнеси получателю

Почтальон относит и говорит ОС (уведомляет): "Я отнёс !"

2) Получение
Почтальон приносит шишки ( входящие байты ) и относит к месту (адрес), где лежит коробка ( буфер приёма ), кладёт и говорит (уведомляет) ОС: "Принёс шишки !"
ОС забирает шишки
-----------------------------------------------------------------------------

Спрашивается, почему нигде в сети нет такой простоты. Как-будто изучающие ОСдев изначально профессионалы.
И тут начинается: "Структуры, кольца, очереди, цепочки, ..."

А должны быть коробки и адреса
0
Эксперт Hardware
Эксперт Hardware
 Аватар для R71MT
6215 / 2449 / 403
Регистрация: 29.07.2014
Сообщений: 3,181
Записей в блоге: 4
13.12.2023, 20:53
Цитата Сообщение от Teamur Посмотреть сообщение
Спрашивается, почему нигде в сети нет такой простоты. Как-будто изучающие ОСдев изначально профессионалы.
потому, что ос не пишут новички - у тебя должна быть хоть какая-то база.

Цитата Сообщение от Teamur Посмотреть сообщение
Я собираюсь использовать спецификацию virtio 1.2
блин я ещё прошлый раз говорил, что нужно читать старую доку "DRAFT" (черновик).
в новой всё перемешано, и трудно будет отфильтровать в ней то, что нужно тебе - там в основном для девайса в режиме Modern, а у тебя Legacy (Transitional, переходное). Вот фрагменты из неё:

Кликните здесь для просмотра всего текста


2.3 Конфигурация виртуальной очереди
Поскольку устройство может иметь ноль и более очередей для массовой передачи данных (например, у сетевого драйвера их 2), драйверу необходимо настроить их как часть конфигурации, специфичной для устройства. Это делается следующим образом, для каждой виртуальной очереди устройства:

1. Запишите индекс очереди (первая равна 0) в поле выбора очереди.
2. Считайте её размер из поля «QueueSize», которое всегда степень 2. Если размер равно 0, очереди не существует.
3. Выделите и обнулите очередь в непрерывной физ.памяти с выравниванием на 4096 байт. Запишите физ.адрес разделенный на 4096, в поле "QueueAddress".
4. Если на устройстве вкл MSI-X, выберите вектор, который будет использоваться для запроса прерываний, инициируемых событиями очереди. Запишите номер записи таблицы MSI-X соответствующий этому вектору, в поле "QueueVector". Чтение поля вектора очереди: в случае успеха возвращается ранее записанное значение; в случае ошибки возвращается значение NO_VECTOR.

2.3.2 Таблица дескрипторов
Таблица дескрипторов относится к буферам, которые гость использует для устройства. Адреса являются физическими, а буферы можно объединять в цепочку через поле next. Каждый дескриптор описывает буфер, который доступен только для чтения(R) или только для записи(W), но цепочка дескрипторов может содержать смешанные буферы R/W. Цепочки дескрипторов не могут иметь общую длину более 2^32 байт. Кол-во дескрипторов в таблице задается полем "QueueSize" для данной вирт.очереди.

Assembler
1
2
3
4
5
6
7
8
9
10
11
struct VIRTQ_DESC
   addr       dq  0   ; Адрес буфера (гостевой)
   len        dd  0   ; Его длина
   flags      dw  0   ; Указанные ниже флаги
   next       dw  0   ; Следущее поле, если флаг = NEXT
ends
 
#define flags
VRING_DESC_F_NEXT     = 1  ; Это помечает буфер как продолжение через следующее поле.
VRING_DESC_F_WRITE    = 2  ; Буфер только для записи (в противном случае только для чтения).
VRING_DESC_F_INDIRECT = 4  ; Это означает, что буфер содержит список дескрипторов буфера.
2.3.4 Доступное кольцо (Available) - драйвер
Доступное кольцо относится к тому, какие дескрипторы мы предлагаем устройству: оно относится к главе цепочки дескрипторов. Поле flags на данный момент равно 0/1: 1 указывает на то, что нам не нужно прерывание, когда устройство потребляет дескриптор из доступного кольца.

Assembler
1
2
3
4
5
6
struct VIRTQ_AVAIL
   flags        dw  0   ;
   idx          dw  0   ;
   ring         dw  0   ; VIRTQ_DESC.len  (Queue Size)
   used_event   dw  0   ; только если VIRTIO_F_EVENT_IDX
ends
Поле idx начинается с 0 и указывает, куда мы поместим следующую запись дескриптора (по модулю размера кольца).
В качестве альтернативы гость может попросить устройство задержать прерывания до тех пор, пока запись с индексом, указанным полем Used_event, не будет записана в используемое кольцо (эквивалентно, пока поле idx в используемом кольце не достигнет значения Used_event +1). Метод, используемый устройством, контролируется битом функции VIRTIO_RING_F_EVENT_IDX (см.3). Это подавление прерываний является всего лишь оптимизацией; он не может полностью подавлять прерывания.

2.3.5 Использованное кольцо (Used) - устройство
В использованное кольцо устройство возвращает индексы буферов после того, как с ними покончено.
Поле flags может использоваться устройством чтобы указать, что уведомление не требуется, когда гость добавляется к доступному кольцу.

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
struct VIRTQ_USED_ELEM_RING
   avail_event  dw  0    ; только если VIRTIO_F_EVENT_IDX
ends
struct VIRTQ_USED_ELEM
   id           dd  0    ; Индекс начала используемой цепочки дескрипторов
   len          dd  0    ; Общая длина использованной (записанной) цепочки дескрипторов
ends
struct VIRTQ_USED
   flags        dw  0    ;
   idx          dw  0    ;
   vuer         VIRTQ_USED_ELEM_RING
   vue          VIRTQ_USED_ELEM
ends
Каждая запись в кольце представляет собой пару: головная запись цепочки дескрипторов, описывающей буфер (она соответствует записи, размещенной в доступном кольце гостем ранее), и общее количество байтов, записанных в буфер. Последнее чрезвычайно полезно для гостей, использующих ненадежные буферы: если вы не знаете точно, сколько записано устройством, обычно приходится обнулять буфер, чтобы исключить утечку данных.

2.4 Работа устройства
Работа устройства состоит из двух частей: подача новых буферов в устройство, и обработка использованных буферов из устройства. Например, сетевое устройство virtio имеет 2 очереди: очередь передачи и очередь приема.

Драйвер добавляет исходящие пакеты (только для чтения) в вирт.очередь передачи, а затем освобождает их после использования. Аналогичным образом, входящие буферы (только для записи) добавляются в очередь приема и обрабатываются после их использования.

2.4.1 Подача буферов в устройство
Реальная передача буферов из гостевой ОС на устройство происходит следующим образом:

1. Поместите буфер(ы) в свободный дескриптор(ы).
Если свободных дескрипторов нет, гость может уведомить устройство, даже если уведомления подавлены (чтобы уменьшить задержку).
2. Поместите идентификатор буфера в следующую запись доступного кольца.
3. Шаги (1) и (2) можно выполнять повторно, если возможно группирование.
4. Необходимо выполнить барьер памяти, чтобы гарантировать, что устройство видит обновленную таблицу дескрипторов и доступное кольцо перед следующим шагом.
5. Доступное поле idx должно быть увеличено на количество записей, добавленных в доступное кольцо.
6. Необходимо выполнить барьер памяти, чтобы гарантировать обновление поля idx перед проверкой подавления уведомлений.
7. Если уведомления не подавлены, устройство должно получать уведомления о новых буферах.

Обратите внимание, что приведенный выше код не принимает меры предосторожности против обхода доступного кольцевого буфера: это невозможно, поскольку кольцевой буфер имеет тот же размер, что и таблица дескрипторов, поэтому шаг (1) предотвратит такую ситуацию. Кроме того, максимальный размер очереди составляет 32768 (он должен быть степенью 2, что соответствует 16 битам), поэтому 16-битное значение idx всегда позволяет отличить полный и пустой буфер. Вот описание каждого этапа более подробно.

2.4.1.1 Размещение буферов в таблице дескрипторов
Буфер состоит из нуля или более физически смежных элементов только для чтения, за которыми следуют ноль или более физически смежных элементов только для записи (в нем должен быть хотя бы один элемент). Этот алгоритм отображает его в таблицу дескрипторов:

1. для каждого буферного элемента, b:
(a) Получить следующую свободную запись таблицы дескрипторов, d
(b) Установите d.addr в физический адрес начала b
(c) Установите d.len равным длине b.
(d) Если b доступен только для записи, установите для d.flags значение VRING_DESC_F_WRITE, в противном случае — 0.
(e) Если после этого есть элемент буфера:
- Установите d.next в индекс следующего свободного элемента дескриптора.
- Установите бит VRING_DESC_F_NEXT в d.flags.

На практике поля d.next обычно используются для связывания свободных дескрипторов, а перед началом сопоставления ведется отдельный счетчик для проверки наличия достаточного количества свободных дескрипторов.

2.4.1.3 Обновление индексного поля
Как только поле idx виртуальной очереди будет обновлено, устройство сможет получить доступ к созданным нами записям дескриптора и памяти, к которой они относятся. Вот почему перед обновлением idx обычно используется барьер памяти, чтобы гарантировать, что он видит самую последнюю копию. Поле idx всегда увеличивается, и мы позволяем ему автоматически переноситься на 65536.
2
 Аватар для Teamur
29 / 29 / 5
Регистрация: 06.01.2015
Сообщений: 336
14.12.2023, 09:44  [ТС]
R71MT, здравствуйте.

А надо ли будет делать бесконечный цикл для того, чтобы проверять наличие входящего трафика?

И надо будет проверять QUEUE_NOTIFY ?

Или просто проверять буферы на изменения, наличие данных?

Добавлено через 27 минут
Каким образом в памяти представлено кольцо?

Скажем есть 8 сегментов кольца, в последнем сегменте должен быть указатель на первый сегмент?
0
Эксперт Hardware
Эксперт Hardware
 Аватар для R71MT
6215 / 2449 / 403
Регистрация: 29.07.2014
Сообщений: 3,181
Записей в блоге: 4
14.12.2023, 11:33
Цитата Сообщение от Teamur Посмотреть сообщение
А надо ли будет делать бесконечный цикл для того, чтобы проверять наличие входящего трафика?
Надо.

Цитата Сообщение от Teamur Посмотреть сообщение
Каким образом в памяти представлено кольцо?
В виде массива структур "VIRTQ_DESC" (дескрипторы) - кол-во этих структур лежит в поле "QueueSize" порта.

Цитата Сообщение от Teamur Посмотреть сообщение
Скажем есть 8 сегментов кольца, в последнем сегменте должен быть указатель на первый сегмент?
Нет.
Поле "idx" в структуре Avail хранит индекс сл.дескриптора в кольце, т.е. idx всегда = текущий +1.
В поле "QueueSize" хост записывает значение кратно(2) так, что при достижении макс.значения, "idx" опять сбрасывается в нуль, превращая очередь в кольцо. Например, если размер кольца в поле "QueueSize" равен 256 структур "VIRTQ_DESC" (0x100 как у тебя), то "idx=1" в Avail будет ссылаться на тот-же дескриптор, что и "idx=257, 513" и т.д. Таким образом, любое значение в поле "idx" всегда будет действительным, заворачиваясь в кольцо Ring.

Цитата Сообщение от Teamur Посмотреть сообщение
И надо будет проверять QUEUE_NOTIFY ?
Или просто проверять буферы на изменения, наличие данных?
Оповещения могут быть настроены или через прерывания MSI-X, или через флаг "Event" структуры "Avail" (Used тоже имеет этот флаг). Но для этого должна быть согласована функция "VIRTIO_RING_F_EVENT_IDX" бит(30). Теперь хост будет чекать флаг в "Avail", а ты в "Used".
2
 Аватар для Teamur
29 / 29 / 5
Регистрация: 06.01.2015
Сообщений: 336
15.12.2023, 07:51  [ТС]
R71MT, здравствуйте

Assembler
1
addr       dq  0   ; Адрес буфера (гостевой)
но в Unreal Mode максимум 32-битная адресация, значит я не смогу обратиться к 64-битному адресу дескриптора?
0
Эксперт Hardware
Эксперт Hardware
 Аватар для R71MT
6215 / 2449 / 403
Регистрация: 29.07.2014
Сообщений: 3,181
Записей в блоге: 4
15.12.2023, 08:45
Цитата Сообщение от Teamur Посмотреть сообщение
значит я не смогу обратиться к 64-битному адресу дескриптора?
так это просто поле в структуре 64-битное,
а ты можешь записывать в него хоть 16, хоть 32-битный адрес.

Вот попробуй загрузить на сервер этот образ флопа..
Здесь номер диска в DL сохраняется, поэтому если причина была в этом, должен отработать исправно. Адреса буферов 0х00120000 и 0х00130000, а маска функций 0x400FCCA3. Он выводит дамп регионов свободной памяти в системе, поэтому задай в батнике минимум 512 МБ для ОЗУ, а не как у тебя сейчас 12 МБ.
Вложения
Тип файла: zip VirtioNet.zip (2.6 Кб, 3 просмотров)
2
 Аватар для Teamur
29 / 29 / 5
Регистрация: 06.01.2015
Сообщений: 336
15.12.2023, 08:49  [ТС]
Можно ли реализовать сначала IN (RECEIVE) очередь, опустив OUT (TRANSMIT), тк нечего и некуда передавать данные ?

Для начала я хочу просто послушать сеть и вывести N байтов в консоль, нап 128 байтов

Вот так я настраиваю дескриптор и кольцо RING_USED, которое будет заполнять NIC
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
; IN_DESCRIPTOR ( один дескриптор = одно звено -> нет цепочки дескрипторов )
mov eax, [IN_QUEUE_ADDR]     ; EAX = 00100000h
add eax, 64                  ; пропуск 8 Б, адрес Q_desc_addr 1 дескриптора
mov dword[eax], 128          ; 4 Б, кладу размер буфера Q_desc_len
add eax, 4                   ; -> к полю Q_desc_flags
mov word[eax], 4             ; 2 Б, RING_DESC_F_INDIRECT = 4, для чтения трафика
add eax, 2                   ; -> к полю Q_desc_next
add eax, 2                   ; 2 Б, пропускаю, тк там всё равно нули = только один дескриптор
 
; RING_USED - Используемое Кольцо ( NIC )
add eax, 2            ; 2 Б, пропускаю avail_ring_flags
add eax, 2            ; 2 Б, пропускаю avail_ring_idx, тк индекс первого дескриптора - 0
mov word[eax], 256    ; 2 Б, размер кольца = 256 дескрипторов (записей)
add eax, 2            ; -> к полю avail_event
add eax, 2            ; 2 Б, пропуск, тк там 0
Также для наглядности:
https://docs.rs/crate/virtio-queue/latest
0
Эксперт Hardware
Эксперт Hardware
 Аватар для R71MT
6215 / 2449 / 403
Регистрация: 29.07.2014
Сообщений: 3,181
Записей в блоге: 4
15.12.2023, 10:16
Цитата Сообщение от Teamur Посмотреть сообщение
Можно ли реализовать сначала IN (RECEIVE) очередь,
можно
Цитата Сообщение от Teamur Посмотреть сообщение
Вот так я настраиваю дескриптор и кольцо RING_USED
абсолютное непонимание темы - это не будет работать.
• во-первых к области буферов нужно обращаться через UnrealMode и регистр fs,
• во-вторых буфер, который определяем в порту, это не буфер приёма/передачи данных,
• в третьих нужно заполнять весь массив дескрипторов, в конце которого хост рассчитывает найти Avail,
• в четвёртых линк выше вообще не имеет отношения к текущей задачи,
ну и далее в том-же духе..
2
 Аватар для Teamur
29 / 29 / 5
Регистрация: 06.01.2015
Сообщений: 336
15.12.2023, 11:57  [ТС]
R71MT, тем временем на сервере ваш образ сработал:
Миниатюры
x64 Сервер  
0
 Аватар для Teamur
29 / 29 / 5
Регистрация: 06.01.2015
Сообщений: 336
15.12.2023, 12:37  [ТС]
Цитата Сообщение от R71MT Посмотреть сообщение
заполнять весь массив дескрипторов
если в первом дескрипторе будет адрес буфера с данными и размер,

то в остальных 255 дескрипторах эти поля будут пустыми?
0
Эксперт Hardware
Эксперт Hardware
 Аватар для R71MT
6215 / 2449 / 403
Регистрация: 29.07.2014
Сообщений: 3,181
Записей в блоге: 4
15.12.2023, 14:03
Цитата Сообщение от Teamur Посмотреть сообщение
то в остальных 255 дескрипторах эти поля будут пустыми?
да.. поскольку это тупо резерв под дескрипторы.

В общих чертах схема там примерно следующая:

1. Сначала определяем первый QueueAddress = 0х00120000, после чего считываем с порта регистр QueueSize = 0х0100. На самом деле это не размер "Size", а кол-во выделенных тебе дескрипторов (здесь 256 штук). Если размер одного дескриптора 16-байт (см.структуру VIRTQ_DESC), а всего дескрипторов 256, то под всю очередь "Queue" потребуется 4 КБ памяти, адрес которой мы и передали хосту в виде QueueAddress = 0х00120000. На этапе настройки очереди, эту область памяти обязательно нужно забить нулями!

2. В дескрипторах ты указываешь уже адрес/размер буфера данных, а в поле "Flag" двоичной маской определяешь тип буфера - для чтения(0000b), или для записи(0010b). Поскольку ты просто ждёшь от хоста данные, то указываешь "запись". Второй QueueAddress = 0х00130000 в порту можно использовать уже под буфер приёма данных, указав его в 64-битном поле "Addr" дескриптора.

3. Согласно спеке хост знает, что после очереди Queue должна располагаться структура "AVAIL", которая хосту доступна только для чтения, а тебе для записи. В этой Avail указываешь, какой из 256 дескрипторов активен на данный момент, указывая его индекс в поле "Idx".

4. После структуры "Avail", в памяти распологается структура "Used", которая доступна теперь хосту на запись, а тебе только на чтение. Однако в спеке говорится, что "Used" должна быть выровнена на 4КБ границу в памяти, поэтому между Avail и Used должна быть пустая область размером 4КБ - sizeof.Avail (т.е. размер Avail).

5. После того-как заполнишь Avail, хосту нужно послать оповещение. Вообще-то для этого имеется поле "Event" в структурах Avail/Used, но почему-то в образе выше твой хост проигнорировал согласование функции "VIRTIO_F_EVENT_IDX", а без неё фишка с оповещением через структуры не сработает. Да и вся маска функций совсем другая - я требовал 0x400FCCA3, а хост оставил только 0х00003821. Вот с этим нужно будет разобраться. Возможно согласование функций это операция NOT со-значением хоста - хз.

6. По логу твоего хоста видно, что у тебя есть ~1ГБ свободной памяти, о чём свидетельствует 0х3FED8000 в карте памяти.
2
 Аватар для Teamur
29 / 29 / 5
Регистрация: 06.01.2015
Сообщений: 336
15.12.2023, 18:08  [ТС]
Добавлено через 3 минуты
А вот эти 256 дескрипторов образуют цепь и надо в поле next ссылаться на следующий дескриптор?

Добавлено через 11 минут
У следующих за первым дескриптором будет так? :
Assembler
1
2
3
4
Q_desc_addr   dq 0   ; 8 Б, адрес буфера
Q_desc_len    dd 0   ; 4 Б, размер буфера
Q_desc_flags  dw 2   ; 2 Б, флаги    ( 2 - для записи )
Q_desc_next   dw 0   ; 2 Б
Добавлено через 12 минут
Цитата Сообщение от R71MT Посмотреть сообщение
проигнорировал согласование функции "VIRTIO_F_EVENT_IDX", а без неё фишка с оповещением через структуры не сработает
а вообще какой толк в этих оповещениях со стороны хоста, если драйверу всё равно придётся бесконечным циклом проверять пришли ли данные, есть ли изменения в области памяти, куда хост будет класть входящие данные ?

Ведь ОС не может же волшебным образом узнать есть ли обновления, неужели хост может этими оповещениями пробуждать ОС и она вдруг узнаёт.

Я так понимаю в ОС невозможно что-то отслеживать в реальном времени без циклов, верно?
0
Эксперт Hardware
Эксперт Hardware
 Аватар для R71MT
6215 / 2449 / 403
Регистрация: 29.07.2014
Сообщений: 3,181
Записей в блоге: 4
15.12.2023, 19:48
Цитата Сообщение от Teamur Посмотреть сообщение
и надо в поле next ссылаться на следующий дескриптор?
next используешь, когда тебе мало одного буфера - тогда связываешь 2 буфа в цепочку.
тебе это не нужно..

Цитата Сообщение от Teamur Посмотреть сообщение
У следующих за первым дескриптором будет так?
флаг RW зависит от того, передаёшь ты буфер хосту (read), или ожидаешь от него (write).

Цитата Сообщение от Teamur Посмотреть сообщение
а вообще какой толк в этих оповещениях со стороны хоста
ну так никто не заставляет тебя использовать их - хочешь проверяй в ручную.
только что ты собираешься там чекать? тебе-же не константы будут прилетать, а рандом данных.
2
 Аватар для Teamur
29 / 29 / 5
Регистрация: 06.01.2015
Сообщений: 336
15.12.2023, 20:22  [ТС]
Цитата Сообщение от R71MT Посмотреть сообщение
только что ты собираешься там чекать?
хоть с оповещениями хоть без в любом случае там может быть что угодно, нап 8 байт тела запроса, 3 байт заголовка, 76 байт POST-запроса с картинкой и тп.

Надо же в любом случае парсить и определять где начало запроса, где полезная нагрузка и тп

Или когда хост делает оповещение драйверу он указывает где начало Ethernet-пакета ?

В чем плюсы оповещений хоста о наличии входящего трафика, помогает снижать нагрузку ?

Если да, то я только за, но хост, как вы уже сказали, сопротивляется включению уведомлений
0
Эксперт Hardware
Эксперт Hardware
 Аватар для R71MT
6215 / 2449 / 403
Регистрация: 29.07.2014
Сообщений: 3,181
Записей в блоге: 4
16.12.2023, 09:09
Цитата Сообщение от Teamur Посмотреть сообщение
В чем плюсы оповещений хоста
Хосту плевать, какие там данные, и заголовки он не парсит.
В твою структуру USED он просто сбрасывает пару значений - это номер освободившегося дескриптора, и кол-во записанных/прочитанных байт. Для сл.дескриптора он отчитается опять такой-же парой, и т.д. Это поможет тебе найти хотя-бы начало и конец данных, а вытягивать из общей кучи полезную инфу (вырезав заголовок и прочее) ты уже должен сам.

Когда поток данных большой, тебе просто необходимы будут оповещения, иначе ты тупо потеряешься во-входящей инфе. Обработчики прерываний здесь неудобны тем, что работают долго, и пока ты отреагируешь на одно прерывание, тебе поступит ещё куча инфы. Поэтому и ввели "ивенты" в Avail/Used, чтобы сократить время оповещений - это намного удобней, чем int или msi-x. В доке Draft можно найти такое описание очереди:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
struct  DESCRIPTORS     ; [QueueSize]
   Address     dq  0    ; 64-битный адрес буфера
   Length      dd  0    ; 32-битный его размер
   Flags       dw  0    ; 0001b = Next, 0010b = Write, 0100b = Indirect (тебе не нужен)
   Next        dw  0    ; Если флаг Next=1, индекс сл.дескриптора
ends
 
struct  AVAILABLE
   Flags       dw  0           ; 1= Прерывания не нужны
   Idx         dw  0           ; Индекс сл.дескриптора
   Ring        dw  [QueueSize] ; Список индексов активных дескрипторов
   UsedEvent   dw  0           ; Оповещение, если "VIRTIO_F_EVENT_IDX" согласован
ends
 
struct  USED
   Flags       dw  0           ; 1= Оповещения не нужны
   Idx         dw  0           ; Индекс сл.дескриптора
      struct  RING [QueueSize]
         Index    dw  0        ; Индекс освободившегося дескриптора
         Length   dd  0        ; Кол-во записаных/прочитанных байт
      ends
   AvailEvent  dw  0           ; Оповещение, если "VIRTIO_F_EVENT_IDX" согласован
ends
 
;*****************************************
; Теперь вся очередь имеет такой формат 
;*****************************************
 
struct  VIRTUAL_QUEUE
   desc       DESCRIPTORS   ; массив дескрипторов (кол-во = QueueSize)
   avail      AVAILABLE     ; структура AVAIL
   padding    db  ?         ; (!) выравнивание на 4096 байт границу
   used       USED          ; структура USED
ends
Ring в структуре Avail - это просто массив 16-битных значений (кол-во вордов указывает QueueSize). А кольцо Ring в Used - это уже пары значений. Сама-же вирт.очередь в хвосте включает в себя сначала весь массив дескрипторов, затем сразу вложенную структуру "Avail", потом байты выравнивания, и завершает очередь структура "Used". Вот скрин с пояснением алго работы VirtioNet очереди:
Миниатюры
x64 Сервер  
2
 Аватар для Teamur
29 / 29 / 5
Регистрация: 06.01.2015
Сообщений: 336
16.12.2023, 14:48  [ТС]
R71MT, спасибо за подробные разъяснения.

Завтра я попробую выложить что-то толковое, без вас я бы возился полгода
0
 Аватар для Teamur
29 / 29 / 5
Регистрация: 06.01.2015
Сообщений: 336
17.12.2023, 09:03  [ТС]
R71MT, правильно ли сейчас я заполняю 1-й дескриптор IN очереди ?

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
jmp SetDesc_1
 
 IN_QUEUE_ADDR dd 0x00120000   ; Адрес IN  очереди
OUT_QUEUE_ADDR dd 0x00130000   ; Адрес OUT очереди
 
   IN_BUF_ADDR dw 0x9000  ; место в памяти куда NIC будет класть байты
   IN_BUF_SIZE dw 128     ; кол-во байтов, которые хочу получить от NIC
 
   BUF_F_WRITE dw 2              ; 0010b Флаг разрешает запись в буфер
   NO_NEXT_BUF dw 0              ; Буфер не продолжается в след дескрипторе
 
SetDesc_1:                       ; 16 Б
mov eax, IN_QUEUE_ADDR
mov word[FS:eax], IN_BUF_ADDR    ; адрес буфера
add eax, 8                       ; 8 Б поле
mov word[FS:eax], IN_BUF_SIZE    ; размер буфера
add eax, 4                       ; 4 Б
mov word[FS:eax], BUF_F_WRITE    ; флаг записи
add eax, 2                       ; 2 Б
mov word[FS:eax], NO_NEXT_BUF    ; пустое поле NEXT
add eax, 2                       ; 1-й дескриптор заполнен
Добавлено через 9 минут
Цитата Сообщение от R71MT Посмотреть сообщение
0х00120000. На этапе настройки очереди, эту область памяти обязательно нужно забить нулями!
а разве изначально там не нули?
Наверное при включении ПК в оперативке всегда рандомные данные

Добавлено через 10 минут
Цитата Сообщение от R71MT Посмотреть сообщение
к области буферов нужно обращаться через UnrealMode и регистр fs
ОС сейчас в Unreal Mode, почему именно регистр FS, ведь можно записывать по адресу так
Assembler
1
mov dword[address], value
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
17.12.2023, 09:03

Сервер HP Primergy Econel 200 S2, Win2008R2 x64, RAID10 4x2000Gb падает скорость чтения/записи по сети
Здравствуйте. Подскажите, пожалуйста, в чем может быть проблема: Сервер бэкапов HP Primergy Econel 200 S2 Встроенный SATA RAID...

Linux Mint 20 x64, Firefox 79 x64. Отключить замыливание текста
Поставил Linux Mint 20, отключил сглаживание шрифтов, поставил шрифты от Windows XP, все хорошо, все нравится. Только в Firefox остался...

HP Pavilion g7 - 2160er переустановил Windows HP x64 на Ultimate x64 - проблема с подсветкой монитора
HP Pavilion g7 - 2160er переустановил windows home premium x64 на Ultimate x64/ Стала выеживаться подсветка монитора - хочет работает,...

Нестандартная ситуация, установка еще одной w7 x64 на уже установленный комп с w7 x64
Всем доброго времени суток ! Не совсем стандартная ситуация, которая посадила меня на гвоздь в позе "шпагат" ))) Есть машинка...

Ищу обновления KB938397-x64 и KB968730-x64 для Windows Server 2003x64
Господа плиз ХЕЛП! Ищем обновы KB938397x64 и KB968730x64 для Windows Server 2003x64 RUS, а то сволочной сервер 1С не видит интеренет. ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
180
Ответ Создать тему
Новые блоги и статьи
сукцессия 43. Вторая научная статья за месяц- прайминг и гатгил
anaschu 25.07.2026
две стороны одной монеты
Более приземисто - Эстафету хвоста в .cdl (деревья эстафеты в сад).
Hrethgir 24.07.2026
В будущем, после написания блока инверсии обхода дерева (эстафеты хвоста), я планирую вернуться к нашему прошлому разговору о том, обладают ли знания целеполаганием. Тогда я пришел к выводу, что. . .
Вот представьте что вам дали бессмертие.
kumehtar 24.07.2026
Вот представьте что вам дали бессмертие, ничего более не меняя. Вообще ничего, только бессмертие в нынешнем виде. Рады были бы? Что бы вы тут делали всё это время? Никакой пенсии. Никакого нового. . .
сукцессия 41
anaschu 24.07.2026
Численная верификация бифуркации в агентной модели лесной сукцессии: от одного параметра к ансамблю Автор: пользователь @Shumilov_AS | Раздел: Прикладная математика / Численные методы Кратко. . .
сукцессия 40. Ансамблевая кластерная параметризаци, часть 1.
anaschu 24.07.2026
Пр# Сопровождение научной статьи ИИ-ассистентом: подготовка публикации и калибровка агентно-ориентированной модели сукцессии микоризных систем **Полевые заметки о двухнедельной совместной работе**. . .
Теория всего 12. ВГК на планете в стратегической игре "терра"
anaschu 21.07.2026
### Главные семантические изменения и дешифровка новой физики 1. **`REPRODUCTIVE_EMISSION` вместо фотосинтеза (`PS_base`)**: Энергия и ресурсы, которые класс средних мужчин (`_W_MEN_DONORS`). . .
Публикация отклонённая на хабре. Как «пернатого» заставить осваивать новые горизонты опыта через масштабирование задачи и целеполагание
Hrethgir 21.07.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11948&stc=1&d=1784657928 Привет Хабр. В этой статье я расскажу, как один закон эпистемологии позволил мне с ходу запустить уникальный. . .
Теория всего 11. Основные параметры
anaschu 21.07.2026
Дешифровка тензорного ядра Soil Chemistry 2. 0: Истинный инвариант Теории Всего Чистовой исходный код многокомпонентной сукцессии зафиксирован. Модель оперирует единым вектором состояния. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru