mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-08 11:55:24 +00:00
gpu/intel: PPGTT allocation optimization
Use range allocator as cache for page mappings instead of allocating from platform driver for each page table. issue #4380
This commit is contained in:
parent
94405e9280
commit
96ab58691a
@ -447,7 +447,7 @@ struct Igd::Device
|
||||
:
|
||||
ctx (device._env.rm(), alloc, device, CONTEXT::CONTEXT_PAGES, 1 /* omit GuC page */),
|
||||
ring(device._env.rm(), alloc, device, CONTEXT::RING_PAGES, 0),
|
||||
ppgtt_allocator(device._env.rm(), device._pci_backend_alloc),
|
||||
ppgtt_allocator(alloc, device._env.rm(), device._pci_backend_alloc),
|
||||
ppgtt_scratch(device._pci_backend_alloc)
|
||||
{
|
||||
/* PPGTT */
|
||||
@ -1570,8 +1570,16 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
|
||||
Igd::Ggtt::Mapping map { };
|
||||
|
||||
addr_t phys_addr { 0 };
|
||||
size_t size { 0 };
|
||||
|
||||
Buffer(Gpu::Buffer_id id, Genode::Dataspace_capability cap)
|
||||
: id { id }, cap { cap } { }
|
||||
: id { id }, cap { cap }
|
||||
{
|
||||
Dataspace_client buf(cap);
|
||||
phys_addr = buf.phys_addr();
|
||||
size = buf.size();
|
||||
}
|
||||
|
||||
virtual ~Buffer() { }
|
||||
};
|
||||
@ -1592,7 +1600,6 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
|
||||
Genode::uint64_t seqno { 0 };
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -1867,11 +1874,7 @@ class Gpu::Session_component : public Genode::Session_object<Gpu::Session>
|
||||
|
||||
Resource_guard::Reservation reserve = _resource_guard.map_buffer_ppgtt();
|
||||
|
||||
Genode::Dataspace_client buf(buffer.cap);
|
||||
/* XXX check that actual_size matches alloc_buffer size */
|
||||
Genode::size_t const actual_size = buf.size();
|
||||
Genode::addr_t const phys_addr = buf.phys_addr();
|
||||
_vgpu.rcs_map_ppgtt(va, phys_addr, actual_size);
|
||||
_vgpu.rcs_map_ppgtt(va, buffer.phys_addr, buffer.size);
|
||||
buffer.ppgtt_va = va;
|
||||
buffer.ppgtt_va_valid = true;
|
||||
result = OK;
|
||||
|
@ -32,28 +32,46 @@ class Igd::Ppgtt_allocator : public Genode::Translation_table_allocator
|
||||
Genode::Region_map &_rm;
|
||||
Utils::Backend_alloc &_backend;
|
||||
|
||||
enum { ELEMENTS = 256, };
|
||||
enum { ELEMENTS = 128, }; /* max 128M for page tables */
|
||||
Utils::Address_map<ELEMENTS> _map { };
|
||||
|
||||
Genode::Allocator_avl _range;
|
||||
|
||||
public:
|
||||
|
||||
Ppgtt_allocator(Genode::Region_map &rm,
|
||||
Ppgtt_allocator(Genode::Allocator &md_alloc,
|
||||
Genode::Region_map &rm,
|
||||
Utils::Backend_alloc &backend)
|
||||
:
|
||||
_rm { rm },
|
||||
_backend { backend }
|
||||
_backend { backend },
|
||||
_range { &md_alloc }
|
||||
{ }
|
||||
|
||||
~Ppgtt_allocator()
|
||||
{
|
||||
_map.for_each([&](Utils::Address_map<ELEMENTS>::Element &elem) {
|
||||
_rm.detach(elem.va);
|
||||
_backend.free(elem.ds_cap);
|
||||
elem.invalidate();
|
||||
});
|
||||
}
|
||||
|
||||
/*************************
|
||||
** Allocator interface **
|
||||
*************************/
|
||||
|
||||
Alloc_result try_alloc(size_t size) override
|
||||
{
|
||||
Alloc_result result = _range.alloc_aligned(size, 12);
|
||||
if (result.ok()) return result;
|
||||
|
||||
Genode::Ram_dataspace_capability ds { };
|
||||
|
||||
size_t alloc_size = 1024*1024;
|
||||
|
||||
try {
|
||||
ds = _backend.alloc(size, _caps_guard, _ram_guard);
|
||||
ds = _backend.alloc(alloc_size);
|
||||
}
|
||||
catch (Genode::Out_of_ram) { return Alloc_error::OUT_OF_RAM; }
|
||||
catch (Genode::Out_of_caps) { return Alloc_error::OUT_OF_CAPS; }
|
||||
@ -64,8 +82,11 @@ class Igd::Ppgtt_allocator : public Genode::Translation_table_allocator
|
||||
try {
|
||||
void * const ptr = _rm.attach(ds);
|
||||
|
||||
if (_map.add(ds, ptr))
|
||||
return ptr;
|
||||
if (_map.add(ds, ptr) == true) {
|
||||
_range.add_range((Genode::addr_t)ptr, alloc_size);
|
||||
result = _range.alloc_aligned(size, 12);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* _map.add failed, roll back _rm.attach */
|
||||
_rm.detach(ptr);
|
||||
@ -76,22 +97,14 @@ class Igd::Ppgtt_allocator : public Genode::Translation_table_allocator
|
||||
|
||||
/* roll back allocation */
|
||||
_backend.free(ds);
|
||||
|
||||
return alloc_error;
|
||||
}
|
||||
|
||||
void free(void *addr, size_t) override
|
||||
void free(void *addr, size_t size) override
|
||||
{
|
||||
if (addr == nullptr) { return; }
|
||||
|
||||
Genode::Ram_dataspace_capability cap = _map.remove(addr);
|
||||
if (!cap.valid()) {
|
||||
Genode::error("could not lookup capability for addr: ", addr);
|
||||
return;
|
||||
}
|
||||
|
||||
_rm.detach(addr);
|
||||
_backend.free(cap);
|
||||
_range.free(addr, size);
|
||||
}
|
||||
|
||||
bool need_size_for_free() const override { return false; }
|
||||
@ -104,15 +117,15 @@ class Igd::Ppgtt_allocator : public Genode::Translation_table_allocator
|
||||
void *phys_addr(void *va) override
|
||||
{
|
||||
if (va == nullptr) { return nullptr; }
|
||||
typename Utils::Address_map<ELEMENTS>::Element *e = _map.phys_addr(va);
|
||||
return e ? (void*)e->pa : nullptr;
|
||||
addr_t pa = _map.phys_addr(va);
|
||||
return pa ? (void *)pa : nullptr;
|
||||
}
|
||||
|
||||
void *virt_addr(void *pa) override
|
||||
{
|
||||
if (pa == nullptr) { return nullptr; }
|
||||
typename Utils::Address_map<ELEMENTS>::Element *e = _map.virt_addr(pa);
|
||||
return e ? (void*)e->va : nullptr;
|
||||
addr_t virt = _map.virt_addr(pa);
|
||||
return virt ? (void*)virt : nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -45,29 +45,30 @@ namespace Utils {
|
||||
template <unsigned int ELEMENTS>
|
||||
class Utils::Address_map
|
||||
{
|
||||
using addr_t = Genode::addr_t;
|
||||
|
||||
public:
|
||||
|
||||
struct Element
|
||||
{
|
||||
Ram ds_cap { };
|
||||
void *va { nullptr };
|
||||
void *pa { nullptr };
|
||||
uint32_t index { 0 };
|
||||
Ram ds_cap { };
|
||||
addr_t va { 0 };
|
||||
addr_t pa { 0 };
|
||||
size_t size { 0 };
|
||||
|
||||
Element() { }
|
||||
|
||||
Element(uint32_t index, Ram ds_cap, void *va)
|
||||
Element(Ram ds_cap, void *va)
|
||||
:
|
||||
ds_cap(ds_cap),
|
||||
va(va),
|
||||
pa((void *)Genode::Dataspace_client(ds_cap).phys_addr()),
|
||||
index(index)
|
||||
va((addr_t)va),
|
||||
pa(Genode::Dataspace_client(ds_cap).phys_addr()),
|
||||
size(Genode::Dataspace_client(ds_cap).size())
|
||||
{ }
|
||||
|
||||
Element(Element const &other)
|
||||
:
|
||||
ds_cap(other.ds_cap), va(other.va), pa(other.pa),
|
||||
index(other.index)
|
||||
ds_cap(other.ds_cap), va(other.va), pa(other.pa)
|
||||
{ }
|
||||
|
||||
Element &operator = (Element const &other)
|
||||
@ -75,11 +76,12 @@ class Utils::Address_map
|
||||
ds_cap = other.ds_cap;
|
||||
va = other.va;
|
||||
pa = other.pa;
|
||||
index = other.index;
|
||||
size = other.size;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool valid() { return va && pa; }
|
||||
bool valid() { return size > 0; }
|
||||
void invalidate() { *this = Element(); };
|
||||
};
|
||||
|
||||
private:
|
||||
@ -108,41 +110,46 @@ class Utils::Address_map
|
||||
for (uint32_t i = 0; i < ELEMENTS; i++) {
|
||||
if (_map[i].valid()) { continue; }
|
||||
|
||||
_map[i] = Element(i, ds_cap, va);
|
||||
_map[i] = Element(ds_cap, va);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Ram remove(void *va)
|
||||
template <typename FN>
|
||||
void for_each(FN const &fn)
|
||||
{
|
||||
Ram cap;
|
||||
|
||||
for (uint32_t i = 0; i < ELEMENTS; i++) {
|
||||
if (_map[i].va != va) { continue; }
|
||||
|
||||
cap = _map[i].ds_cap;
|
||||
_map[i] = Element();
|
||||
break;
|
||||
for (unsigned i = 0; i < ELEMENTS; i++) {
|
||||
if (_map[i].valid()) fn(_map[i]);
|
||||
}
|
||||
|
||||
return cap;
|
||||
}
|
||||
|
||||
Element *phys_addr(void *va)
|
||||
addr_t phys_addr(void *va)
|
||||
{
|
||||
addr_t virt = (addr_t)va;
|
||||
for (uint32_t i = 0; i < ELEMENTS; i++) {
|
||||
if (_map[i].va == va) { return &_map[i]; }
|
||||
if (virt >= _map[i].va && virt < (_map[i].va + _map[i].size))
|
||||
{
|
||||
Genode::off_t offset = virt - _map[i].va;
|
||||
return _map[i].pa + offset;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
Genode::error("phys_addr not found for ", va);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Element *virt_addr(void *pa)
|
||||
addr_t virt_addr(void *pa)
|
||||
{
|
||||
addr_t phys = (addr_t)pa;
|
||||
for (uint32_t i = 0; i < ELEMENTS; i++) {
|
||||
if (_map[i].pa == pa) { return &_map[i]; }
|
||||
if (phys >= _map[i].pa && phys < (_map[i].pa + _map[i].size))
|
||||
{
|
||||
Genode::off_t offset = phys - _map[i].pa;
|
||||
return _map[i].va + offset;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
Genode::error("virt_addr not found for ", pa);
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user