diff --git a/os/src/drivers/acpi/acpi.cc b/os/src/drivers/acpi/acpi.cc index 51d2f83b5..1e9be05d5 100644 --- a/os/src/drivers/acpi/acpi.cc +++ b/os/src/drivers/acpi/acpi.cc @@ -114,6 +114,30 @@ class Irq_override : public List::Element }; +/** + * List that holds the result of the mcfg table parsing which are pointers + * to the extended pci config space - 4k for each device. + */ +class Pci_config_space : public List::Element +{ + public: + + uint32_t _bdf_start; + uint32_t _func_count; + addr_t _base; + + Pci_config_space(uint32_t bdf_start, uint32_t func_count, addr_t base) + : + _bdf_start(bdf_start), _func_count(func_count), _base(base) {} + + static List *list() + { + static List _list; + return &_list; + } + +}; + /** * ACPI table wrapper that for mapping tables to this address space */ @@ -235,6 +259,14 @@ class Table_wrapper for (; mcfg < _table->mcfg_end(); mcfg = mcfg->next()) { PINF("MCFG BASE 0x%llx seg %02x bus %02x-%02x", mcfg->base, mcfg->pci_seg, mcfg->pci_bus_start, mcfg->pci_bus_end); + + /* bus_count * up to 32 devices * 8 function per device * 4k */ + uint32_t bus_count = mcfg->pci_bus_end - mcfg->pci_bus_start + 1; + uint32_t func_count = bus_count * 32 * 8; + uint32_t bus_start = mcfg->pci_bus_start * 32 * 8; + + Pci_config_space::list()->insert( + new (env()->heap()) Pci_config_space(bus_start, func_count, mcfg->base)); } } @@ -867,6 +899,34 @@ class Element : public List::Element } throw -1; } + + static void create_config_file(char * text, size_t max) + { + Pci_config_space *e = Pci_config_space::list()->first(); + + int len = snprintf(text, max, ""); + text += len; + max -= len; + for (; e; e = e->next()) + { + using namespace Genode; + len = snprintf(text, max, "%u", e->_bdf_start); + text += len; + max -= len; + len = snprintf(text, max, "%u" , e->_func_count); + text += len; + max -= len; + len = snprintf(text, max, "0x%lx" , e->_base); + text += len; + max -= len; + } + len = snprintf(text, max, ""); + text += len; + max -= len; + + if (max < 2) + PERR("config file could not be generated, buffer to small"); + } }; @@ -960,7 +1020,6 @@ class Acpi_table table.parse_madt(); } - if (table.is_mcfg()) { PDBG("Found MCFG"); @@ -1200,22 +1259,38 @@ static void dump_rewrite(uint32_t bdf, uint8_t line, uint8_t gsi) (bdf >> 8), (bdf >> 3) & 0x1f, (bdf & 0x7), line, gsi); } +/** + * Parse acpi table + */ +static void init_acpi_table() { + static Acpi_table table; +} + +/** + * Create config file for pci_drv + */ +void Acpi::create_pci_config_file(char * config_space, + Genode::size_t config_space_max) +{ + init_acpi_table(); + Element::create_config_file(config_space, config_space_max); +} /** * Rewrite GSIs of PCI config space */ -void Acpi::rewrite_irq(Pci::Session_capability &session) +void Acpi::configure_pci_devices(Pci::Session_capability &session) { - static Acpi_table table; + init_acpi_table(); static Pci_bridge bridge(session); - /* if no _PIC method could be found return */ - if (Element::supported_acpi_format()) - PINF("ACPI table format is supported by this driver"); - else { - PWRN("ACPI table format not supported will not rewrite GSIs"); - return; - } + /* if no _PIC method could be found don't rewrite */ + bool acpi_rewrite = Element::supported_acpi_format(); + + if (acpi_rewrite) + PINF("ACPI table format is supported - rewrite GSIs"); + else + PWRN("ACPI table format not supported - will not rewrite GSIs"); Pci::Session_client pci(session); Pci::Device_capability device_cap = pci.first_device(), prev_device_cap; @@ -1224,7 +1299,8 @@ void Acpi::rewrite_irq(Pci::Session_capability &session) prev_device_cap = device_cap; Pci_client device(device_cap); - if (!device.is_bridge()) { + /* rewrite IRQs */ + if (acpi_rewrite && !device.is_bridge()) { uint32_t device_bdf = device.bdf(); uint32_t bridge_bdf = Pci_bridge::bridge_bdf(device_bdf); uint32_t irq_pin = device.irq_pin(); @@ -1241,6 +1317,7 @@ void Acpi::rewrite_irq(Pci::Session_capability &session) device_cap = pci.next_device(device_cap); pci.release_device(prev_device_cap); } + } diff --git a/os/src/drivers/acpi/acpi.h b/os/src/drivers/acpi/acpi.h index 2685fd281..3ec9be424 100644 --- a/os/src/drivers/acpi/acpi.h +++ b/os/src/drivers/acpi/acpi.h @@ -22,14 +22,27 @@ class Acpi public: /** - * Rewrite PCI-config space with GSIs found in ACPI tables + * Constructor */ - static void rewrite_irq(Pci::Session_capability &session); + Acpi(); + + /** + * Generate config file for pci_drv containing pointers to the + * extended PCI config space (since PCI Express) + */ + static void create_pci_config_file(char * config_space, + Genode::size_t config_space_max); + + /** + * Rewrite PCI-config space with GSIs found in ACPI tables. + */ + static void configure_pci_devices(Pci::Session_capability &session); /** * Return override GSI for IRQ */ static unsigned override(unsigned irq, unsigned *mode); + }; #endif /* _ACPI_H_ */ diff --git a/os/src/drivers/acpi/main.cc b/os/src/drivers/acpi/main.cc index 4485a023c..86f9355c8 100644 --- a/os/src/drivers/acpi/main.cc +++ b/os/src/drivers/acpi/main.cc @@ -156,12 +156,15 @@ class Pci_policy : public Genode::Slave_policy, public Pci::Provider Genode::Root_capability _cap; Genode::Rpc_entrypoint &_pci_ep; Genode::Rpc_entrypoint &_irq_ep; + Genode::Lock _lock; protected: char const **_permitted_services() const { - static char const *permitted_services[] = { "CPU", "CAP", "RM", "LOG", "IO_PORT", 0 }; + static char const *permitted_services[] = { "CPU", "CAP", "RM", + "LOG", "IO_PORT", + "SIGNAL", 0}; return permitted_services; }; @@ -178,7 +181,7 @@ class Pci_policy : public Genode::Slave_policy, public Pci::Provider session = static_cap_cast(Root_client(_cap).session(args)); } catch (...) { return; } - Acpi::rewrite_irq(session); + Acpi::configure_pci_devices(session); /* announce PCI/IRQ services to parent */ static Pci::Root pci_root(*this); @@ -195,7 +198,9 @@ class Pci_policy : public Genode::Slave_policy, public Pci::Provider Pci_policy(Genode::Rpc_entrypoint &slave_ep, Genode::Rpc_entrypoint &pci_ep, Genode::Rpc_entrypoint &irq_ep) - : Slave_policy("pci_drv", slave_ep), _pci_ep(pci_ep), _irq_ep(irq_ep) + : + Slave_policy("pci_drv", slave_ep, Genode::env()->ram_session()), + _pci_ep(pci_ep), _irq_ep(irq_ep), _lock(Genode::Lock::LOCKED) { } bool announce_service(const char *service_name, @@ -209,12 +214,20 @@ class Pci_policy : public Genode::Slave_policy, public Pci::Provider _cap = root; - /* connect session and start ACPI parsing */ - _acpi_session(); + /* unblock main thread blocked in wait_for_pci_drv */ + _lock.unlock(); return true; } + void wait_for_pci_drv() { + /* wait until pci drv is ready */ + _lock.lock(); + + /* connect session and start ACPI parsing */ + _acpi_session(); + } + Genode::Root_capability root() { return _cap; } }; @@ -224,6 +237,7 @@ int main(int argc, char **argv) using namespace Genode; enum { STACK_SIZE = 2*4096 }; + static Cap_connection cap; static Rpc_entrypoint ep(&cap, STACK_SIZE, "acpi_ep"); @@ -234,8 +248,18 @@ int main(int argc, char **argv) /* use 'pci_drv' as slave service */ static Rpc_entrypoint pci_ep(&cap, STACK_SIZE, "pci_slave"); static Pci_policy pci_policy(pci_ep, ep, irq_ep); + + /* generate config file for pci_drv */ + char buf[256]; + Acpi::create_pci_config_file(buf, sizeof(buf)); + pci_policy.configure(buf); + + /* use 'pci_drv' as slave service */ static Genode::Slave pci_slave(pci_ep, pci_policy, 1024 * 1024); + /* wait until pci drv is online and then make the acpi work */ + pci_policy.wait_for_pci_drv(); + Genode::sleep_forever(); return 0; } diff --git a/os/src/drivers/acpi/x86/target.mk b/os/src/drivers/acpi/x86/target.mk index b41b79351..e7ec37b17 100644 --- a/os/src/drivers/acpi/x86/target.mk +++ b/os/src/drivers/acpi/x86/target.mk @@ -1,4 +1,4 @@ -TARGET = acpi_drv + TARGET = acpi_drv REQUIRES = x86 SRC_CC = main.cc acpi.cc LIBS = base