Ядро OS X pani c при попытке доступа к регистру отображения памяти PCI - PullRequest
0 голосов
/ 10 апреля 2020

код, на который я ссылаюсь, это здесь

когда я создаю отображение памяти для pcidevice, я всегда получаю одно и то же значение для getPhysicalAddress и getVirtualAddress: например,

pciDevice = OSDynamicCast(IOPCIDevice, provider);
deviceMap = pciDevice->mapDeviceMemoryWithRegister(kIOPCIConfigBaseAddress0);

deviceRegisters = (struct oxygen *)  deviceMap->getVirtualAddress();
pciDevice->setMemoryEnable(true);
pciDevice->setBusMasterEnable(true);
deviceMap->getPhysicalAddress();

Теперь, на самом деле, я не слишком удивлен этим, потому что я думаю, что это точка "DMA".

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

верно ли это понимание?

теперь по основной проблеме: я испытываю панику ядра, вызванную любым доступом или назначением членов deviceRegisters Например,

kprintf("Xonar Vendor ID:0x%04x, Device ID:0x%04x, SubDevice ID:0x%04x, Physical Address:%lu\n",
       vendor_id, dev_id, subdev_id, deviceRegisters->addr);

, что говорит мне о том, что я делаю что-то не так с точки зрения распределения, так как доступ к членам этой структуры не должен вызывать пани c.

, однако, если вы смотрите здесь листинг 3-2: https://developer.apple.com/library/archive/documentation/DeviceDrivers/Conceptual/WritingAudioDrivers/ImplementDriver/ImplementDriver.html# // apple_ref / doc / uid / TP30000732-DontLinkElementID_15

именно так и должно быть.

мудрец (pmj) предположил, что я должен использовать функции ioRead / Write для назначения / доступа к этим значениям, но это на самом деле не согласуется с (по общему признанию) скелетным кодом, предоставленным Apple. что может вызвать проблемы с доступом к этому отображению памяти? конечно, необходимость делать арифметику указателя c для назначения / чтения значений, хотя, возможно, и правильная, не является ли целью этого проекта?

1 Ответ

1 голос
/ 12 апреля 2020

когда я создаю отображение памяти для pcidevice, я всегда получаю одно и то же значение для getPhysicalAddress и getVirtualAddress: например,

Являются ли значения случайно в диапазоне 0x0..0xffff ?

Я очень сильно подозреваю, что это диапазон ввода-вывода в вашем PCI-устройстве , а не диапазон памяти.

Способ проверки это в вашем коде:

if (0 != (kIOPCIIOSpace & pciDevice->configRead32(kIOPCIConfigBaseAddress0))
{
    // port mapped range
}
else
{
    // memory mapped range
}

Смотрите также: { ссылка }

Теперь, на самом деле, я не слишком удивлен этим, потому что я думаю, что это точка «DMA».

Нет, сопоставленный с портами ввод-вывод в значительной степени противоположен DMA. Конечно, вы можете использовать сопоставленные с портом входы / выходы, чтобы инициировать передачу DMA, если именно так работает ваше устройство, поэтому, возможно, было бы лучше сформулировать это как ортогональное к DMA.

DMA - это устройства, имеющие прямой доступ системная память. PCI-шины - это регистры или память, которые обращаются к процессору.

Если у нас есть какое-то отображение в драйвере, то все, что нам нужно, это один. то есть физический адрес - это виртуальный адрес, так как это единственное место, где нам нужно выполнить «память в память» (восстановление данных процессора на звуковую карту PCI), верно ли это понимание?

Нет, по крайней мере на x86 адресное пространство порта ввода / вывода полностью отделено от адресного пространства физической памяти и поэтому также не может быть отображено в виртуальное адресное пространство, поскольку MMU выполняет преобразование между виртуальным и физическим памятью пространствами. На x86 есть специальные машинные инструкции, in и out, для чтения и записи с портов ввода / вывода. На большинстве архитектур (для OS X, в частности, PP C, но я думаю, что это также относится и к ARM), существует некоторая форма отображения памяти, однако. Я не знаю, как это работает в деталях на этих архитектурах, но для целей этого вопроса вам не нужно особенно заботиться:

Независимый от архитектуры способ выполнения операций ввода-вывода для порта диапазон отображения в кеше macOS должен использовать методы ioread* и iowrite* для IOPCIDevice, где * может быть 8, 16 или 32 для 3 различных возможных операций ввода-вывода размеры слов, разрешенные стандартом PCI.

Теперь для основной проблемы: я испытываю панику ядра, вызванную любым доступом или назначением членов deviceRegisters, например:

Предполагая, что вы на самом деле имеете дело с диапазоном портов ввода-вывода в вашем устройстве, это объясняет панику ядра. Используйте pciDevice->ioread16(register_offset, deviceMap) или аналогичный.

мудрец (pmj) предложил мне использовать функции ioRead / Write для назначения / доступа к этим значениям, но это на самом деле не сочетается с (по общему признанию, старым) скелетом код, предоставленный Apple.

В документе, на который вы ссылаетесь, предполагается, что BAR устройства относится к диапазону сопоставленной памяти, а не к диапазону ввода-вывода с сопоставлением портов.

...