From 250275fbfbc86afeb6989fb91e3dbac186a631e1 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Tue, 13 Sep 2022 14:27:24 +0200 Subject: [PATCH] gpu_drv: use generic platform API Ref genodelabs/genode#4578 --- repos/os/src/drivers/gpu/intel/ggtt.h | 35 +- repos/os/src/drivers/gpu/intel/main.cc | 313 +++++++-------- repos/os/src/drivers/gpu/intel/mmio.h | 22 +- .../src/drivers/gpu/intel/platform_session.h | 372 ++++++++++-------- repos/os/src/drivers/gpu/intel/resources.h | 370 ----------------- repos/os/src/drivers/gpu/intel/types.h | 8 +- 6 files changed, 385 insertions(+), 735 deletions(-) delete mode 100644 repos/os/src/drivers/gpu/intel/resources.h diff --git a/repos/os/src/drivers/gpu/intel/ggtt.h b/repos/os/src/drivers/gpu/intel/ggtt.h index 4b8e4ab1c8..b17a034a31 100644 --- a/repos/os/src/drivers/gpu/intel/ggtt.h +++ b/repos/os/src/drivers/gpu/intel/ggtt.h @@ -21,10 +21,7 @@ #include -namespace Igd { - - struct Ggtt; -} +namespace Igd { struct Ggtt; } /* * Global Graphics Translation Table @@ -57,6 +54,12 @@ class Igd::Ggtt private: + /* + * Noncopyable + */ + Ggtt(Ggtt const &); + Ggtt &operator = (Ggtt const &); + /* * IHD-OS-BDW-Vol 5-11.15 p. 44 */ @@ -113,7 +116,8 @@ class Igd::Ggtt uint64_t *_entries; - addr_t const _scratch_page; + Platform::Dma_buffer _scratch_page; + size_t const _aperture_size; size_t const _aperture_entries; @@ -133,6 +137,7 @@ class Igd::Ggtt /** * Constructor * + * \param platform reference to Platform::Connection object * \param mmio reference to Igd::Mmio object * \param base virtual base address of GGTT start * \param size size of GGTT in bytes @@ -140,9 +145,8 @@ class Igd::Ggtt * \param scratch_page physical address of the scratch page * \param fb_size size of the framebuffer region in the GTT in bytes */ - Ggtt(Igd::Mmio &mmio, addr_t base, size_t size, - size_t aperture_size, addr_t scratch_page, - size_t fb_size) + Ggtt(Platform::Connection & platform, Igd::Mmio &mmio, + addr_t base, size_t size, size_t aperture_size, size_t fb_size) : _mmio(mmio), _base(base), @@ -150,7 +154,7 @@ class Igd::Ggtt /* make the last entry/page unavailable */ _num_entries((_size / 8) - 1), _entries((uint64_t*)_base), - _scratch_page(scratch_page), + _scratch_page(platform, PAGE_SIZE, Genode::UNCACHED), _aperture_size(aperture_size), _aperture_entries(_aperture_size / PAGE_SIZE) { @@ -160,7 +164,7 @@ class Igd::Ggtt _space.set(i); } for (size_t i = fb_entries; i < _num_entries; i++) { - _insert_pte(_scratch_page, i); + _insert_pte(_scratch_page.dma_addr(), i); } } @@ -197,7 +201,7 @@ class Igd::Ggtt } _space.clear(offset); - _insert_pte(_scratch_page, offset); + _insert_pte(_scratch_page.dma_addr(), offset); } /** @@ -270,13 +274,6 @@ class Igd::Ggtt */ size_t entries() const { return _num_entries; } - /** - * Get scratch page address - * - * \return physical address of the scratch page - */ - addr_t scratch_page() const { return _scratch_page; } - /********************* ** Debug interface ** *********************/ @@ -290,7 +287,7 @@ class Igd::Ggtt log("GGTT"); log(" vaddr:", Hex(_base), " size:", Hex(_size), " entries:", _num_entries, " used:", _space.used(), " aperture_size:", Hex(_aperture_size)); - log(" scratch_page:", Hex(_scratch_page), " (PA)"); + log(" scratch_page:", Hex(_scratch_page.dma_addr()), " (PA)"); if (!dump_entries) { return; } diff --git a/repos/os/src/drivers/gpu/intel/main.cc b/repos/os/src/drivers/gpu/intel/main.cc index 51ffb00c29..f0f1189553 100644 --- a/repos/os/src/drivers/gpu/intel/main.cc +++ b/repos/os/src/drivers/gpu/intel/main.cc @@ -24,10 +24,8 @@ #include #include #include -#include -#include -#include -#include +#include +#include #include #include #include @@ -42,12 +40,10 @@ #include #include #include -#include #include #include #include - using namespace Genode; @@ -78,18 +74,21 @@ struct Igd::Device struct Out_of_ram : Genode::Exception { }; struct Could_not_map_buffer : Genode::Exception { }; - Env &_env; - Allocator &_md_alloc; - enum { WATCHDOG_TIMEOUT = 1*1000*1000, }; + Env & _env; + Allocator & _md_alloc; + Platform::Connection & _platform; + Rm_connection & _rm; + Igd::Mmio & _mmio; + Platform::Device::Mmio & _gmadr; + uint8_t _gmch_ctl; + Timer::Connection _timer { _env }; + /********* ** PCI ** *********/ - Resources &_resources; - Platform::Device_client &_device { _resources.gpu_client() }; - struct Pci_backend_alloc : Utils::Backend_alloc { Platform::Connection &_pci; @@ -98,7 +97,8 @@ struct Igd::Device Ram_dataspace_capability alloc(size_t size) override { - return _pci.with_upgrade([&] () { + return _pci.retry_with_upgrade(Genode::Ram_quota{PAGE_SIZE}, + Genode::Cap_quota{8}, [&] () { return _pci.alloc_dma_buffer(size, Genode::UNCACHED); }); } @@ -117,7 +117,7 @@ struct Igd::Device return _pci.dma_addr(ds_cap); } - } _pci_backend_alloc { _resources.platform() }; + } _pci_backend_alloc { _platform }; Device_info _info { }; @@ -127,41 +127,9 @@ struct Igd::Device Gpu::Info_intel::Eu_total _eus { }; Gpu::Info_intel::Subslices _subslices { }; - void _pci_info(String<64> const &descr) const - { - using namespace Genode; - - uint16_t const vendor_id = _device.vendor_id(); - uint16_t const device_id = _device.device_id(); - - uint8_t bus = 0, dev = 0, fun = 0; - _device.bus_address(&bus, &dev, &fun); - - log("Found: '", descr, "' gen=", _info.generation, - " rev=", _revision.value, " ", - "[", Hex(vendor_id), ":", Hex(device_id), "] (", - Hex(bus, Hex::OMIT_PREFIX), ":", - Hex(dev, Hex::OMIT_PREFIX), ".", - Hex(fun, Hex::OMIT_PREFIX), ")"); - - enum { PCI_NUM_RES = 6 }; - for (int i = 0; i < PCI_NUM_RES; i++) { - - using Resource = Platform::Device::Resource; - - Resource const resource = _device.resource(i); - - if (resource.type() == Resource::INVALID) { continue; } - - log(" Resource ", i, " " - "(", resource.type() == Resource::IO ? "I/O" : "MEM", "): " - "base=", Genode::Hex(resource.base()), " " - "size=", Genode::Hex(resource.size()), " ", - (resource.prefetchable() ? "prefetchable" : "")); - } - } - - bool _supported(Xml_node &supported) + bool _supported(Xml_node & supported, + uint16_t dev_id, + uint8_t rev_id) { bool found = false; @@ -173,7 +141,7 @@ struct Igd::Device uint16_t const device = node.attribute_value("device", 0U); uint8_t const generation = node.attribute_value("generation", 0U); String<16> const platform = node.attribute_value("platform", String<16>("unknown")); - String<64> const desc = node.attribute_value("description", String<64>("unknown")); + //String<64> const desc = node.attribute_value("description", String<64>("unknown")); if (vendor != 0x8086 /* Intel */ || generation < 8) return; @@ -188,10 +156,9 @@ struct Igd::Device if (info.platform == Igd::Device_info::Platform::UNKNOWN) return; - if (info.id == _device.device_id()) { + if (info.id == dev_id) { _info = info; - _revision.value = _resources.config_read(8); - _pci_info(desc.string()); + _revision.value = rev_id; found = true; return; @@ -218,13 +185,40 @@ struct Igd::Device ** GGTT ** **********/ - Genode::Constructible _ggtt { }; - /********** - ** MMIO ** - **********/ + size_t _ggtt_size() + { + /* + * IHD-OS-BDW-Vol 2c-11.15 p. 1068 + */ + struct MGGC_0_2_0_PCI : Genode::Register<16> + { + struct Graphics_mode_select : Bitfield<8, 8> { }; + struct Gtt_graphics_memory_size : Bitfield<6, 2> { }; + struct Versatile_acceleration_mode_enable : Bitfield<3, 1> { }; + struct Igd_vga_disable : Bitfield<2, 1> { }; + struct Ggc_lock : Bitfield<0, 1> { }; + }; + enum { PCI_GMCH_CTL = 0x50, }; + MGGC_0_2_0_PCI::access_t v = _gmch_ctl; - Igd::Mmio &_mmio { _resources.mmio() }; + { + log("MGGC_0_2_0_PCI"); + log(" Graphics_mode_select: ", Hex(MGGC_0_2_0_PCI::Graphics_mode_select::get(v))); + log(" Gtt_graphics_memory_size: ", Hex(MGGC_0_2_0_PCI::Gtt_graphics_memory_size::get(v))); + log(" Versatile_acceleration_mode_enable: ", Hex(MGGC_0_2_0_PCI::Versatile_acceleration_mode_enable::get(v))); + log(" Igd_vga_disable: ", Hex(MGGC_0_2_0_PCI::Igd_vga_disable::get(v))); + log(" Ggc_lock: ", Hex(MGGC_0_2_0_PCI::Ggc_lock::get(v))); + } + + return (1u << MGGC_0_2_0_PCI::Gtt_graphics_memory_size::get(v)) << 20; + } + + addr_t _ggtt_base() const { + return _mmio.base() + (_mmio.size() / 2); } + + Igd::Ggtt _ggtt { _platform, _mmio, _ggtt_base(), + _ggtt_size(), _gmadr.size(), APERTURE_RESERVED }; /************ ** MEMORY ** @@ -250,14 +244,17 @@ struct Igd::Device struct Ggtt_mmio_mapping : Ggtt::Mapping { - Region_map_client _rm; + Region_map_client _rmc; - Ggtt_mmio_mapping(Resources &resources, Ggtt::Offset offset, size_t size) + Ggtt_mmio_mapping(Rm_connection & rm, + Dataspace_capability cap, + Ggtt::Offset offset, + size_t size) : - _rm(resources.rm().create(size)) + _rmc(rm.create(size)) { - _rm.attach_at(resources.gmadr_ds(), 0, size, offset * PAGE_SIZE); - Ggtt::Mapping::cap = _rm.dataspace(); + _rmc.attach_at(cap, 0, size, offset * PAGE_SIZE); + Ggtt::Mapping::cap = _rmc.dataspace(); Ggtt::Mapping::offset = offset; } @@ -280,10 +277,10 @@ struct Igd::Device */ Genode::Registered *mem = new (&alloc) Genode::Registered(_ggtt_mmio_mapping_registry, - _resources, offset, size); + _rm, _gmadr.cap(), offset, size); for (size_t i = 0; i < size; i += PAGE_SIZE) { addr_t const pa = phys_addr + i; - _ggtt->insert_pte(pa, offset + (i / PAGE_SIZE)); + _ggtt.insert_pte(pa, offset + (i / PAGE_SIZE)); } return *mem; @@ -296,7 +293,7 @@ struct Igd::Device auto lookup_and_free = [&] (Ggtt_mmio_mapping &m) { if (!(m.cap == cap)) { return; } - _ggtt->remove_pte_range(m.offset, num); + _ggtt.remove_pte_range(m.offset, num); Genode::destroy(&alloc, &m); }; @@ -420,7 +417,7 @@ struct Igd::Device : device(device), alloc(alloc), - offset(device._ggtt->find_free(pages, true)), + offset(device._ggtt.find_free(pages, true)), skip(skip_pages), ram_ds(device, device._alloc_dataspace(pages * PAGE_SIZE)), map(device, *this, alloc), @@ -922,7 +919,7 @@ struct Igd::Device _submit_execlist(rcs); _active_vgpu = gpu; - _resources.timer().trigger_once(WATCHDOG_TIMEOUT); + _timer.trigger_once(WATCHDOG_TIMEOUT); } /********** @@ -1030,56 +1027,28 @@ struct Igd::Device /** * Constructor */ - Device(Genode::Env &env, - Genode::Allocator &alloc, - Resources &resources, - Genode::Xml_node &supported) + Device(Genode::Env & env, + Genode::Allocator & alloc, + Platform::Connection & platform, + Rm_connection & rm, + Igd::Mmio & mmio, + Platform::Device::Mmio & gmadr, + Genode::Xml_node & supported, + uint16_t device_id, + uint8_t revision, + uint8_t gmch_ctl) : - _env(env), _md_alloc(alloc), _resources(resources) + _env(env), _md_alloc(alloc), _platform(platform), _rm(rm), + _mmio(mmio), _gmadr(gmadr), _gmch_ctl(gmch_ctl) { using namespace Genode; - if (!_supported(supported)) { throw Unsupported_device(); } + if (!_supported(supported, device_id, revision)) + throw Unsupported_device(); - /* - * IHD-OS-BDW-Vol 2c-11.15 p. 1068 - */ - struct MGGC_0_2_0_PCI : Genode::Register<16> - { - struct Graphics_mode_select : Bitfield<8, 8> { }; - struct Gtt_graphics_memory_size : Bitfield<6, 2> { }; - struct Versatile_acceleration_mode_enable : Bitfield<3, 1> { }; - struct Igd_vga_disable : Bitfield<2, 1> { }; - struct Ggc_lock : Bitfield<0, 1> { }; - }; - enum { PCI_GMCH_CTL = 0x50, }; - MGGC_0_2_0_PCI::access_t v = _resources.config_read(PCI_GMCH_CTL); + _ggtt.dump(); - { - log("MGGC_0_2_0_PCI"); - log(" Graphics_mode_select: ", Hex(MGGC_0_2_0_PCI::Graphics_mode_select::get(v))); - log(" Gtt_graphics_memory_size: ", Hex(MGGC_0_2_0_PCI::Gtt_graphics_memory_size::get(v))); - log(" Versatile_acceleration_mode_enable: ", Hex(MGGC_0_2_0_PCI::Versatile_acceleration_mode_enable::get(v))); - log(" Igd_vga_disable: ", Hex(MGGC_0_2_0_PCI::Igd_vga_disable::get(v))); - log(" Ggc_lock: ", Hex(MGGC_0_2_0_PCI::Ggc_lock::get(v))); - } - - /* map PCI resources */ - addr_t gttmmadr_base = _resources.map_gttmmadr(); - - /* GGTT */ - addr_t const scratch_page = _resources.scratch_page(); - - /* reserverd size for framebuffer */ - size_t const aperture_reserved = resources.gmadr_platform_size(); - - size_t const ggtt_size = (1u << MGGC_0_2_0_PCI::Gtt_graphics_memory_size::get(v)) << 20; - addr_t const ggtt_base = gttmmadr_base + (_resources.gttmmadr_size() / 2); - size_t const gmadr_size = _resources.gmadr_size(); - _ggtt.construct(_mmio, ggtt_base, ggtt_size, gmadr_size, scratch_page, aperture_reserved); - _ggtt->dump(); - - _vgpu_avail = (gmadr_size - aperture_reserved) / Vgpu::APERTURE_SIZE; + _vgpu_avail = (_gmadr.size() - APERTURE_RESERVED) / Vgpu::APERTURE_SIZE; _device_reset_and_init(); @@ -1121,7 +1090,7 @@ struct Igd::Device /* apply generation specific workarounds */ apply_workarounds(_mmio, _info.generation); - _resources.timer().sigh(_watchdog_timeout_sigh); + _timer.sigh(_watchdog_timeout_sigh); } void _clock_gating() @@ -1363,7 +1332,7 @@ struct Igd::Device size_t const size = Genode::Dataspace_client(cap).size(); size_t const num = size / PAGE_SIZE; - Ggtt::Offset const offset = _ggtt->find_free(num, aperture); + Ggtt::Offset const offset = _ggtt.find_free(num, aperture); return map_dataspace_ggtt(guard, cap, offset); } @@ -1464,8 +1433,6 @@ struct Igd::Device void enable_master_irq() { _mmio.enable_master_irq(); } - Resources &resources() { return _resources; } - private: /* @@ -2146,31 +2113,31 @@ class Gpu::Root : public Gpu::Root_component }; -struct Main +struct Initialization_failed : Genode::Exception { }; + + +struct Main : Irq_ack_handler, Gpu_reset_handler { - Genode::Env &_env; + Env & _env; + Sliced_heap _root_heap { _env.ram(), _env.rm() }; + Gpu::Root _gpu_root { _env, _root_heap }; + Attached_rom_dataspace _config_rom { _env, "config" }; + Heap _md_alloc { _env.ram(), _env.rm() }; + Platform::Connection _platform { _env }; + Platform::Device _device { _platform }; + Platform::Device::Irq _irq { _device }; + Igd::Mmio _mmio { _device, _env }; + Platform::Device::Mmio _gmadr { _device, { 1 } }; + Rm_connection _rm { _env }; + Io_signal_handler
_irq_dispatcher { _env.ep(), *this, + &Main::handle_irq }; + Signal_handler
_config_sigh { _env.ep(), *this, + &Main::_handle_config_update }; - /********* - ** Gpu ** - *********/ + Platform::Root _platform_root { _env, _md_alloc, _platform, *this, *this, + _mmio, _gmadr, _rm }; - Genode::Sliced_heap _root_heap { _env.ram(), _env.rm() }; - Gpu::Root _gpu_root { _env, _root_heap }; - Genode::Attached_rom_dataspace _config_rom { _env, "config" }; - - Genode::Heap _device_md_alloc { _env.ram(), _env.rm() }; - Genode::Constructible _device { }; - Igd::Resources _gpu_resources { _env, _device_md_alloc, - *this, &Main::ack_irq }; - - Genode::Irq_session_client _irq { _gpu_resources.gpu_client().irq(0) }; - Genode::Signal_handler
_irq_dispatcher { - _env.ep(), *this, &Main::handle_irq }; - - Constructible _platform_root { }; - - Genode::Signal_handler
_config_sigh { - _env.ep(), *this, &Main::_handle_config_update }; + Genode::Constructible _igd_device { }; Main(Genode::Env &env) : @@ -2180,29 +2147,33 @@ struct Main /* IRQ */ _irq.sigh(_irq_dispatcher); - _irq.ack_irq(); /* GPU */ _handle_config_update(); - - /* platform service */ - _platform_root.construct(_env, _device_md_alloc, _gpu_resources); } - void _handle_config_update() + void _create_device() { - _config_rom.update(); + uint16_t device_id; + uint8_t revision; + uint8_t gmch_ctl; - if (!_config_rom.valid()) { return; } - - if (_device.constructed()) { - Genode::log("gpu device already initialized - ignore"); - return; - } + _platform.update(); + _platform.with_xml([&] (Xml_node node) { + node.with_optional_sub_node("device", [&] (Xml_node node) { + node.with_optional_sub_node("pci-config", [&] (Xml_node node) { + device_id = node.attribute_value("device_id", 0U); + revision = node.attribute_value("revision", 0U); + gmch_ctl = node.attribute_value("intel_gmch_control", 0U); + }); + }); + }); try { - _device.construct(_env, _device_md_alloc, _gpu_resources, _config_rom.xml()); - _gpu_root.manage(*_device); + _igd_device.construct(_env, _md_alloc, _platform, _rm, _mmio, + _gmadr, _config_rom.xml(), device_id, + revision, gmch_ctl); + _gpu_root.manage(*_igd_device); _env.parent().announce(_env.ep().manage(_gpu_root)); } catch (Igd::Device::Unsupported_device) { Genode::warning("No supported Intel GPU detected - no GPU service"); @@ -2211,14 +2182,28 @@ struct Main } } + void _handle_config_update() + { + _config_rom.update(); + + if (!_config_rom.valid()) { return; } + + if (_igd_device.constructed()) { + Genode::log("gpu device already initialized - ignore"); + return; + } + + _create_device(); + } + void handle_irq() { unsigned master = 0; - if (_device.constructed()) - master = _device->handle_irq(); + if (_igd_device.constructed()) + master = _igd_device->handle_irq(); /* GPU not present forward all IRQs to platform client */ else { - _platform_root->handle_irq(); + _platform_root.handle_irq(); return; } @@ -2228,19 +2213,25 @@ struct Main */ using Master = Igd::Mmio::MASTER_INT_CTL; if (Master::De_interrupts_pending::get(master) && - (_platform_root->handle_irq())) + (_platform_root.handle_irq())) return; ack_irq(); } - void ack_irq() + void ack_irq() override { - if (_device.constructed()) { - _device->enable_master_irq(); + if (_igd_device.constructed()) { + _igd_device->enable_master_irq(); } - _irq.ack_irq(); + _irq.ack(); + } + + void reset() override + { + addr_t const base = _mmio.base() + (_mmio.size() / 2); + Igd::Ggtt(_platform, _mmio, base, Igd::GTT_RESERVED, 0, 0); } }; @@ -2250,7 +2241,7 @@ void Component::construct(Genode::Env &env) static Constructible
main; try { main.construct(env); - } catch (Igd::Resources::Initialization_failed) { + } catch (Initialization_failed) { Genode::warning("Intel GPU resources not found."); env.parent().exit(0); } diff --git a/repos/os/src/drivers/gpu/intel/mmio.h b/repos/os/src/drivers/gpu/intel/mmio.h index 44eea1536f..fa99778151 100644 --- a/repos/os/src/drivers/gpu/intel/mmio.h +++ b/repos/os/src/drivers/gpu/intel/mmio.h @@ -16,19 +16,17 @@ /* Genode includes */ #include -#include +#include +#include /* local includes */ #include -namespace Igd { - - class Mmio; -} +namespace Igd { class Mmio; } -class Igd::Mmio : public Genode::Mmio +class Igd::Mmio : public Platform::Device::Mmio { public: @@ -936,7 +934,13 @@ class Igd::Mmio : public Genode::Mmio private: - Mmio::Delayer &_delayer; + struct Timer_delayer : Genode::Mmio::Delayer + { + Timer::Connection _timer; + Timer_delayer(Genode::Env & env) : _timer(env) { } + + void usleep(uint64_t us) override { _timer.usleep(us); } + } _delayer; void _fw_reset_gen8() { @@ -1419,8 +1423,8 @@ class Igd::Mmio : public Genode::Mmio public: - Mmio(Mmio::Delayer &delayer, addr_t const base) - : Genode::Mmio(base), _delayer(delayer) { } + Mmio(Platform::Device & device, Genode::Env & env) + : Platform::Device::Mmio(device, {0}), _delayer(env) { } template void write_post(typename T::access_t const value) diff --git a/repos/os/src/drivers/gpu/intel/platform_session.h b/repos/os/src/drivers/gpu/intel/platform_session.h index 6c58c31fd1..d68f139f42 100644 --- a/repos/os/src/drivers/gpu/intel/platform_session.h +++ b/repos/os/src/drivers/gpu/intel/platform_session.h @@ -11,54 +11,63 @@ * under the terms of the GNU Affero General Public License version 3. */ -#include +#include +#include +#include +#include + +struct Irq_ack_handler +{ + virtual ~Irq_ack_handler() {} + virtual void ack_irq() = 0; +}; + +struct Gpu_reset_handler +{ + virtual ~Gpu_reset_handler() {} + virtual void reset() = 0; +}; namespace Platform { -class Device_component; -class Session_component; -class Io_mem_session_component; -class Io_mem_session_component_gmadr; -class Irq_session_component; -class Root; + using namespace Genode; + + class Device_component; + class Session_component; + class Io_mem_session_component; + class Irq_session_component; + class Root; } +using Range = Platform::Device_interface::Range; + +struct Main; class Platform::Irq_session_component : public Rpc_object { private: - Igd::Resources &_resources; + Irq_ack_handler & _ack_handler; Signal_context_capability _sigh { }; public: - Irq_session_component(Igd::Resources &resources) - : - _resources(resources) - { } + Irq_session_component(Irq_ack_handler & ack_handler) + : _ack_handler(ack_handler) { } - void ack_irq() override - { - _resources.ack_irq(); - } + void ack_irq() override { _ack_handler.ack_irq(); } - void sigh(Signal_context_capability sigh) override - { - _sigh = sigh; - } + void sigh(Signal_context_capability sigh) override { + _sigh = sigh; } bool handle_irq() { if (!_sigh.valid()) return false; Signal_transmitter(_sigh).submit(); - return true; } - Info info() override - { - return Info { Info::INVALID, 0, 0 }; - } + Info info() override { + return Info { Info::INVALID, 0, 0 }; } }; @@ -66,57 +75,47 @@ class Platform::Io_mem_session_component : public Rpc_object { private: - Igd::Resources &_resources; + Io_mem_dataspace_capability _ds_cap; public: - Io_mem_session_component(Igd::Resources &resources) - : - _resources(resources) { } + Io_mem_session_component(Dataspace_capability cap) + : _ds_cap(static_cap_cast(cap)) { } Io_mem_dataspace_capability dataspace() override { - return _resources.gttmmadr_platform_ds(); + return _ds_cap; } }; -class Platform::Io_mem_session_component_gmadr : public Rpc_object +class Platform::Device_component : public Rpc_object { private: - Igd::Resources &_resources; + Env & _env; + Io_mem_session_component _gttmmadr_io; + Range _gttmmadr_range; + Io_mem_session_component _gmadr_io; + Range _gmadr_range; + Irq_session_component _irq; public: - Io_mem_session_component_gmadr(Igd::Resources &resources) + Device_component(Env & env, + Irq_ack_handler & ack_handler, + Dataspace_capability gttmmadr_ds_cap, + Range gttmmadr_range, + Dataspace_capability gmadr_ds_cap, + Range gmadr_range) : - _resources(resources) { } - - Io_mem_dataspace_capability dataspace() override - { - return _resources.gmadr_platform_ds(); - } -}; - - -class Platform::Device_component : public Rpc_object -{ - private: - - Env &_env; - Igd::Resources &_resources; - Device_client &_device { _resources.gpu_client() }; - - Io_mem_session_component _gttmmadr_io { _resources }; - Io_mem_session_component_gmadr _gmadr_io { _resources }; - Irq_session_component _irq { _resources }; - - public: - - Device_component(Env &env, Igd::Resources &resources) - : - _env(env), _resources(resources) + _env(env), + _gttmmadr_io(gttmmadr_ds_cap), + _gttmmadr_range(gttmmadr_range), + _gmadr_io(gmadr_ds_cap), + _gmadr_range(gmadr_range), + _irq(ack_handler) { _env.ep().rpc_ep().manage(&_gttmmadr_io); _env.ep().rpc_ep().manage(&_gmadr_io); @@ -130,69 +129,31 @@ class Platform::Device_component : public Rpc_object _env.ep().rpc_ep().dissolve(&_irq); } - Irq_session_capability irq(uint8_t) override + Irq_session_capability irq(unsigned) { return _irq.cap(); } - Io_mem_session_capability io_mem(uint8_t v_id, Cache /* caching */, - addr_t /* offset */, - size_t /* size */) override + Io_mem_session_capability io_mem(unsigned idx, + Range & range, + Cache /* ignore caching */) { - if (v_id == 0) - return _gttmmadr_io.cap(); + range.start = 0; - if (v_id == 1) + if (idx == 0) { + range.size = _gttmmadr_range.size; + return _gttmmadr_io.cap(); + } + + if (idx == 1) { + range.size = _gmadr_range.size; return _gmadr_io.cap(); + } return Io_mem_session_capability(); } - void bus_address(unsigned char *bus, unsigned char *dev, - unsigned char *fn) override - { - _device.bus_address(bus, dev, fn); - } - - unsigned short vendor_id() override - { - return _device.vendor_id(); - } - - unsigned short device_id() override - { - return _device.device_id(); - } - - unsigned class_code() override - { - return _device.class_code(); - } - - Resource resource(int resource_id) override - { - /* bar 0 is io mem/gtt */ - if (resource_id == 0) - return Resource(_resources.gttmmadr_base(), _resources.gttmmadr_size()); - - /* bar 2 is GMADR (i.e., aperture) */ - if(resource_id == 2) - return Resource(_resources.gmadr_base(), _resources.gmadr_platform_size()); - - return Resource(); - } - - unsigned config_read(unsigned char address, Access_size size) override - { - return _device.config_read(address, size); - } - - void config_write(unsigned char /* address */, unsigned /* value */, - Access_size/* size */) override - { - } - - Io_port_session_capability io_port(uint8_t /* id */) override + Io_port_session_capability io_port_range(unsigned /* id */) { Genode::error(__func__, " is not supported"); return Io_port_session_capability(); @@ -206,37 +167,47 @@ class Platform::Session_component : public Rpc_object { private: - Env &_env; - Device_component _device_component; - Connection &_platform; - Device_capability _bridge; - Igd::Resources &_resources; - - struct Dma_cap - { - Ram_dataspace_capability cap; - - Dma_cap(Ram_dataspace_capability cap) - : cap(cap) { } - - virtual ~Dma_cap() { } - }; + Env & _env; + Connection & _platform; + Gpu_reset_handler & _reset_handler; + Heap _heap { _env.ram(), _env.rm() }; + Device_component _device_component; + bool _acquired { false }; /* * track DMA memory allocations so we can free them at session * destruction */ - Registry> _dma_registry { }; + struct Buffer : Dma_buffer, Registry::Element + { + Buffer(Registry & registry, + Connection & platform, + size_t size, + Cache cache) + : + Dma_buffer(platform, size, cache), + Registry::Element(registry, *this) {} + }; + Registry _dma_registry { }; public: - Session_component(Env &env, Igd::Resources &resources) + using Device_capability = Capability; + + Session_component(Env & env, + Connection & platform, + Irq_ack_handler & ack_handler, + Gpu_reset_handler & reset_handler, + Dataspace_capability gttmmadr_ds_cap, + Range gttmmadr_range, + Dataspace_capability gmadr_ds_cap, + Range gmadr_range) : _env(env), - _device_component(env, resources), - _platform(resources.platform()), - _bridge(resources.host_bridge_cap()), - _resources(resources) + _platform(platform), + _reset_handler(reset_handler), + _device_component(env, ack_handler, gttmmadr_ds_cap, gttmmadr_range, + gmadr_ds_cap, gmadr_range) { _env.ep().rpc_ep().manage(&_device_component); } @@ -246,72 +217,63 @@ class Platform::Session_component : public Rpc_object _env.ep().rpc_ep().dissolve(&_device_component); /* clear ggtt */ - _resources.gtt_platform_reset(); + _reset_handler.reset(); /* free DMA allocations */ - _dma_registry.for_each([&](Dma_cap &dma) { - _platform.free_dma_buffer(dma.cap); - destroy(&_resources.heap(), &dma); + _dma_registry.for_each([&](Buffer & dma) { + destroy(_heap, &dma); }); } - Device_capability first_device(unsigned device_class, unsigned) override + Device_capability acquire_single_device() override { - if (device_class == _resources.isa_bridge_class()) - return _resources.isa_bridge_cap(); + if (_acquired) + return Device_capability(); - return _bridge; - } - - Device_capability next_device(Device_capability prev_device, - unsigned, unsigned) override - { - if (!prev_device.valid()) - return _bridge; - - if (prev_device == _bridge) - return _device_component.cap(); - - if (prev_device == _device_component.cap()) - return _resources.isa_bridge_cap(); - - return Device_capability(); + _acquired = true; + return _device_component.cap(); } void release_device(Device_capability) override { - return; + _acquired = false; } - Device_capability device(Device_name const & /* string */) override + Device_capability acquire_device(Device_name const & /* string */) override { - Genode::error(__func__, " is not supported"); - return Device_capability(); + return acquire_single_device(); } Ram_dataspace_capability alloc_dma_buffer(size_t size, Cache cache) override { - Ram_dataspace_capability cap = _platform.alloc_dma_buffer(size, cache); - new (&_resources.heap()) Registered(_dma_registry, cap); - return cap; + Buffer & db = *(new (_heap) + Buffer(_dma_registry, _platform, size, cache)); + return static_cap_cast(db.cap()); } void free_dma_buffer(Ram_dataspace_capability cap) override { if (!cap.valid()) return; - _dma_registry.for_each([&](Dma_cap &dma) { - if ((dma.cap == cap) == false) return; - _platform.free_dma_buffer(cap); - destroy(&_resources.heap(), &dma); + _dma_registry.for_each([&](Buffer & db) { + if ((db.cap() == cap) == false) return; + destroy(_heap, &db); }); } addr_t dma_addr(Ram_dataspace_capability cap) override { - return _platform.dma_addr(cap); + addr_t ret = 0UL; + _dma_registry.for_each([&](Buffer & db) { + if ((db.cap() == cap) == false) return; + ret = db.dma_addr(); + }); + return ret; } + Rom_session_capability devices_rom() override { + return _platform.devices_rom(); } + bool handle_irq() { return _device_component.handle_irq(); } }; @@ -320,23 +282,83 @@ class Platform::Root : public Root_component _session { }; - Igd::Resources &_resources; public: - Root(Env &env, Allocator &md_alloc, Igd::Resources &resources) + Root(Env & env, + Allocator & md_alloc, + Connection & platform, + Irq_ack_handler & ack_handler, + Gpu_reset_handler & reset_handler, + Igd::Mmio & mmio, + Device::Mmio & gmadr, + Rm_connection & rm) : - Root_component(&env.ep().rpc_ep(), &md_alloc), - _env(env), _resources(resources) + Root_component(&env.ep().rpc_ep(), &md_alloc), + _env(env), + _platform(platform), + _ack_handler(ack_handler), + _reset_handler(reset_handler), + _gttmmadr_rm(rm.create(mmio.size())), + _gttmmadr_range{1<<30, mmio.size()}, + _gmadr_rm(rm.create(Igd::APERTURE_RESERVED)), + _gmadr_range{1<<29, gmadr.size()} { + using namespace Igd; + + /******************************** + ** Prepare managed dataspaces ** + ********************************/ + + /* GTT starts at half of the mmio memory */ + size_t const gttm_half_size = mmio.size() / 2; + off_t const gtt_offset = gttm_half_size; + + if (gttm_half_size < GTT_RESERVED) { + Genode::error("GTTM size too small"); + return; + } + + /* attach actual iomem + reserved */ + _gttmmadr_rm.attach_at(mmio.cap(), 0, gtt_offset); + + /* attach beginning of GTT */ + _gttmmadr_rm.attach_at(mmio.cap(), gtt_offset, + GTT_RESERVED, gtt_offset); + + /* attach the rest of the GTT as dummy RAM */ + Genode::Ram_dataspace_capability dummmy_gtt_ds { + _env.ram().alloc(PAGE_SIZE) }; + size_t remainder = gttm_half_size - GTT_RESERVED; + for (off_t offset = gtt_offset + GTT_RESERVED; + remainder > 0; + offset += PAGE_SIZE, remainder -= PAGE_SIZE) { + rm.retry_with_upgrade(Genode::Ram_quota{PAGE_SIZE}, + Genode::Cap_quota{8}, [&]() { + _gttmmadr_rm.attach_at(dummmy_gtt_ds, offset, PAGE_SIZE); }); + } + + _gmadr_rm.attach_at(gmadr.cap(), 0, APERTURE_RESERVED); + env.parent().announce(env.ep().manage(*this)); } Session_component *_create_session(char const * /* args */) override { - _session.construct(_env, _resources); + _session.construct(_env, _platform, _ack_handler, _reset_handler, + _gttmmadr_rm.dataspace(), _gttmmadr_range, + _gmadr_rm.dataspace(), _gmadr_range); return &*_session; } @@ -344,8 +366,8 @@ class Platform::Root : public Root_component -#include - -namespace Igd { - class Resources; -} - -struct Main; - -class Igd::Resources : Genode::Noncopyable -{ - public: - - struct Initialization_failed : Genode::Exception { }; - - private: - - using Io_mem_connection = Genode::Io_mem_connection; - using Io_mem_dataspace_capability = Genode::Io_mem_dataspace_capability; - using Ram_dataspace_capability = Genode::Ram_dataspace_capability; - using Dataspace_capability = Genode::Dataspace_capability; - - Genode::Env &_env; - Genode::Heap &_heap; - - /* timer */ - Timer::Connection _timer { _env }; - - struct Timer_delayer : Genode::Mmio::Delayer - { - Timer::Connection &_timer; - Timer_delayer(Timer::Connection &timer) : _timer(timer) { } - - void usleep(uint64_t us) override { _timer.usleep(us); } - - } _delayer { _timer }; - - /* irq callback */ - Main &_obj; - void (Main::*_ack_irq) (); - - /* platform session */ - Platform::Connection _platform { _env }; - - Platform::Device_capability _gpu_cap { }; - Platform::Device_capability _host_bridge_cap { }; - Platform::Device_capability _isa_bridge_cap { }; - Genode::Constructible _gpu_client { }; - - /* mmio + ggtt */ - Platform::Device::Resource _gttmmadr { }; - Io_mem_dataspace_capability _gttmmadr_ds { }; - Genode::Io_mem_session_capability _gttmmadr_io { }; - addr_t _gttmmadr_local { 0 }; - - Genode::Constructible _mmio { }; - - /* scratch page for ggtt */ - Ram_dataspace_capability _scratch_page_ds { - _platform.with_upgrade([&] () { - return _platform.alloc_dma_buffer(PAGE_SIZE, Genode::UNCACHED); }) }; - - addr_t _scratch_page { - _platform.dma_addr(_scratch_page_ds) }; - - /* aperture */ - enum { - /* reserved aperture for platform service */ - APERTURE_RESERVED = 64u<<20, - /* reserved GTT for platform service, GTT entry is 8 byte */ - GTT_RESERVED = (APERTURE_RESERVED/PAGE_SIZE) * 8, - }; - - Genode::Rm_connection _rm_connection { _env }; - - Platform::Device::Resource _gmadr { }; - Io_mem_dataspace_capability _gmadr_ds { }; - Genode::Io_mem_session_capability _gmadr_io { }; - Genode::Region_map_client _gmadr_rm { _rm_connection.create(APERTURE_RESERVED) }; - - - /* managed dataspace for local platform service */ - Genode::Constructible _gttmmadr_rm { }; - - void _create_gttmmadr_rm() - { - using off_t = Genode::off_t; - - size_t const gttm_half_size = gttmmadr_size() / 2; - /* GTT starts at half of the mmio memory */ - off_t const gtt_offset = gttm_half_size; - - if (gttm_half_size < GTT_RESERVED) { - Genode::error("GTTM size too small"); - return; - } - - _gttmmadr_rm.construct(_rm_connection.create((gttmmadr_size()))); - - /* attach actual iomem + reserved */ - _gttmmadr_rm->attach_at(_gttmmadr_ds, 0, gtt_offset); - - /* attach beginning of GTT */ - _gttmmadr_rm->attach_at(_gttmmadr_ds, gtt_offset, GTT_RESERVED, gtt_offset); - - /* attach the rest of the GTT as dummy RAM */ - Genode::Ram_dataspace_capability dummmy_gtt_ds { _env.ram().alloc(PAGE_SIZE) }; - size_t remainder = gttm_half_size - GTT_RESERVED; - for (off_t offset = gtt_offset + GTT_RESERVED; - remainder > 0; - offset += PAGE_SIZE, remainder -= PAGE_SIZE) { - _rm_connection.retry_with_upgrade(Genode::Ram_quota{4096}, - Genode::Cap_quota{8}, [&]() { - _gttmmadr_rm->attach_at(dummmy_gtt_ds, offset, PAGE_SIZE); - }); - } - } - - /********* - ** Pci ** - *********/ - - void _find_devices() - { - using namespace Platform; - - auto _scan_pci = [&] (Platform::Connection &pci, - Device_capability const &prev, - bool release) { - Device_capability cap = pci.with_upgrade([&]() { - return pci.next_device(prev, 0, 0); }); - - if (prev.valid() && release) { pci.release_device(prev); } - return cap; - }; - - Device_capability cap; - bool release = false; - while ((cap = _scan_pci(_platform, cap, release)).valid()) { - Device_client device(cap); - - unsigned char bus = 0xff, dev = 0xff, func = 0xff; - device.bus_address(&bus, &dev, &func); - - /* host pci bridge */ - if (bus == 0 && dev == 0 && func == 0) { - _host_bridge_cap = cap; - release = false; - continue; - } - - /* gpu */ - if ((device.class_code() >> 8) == 0x0300) { - _gpu_cap = cap; - release = false; - continue; - } - - if (device.class_code() == isa_bridge_class()) { - _isa_bridge_cap = cap; - release = false; - continue; - } - - release = true; - } - } - - bool _mch_enabled() - { - using namespace Platform; - - if (!_host_bridge_cap.valid()) { return false; } - - Device_client device(_host_bridge_cap); - - /* - * 5th Gen Core Processor datasheet vol 2 p. 48 - */ - enum { MCHBAR_OFFSET = 0x48, }; - struct MCHBAR : Genode::Register<64> - { - struct Mchbaren : Bitfield<0, 1> { }; - }; - - MCHBAR::access_t const v = device.config_read(MCHBAR_OFFSET, - Platform::Device::ACCESS_32BIT); - return MCHBAR::Mchbaren::get(v); - } - - template - static Platform::Device::Access_size _access_size(T) - { - switch (sizeof(T)) { - case 1: return Platform::Device::ACCESS_8BIT; - case 2: return Platform::Device::ACCESS_16BIT; - default: return Platform::Device::ACCESS_32BIT; - } - } - - void _enable_pci_bus_master() - { - enum { - PCI_CMD_REG = 4, - PCI_BUS_MASTER = 1<<2, - }; - - uint16_t cmd = config_read(PCI_CMD_REG); - cmd |= PCI_BUS_MASTER; - config_write(PCI_CMD_REG, cmd); - } - - public: - - Resources(Genode::Env &env, Genode::Heap &heap, - Main &obj, void (Main::*ack_irq) ()) - : - _env(env), _heap(heap), _obj(obj), _ack_irq(ack_irq) - { - /* initial donation for device pd */ - _platform.upgrade_ram(1024*1024); - - _find_devices(); - if (!_gpu_cap.valid() || !_mch_enabled()) { - throw Initialization_failed(); - } - - _gpu_client.construct(_gpu_cap); - - /* - * The intel display driver (as client of this gpu driver) - * uses the platform.io_mem() cap interface to obtain the io_mem - * capabilities. The need for directly handling with the physical - * io_mem addresses is not desired and the legacy path. So dummy - * addresses are used here just as placeholder for implementing - * the platform.resource() RPC interface. - */ - - _gttmmadr_io = _gpu_client->io_mem(0); - _gttmmadr_ds = Genode::Io_mem_session_client(_gttmmadr_io).dataspace(); - _gttmmadr = Platform::Device::Resource(1u << 30 /* dummy */, - Genode::Dataspace_client(_gttmmadr_ds).size()); - - _gmadr_io = _gpu_client->io_mem(1, Genode::Cache::WRITE_COMBINED); - _gmadr_ds = Genode::Io_mem_session_client(_gmadr_io).dataspace(); - _gmadr_rm.attach_at(_gmadr_ds, 0, APERTURE_RESERVED); - _gmadr = Platform::Device::Resource(1u << 29 /* dummy */, - Genode::Dataspace_client(_gmadr_ds).size()); - - _enable_pci_bus_master(); - - log("Reserved beginning ", - Genode::Number_of_bytes(APERTURE_RESERVED), - " of aperture for platform service"); - } - - ~Resources() - { - _platform.release_device(_gpu_cap); - _platform.release_device(_host_bridge_cap); - } - - Genode::Rm_connection &rm() { return _rm_connection; } - - addr_t map_gttmmadr() - { - if (!_gttmmadr_ds.valid()) - throw Initialization_failed(); - - if (_gttmmadr_local) return _gttmmadr_local; - - _gttmmadr_local = (addr_t)(_env.rm().attach(_gttmmadr_ds, _gttmmadr.size())); - - log("Map res:", 0, - " base:", Genode::Hex(_gttmmadr.base()), - " size:", Genode::Hex(_gttmmadr.size()), - " vaddr:", Genode::Hex(_gttmmadr_local)); - - return _gttmmadr_local; - } - - template - T config_read(unsigned int const devfn) - { - T val = 0; - _platform.with_upgrade([&] () { - val = _gpu_client->config_read(devfn, _access_size(val)); - }); - - return val; - } - - template - void config_write(unsigned int const devfn, T val) - { - _platform.with_upgrade([&] () { - _gpu_client->config_write(devfn, val, _access_size(val)); - }); - } - - void ack_irq() { (_obj.*_ack_irq)(); } - - Genode::Heap &heap() { return _heap; } - Timer::Connection &timer() { return _timer; }; - addr_t scratch_page() const { return _scratch_page; } - - Platform::Connection &platform() { return _platform; } - Platform::Device_client &gpu_client() { return *_gpu_client; } - Platform::Device_capability host_bridge_cap() { return _host_bridge_cap; } - Platform::Device_capability isa_bridge_cap() { return _isa_bridge_cap; } - unsigned isa_bridge_class() const { return 0x601u << 8; } - - addr_t gmadr_base() const { return _gmadr.base(); } - size_t gmadr_size() const { return _gmadr.size(); } - Dataspace_capability gmadr_ds() const { return _gmadr_ds; } - - addr_t gttmmadr_base() const { return _gttmmadr.base(); } - size_t gttmmadr_size() const { return _gttmmadr.size(); } - - size_t gmadr_platform_size() const { return APERTURE_RESERVED; } - size_t gttmmadr_platform_size() const { return GTT_RESERVED; } - - Io_mem_dataspace_capability gttmmadr_platform_ds() - { - using namespace Genode; - - if (!_gttmmadr_rm.constructed()) - _create_gttmmadr_rm(); - - if (!_gttmmadr_rm.constructed()) - return { }; - - return static_cap_cast(_gttmmadr_rm->dataspace()); - } - - Io_mem_dataspace_capability gmadr_platform_ds() - { - using namespace Genode; - return static_cap_cast(_gmadr_rm.dataspace()); - } - - void gtt_platform_reset() - { - addr_t const base = map_gttmmadr() + (gttmmadr_size() / 2); - Igd::Ggtt(mmio(), base, gttmmadr_platform_size(), 0, scratch_page(), 0); - } - - Igd::Mmio &mmio() - { - if (!_mmio.constructed()) - _mmio.construct(_delayer, map_gttmmadr()); - - return *_mmio; - } -}; - diff --git a/repos/os/src/drivers/gpu/intel/types.h b/repos/os/src/drivers/gpu/intel/types.h index 4a839d818c..1c2ec0b957 100644 --- a/repos/os/src/drivers/gpu/intel/types.h +++ b/repos/os/src/drivers/gpu/intel/types.h @@ -28,7 +28,13 @@ namespace Igd { using addr_t = Genode::addr_t; using size_t = Genode::size_t; - enum { PAGE_SIZE = 4096, }; + enum { + PAGE_SIZE = 4096, + /* reserved aperture for platform service */ + APERTURE_RESERVED = 64u<<20, + /* reserved GTT for platform service, GTT entry is 8 byte */ + GTT_RESERVED = (APERTURE_RESERVED/PAGE_SIZE) * 8, + }; inline void wmb() { asm volatile ("sfence": : :"memory"); } }