Reputation: 51
The problem is this, under the configuration of Macmini 2018 (OS 10.14.6, intel i7), a pcie kext driver has been developed, and the test is normal. Now trying to run it on a Macbookair 2022 (OS 13.2.1 M2) configuration, There is no field after kextload
,But after performing the DMA operation, it crashes immediately。
The crash log is as follows:
panic(cpu 2 caller 0xfffffe00168523d4): "apciec[pcic1-bridge]::handleInterrupt: Request address is greater than 32 bits linksts=0x99000001 pcielint=0x00220000 linkcdmsts=0x00000800 (ltssm 0x11=L0)\n" @AppleT8103PCIeCPort.cpp:1301
Debugger message: panic
Memory ID: 0x6
OS release type: User
OS version: 22D68
Kernel version: Darwin Kernel Version 22.3.0: Mon Jan 30 20:38:43 PST 2023; root:xnu-8792.81.3~2/RELEASE_ARM64_T8112
Fileset Kernelcache UUID: 7C9F817DCC61EAD876DFC5403368626E
Kernel UUID: 6F3F5CD6-B730-390E-9E53-B9E5B751EBE7
Boot session UUID: 99BF44ED-42BC-4B16-8B29-1BC7E8F1DF22
iBoot version: iBoot-8419.80.7
secure boot?: YES
roots installed: 0
Paniclog version: 14
KernelCache slide: 0x000000000cd8c000
KernelCache base: 0xfffffe0013d90000
Kernel slide: 0x000000000e018000
Kernel text base: 0xfffffe001501c000
Kernel text exec slide: 0x000000000e100000
Kernel text exec base: 0xfffffe0015104000
mach_absolute_time: 0x14c8fbf9a
Epoch Time: sec usec
Boot : 0x64111c5d 0x000dc134
Sleep : 0x00000000 0x00000000
Wake : 0x00000000 0x00000000
Calendar: 0x64111d40 0x000ad586
Checking the kext log, I found that the scatter-gather list generated by using IODMACommand::withSpecification
with the kMapped
parameter is different from what I thought when mapping a large amount of data.
Only one MemDescriptor will be generated under Macmini 2018, but under Macbook Air 2022 will generate multiple.
I think Macmini2018 is right, as long as kMapped is set, IOMMU will be used to convert the discrete physical memory into a virtual memory and give it to the IO device for DMA, but it is not the case under M1/M2.
The following is part of my kext code.This piece of code converts the memory into a scatter-gather list.
cmd = IODMACommand::withSpecification(
// outSegFunc - Host endian since we read the address data with the cpu
// and 64 bit wide quantities
kIODMACommandOutputHost64,
// numAddressBits
64,
// maxSegmentSize - zero for unrestricted physically contiguous chunks
0,
// mappingOptions - kMapped for DMA addresses
IODMACommand::kMapped,
// maxTransferSize - no restriction
0,
// alignment - no restriction
1 );
if (!cmd)
{
IOLog("IODMACommand::withSpecification failed\n");
break;
}
// point at the memory descriptor and use the auto prepare option
// to prepare the entire range
err = cmd->setMemoryDescriptor(memDesc);
if (kIOReturnSuccess != err)
{
IOLog("[%s] : setMemoryDescriptor failed (0x%x)\n", __func__, err);
break;
}
IOLog("[%s] :Flag = 0x%x, Tag = 0x%x\n",__func__, memDesc->getFlags(), memDesc->getTag());
UInt64 offset = 0;
while (offset < memDesc->getLength())
{
IODMACommand::Segment64 segment;
UInt32 numSeg = 1;
if (num > (TRANSFER_MAX_DESC-1))
{
IOLog("xfer_submit: too many numSeg:%d\n", num);
break;
}
err = cmd->gen64IOVMSegments(&offset, &segment, &numSeg);
if (err || numSeg != 1 )
{
IOLog("xfer_submit - could not generate segments err (%p) numSegments (%d) fIOVMAddr (0x%qx) fLength (0x%qx)",
(void*)err, (int)numSeg, segment.fIOVMAddr, segment.fLength);
break;
}
else
{
engine->segments64.fIOVMAddr = segment.fIOVMAddr;
engine->segments64.fLength = segment.fLength;
IOLog("%s::gen64IOVMSegments() addr 0x%qx, len %llu\n",
getName(), segment.fIOVMAddr, segment.fLength);
}
num++;
}
What is the reason for the kext crash? The kext has been designed according to the 64bit method. Why does it still prompt 32bit related exceptions?
Why are the numbers of scatter-gather lists generated by Macmini2018 and Macbook2022 different? Shouldn't only one be generated after using the IOMMU?
How to use IODMACommand::withSpecification
with the parameter kMapped
just to generate a Mem Descriptor How should I modify it, because my kext has not yet implemented the SGDMA function.
Upvotes: 2
Views: 236