diff --git a/repos/os/src/drivers/gpu/intel/main.cc b/repos/os/src/drivers/gpu/intel/main.cc index bb6b82162a..0261acc5e8 100644 --- a/repos/os/src/drivers/gpu/intel/main.cc +++ b/repos/os/src/drivers/gpu/intel/main.cc @@ -305,7 +305,7 @@ struct Igd::Device return ds; } - void _free_dataspace(Ram_dataspace_capability const cap) + void free_dataspace(Ram_dataspace_capability const cap) { if (!cap.valid()) { return; } @@ -330,9 +330,9 @@ struct Igd::Device Genode::Registry> _ggtt_mmio_mapping_registry { }; - Ggtt_mmio_mapping const &_map_dataspace_ggtt(Genode::Allocator &alloc, - Genode::Dataspace_capability cap, - Ggtt::Offset offset) + Ggtt_mmio_mapping const &map_dataspace_ggtt(Genode::Allocator &alloc, + Genode::Dataspace_capability cap, + Ggtt::Offset offset) { Genode::Dataspace_client client(cap); addr_t const phys_addr = client.phys_addr(); @@ -356,7 +356,7 @@ struct Igd::Device return *mem; } - void _unmap_dataspace_ggtt(Genode::Allocator &alloc, Genode::Dataspace_capability cap) + void unmap_dataspace_ggtt(Genode::Allocator &alloc, Genode::Dataspace_capability cap) { size_t const num = Genode::Dataspace_client(cap).size() / PAGE_SIZE; @@ -445,6 +445,68 @@ struct Igd::Device void dump() { _elem0.dump(); } }; + struct Ggtt_map_memory + { + struct Dataspace_guard { + Device &device; + Ram_dataspace_capability const ds; + + Dataspace_guard(Device &device, Ram_dataspace_capability ds) + : device(device), ds(ds) + { } + + ~Dataspace_guard() + { + if (ds.valid()) + device.free_dataspace(ds); + } + }; + + struct Mapping_guard { + Device &device; + Allocator &alloc; + Ggtt::Mapping const ↦ + + Mapping_guard(Device &device, Ggtt_map_memory &gmm, Allocator &alloc) + : + device(device), + alloc(alloc), + map(device.map_dataspace_ggtt(alloc, gmm.ram_ds.ds, gmm.offset)) + { } + + ~Mapping_guard() { device.unmap_dataspace_ggtt(alloc, map.cap); } + }; + + Device const &device; + Allocator const &alloc; + Ggtt::Offset const offset; + Ggtt::Offset const skip; + Dataspace_guard const ram_ds; + Mapping_guard const map; + Attached_dataspace const ram; + + addr_t vaddr() const + { + return reinterpret_cast(ram.local_addr()) + + (skip * PAGE_SIZE); + } + + addr_t gmaddr() const { /* graphics memory address */ + return (offset + skip) * PAGE_SIZE; } + + Ggtt_map_memory(Region_map &rm, Allocator &alloc, Device &device, + Ggtt::Offset const pages, Ggtt::Offset const skip_pages) + : + device(device), + alloc(alloc), + offset(device._ggtt->find_free(pages, true)), + skip(skip_pages), + ram_ds(device, device._alloc_dataspace(pages * PAGE_SIZE)), + map(device, *this, alloc), + ram(rm, map.map.cap) + { } + }; + template struct Engine { @@ -453,72 +515,68 @@ struct Igd::Device RING_PAGES = CONTEXT::RING_PAGES, }; - Genode::Ram_dataspace_capability ctx_ds; - Ggtt::Mapping const &ctx_map; - addr_t const ctx_vaddr; - addr_t const ctx_gmaddr; + Ggtt_map_memory ctx; /* context memory */ + Ggtt_map_memory ring; /* ring memory */ - Genode::Ram_dataspace_capability ring_ds; - Ggtt::Mapping const &ring_map; - addr_t const ring_vaddr; - addr_t const ring_gmaddr; - - Ppgtt_allocator &ppgtt_allocator; - Ppgtt *ppgtt; - Ppgtt_scratch *ppgtt_scratch; + Ppgtt_allocator ppgtt_allocator; + Ppgtt_scratch ppgtt_scratch; + Ppgtt *ppgtt { nullptr }; Genode::Constructible context { }; Genode::Constructible execlist { }; - Engine(uint32_t id, - Ram ctx_ds, - Ggtt::Mapping const &ctx_map, - addr_t const ctx_vaddr, - addr_t const ctx_gmaddr, - Ram ring_ds, - Ggtt::Mapping const &ring_map, - addr_t const ring_vaddr, - addr_t const ring_gmaddr, - Ppgtt_allocator &ppgtt_allocator, - Ppgtt *ppgtt, - Ppgtt_scratch *ppgtt_scratch, - addr_t const pml4) + Engine(Igd::Device &device, + uint32_t id, + Allocator &alloc) : - ctx_ds(ctx_ds), - ctx_map(ctx_map), - ctx_vaddr(ctx_vaddr), - ctx_gmaddr(ctx_gmaddr), - ring_ds(ring_ds), - ring_map(ring_map), - ring_vaddr(ring_vaddr), - ring_gmaddr(ring_gmaddr), - ppgtt_allocator(ppgtt_allocator), - ppgtt(ppgtt), - ppgtt_scratch(ppgtt_scratch) + 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_scratch(device._pci_backend_alloc) { - size_t const ring_size = RING_PAGES * PAGE_SIZE; + /* PPGTT */ + device._populate_scratch(ppgtt_scratch); - /* setup context */ - context.construct(ctx_vaddr, ring_gmaddr, ring_size, pml4); + ppgtt = new (ppgtt_allocator) Igd::Ppgtt(&ppgtt_scratch.pdp); - /* setup execlist */ - execlist.construct(id, ctx_gmaddr, ring_vaddr, ring_size); - execlist->ring_reset(); + try { + size_t const ring_size = RING_PAGES * PAGE_SIZE; + + /* get PML4 address */ + addr_t const ppgtt_phys_addr = _ppgtt_phys_addr(ppgtt_allocator, + ppgtt); + addr_t const pml4 = ppgtt_phys_addr | 1; + + /* setup context */ + context.construct(ctx.vaddr(), ring.gmaddr(), ring_size, pml4); + + /* setup execlist */ + execlist.construct(id, ctx.gmaddr(), ring.vaddr(), ring_size); + execlist->ring_reset(); + } catch (...) { + _destruct(); + throw; + } } - ~Engine() + ~Engine() { _destruct(); }; + + void _destruct() { + if (ppgtt) + Genode::destroy(ppgtt_allocator, ppgtt); + execlist.destruct(); context.destruct(); } size_t ring_size() const { return RING_PAGES * PAGE_SIZE; } - addr_t hw_status_page() const { return ctx_gmaddr; } + addr_t hw_status_page() const { return ctx.gmaddr(); } uint64_t seqno() const { - Utils::clflush((uint32_t*)(ctx_vaddr + 0xc0)); - return *(uint32_t*)(ctx_vaddr + 0xc0); } + Utils::clflush((uint32_t*)(ctx.vaddr() + 0xc0)); + return *(uint32_t*)(ctx.vaddr() + 0xc0); } private: @@ -531,79 +589,32 @@ struct Igd::Device void _fill_page(Genode::Ram_dataspace_capability ds, addr_t v) { - uint64_t * const p = _env.rm().attach(ds); + Attached_dataspace ram(_env.rm(), ds); + uint64_t * const p = ram.local_addr(); + for (size_t i = 0; i < Ppgtt_scratch::MAX_ENTRIES; i++) { p[i] = v; } - _env.rm().detach(p); } - void _populate_scratch(Ppgtt_scratch *scratch) + void _populate_scratch(Ppgtt_scratch &scratch) { - _fill_page(scratch->pt.ds, scratch->page.addr); - _fill_page(scratch->pd.ds, scratch->pt.addr); - _fill_page(scratch->pdp.ds, scratch->pd.addr); + _fill_page(scratch.pt.ds, scratch.page.addr); + _fill_page(scratch.pd.ds, scratch.pt.addr); + _fill_page(scratch.pdp.ds, scratch.pd.addr); } + template Engine *_alloc_engine(Allocator &md_alloc, uint32_t const id) { - /* alloc context memory */ - size_t const ctx_offset = _ggtt->find_free(CONTEXT::CONTEXT_PAGES, true); - size_t const ctx_size = CONTEXT::CONTEXT_PAGES * PAGE_SIZE; - Ram ctx_ds = _alloc_dataspace(ctx_size); - Ggtt::Mapping const &ctx_map = _map_dataspace_ggtt(md_alloc, ctx_ds, ctx_offset); - addr_t const ctx_vaddr = (addr_t)_env.rm().attach(ctx_map.cap) + PAGE_SIZE /* omit GuC page */; - addr_t const ctx_gmaddr = (ctx_offset + 1 /* omit GuC page */) * PAGE_SIZE; - - /* alloc ring memory */ - size_t const ring_offset = _ggtt->find_free(Rcs_context::RING_PAGES, true); - size_t const ring_size = CONTEXT::RING_PAGES * PAGE_SIZE; - Ram ring_ds = _alloc_dataspace(ring_size); - Ggtt::Mapping const &ring_map = _map_dataspace_ggtt(md_alloc, ring_ds, ring_offset); - addr_t const ring_vaddr = _env.rm().attach(ring_map.cap); - addr_t const ring_gmaddr = ring_offset * PAGE_SIZE; - - /* PPGTT */ - Igd::Ppgtt_allocator *ppgtt_allocator = - new (&md_alloc) Igd::Ppgtt_allocator(_env.rm(), _pci_backend_alloc); - - Igd::Ppgtt_scratch *scratch = - new (&md_alloc) Igd::Ppgtt_scratch(_pci_backend_alloc); - _populate_scratch(scratch); - - Igd::Ppgtt *ppgtt = - new (ppgtt_allocator) Igd::Ppgtt(&scratch->pdp); - - /* get PML4 address */ - addr_t const ppgtt_phys_addr = _ppgtt_phys_addr(*ppgtt_allocator, ppgtt); - addr_t const pml4 = ppgtt_phys_addr | 1; - - return new (&md_alloc) Engine(id + CONTEXT::HW_ID, - ctx_ds, ctx_map, ctx_vaddr, ctx_gmaddr, - ring_ds, ring_map, ring_vaddr, ring_gmaddr, - *ppgtt_allocator, ppgtt, scratch, pml4); + return new (&md_alloc) Engine(*this, id + CONTEXT::HW_ID, + md_alloc); } template void _free_engine(Allocator &md_alloc, Engine *engine) { - /* free PPGTT */ - Genode::destroy(&md_alloc, engine->ppgtt_scratch); - Genode::destroy(&engine->ppgtt_allocator, engine->ppgtt); - Genode::destroy(&md_alloc, &engine->ppgtt_allocator); - /* free ring memory */ - { - _env.rm().detach(engine->ring_vaddr); - _unmap_dataspace_ggtt(md_alloc, engine->ring_map.cap); - _free_dataspace(engine->ring_ds); - } - /* free context memory */ - { - _env.rm().detach(engine->ctx_vaddr - PAGE_SIZE); - _unmap_dataspace_ggtt(md_alloc, engine->ctx_map.cap); - _free_dataspace(engine->ctx_ds); - } /* free engine */ Genode::destroy(&md_alloc, engine); } @@ -783,7 +794,7 @@ struct Igd::Device try { rcs.ppgtt->insert_translation(vo, pa, size, pf, &rcs.ppgtt_allocator, - &rcs.ppgtt_scratch->pdp); + &rcs.ppgtt_scratch.pdp); } catch (Igd::Ppgtt_allocator::Out_of_memory) { throw Igd::Device::Out_of_ram(); } catch (...) { @@ -796,7 +807,7 @@ struct Igd::Device { rcs.ppgtt->remove_translation(vo, size, &rcs.ppgtt_allocator, - &rcs.ppgtt_scratch->pdp); + &rcs.ppgtt_scratch.pdp); } }; @@ -1254,7 +1265,7 @@ struct Igd::Device try { size_t const num = size / PAGE_SIZE; Ggtt::Offset const offset = _ggtt->find_free(num, aperture); - return _map_dataspace_ggtt(guard, cap, offset); + return map_dataspace_ggtt(guard, cap, offset); } catch (...) { throw Could_not_map_buffer(); } @@ -1268,7 +1279,7 @@ struct Igd::Device */ void unmap_buffer(Genode::Allocator &guard, Ggtt::Mapping mapping) { - _unmap_dataspace_ggtt(guard, mapping.cap); + unmap_dataspace_ggtt(guard, mapping.cap); } /**