* Refactored _AdaptToReserved() out of Aperture::AllocateMemory(), as it's now

also used in BindMemory() and UnbindMemory() - before the latter two were
  just not working correctly for memory in the reserved region.
* The Aperture destructor now also frees (and unbinds) all still existing
  allocations.
* Aperture::fFirstMemory was not initialized.
* Added some more debug output.
* BindMemory()'s vertical to physical address translation didn't work correctly.
* alignment must be at least B_PAGE_SIZE in _Insert().
* bind_aperture() needs to pass the B_APERTURE_NON_RESERVED flag to
  CreateMemory().


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23774 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-01-28 13:44:13 +00:00
parent 02998a5deb
commit 7e6d23431c

View File

@ -80,7 +80,7 @@ struct aperture_memory : HashTableLink<aperture_memory> {
addr_t base;
size_t size;
uint32 flags;
#ifdef __HAIKU__
#if defined(__HAIKU__) && !defined(GART_TEST)
union {
vm_page **pages;
vm_page *page;
@ -145,8 +145,8 @@ public:
struct lock &Lock() { return fLock; }
private:
bool _AdaptToReserved(addr_t &base, size_t &size, int32 *_offset = NULL);
void _Free(aperture_memory *memory);
void _Remove(aperture_memory *memory);
status_t _Insert(aperture_memory *memory, size_t size, size_t alignment,
uint32 flags);
@ -402,6 +402,7 @@ Aperture::Aperture(agp_gart_bus_module_info *module, void *aperture)
:
fModule(module),
fHashTable(fInfo),
fFirstMemory(NULL),
fPrivateAperture(aperture)
{
fModule->get_aperture_info(fPrivateAperture, &fInfo);
@ -412,6 +413,10 @@ Aperture::Aperture(agp_gart_bus_module_info *module, void *aperture)
Aperture::~Aperture()
{
while (fFirstMemory != NULL) {
DeleteMemory(fFirstMemory);
}
fModule->delete_aperture(fPrivateAperture);
put_module(fModule->info.name);
}
@ -431,6 +436,8 @@ Aperture::GetInfo(aperture_info *info)
void
Aperture::DeleteMemory(aperture_memory *memory)
{
TRACE("delete memory %p\n", memory);
UnbindMemory(memory);
_Free(memory);
_Remove(memory);
@ -453,8 +460,11 @@ Aperture::CreateMemory(size_t size, size_t alignment, uint32 flags)
return NULL;
}
TRACE("create memory %p, base %lx, size %lx, flags %lx\n", memory,
memory->base, memory->size, flags);
memory->flags = flags;
#ifdef __HAIKU__
#if defined(__HAIKU__) && !defined(GART_TEST)
memory->pages = NULL;
#else
memory->area = -1;
@ -465,23 +475,45 @@ Aperture::CreateMemory(size_t size, size_t alignment, uint32 flags)
}
bool
Aperture::_AdaptToReserved(addr_t &base, size_t &size, int32 *_offset)
{
addr_t reservedEnd = fInfo.base + fInfo.reserved_size;
if (reservedEnd <= base)
return false;
if (reservedEnd >= base + size) {
size = 0;
return true;
}
if (_offset != NULL)
*_offset = reservedEnd - base;
size -= reservedEnd - base;
base = reservedEnd;
return true;
}
status_t
Aperture::AllocateMemory(aperture_memory *memory, uint32 flags)
{
// We don't need to allocate stolen memory - it's
// We don't need to allocate reserved memory - it's
// already there for us to use
addr_t reservedEnd = fInfo.base + fInfo.reserved_size;
addr_t base = memory->base;
size_t size = memory->size;
if (reservedEnd > memory->base) {
if (reservedEnd >= memory->base + memory->size)
if (_AdaptToReserved(base, size)) {
if (size == 0) {
TRACE("allocation is made of reserved memory\n");
return B_OK;
}
memset((void *)memory->base, 0, reservedEnd - memory->base);
// TODO: this requires the aperture to be mapped!
size -= reservedEnd - memory->base;
memset((void *)memory->base, 0, memory->size - size);
}
TRACE("allocate %ld bytes out of %ld\n", size, memory->size);
#ifdef __HAIKU__
#if defined(__HAIKU__) && !defined(GART_TEST)
uint32 count = size / B_PAGE_SIZE;
if ((flags & B_APERTURE_NEED_PHYSICAL) != 0) {
@ -527,7 +559,15 @@ Aperture::UnbindMemory(aperture_memory *memory)
if ((memory->flags & BIND_APERTURE) == 0)
return B_BAD_VALUE;
addr_t start = memory->base - Base();
// We must not unbind reserved memory
addr_t base = memory->base;
size_t size = memory->size;
if (_AdaptToReserved(base, size) && size == 0) {
memory->flags &= ~BIND_APERTURE;
return B_OK;
}
addr_t start = base - Base();
for (addr_t offset = 0; offset < memory->size; offset += B_PAGE_SIZE) {
status_t status = fModule->unbind_page(fPrivateAperture, start + offset);
@ -536,36 +576,54 @@ Aperture::UnbindMemory(aperture_memory *memory)
}
memory->flags &= ~BIND_APERTURE;
fModule->flush_tlbs(fPrivateAperture);
return B_OK;
}
status_t
Aperture::BindMemory(aperture_memory *memory, addr_t base, size_t size,
Aperture::BindMemory(aperture_memory *memory, addr_t address, size_t size,
bool physical)
{
addr_t start = memory->base - Base();
// We don't need to bind reserved memory
addr_t base = memory->base;
int32 offset;
if (_AdaptToReserved(base, size, &offset)) {
if (size == 0) {
TRACE("reserved memory already bound\n");
memory->flags |= BIND_APERTURE;
return B_OK;
}
address += offset;
}
addr_t start = base - Base();
TRACE("bind %ld bytes at %lx\n", size, base);
for (addr_t offset = 0; offset < size; offset += B_PAGE_SIZE) {
status_t status;
addr_t address;
addr_t physicalAddress;
if (!physical) {
physical_entry entry;
address = (addr_t)entry.address;
status = get_memory_map((void *)(base + offset), B_PAGE_SIZE,
status = get_memory_map((void *)(address + offset), B_PAGE_SIZE,
&entry, 1);
if (status < B_OK)
return status;
} else
address = base + offset;
status = fModule->bind_page(fPrivateAperture, start + offset, address);
physicalAddress = (addr_t)entry.address;
} else
physicalAddress = address + offset;
status = fModule->bind_page(fPrivateAperture, start + offset,
physicalAddress);
if (status < B_OK)
return status;
}
memory->flags |= BIND_APERTURE;
fModule->flush_tlbs(fPrivateAperture);
return B_OK;
}
@ -576,7 +634,7 @@ Aperture::_Free(aperture_memory *memory)
if ((memory->flags & ALLOCATED_APERTURE) == 0)
return;
#ifdef __HAIKU__
#if defined(__HAIKU__) && !defined(GART_TEST)
// Remove the stolen area from the allocation
size_t size = memory->size;
addr_t reservedEnd = fInfo.base + fInfo.reserved_size;
@ -641,6 +699,9 @@ Aperture::_Insert(aperture_memory *memory, size_t size, size_t alignment,
if (size == 0 || size > fInfo.size)
return B_BAD_VALUE;
if (alignment < B_PAGE_SIZE)
alignment = B_PAGE_SIZE;
addr_t start = fInfo.base;
if ((flags & (B_APERTURE_NON_RESERVED | B_APERTURE_NEED_PHYSICAL)) != 0)
start += fInfo.reserved_size;
@ -689,6 +750,8 @@ Aperture::_Insert(aperture_memory *memory, size_t size, size_t alignment,
// got a spot
foundSpot = true;
memory->base = ROUNDUP(last->base + last->size, alignment);
if (memory->base < start)
memory->base = start;
}
if (!foundSpot)
@ -898,10 +961,10 @@ allocate_memory(aperture_id id, size_t size, size_t alignment, uint32 flags,
if (aperture == NULL)
return B_ENTRY_NOT_FOUND;
Autolock _(aperture->Lock());
size = ROUNDUP(size, B_PAGE_SIZE);
Autolock _(aperture->Lock());
aperture_memory *memory = aperture->CreateMemory(size, alignment, flags);
if (memory == NULL)
return B_NO_MEMORY;
@ -915,7 +978,7 @@ allocate_memory(aperture_id id, size_t size, size_t alignment, uint32 flags,
}
if (_physicalBase != NULL && (flags & B_APERTURE_NEED_PHYSICAL) != 0) {
#ifdef __HAIKU__
#if defined(__HAIKU__) && !defined(GART_TEST)
*_physicalBase = memory->page->physical_page_number * B_PAGE_SIZE;
#else
physical_entry entry;
@ -981,12 +1044,14 @@ bind_aperture(aperture_id id, area_id area, addr_t base, size_t size,
if (aperture == NULL)
return B_ENTRY_NOT_FOUND;
if (size == 0 || size > aperture->Size()
|| (area < 0 && (base & (B_PAGE_SIZE - 1)) != 0)
|| (area < 0 && base == 0))
return B_BAD_VALUE;
if (area < 0) {
if (size == 0 || size > aperture->Size()
|| (base & (B_PAGE_SIZE - 1)) != 0
|| base == 0)
return B_BAD_VALUE;
size = ROUNDUP(size, B_PAGE_SIZE);
size = ROUNDUP(size, B_PAGE_SIZE);
}
if (area >= 0) {
// get base and size from area
@ -1009,7 +1074,8 @@ bind_aperture(aperture_id id, area_id area, addr_t base, size_t size,
return B_BAD_VALUE;
} else {
// create new memory object
memory = aperture->CreateMemory(size, alignment, 0);
memory = aperture->CreateMemory(size, alignment,
B_APERTURE_NON_RESERVED);
if (memory == NULL)
return B_NO_MEMORY;
}