mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-24 07:46:42 +00:00
parent
03cec5cdd7
commit
250275fbfb
@ -21,10 +21,7 @@
|
|||||||
#include <mmio.h>
|
#include <mmio.h>
|
||||||
|
|
||||||
|
|
||||||
namespace Igd {
|
namespace Igd { struct Ggtt; }
|
||||||
|
|
||||||
struct Ggtt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global Graphics Translation Table
|
* Global Graphics Translation Table
|
||||||
@ -57,6 +54,12 @@ class Igd::Ggtt
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Noncopyable
|
||||||
|
*/
|
||||||
|
Ggtt(Ggtt const &);
|
||||||
|
Ggtt &operator = (Ggtt const &);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IHD-OS-BDW-Vol 5-11.15 p. 44
|
* IHD-OS-BDW-Vol 5-11.15 p. 44
|
||||||
*/
|
*/
|
||||||
@ -113,7 +116,8 @@ class Igd::Ggtt
|
|||||||
|
|
||||||
uint64_t *_entries;
|
uint64_t *_entries;
|
||||||
|
|
||||||
addr_t const _scratch_page;
|
Platform::Dma_buffer _scratch_page;
|
||||||
|
|
||||||
size_t const _aperture_size;
|
size_t const _aperture_size;
|
||||||
size_t const _aperture_entries;
|
size_t const _aperture_entries;
|
||||||
|
|
||||||
@ -133,6 +137,7 @@ class Igd::Ggtt
|
|||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
|
* \param platform reference to Platform::Connection object
|
||||||
* \param mmio reference to Igd::Mmio object
|
* \param mmio reference to Igd::Mmio object
|
||||||
* \param base virtual base address of GGTT start
|
* \param base virtual base address of GGTT start
|
||||||
* \param size size of GGTT in bytes
|
* \param size size of GGTT in bytes
|
||||||
@ -140,9 +145,8 @@ class Igd::Ggtt
|
|||||||
* \param scratch_page physical address of the scratch page
|
* \param scratch_page physical address of the scratch page
|
||||||
* \param fb_size size of the framebuffer region in the GTT in bytes
|
* \param fb_size size of the framebuffer region in the GTT in bytes
|
||||||
*/
|
*/
|
||||||
Ggtt(Igd::Mmio &mmio, addr_t base, size_t size,
|
Ggtt(Platform::Connection & platform, Igd::Mmio &mmio,
|
||||||
size_t aperture_size, addr_t scratch_page,
|
addr_t base, size_t size, size_t aperture_size, size_t fb_size)
|
||||||
size_t fb_size)
|
|
||||||
:
|
:
|
||||||
_mmio(mmio),
|
_mmio(mmio),
|
||||||
_base(base),
|
_base(base),
|
||||||
@ -150,7 +154,7 @@ class Igd::Ggtt
|
|||||||
/* make the last entry/page unavailable */
|
/* make the last entry/page unavailable */
|
||||||
_num_entries((_size / 8) - 1),
|
_num_entries((_size / 8) - 1),
|
||||||
_entries((uint64_t*)_base),
|
_entries((uint64_t*)_base),
|
||||||
_scratch_page(scratch_page),
|
_scratch_page(platform, PAGE_SIZE, Genode::UNCACHED),
|
||||||
_aperture_size(aperture_size),
|
_aperture_size(aperture_size),
|
||||||
_aperture_entries(_aperture_size / PAGE_SIZE)
|
_aperture_entries(_aperture_size / PAGE_SIZE)
|
||||||
{
|
{
|
||||||
@ -160,7 +164,7 @@ class Igd::Ggtt
|
|||||||
_space.set(i);
|
_space.set(i);
|
||||||
}
|
}
|
||||||
for (size_t i = fb_entries; i < _num_entries; 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);
|
_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; }
|
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 **
|
** Debug interface **
|
||||||
*********************/
|
*********************/
|
||||||
@ -290,7 +287,7 @@ class Igd::Ggtt
|
|||||||
log("GGTT");
|
log("GGTT");
|
||||||
log(" vaddr:", Hex(_base), " size:", Hex(_size), " entries:", _num_entries,
|
log(" vaddr:", Hex(_base), " size:", Hex(_size), " entries:", _num_entries,
|
||||||
" used:", _space.used(), " aperture_size:", Hex(_aperture_size));
|
" 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; }
|
if (!dump_entries) { return; }
|
||||||
|
|
||||||
|
@ -24,10 +24,8 @@
|
|||||||
#include <dataspace/client.h>
|
#include <dataspace/client.h>
|
||||||
#include <gpu_session/gpu_session.h>
|
#include <gpu_session/gpu_session.h>
|
||||||
#include <gpu/info_intel.h>
|
#include <gpu/info_intel.h>
|
||||||
#include <io_mem_session/connection.h>
|
#include <platform_session/dma_buffer.h>
|
||||||
#include <irq_session/connection.h>
|
#include <platform_session/device.h>
|
||||||
#include <legacy/x86/platform_device/client.h>
|
|
||||||
#include <legacy/x86/platform_session/connection.h>
|
|
||||||
#include <root/component.h>
|
#include <root/component.h>
|
||||||
#include <timer_session/connection.h>
|
#include <timer_session/connection.h>
|
||||||
#include <util/fifo.h>
|
#include <util/fifo.h>
|
||||||
@ -42,12 +40,10 @@
|
|||||||
#include <ggtt.h>
|
#include <ggtt.h>
|
||||||
#include <context.h>
|
#include <context.h>
|
||||||
#include <context_descriptor.h>
|
#include <context_descriptor.h>
|
||||||
#include <resources.h>
|
|
||||||
#include <platform_session.h>
|
#include <platform_session.h>
|
||||||
#include <ring_buffer.h>
|
#include <ring_buffer.h>
|
||||||
#include <workarounds.h>
|
#include <workarounds.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
|
|
||||||
@ -78,18 +74,21 @@ struct Igd::Device
|
|||||||
struct Out_of_ram : Genode::Exception { };
|
struct Out_of_ram : Genode::Exception { };
|
||||||
struct Could_not_map_buffer : Genode::Exception { };
|
struct Could_not_map_buffer : Genode::Exception { };
|
||||||
|
|
||||||
Env &_env;
|
|
||||||
Allocator &_md_alloc;
|
|
||||||
|
|
||||||
enum { WATCHDOG_TIMEOUT = 1*1000*1000, };
|
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 **
|
** PCI **
|
||||||
*********/
|
*********/
|
||||||
|
|
||||||
Resources &_resources;
|
|
||||||
Platform::Device_client &_device { _resources.gpu_client() };
|
|
||||||
|
|
||||||
struct Pci_backend_alloc : Utils::Backend_alloc
|
struct Pci_backend_alloc : Utils::Backend_alloc
|
||||||
{
|
{
|
||||||
Platform::Connection &_pci;
|
Platform::Connection &_pci;
|
||||||
@ -98,7 +97,8 @@ struct Igd::Device
|
|||||||
|
|
||||||
Ram_dataspace_capability alloc(size_t size) override
|
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); });
|
return _pci.alloc_dma_buffer(size, Genode::UNCACHED); });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ struct Igd::Device
|
|||||||
return _pci.dma_addr(ds_cap);
|
return _pci.dma_addr(ds_cap);
|
||||||
}
|
}
|
||||||
|
|
||||||
} _pci_backend_alloc { _resources.platform() };
|
} _pci_backend_alloc { _platform };
|
||||||
|
|
||||||
|
|
||||||
Device_info _info { };
|
Device_info _info { };
|
||||||
@ -127,41 +127,9 @@ struct Igd::Device
|
|||||||
Gpu::Info_intel::Eu_total _eus { };
|
Gpu::Info_intel::Eu_total _eus { };
|
||||||
Gpu::Info_intel::Subslices _subslices { };
|
Gpu::Info_intel::Subslices _subslices { };
|
||||||
|
|
||||||
void _pci_info(String<64> const &descr) const
|
bool _supported(Xml_node & supported,
|
||||||
{
|
uint16_t dev_id,
|
||||||
using namespace Genode;
|
uint8_t rev_id)
|
||||||
|
|
||||||
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 found = false;
|
bool found = false;
|
||||||
|
|
||||||
@ -173,7 +141,7 @@ struct Igd::Device
|
|||||||
uint16_t const device = node.attribute_value("device", 0U);
|
uint16_t const device = node.attribute_value("device", 0U);
|
||||||
uint8_t const generation = node.attribute_value("generation", 0U);
|
uint8_t const generation = node.attribute_value("generation", 0U);
|
||||||
String<16> const platform = node.attribute_value("platform", String<16>("unknown"));
|
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)
|
if (vendor != 0x8086 /* Intel */ || generation < 8)
|
||||||
return;
|
return;
|
||||||
@ -188,10 +156,9 @@ struct Igd::Device
|
|||||||
if (info.platform == Igd::Device_info::Platform::UNKNOWN)
|
if (info.platform == Igd::Device_info::Platform::UNKNOWN)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (info.id == _device.device_id()) {
|
if (info.id == dev_id) {
|
||||||
_info = info;
|
_info = info;
|
||||||
_revision.value = _resources.config_read<uint8_t>(8);
|
_revision.value = rev_id;
|
||||||
_pci_info(desc.string());
|
|
||||||
|
|
||||||
found = true;
|
found = true;
|
||||||
return;
|
return;
|
||||||
@ -218,13 +185,40 @@ struct Igd::Device
|
|||||||
** GGTT **
|
** GGTT **
|
||||||
**********/
|
**********/
|
||||||
|
|
||||||
Genode::Constructible<Igd::Ggtt> _ggtt { };
|
|
||||||
|
|
||||||
/**********
|
size_t _ggtt_size()
|
||||||
** MMIO **
|
{
|
||||||
**********/
|
/*
|
||||||
|
* 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 **
|
** MEMORY **
|
||||||
@ -250,14 +244,17 @@ struct Igd::Device
|
|||||||
|
|
||||||
struct Ggtt_mmio_mapping : Ggtt::Mapping
|
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);
|
_rmc.attach_at(cap, 0, size, offset * PAGE_SIZE);
|
||||||
Ggtt::Mapping::cap = _rm.dataspace();
|
Ggtt::Mapping::cap = _rmc.dataspace();
|
||||||
Ggtt::Mapping::offset = offset;
|
Ggtt::Mapping::offset = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,10 +277,10 @@ struct Igd::Device
|
|||||||
*/
|
*/
|
||||||
Genode::Registered<Ggtt_mmio_mapping> *mem = new (&alloc)
|
Genode::Registered<Ggtt_mmio_mapping> *mem = new (&alloc)
|
||||||
Genode::Registered<Ggtt_mmio_mapping>(_ggtt_mmio_mapping_registry,
|
Genode::Registered<Ggtt_mmio_mapping>(_ggtt_mmio_mapping_registry,
|
||||||
_resources, offset, size);
|
_rm, _gmadr.cap(), offset, size);
|
||||||
for (size_t i = 0; i < size; i += PAGE_SIZE) {
|
for (size_t i = 0; i < size; i += PAGE_SIZE) {
|
||||||
addr_t const pa = phys_addr + i;
|
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;
|
return *mem;
|
||||||
@ -296,7 +293,7 @@ struct Igd::Device
|
|||||||
auto lookup_and_free = [&] (Ggtt_mmio_mapping &m) {
|
auto lookup_and_free = [&] (Ggtt_mmio_mapping &m) {
|
||||||
if (!(m.cap == cap)) { return; }
|
if (!(m.cap == cap)) { return; }
|
||||||
|
|
||||||
_ggtt->remove_pte_range(m.offset, num);
|
_ggtt.remove_pte_range(m.offset, num);
|
||||||
Genode::destroy(&alloc, &m);
|
Genode::destroy(&alloc, &m);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -420,7 +417,7 @@ struct Igd::Device
|
|||||||
:
|
:
|
||||||
device(device),
|
device(device),
|
||||||
alloc(alloc),
|
alloc(alloc),
|
||||||
offset(device._ggtt->find_free(pages, true)),
|
offset(device._ggtt.find_free(pages, true)),
|
||||||
skip(skip_pages),
|
skip(skip_pages),
|
||||||
ram_ds(device, device._alloc_dataspace(pages * PAGE_SIZE)),
|
ram_ds(device, device._alloc_dataspace(pages * PAGE_SIZE)),
|
||||||
map(device, *this, alloc),
|
map(device, *this, alloc),
|
||||||
@ -922,7 +919,7 @@ struct Igd::Device
|
|||||||
_submit_execlist(rcs);
|
_submit_execlist(rcs);
|
||||||
|
|
||||||
_active_vgpu = gpu;
|
_active_vgpu = gpu;
|
||||||
_resources.timer().trigger_once(WATCHDOG_TIMEOUT);
|
_timer.trigger_once(WATCHDOG_TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********
|
/**********
|
||||||
@ -1030,56 +1027,28 @@ struct Igd::Device
|
|||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*/
|
*/
|
||||||
Device(Genode::Env &env,
|
Device(Genode::Env & env,
|
||||||
Genode::Allocator &alloc,
|
Genode::Allocator & alloc,
|
||||||
Resources &resources,
|
Platform::Connection & platform,
|
||||||
Genode::Xml_node &supported)
|
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;
|
using namespace Genode;
|
||||||
|
|
||||||
if (!_supported(supported)) { throw Unsupported_device(); }
|
if (!_supported(supported, device_id, revision))
|
||||||
|
throw Unsupported_device();
|
||||||
|
|
||||||
/*
|
_ggtt.dump();
|
||||||
* 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<uint16_t>(PCI_GMCH_CTL);
|
|
||||||
|
|
||||||
{
|
_vgpu_avail = (_gmadr.size() - APERTURE_RESERVED) / Vgpu::APERTURE_SIZE;
|
||||||
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;
|
|
||||||
|
|
||||||
_device_reset_and_init();
|
_device_reset_and_init();
|
||||||
|
|
||||||
@ -1121,7 +1090,7 @@ struct Igd::Device
|
|||||||
/* apply generation specific workarounds */
|
/* apply generation specific workarounds */
|
||||||
apply_workarounds(_mmio, _info.generation);
|
apply_workarounds(_mmio, _info.generation);
|
||||||
|
|
||||||
_resources.timer().sigh(_watchdog_timeout_sigh);
|
_timer.sigh(_watchdog_timeout_sigh);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _clock_gating()
|
void _clock_gating()
|
||||||
@ -1363,7 +1332,7 @@ struct Igd::Device
|
|||||||
|
|
||||||
size_t const size = Genode::Dataspace_client(cap).size();
|
size_t const size = Genode::Dataspace_client(cap).size();
|
||||||
size_t const num = size / PAGE_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);
|
return map_dataspace_ggtt(guard, cap, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1464,8 +1433,6 @@ struct Igd::Device
|
|||||||
|
|
||||||
void enable_master_irq() { _mmio.enable_master_irq(); }
|
void enable_master_irq() { _mmio.enable_master_irq(); }
|
||||||
|
|
||||||
Resources &resources() { return _resources; }
|
|
||||||
|
|
||||||
private:
|
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 **
|
|
||||||
*********/
|
|
||||||
|
|
||||||
Genode::Sliced_heap _root_heap { _env.ram(), _env.rm() };
|
|
||||||
Gpu::Root _gpu_root { _env, _root_heap };
|
Gpu::Root _gpu_root { _env, _root_heap };
|
||||||
Genode::Attached_rom_dataspace _config_rom { _env, "config" };
|
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<Main> _irq_dispatcher { _env.ep(), *this,
|
||||||
|
&Main::handle_irq };
|
||||||
|
Signal_handler<Main> _config_sigh { _env.ep(), *this,
|
||||||
|
&Main::_handle_config_update };
|
||||||
|
|
||||||
Genode::Heap _device_md_alloc { _env.ram(), _env.rm() };
|
Platform::Root _platform_root { _env, _md_alloc, _platform, *this, *this,
|
||||||
Genode::Constructible<Igd::Device> _device { };
|
_mmio, _gmadr, _rm };
|
||||||
Igd::Resources _gpu_resources { _env, _device_md_alloc,
|
|
||||||
*this, &Main::ack_irq };
|
|
||||||
|
|
||||||
Genode::Irq_session_client _irq { _gpu_resources.gpu_client().irq(0) };
|
Genode::Constructible<Igd::Device> _igd_device { };
|
||||||
Genode::Signal_handler<Main> _irq_dispatcher {
|
|
||||||
_env.ep(), *this, &Main::handle_irq };
|
|
||||||
|
|
||||||
Constructible<Platform::Root> _platform_root { };
|
|
||||||
|
|
||||||
Genode::Signal_handler<Main> _config_sigh {
|
|
||||||
_env.ep(), *this, &Main::_handle_config_update };
|
|
||||||
|
|
||||||
Main(Genode::Env &env)
|
Main(Genode::Env &env)
|
||||||
:
|
:
|
||||||
@ -2180,29 +2147,33 @@ struct Main
|
|||||||
|
|
||||||
/* IRQ */
|
/* IRQ */
|
||||||
_irq.sigh(_irq_dispatcher);
|
_irq.sigh(_irq_dispatcher);
|
||||||
_irq.ack_irq();
|
|
||||||
|
|
||||||
/* GPU */
|
/* GPU */
|
||||||
_handle_config_update();
|
_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; }
|
_platform.update();
|
||||||
|
_platform.with_xml([&] (Xml_node node) {
|
||||||
if (_device.constructed()) {
|
node.with_optional_sub_node("device", [&] (Xml_node node) {
|
||||||
Genode::log("gpu device already initialized - ignore");
|
node.with_optional_sub_node("pci-config", [&] (Xml_node node) {
|
||||||
return;
|
device_id = node.attribute_value("device_id", 0U);
|
||||||
}
|
revision = node.attribute_value("revision", 0U);
|
||||||
|
gmch_ctl = node.attribute_value("intel_gmch_control", 0U);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
_device.construct(_env, _device_md_alloc, _gpu_resources, _config_rom.xml());
|
_igd_device.construct(_env, _md_alloc, _platform, _rm, _mmio,
|
||||||
_gpu_root.manage(*_device);
|
_gmadr, _config_rom.xml(), device_id,
|
||||||
|
revision, gmch_ctl);
|
||||||
|
_gpu_root.manage(*_igd_device);
|
||||||
_env.parent().announce(_env.ep().manage(_gpu_root));
|
_env.parent().announce(_env.ep().manage(_gpu_root));
|
||||||
} catch (Igd::Device::Unsupported_device) {
|
} catch (Igd::Device::Unsupported_device) {
|
||||||
Genode::warning("No supported Intel GPU detected - no GPU service");
|
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()
|
void handle_irq()
|
||||||
{
|
{
|
||||||
unsigned master = 0;
|
unsigned master = 0;
|
||||||
if (_device.constructed())
|
if (_igd_device.constructed())
|
||||||
master = _device->handle_irq();
|
master = _igd_device->handle_irq();
|
||||||
/* GPU not present forward all IRQs to platform client */
|
/* GPU not present forward all IRQs to platform client */
|
||||||
else {
|
else {
|
||||||
_platform_root->handle_irq();
|
_platform_root.handle_irq();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2228,19 +2213,25 @@ struct Main
|
|||||||
*/
|
*/
|
||||||
using Master = Igd::Mmio::MASTER_INT_CTL;
|
using Master = Igd::Mmio::MASTER_INT_CTL;
|
||||||
if (Master::De_interrupts_pending::get(master) &&
|
if (Master::De_interrupts_pending::get(master) &&
|
||||||
(_platform_root->handle_irq()))
|
(_platform_root.handle_irq()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ack_irq();
|
ack_irq();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ack_irq()
|
void ack_irq() override
|
||||||
{
|
{
|
||||||
if (_device.constructed()) {
|
if (_igd_device.constructed()) {
|
||||||
_device->enable_master_irq();
|
_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> main;
|
static Constructible<Main> main;
|
||||||
try {
|
try {
|
||||||
main.construct(env);
|
main.construct(env);
|
||||||
} catch (Igd::Resources::Initialization_failed) {
|
} catch (Initialization_failed) {
|
||||||
Genode::warning("Intel GPU resources not found.");
|
Genode::warning("Intel GPU resources not found.");
|
||||||
env.parent().exit(0);
|
env.parent().exit(0);
|
||||||
}
|
}
|
||||||
|
@ -16,19 +16,17 @@
|
|||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/log.h>
|
#include <base/log.h>
|
||||||
#include <util/mmio.h>
|
#include <platform_session/device.h>
|
||||||
|
#include <timer_session/connection.h>
|
||||||
|
|
||||||
/* local includes */
|
/* local includes */
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
|
|
||||||
namespace Igd {
|
namespace Igd { class Mmio; }
|
||||||
|
|
||||||
class Mmio;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class Igd::Mmio : public Genode::Mmio
|
class Igd::Mmio : public Platform::Device::Mmio
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -936,7 +934,13 @@ class Igd::Mmio : public Genode::Mmio
|
|||||||
|
|
||||||
private:
|
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()
|
void _fw_reset_gen8()
|
||||||
{
|
{
|
||||||
@ -1419,8 +1423,8 @@ class Igd::Mmio : public Genode::Mmio
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Mmio(Mmio::Delayer &delayer, addr_t const base)
|
Mmio(Platform::Device & device, Genode::Env & env)
|
||||||
: Genode::Mmio(base), _delayer(delayer) { }
|
: Platform::Device::Mmio(device, {0}), _delayer(env) { }
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void write_post(typename T::access_t const value)
|
void write_post(typename T::access_t const value)
|
||||||
|
@ -11,54 +11,63 @@
|
|||||||
* under the terms of the GNU Affero General Public License version 3.
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <legacy/x86/platform_session/platform_session.h>
|
#include <region_map/client.h>
|
||||||
|
#include <rm_session/connection.h>
|
||||||
|
#include <platform_session/platform_session.h>
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
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 {
|
namespace Platform {
|
||||||
class Device_component;
|
using namespace Genode;
|
||||||
class Session_component;
|
|
||||||
class Io_mem_session_component;
|
class Device_component;
|
||||||
class Io_mem_session_component_gmadr;
|
class Session_component;
|
||||||
class Irq_session_component;
|
class Io_mem_session_component;
|
||||||
class Root;
|
class Irq_session_component;
|
||||||
|
class Root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using Range = Platform::Device_interface::Range;
|
||||||
|
|
||||||
|
struct Main;
|
||||||
|
|
||||||
class Platform::Irq_session_component : public Rpc_object<Irq_session>
|
class Platform::Irq_session_component : public Rpc_object<Irq_session>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Igd::Resources &_resources;
|
Irq_ack_handler & _ack_handler;
|
||||||
Signal_context_capability _sigh { };
|
Signal_context_capability _sigh { };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Irq_session_component(Igd::Resources &resources)
|
Irq_session_component(Irq_ack_handler & ack_handler)
|
||||||
:
|
: _ack_handler(ack_handler) { }
|
||||||
_resources(resources)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void ack_irq() override
|
void ack_irq() override { _ack_handler.ack_irq(); }
|
||||||
{
|
|
||||||
_resources.ack_irq();
|
|
||||||
}
|
|
||||||
|
|
||||||
void sigh(Signal_context_capability sigh) override
|
void sigh(Signal_context_capability sigh) override {
|
||||||
{
|
_sigh = sigh; }
|
||||||
_sigh = sigh;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool handle_irq()
|
bool handle_irq()
|
||||||
{
|
{
|
||||||
if (!_sigh.valid()) return false;
|
if (!_sigh.valid()) return false;
|
||||||
Signal_transmitter(_sigh).submit();
|
Signal_transmitter(_sigh).submit();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Info info() override
|
Info info() override {
|
||||||
{
|
return Info { Info::INVALID, 0, 0 }; }
|
||||||
return Info { Info::INVALID, 0, 0 };
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -66,57 +75,47 @@ class Platform::Io_mem_session_component : public Rpc_object<Io_mem_session>
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Igd::Resources &_resources;
|
Io_mem_dataspace_capability _ds_cap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Io_mem_session_component(Igd::Resources &resources)
|
Io_mem_session_component(Dataspace_capability cap)
|
||||||
:
|
: _ds_cap(static_cap_cast<Io_mem_dataspace>(cap)) { }
|
||||||
_resources(resources) { }
|
|
||||||
|
|
||||||
Io_mem_dataspace_capability dataspace() override
|
Io_mem_dataspace_capability dataspace() override
|
||||||
{
|
{
|
||||||
return _resources.gttmmadr_platform_ds();
|
return _ds_cap;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Platform::Io_mem_session_component_gmadr : public Rpc_object<Io_mem_session>
|
class Platform::Device_component : public Rpc_object<Device_interface,
|
||||||
|
Device_component>
|
||||||
{
|
{
|
||||||
private:
|
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:
|
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) { }
|
_env(env),
|
||||||
|
_gttmmadr_io(gttmmadr_ds_cap),
|
||||||
Io_mem_dataspace_capability dataspace() override
|
_gttmmadr_range(gttmmadr_range),
|
||||||
{
|
_gmadr_io(gmadr_ds_cap),
|
||||||
return _resources.gmadr_platform_ds();
|
_gmadr_range(gmadr_range),
|
||||||
}
|
_irq(ack_handler)
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Platform::Device_component : public Rpc_object<Device>
|
|
||||||
{
|
|
||||||
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.ep().rpc_ep().manage(&_gttmmadr_io);
|
_env.ep().rpc_ep().manage(&_gttmmadr_io);
|
||||||
_env.ep().rpc_ep().manage(&_gmadr_io);
|
_env.ep().rpc_ep().manage(&_gmadr_io);
|
||||||
@ -130,69 +129,31 @@ class Platform::Device_component : public Rpc_object<Device>
|
|||||||
_env.ep().rpc_ep().dissolve(&_irq);
|
_env.ep().rpc_ep().dissolve(&_irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
Irq_session_capability irq(uint8_t) override
|
Irq_session_capability irq(unsigned)
|
||||||
{
|
{
|
||||||
return _irq.cap();
|
return _irq.cap();
|
||||||
}
|
}
|
||||||
|
|
||||||
Io_mem_session_capability io_mem(uint8_t v_id, Cache /* caching */,
|
Io_mem_session_capability io_mem(unsigned idx,
|
||||||
addr_t /* offset */,
|
Range & range,
|
||||||
size_t /* size */) override
|
Cache /* ignore caching */)
|
||||||
{
|
{
|
||||||
if (v_id == 0)
|
range.start = 0;
|
||||||
return _gttmmadr_io.cap();
|
|
||||||
|
|
||||||
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 _gmadr_io.cap();
|
||||||
|
}
|
||||||
|
|
||||||
return Io_mem_session_capability();
|
return Io_mem_session_capability();
|
||||||
}
|
}
|
||||||
|
|
||||||
void bus_address(unsigned char *bus, unsigned char *dev,
|
Io_port_session_capability io_port_range(unsigned /* id */)
|
||||||
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
|
|
||||||
{
|
{
|
||||||
Genode::error(__func__, " is not supported");
|
Genode::error(__func__, " is not supported");
|
||||||
return Io_port_session_capability();
|
return Io_port_session_capability();
|
||||||
@ -206,37 +167,47 @@ class Platform::Session_component : public Rpc_object<Session>
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Env &_env;
|
Env & _env;
|
||||||
|
Connection & _platform;
|
||||||
|
Gpu_reset_handler & _reset_handler;
|
||||||
|
Heap _heap { _env.ram(), _env.rm() };
|
||||||
Device_component _device_component;
|
Device_component _device_component;
|
||||||
Connection &_platform;
|
bool _acquired { false };
|
||||||
Device_capability _bridge;
|
|
||||||
Igd::Resources &_resources;
|
|
||||||
|
|
||||||
struct Dma_cap
|
|
||||||
{
|
|
||||||
Ram_dataspace_capability cap;
|
|
||||||
|
|
||||||
Dma_cap(Ram_dataspace_capability cap)
|
|
||||||
: cap(cap) { }
|
|
||||||
|
|
||||||
virtual ~Dma_cap() { }
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* track DMA memory allocations so we can free them at session
|
* track DMA memory allocations so we can free them at session
|
||||||
* destruction
|
* destruction
|
||||||
*/
|
*/
|
||||||
Registry<Registered<Dma_cap>> _dma_registry { };
|
struct Buffer : Dma_buffer, Registry<Buffer>::Element
|
||||||
|
{
|
||||||
|
Buffer(Registry<Buffer> & registry,
|
||||||
|
Connection & platform,
|
||||||
|
size_t size,
|
||||||
|
Cache cache)
|
||||||
|
:
|
||||||
|
Dma_buffer(platform, size, cache),
|
||||||
|
Registry<Buffer>::Element(registry, *this) {}
|
||||||
|
};
|
||||||
|
Registry<Buffer> _dma_registry { };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Session_component(Env &env, Igd::Resources &resources)
|
using Device_capability = Capability<Platform::Device_interface>;
|
||||||
|
|
||||||
|
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),
|
_env(env),
|
||||||
_device_component(env, resources),
|
_platform(platform),
|
||||||
_platform(resources.platform()),
|
_reset_handler(reset_handler),
|
||||||
_bridge(resources.host_bridge_cap()),
|
_device_component(env, ack_handler, gttmmadr_ds_cap, gttmmadr_range,
|
||||||
_resources(resources)
|
gmadr_ds_cap, gmadr_range)
|
||||||
{
|
{
|
||||||
_env.ep().rpc_ep().manage(&_device_component);
|
_env.ep().rpc_ep().manage(&_device_component);
|
||||||
}
|
}
|
||||||
@ -246,72 +217,63 @@ class Platform::Session_component : public Rpc_object<Session>
|
|||||||
_env.ep().rpc_ep().dissolve(&_device_component);
|
_env.ep().rpc_ep().dissolve(&_device_component);
|
||||||
|
|
||||||
/* clear ggtt */
|
/* clear ggtt */
|
||||||
_resources.gtt_platform_reset();
|
_reset_handler.reset();
|
||||||
|
|
||||||
/* free DMA allocations */
|
/* free DMA allocations */
|
||||||
_dma_registry.for_each([&](Dma_cap &dma) {
|
_dma_registry.for_each([&](Buffer & dma) {
|
||||||
_platform.free_dma_buffer(dma.cap);
|
destroy(_heap, &dma);
|
||||||
destroy(&_resources.heap(), &dma);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Device_capability first_device(unsigned device_class, unsigned) override
|
Device_capability acquire_single_device() override
|
||||||
{
|
{
|
||||||
if (device_class == _resources.isa_bridge_class())
|
if (_acquired)
|
||||||
return _resources.isa_bridge_cap();
|
|
||||||
|
|
||||||
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();
|
return Device_capability();
|
||||||
|
|
||||||
|
_acquired = true;
|
||||||
|
return _device_component.cap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void release_device(Device_capability) override
|
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 acquire_single_device();
|
||||||
return Device_capability();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ram_dataspace_capability alloc_dma_buffer(size_t size, Cache cache) override
|
Ram_dataspace_capability alloc_dma_buffer(size_t size, Cache cache) override
|
||||||
{
|
{
|
||||||
Ram_dataspace_capability cap = _platform.alloc_dma_buffer(size, cache);
|
Buffer & db = *(new (_heap)
|
||||||
new (&_resources.heap()) Registered<Dma_cap>(_dma_registry, cap);
|
Buffer(_dma_registry, _platform, size, cache));
|
||||||
return cap;
|
return static_cap_cast<Ram_dataspace>(db.cap());
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_dma_buffer(Ram_dataspace_capability cap) override
|
void free_dma_buffer(Ram_dataspace_capability cap) override
|
||||||
{
|
{
|
||||||
if (!cap.valid()) return;
|
if (!cap.valid()) return;
|
||||||
|
|
||||||
_dma_registry.for_each([&](Dma_cap &dma) {
|
_dma_registry.for_each([&](Buffer & db) {
|
||||||
if ((dma.cap == cap) == false) return;
|
if ((db.cap() == cap) == false) return;
|
||||||
_platform.free_dma_buffer(cap);
|
destroy(_heap, &db);
|
||||||
destroy(&_resources.heap(), &dma);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
addr_t dma_addr(Ram_dataspace_capability cap) override
|
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(); }
|
bool handle_irq() { return _device_component.handle_irq(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -320,23 +282,83 @@ class Platform::Root : public Root_component<Session_component, Genode::Single_c
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Env &_env;
|
Env & _env;
|
||||||
|
Connection & _platform;
|
||||||
|
Irq_ack_handler & _ack_handler;
|
||||||
|
Gpu_reset_handler & _reset_handler;
|
||||||
|
Region_map_client _gttmmadr_rm;
|
||||||
|
Range _gttmmadr_range;
|
||||||
|
Region_map_client _gmadr_rm;
|
||||||
|
Range _gmadr_range;
|
||||||
|
|
||||||
Constructible<Session_component> _session { };
|
Constructible<Session_component> _session { };
|
||||||
Igd::Resources &_resources;
|
|
||||||
|
|
||||||
public:
|
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<Session_component, Genode::Single_client>(&env.ep().rpc_ep(), &md_alloc),
|
Root_component<Session_component,
|
||||||
_env(env), _resources(resources)
|
Genode::Single_client>(&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));
|
env.parent().announce(env.ep().manage(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
Session_component *_create_session(char const * /* args */) override
|
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;
|
return &*_session;
|
||||||
}
|
}
|
||||||
@ -344,7 +366,7 @@ class Platform::Root : public Root_component<Session_component, Genode::Single_c
|
|||||||
void _upgrade_session(Session_component *, const char *args) override
|
void _upgrade_session(Session_component *, const char *args) override
|
||||||
{
|
{
|
||||||
if (!_session.constructed()) return;
|
if (!_session.constructed()) return;
|
||||||
_resources.platform().upgrade({ ram_quota_from_args(args),
|
_platform.upgrade({ ram_quota_from_args(args),
|
||||||
cap_quota_from_args(args) });
|
cap_quota_from_args(args) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,370 +0,0 @@
|
|||||||
/*
|
|
||||||
* \brief GPU resource handling
|
|
||||||
* \author Sebastian Sumpf
|
|
||||||
* \author Josef Soentgen
|
|
||||||
* \date 2021-07-16
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2021 Genode Labs GmbH
|
|
||||||
*
|
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
|
||||||
* under the terms of the GNU Affero General Public License version 3.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <region_map/client.h>
|
|
||||||
#include <rm_session/connection.h>
|
|
||||||
|
|
||||||
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<Platform::Device_client> _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<Igd::Mmio> _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<Genode::Region_map_client> _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 <typename T>
|
|
||||||
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<uint16_t>(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 <typename T>
|
|
||||||
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 <typename T>
|
|
||||||
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<Io_mem_dataspace>(_gttmmadr_rm->dataspace());
|
|
||||||
}
|
|
||||||
|
|
||||||
Io_mem_dataspace_capability gmadr_platform_ds()
|
|
||||||
{
|
|
||||||
using namespace Genode;
|
|
||||||
return static_cap_cast<Io_mem_dataspace>(_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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -28,7 +28,13 @@ namespace Igd {
|
|||||||
using addr_t = Genode::addr_t;
|
using addr_t = Genode::addr_t;
|
||||||
using size_t = Genode::size_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"); }
|
inline void wmb() { asm volatile ("sfence": : :"memory"); }
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user