Strange MemoryDescriptor behavior
Strange MemoryDescriptor behavior
- Subject: Strange MemoryDescriptor behavior
- From: Maxim Zhuravlev <email@hidden>
- Date: Wed, 10 Oct 2012 18:13:39 +0400
Hi, everyone.
I'm observing the following strange situation:
1) I need to get a physical address of a part of my kext's code. I do
it with the following code:
uint64_t
ClassName::virtualAddressToPhysicalAddress(const void* address) {
IOReturn ioresult = kIOReturnSuccess;
uint64_t result;
IOMemoryDescriptor* descriptor =
IOMemoryDescriptor::withAddressRange((mach_vm_address_t)address, 1,
kIODirectionOut,
kernel_task);
if (descriptor == NULL)
return -1;
if ((ioresult = descriptor->prepare()) == kIOReturnSuccess) {
result = getPhysicalAddressForDescriptor(descriptor);
descriptor->complete();
} else {
return -1;
}
descriptor->release();
return result;
}
uint64_t
ClassName::getPhysicalAddressForDescriptor(IOMemoryDescriptor* descriptor)
{
uint64_t address = -1;
IODMACommand* dma = IODMACommand::withSpecification(kIODMACommandOutputHost64,
64,
0,
IODMACommand::kMapped,
0,
1);
if (!dma)
return address;
if (kIOReturnSuccess == dma->setMemoryDescriptor(descriptor))
{
IODMACommand::Segment64 segments[1];
UInt32 numSegments = 1;
UInt64 offset = 0;
if (kIOReturnSuccess == dma->gen64IOVMSegments(&offset, segments,
&numSegments))
address = segments[0].fIOVMAddr;
dma->clearMemoryDescriptor();
}
dma->release();
return address;
}
2) I need to wire a page in kernel task. I do it with the following code:
void*
ClassName::allocatePage(uint64_t* physical_address, bool within4GB) {
void* result = NULL;
IOBufferMemoryDescriptor* descriptor = NULL;
if (within4GB)
descriptor = IOBufferMemoryDescriptor::inTaskWithPhysicalMask(kernel_task,
kIODirectionInOut|
kIOMemoryPhysicallyContiguous|
kIOMemoryKernelUserShared,
page_size,
0x00000000FFFFFFFFull);
else
descriptor = IOBufferMemoryDescriptor::withOptions(
kIODirectionInOut|kIOMemoryPhysicallyContiguous,
page_size, page_size);
if (descriptor == NULL)
return NULL;
descriptor->prepare();
*physical_address = getPhysicalAddressForDescriptor(descriptor);
result = descriptor->getBytesNoCopy();
if (result)
bzero(result, page_size);
return result;
}
3) I need to call those two subsequently. It used to work and return
different physical addresses.
But starting OS X 10.8.2 they may return same physical address.
I.e. allocatePage may return the same physical address as
virtualAddressToPhysicalAddress called for my kext's code address.
I can observe it on latest MacBooks (Mid 2012) with OS X 10.8.2. It
does work on the same machines with OS X 10.8.1 and earlier.
My question is, if I'm doing it wrong from start, or did something
change in the way the latest OS X version work with aforementioned
hardware?
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-kernel mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden