diff --git a/repos/base/run/platform_drv.inc b/repos/base/run/platform_drv.inc deleted file mode 100644 index 3da9f74d87..0000000000 --- a/repos/base/run/platform_drv.inc +++ /dev/null @@ -1,261 +0,0 @@ -proc have_platform_drv {} { - return [expr [have_board pc]] -} - - -## -# Return name of the USB driver binary -# -proc usb_host_drv_binary { } { - if {[have_board rpi]} { return legacy_rpi_usb_host_drv } - if {[have_board imx6q_sabrelite]} { return legacy_imx6q_sabrelite_usb_host_drv } - if {[have_board pc]} { return pc_usb_host_drv } - return no_usb_drv_available -} - - -## -# Return name of the audio driver binary -# -proc audio_drv_binary { } { - if {[have_board linux]} { return linux_audio_drv } - if {[have_board pc]} { return pci_audio_drv } - return no_audio_drv_available -} - -## -# Return attributes of the audio driver's node -# -proc audio_drv_start_attr { } { - if {[have_board linux]} { return {ld="no"} } - return "" -} - -proc acpi_drv_name { } { - global use_acpica_as_acpi_drv - if {[info exists use_acpica_as_acpi_drv] && $use_acpica_as_acpi_drv} { - return acpica } - - return acpi_drv -} - -proc platform_drv_build_components {} { - set drv_build_components "" - if {[have_board pc]} { - lappend drv_build_components drivers/platform/legacy/x86 - lappend drv_build_components server/report_rom - if {[acpi_drv_name] eq "acpi_drv"} { - lappend drv_build_components drivers/acpi - } - if {[acpi_drv_name] eq "acpica"} { - lappend drv_build_components app/acpica - } - } - return $drv_build_components -} - - -proc append_platform_drv_build_components {} { - global build_components - append build_components { } [platform_drv_build_components] -} - -proc platform_drv_binary {} { - if {[have_board pc]} { return legacy_pc_platform_drv } - return no_platform_drv_available -} - -proc platform_drv_boot_modules {} { - set drv_boot_modules "" - lappend_if [have_platform_drv] drv_boot_modules [platform_drv_binary] - - if {[have_board pc]} { - lappend drv_boot_modules report_rom - lappend drv_boot_modules [acpi_drv_name] - } - - return $drv_boot_modules -} - -proc append_platform_drv_boot_modules {} { - global boot_modules - append boot_modules { } [platform_drv_boot_modules] -} - - -proc platform_drv_policy {} { - - if {![have_board pc]} { - return {} - } - - set drv_policy "" - - if {[acpi_drv_name] eq "acpica"} { - append drv_policy { - } - } - - append drv_policy { - - - - - - - - - - - - - } - - return $drv_policy -} - - -proc platform_drv_priority {} { return "" } -proc platform_drv_add_routing {} { - - if {[acpi_drv_name] eq "acpica"} { - return { - } - } - - return "" -} - - -proc platform_drv_config_config {} { - if {[acpi_drv_name] eq "acpica"} { - return { - } - } - - return {} -} - - -proc platform_drv_config {} { - set drv_config "" - - if {[have_board pc]} { - - append drv_config { - - } - - if {[acpi_drv_name] eq "acpica"} { - append drv_config { - - } - } else { - append drv_config { - } - } - - append drv_config { - - - - - - - } - - append_if [expr {[acpi_drv_name] eq "acpica"}] drv_config { - - - - - } - - append drv_config { - - - - } - - append drv_config " - " - - append drv_config { - - - - - - - - - - } - - append_if [expr {[acpi_drv_name] eq "acpica"}] drv_config { - } - - append drv_config { - - - - - - - - } - - } - - if {[have_platform_drv]} { - - append drv_config { - - - - - } - - append_if [have_board pc] drv_config { - } - - append_if [have_spec arm] drv_config { - } - - append drv_config { - - } - - append drv_config "[platform_drv_add_routing]" - - append_if [have_board pc] drv_config { - } - - append_if [expr [have_board pc]] drv_config { - } - - append_if [expr [have_board rpi] || [have_board pc]] drv_config { - } - - append drv_config { - - } - - append drv_config [platform_drv_config_config] - append drv_config [platform_drv_policy] - - append drv_config { - - } - - } - - return $drv_config -} - - -proc append_platform_drv_config {} { - global config - append config [platform_drv_config] - return $config -} diff --git a/repos/os/include/legacy/x86/platform_device/capability.h b/repos/os/include/legacy/x86/platform_device/capability.h deleted file mode 100644 index 6fc9cd1d5c..0000000000 --- a/repos/os/include/legacy/x86/platform_device/capability.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * \brief Device capability type - * \author Norman Feske - * \date 2008-08-16 - */ - -/* - * Copyright (C) 2008-2017 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. - */ - -#pragma once - -#include -#include - -namespace Platform { typedef Genode::Capability Device_capability; } diff --git a/repos/os/include/legacy/x86/platform_device/client.h b/repos/os/include/legacy/x86/platform_device/client.h deleted file mode 100644 index 5883ec6913..0000000000 --- a/repos/os/include/legacy/x86/platform_device/client.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * \brief Client-side interface for PCI device - * \author Norman Feske - * \date 2008-01-28 - */ - -/* - * Copyright (C) 2008-2017 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. - */ - -#ifndef _INCLUDE__LEGACY__X86__PLATFORM_DEVICE__CLIENT_H_ -#define _INCLUDE__LEGACY__X86__PLATFORM_DEVICE__CLIENT_H_ - -#include -#include -#include -#include - -namespace Platform { struct Device_client; } - - -struct Platform::Device_client : public Rpc_client -{ - Device_client(Device_capability device) - : Rpc_client(device) { } - - void bus_address(unsigned char *bus, unsigned char *dev, unsigned char *fn) override { - call(bus, dev, fn); } - - unsigned short vendor_id() override { - return call(); } - - unsigned short device_id() override { - return call(); } - - unsigned class_code() override { - return call(); } - - Resource resource(int resource_id) override { - return call(resource_id); } - - unsigned config_read(unsigned char address, Access_size size) override { - return call(address, size); } - - void config_write(unsigned char address, unsigned value, Access_size size) override { - call(address, value, size); } - - Irq_session_capability irq(uint8_t id) override { - return call(id); } - - Io_port_session_capability io_port(uint8_t id) override { - return call(id); } - - Io_mem_session_capability io_mem(uint8_t id, - Cache cache = Cache::UNCACHED, - addr_t offset = 0, - size_t size = ~0UL) override { - return call(id, cache, offset, size); } -}; - -#endif /* _INCLUDE__LEGACY__X86__PLATFORM_DEVICE__CLIENT_H_ */ diff --git a/repos/os/include/legacy/x86/platform_device/device.h b/repos/os/include/legacy/x86/platform_device/device.h deleted file mode 100644 index 06f2657fd8..0000000000 --- a/repos/os/include/legacy/x86/platform_device/device.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * \brief Abstract platform device interface - * \author Alexander Boettcher - * \date 2015-03-15 - */ - -/* - * Copyright (C) 2015-2017 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. - */ - -#ifndef _INCLUDE__LEGACY__X86__PLATFORM_DEVICE__DEVICE_H_ -#define _INCLUDE__LEGACY__X86__PLATFORM_DEVICE__DEVICE_H_ - -#include -#include -#include -#include - -namespace Platform { class Abstract_device; } - -struct Platform::Abstract_device : Genode::Interface -{ - /** - * Get IRQ session capability - */ - virtual Genode::Irq_session_capability irq(Genode::uint8_t) = 0; - - /** - * Get IO mem session capability of specified resource id - */ - virtual Genode::Io_mem_session_capability io_mem(Genode::uint8_t, Genode::Cache, - Genode::addr_t, Genode::size_t) = 0; -}; - -#endif /* _INCLUDE__LEGACY__X86__PLATFORM_DEVICE__DEVICE_H_ */ diff --git a/repos/os/include/legacy/x86/platform_device/platform_device.h b/repos/os/include/legacy/x86/platform_device/platform_device.h deleted file mode 100644 index e628a5d689..0000000000 --- a/repos/os/include/legacy/x86/platform_device/platform_device.h +++ /dev/null @@ -1,262 +0,0 @@ -/* - * \brief PCI-device interface - * \author Norman Feske - * \author Christian Helmuth - * \date 2008-01-28 - */ - -/* - * Copyright (C) 2008-2017 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. - */ - -#ifndef _INCLUDE__LEGACY__X86__PLATFORM_DEVICE__PLATFORM_DEVICE_H_ -#define _INCLUDE__LEGACY__X86__PLATFORM_DEVICE__PLATFORM_DEVICE_H_ - -/* Genode includes */ -#include -#include -#include -#include -#include -#include -#include - -/* os includes */ -#include - -namespace Platform { - - using namespace Genode; - - struct Device; -} - - -struct Platform::Device : Platform::Abstract_device -{ - /********************* - ** Exception types ** - *********************/ - - class Resource - { - private: - - unsigned _bar = 0; /* content of base-address register */ - unsigned _size = 0; /* resource size */ - - public: - - /** - * Resource type, either port I/O resource or memory-mapped resource - */ - enum Type { IO, MEMORY, INVALID }; - - /** - * Default constructor - */ - Resource() { } - - /** - * Constructor - * - * \param bar content of base-address register - * \param size resource size - * - * This constructor is only used by the PCI bus driver - * that implements the server-side of the the PCI session. - * If bar is set to zero, the constructed resource description - * represents an INVALID resource. - */ - Resource(unsigned bar, unsigned size) - : _bar(bar), _size(size) { } - - /** - * Return base address of resource - */ - unsigned base() const - { - /* - * Mask out the resource-description bits of the base - * address register. I/O resources use the lowest 2 - * bits, memory resources use the lowest 4 bits. - */ - return _bar & ((type() == IO) ? ~3 : ~15); - } - - /** - * Return resource size in bytes - */ - unsigned size() const { return _size; } - - /** - * Return true if resource is prefetchable memory - */ - bool prefetchable() const - { - return type() == MEMORY && (_bar & (1 << 3)); - } - - /** - * Return resource type - */ - Type type() const - { - if (_bar == 0) - return INVALID; - - return (_bar & 1) ? IO : MEMORY; - } - - /** - * Return raw register content - */ - unsigned bar() const { return _bar; } - }; - - enum { NUM_RESOURCES = 6 }; - - virtual ~Device() { } - - /** - * Return bus, device, and function number of the device - */ - virtual void bus_address(unsigned char *bus, unsigned char *dev, - unsigned char *fn) = 0; - - /** - * Return vendor ID obtained from the PCI config space - */ - virtual unsigned short vendor_id() = 0; - - /** - * Return device ID obtained from the PCI config space - */ - virtual unsigned short device_id() = 0; - - /** - * Return device class code from the PCI config space - */ - virtual unsigned class_code() = 0; - - /** - * Query PCI-resource information - * - * \param resource_id index of according PCI resource of the device - * - * \return resource description - * \retval INVALID the supplied resource ID is invalid - */ - virtual Resource resource(int resource_id) = 0; - - /** - * Access size for operations directly accessing the config space - */ - enum Access_size { ACCESS_8BIT, ACCESS_16BIT, ACCESS_32BIT }; - - /** - * Read configuration space - */ - virtual unsigned config_read(unsigned char address, Access_size size) = 0; - - /** - * Write configuration space - * - * \throw Out_of_ram - * \throw Out_of_caps - */ - virtual void config_write(unsigned char address, unsigned value, - Access_size size) = 0; - - /** - * Query Io_port of specified bar - * - * \param id index of according PCI resource of the device - * - * \throw Out_of_ram - * \throw Out_of_caps - */ - virtual Io_port_session_capability io_port(uint8_t id) = 0; - - /* - * The base classes are defined as follows: - * - * 0x00 | legacy device - * 0x01 | mass-storage controller - * 0x02 | network controller - * 0x03 | display controller - * 0x04 | multimedia device - * 0x05 | memory controller - * 0x06 | bridge device - * 0x07 | simple-communication controller - * 0x08 | base-system peripheral - * 0x09 | input device - * 0x0a | docking station - * 0x0b | processor - * 0x0c | serial bus controller - * 0x0d | wireless controller - * 0x0e | intelligent I/O controller - * 0x0f | satellite-communications controller - * 0x10 | encryption/decryption controller - * 0x11 | data-acquisition and signal-processing controller - * 0x12 | reserved - * ... | - * 0xff | device does not fit in any of the defined classes - */ - - unsigned base_class() { return class_code() >> 16; } - unsigned sub_class() { return (class_code() >> 8) & 0xff; } - - /** - * Convenience method to translate a PCI physical BAR id to a Genode - * virtual one usable with the io_port and io_mem methods. The virtual id - * is solely valid for the specific BAR type. - */ - uint8_t phys_bar_to_virt(uint8_t phys_bar) - { - uint8_t virt_io_port = 0, virt_io_mem = 0; - - for (unsigned i = 0; i < phys_bar; i++) { - Resource::Type type = resource(i).type(); - if (type == Resource::Type::IO) - virt_io_port ++; - else if (type == Resource::Type::MEMORY) - virt_io_mem ++; - } - - Resource::Type type = resource(phys_bar).type(); - return type == Resource::Type::IO ? virt_io_port : virt_io_mem; - } - - /********************* - ** RPC declaration ** - *********************/ - - GENODE_RPC(Rpc_bus_address, void, bus_address, - unsigned char *, unsigned char *, unsigned char *); - GENODE_RPC(Rpc_vendor_id, unsigned short, vendor_id); - GENODE_RPC(Rpc_device_id, unsigned short, device_id); - GENODE_RPC(Rpc_class_code, unsigned, class_code); - GENODE_RPC(Rpc_resource, Resource, resource, int); - GENODE_RPC(Rpc_config_read, unsigned, config_read, - unsigned char, Access_size); - GENODE_RPC_THROW(Rpc_config_write, void, config_write, - GENODE_TYPE_LIST(Out_of_ram, Out_of_caps), - unsigned char, unsigned, Access_size); - GENODE_RPC(Rpc_irq, Irq_session_capability, irq, uint8_t); - GENODE_RPC_THROW(Rpc_io_port, Io_port_session_capability, io_port, - GENODE_TYPE_LIST(Out_of_ram, Out_of_caps), - uint8_t); - GENODE_RPC_THROW(Rpc_io_mem, Io_mem_session_capability, io_mem, - GENODE_TYPE_LIST(Out_of_ram, Out_of_caps), - uint8_t, Cache, addr_t, size_t); - - GENODE_RPC_INTERFACE(Rpc_bus_address, Rpc_vendor_id, Rpc_device_id, - Rpc_class_code, Rpc_resource, Rpc_config_read, - Rpc_config_write, Rpc_irq, Rpc_io_port, Rpc_io_mem); -}; - -#endif /* _INCLUDE__LEGACY__X86__PLATFORM_DEVICE__PLATFORM_DEVICE_H_ */ diff --git a/repos/os/include/legacy/x86/platform_session/capability.h b/repos/os/include/legacy/x86/platform_session/capability.h deleted file mode 100644 index d6b128b020..0000000000 --- a/repos/os/include/legacy/x86/platform_session/capability.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * \brief Platform session capability type - * \author Stefan Kalkowski - * \date 2013-04-29 - */ - -/* - * Copyright (C) 2013-2017 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. - */ - -#ifndef _INCLUDE__LEGACY__X86__PLATFORM_SESSION__CAPABILITY_H_ -#define _INCLUDE__LEGACY__X86__PLATFORM_SESSION__CAPABILITY_H_ - -#include -#include - -namespace Platform { typedef Genode::Capability Session_capability; } - -#endif /* _INCLUDE__LEGACY__X86__PLATFORM_SESSION__CAPABILITY_H_ */ diff --git a/repos/os/include/legacy/x86/platform_session/client.h b/repos/os/include/legacy/x86/platform_session/client.h deleted file mode 100644 index e3ad1016cd..0000000000 --- a/repos/os/include/legacy/x86/platform_session/client.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * \brief Client-side PCI-session interface - * \author Norman Feske - * \date 2008-01-28 - */ - -/* - * Copyright (C) 2008-2017 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. - */ - -#ifndef _INCLUDE__LEGACY__X86__PLATFORM_SESSION_H_ -#define _INCLUDE__LEGACY__X86__PLATFORM_SESSION_H_ - -#include -#include -#include - -namespace Platform { struct Client; } - - -struct Platform::Client : public Rpc_client -{ - Client(Session_capability session) : Rpc_client(session) { } - - Device_capability first_device(unsigned device_class = 0, - unsigned class_mask = 0) override { - return call(device_class, class_mask); } - - Device_capability next_device(Device_capability prev_device, - unsigned device_class = 0, - unsigned class_mask = 0) override { - return call(prev_device, device_class, class_mask); } - - void release_device(Device_capability device) override { - call(device); } - - Ram_dataspace_capability alloc_dma_buffer(size_t size, Cache cache) override { - return call(size, cache); } - - void free_dma_buffer(Ram_dataspace_capability cap) override { - call(cap); } - - addr_t dma_addr(Ram_dataspace_capability cap) override { - return call(cap); } - - Device_capability device(Device_name const &device) override { - return call(device); } -}; - -#endif /* _INCLUDE__LEGACY__X86__PLATFORM_SESSION_H_ */ diff --git a/repos/os/include/legacy/x86/platform_session/connection.h b/repos/os/include/legacy/x86/platform_session/connection.h deleted file mode 100644 index e0943e91c2..0000000000 --- a/repos/os/include/legacy/x86/platform_session/connection.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * \brief Connection to Platform service - * \author Norman Feske - * \date 2008-08-22 - */ - -/* - * Copyright (C) 2008-2017 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. - */ - -#ifndef _INCLUDE__LEGACY__X86__PLATFORM_SESSION__CONNECTION_H_ -#define _INCLUDE__LEGACY__X86__PLATFORM_SESSION__CONNECTION_H_ - -#include -#include -#include - -namespace Platform { struct Connection; } - - -struct Platform::Connection : Genode::Connection, Client -{ - /** - * Constructor - */ - Connection(Env &env) - : - Genode::Connection(env, session(env.parent(), - "ram_quota=16K, cap_quota=%u", - CAP_QUOTA)), - Client(cap()) - { } - - template - auto with_upgrade(FUNC func) -> decltype(func()) - { - return retry( - [&] () { - return retry( - [&] () { return func(); }, - [&] () { this->upgrade_caps(2); }); - }, - [&] () { this->upgrade_ram(4096); } - ); - } -}; - -#endif /* _INCLUDE__LEGACY__X86__PLATFORM_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/legacy/x86/platform_session/platform_session.h b/repos/os/include/legacy/x86/platform_session/platform_session.h deleted file mode 100644 index d8ba9a6028..0000000000 --- a/repos/os/include/legacy/x86/platform_session/platform_session.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * \brief Platform session interface - * \author Norman Feske - * \date 2008-01-28 - */ - -/* - * Copyright (C) 2008-2017 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. - */ - -#ifndef _INCLUDE__LEGACY__X86__PLATFORM_SESSION__PLATFORM_SESSION_H_ -#define _INCLUDE__LEGACY__X86__PLATFORM_SESSION__PLATFORM_SESSION_H_ - -/* Genode includes */ -#include -#include -#include - -/* os includes */ -#include -#include - -namespace Platform { struct Session; } - - -struct Platform::Session : Genode::Session -{ - /** - * \noapi - */ - static const char *service_name() { return "Platform"; } - - enum { RAM_QUOTA = 16 * 1024, CAP_QUOTA = 2 }; - - virtual ~Session() { } - - /** - * Find first accessible device - */ - virtual Device_capability first_device(unsigned, unsigned) = 0; - - /** - * Find next accessible device - * - * \param prev_device previous device - * - * The 'prev_device' argument is used to iterate through all - * devices. - */ - virtual Device_capability next_device(Device_capability prev_device, - unsigned, unsigned) = 0; - - /** - * Free server-internal data structures representing the device - * - * Use this method to relax the heap partition of your PCI session. - */ - virtual void release_device(Device_capability device) = 0; - - typedef Rpc_in_buffer<8> Device_name; - - /** - * Provide non-PCI device known by unique name - */ - virtual Device_capability device(Device_name const &string) = 0; - - /** - * Allocate memory suitable for DMA - */ - virtual Ram_dataspace_capability alloc_dma_buffer(size_t, Cache) = 0; - - /** - * Free previously allocated DMA memory - */ - virtual void free_dma_buffer(Ram_dataspace_capability) = 0; - - /** - * Return the bus address of the previously allocated DMA memory - */ - virtual addr_t dma_addr(Ram_dataspace_capability) = 0; - - /********************* - ** RPC declaration ** - *********************/ - - GENODE_RPC_THROW(Rpc_first_device, Device_capability, first_device, - GENODE_TYPE_LIST(Out_of_ram, Out_of_caps), - unsigned, unsigned); - GENODE_RPC_THROW(Rpc_next_device, Device_capability, next_device, - GENODE_TYPE_LIST(Out_of_ram, Out_of_caps), - Device_capability, unsigned, unsigned); - GENODE_RPC(Rpc_release_device, void, release_device, Device_capability); - GENODE_RPC_THROW(Rpc_alloc_dma_buffer, Ram_dataspace_capability, - alloc_dma_buffer, - GENODE_TYPE_LIST(Out_of_ram, Out_of_caps), - size_t, Cache); - GENODE_RPC(Rpc_free_dma_buffer, void, free_dma_buffer, - Ram_dataspace_capability); - GENODE_RPC(Rpc_dma_addr, addr_t, dma_addr, Ram_dataspace_capability); - GENODE_RPC_THROW(Rpc_device, Device_capability, device, - GENODE_TYPE_LIST(Out_of_ram, Out_of_caps), - Device_name const &); - - GENODE_RPC_INTERFACE(Rpc_first_device, Rpc_next_device, - Rpc_release_device, Rpc_alloc_dma_buffer, - Rpc_free_dma_buffer, Rpc_dma_addr, Rpc_device); -}; - -#endif /* _INCLUDE__LEGACY__X86__PLATFORM_SESSION__PLATFORM_SESSION_H_ */ diff --git a/repos/os/recipes/api/platform_session/content.mk b/repos/os/recipes/api/platform_session/content.mk index eab9147ce0..ea809d6d40 100644 --- a/repos/os/recipes/api/platform_session/content.mk +++ b/repos/os/recipes/api/platform_session/content.mk @@ -1,9 +1,3 @@ -INCLUDE_SUB_DIRS := platform_session \ - legacy/x86/platform_session \ - legacy/x86/platform_device - -INCLUDE_DIRS := $(addprefix include/,$(INCLUDE_SUB_DIRS)) - -MIRRORED_FROM_REP_DIR := $(INCLUDE_DIRS) +MIRRORED_FROM_REP_DIR := include/platform_session include $(REP_DIR)/recipes/api/session.inc diff --git a/repos/os/src/drivers/platform/legacy/x86/README b/repos/os/src/drivers/platform/legacy/x86/README deleted file mode 100644 index 6391dc0346..0000000000 --- a/repos/os/src/drivers/platform/legacy/x86/README +++ /dev/null @@ -1,207 +0,0 @@ -This directory contains the implementation of Genode's x86 platform driver. - -Behavior --------- - -On startup the driver scans the PCI bus hierarchy and stores the found devices. -Per client a policy must be configured that states which client can -access certain devices to form a virtual pci bus per client. The client may -iterate through the virtual pci bus using the 'first' and 'next' methods of -the platform_session interface to discover all available devices of the virtual -bus. Non PCI devices may be discovered by using 'device' of the -platform_session interface. As a result of the discovery a client obtains a -device capability. - -With the device capability the resources of the devices can be obtained, e.g. -io_port, io_mem and irq of the platform_device interface. - -Policy usage ------------- - -A policy may contain several nodes describing several devices. The entries of -a policy may describe PCI devices as non PCI devices. A PCI device is -explicitly configured by the triple 'bus', 'device', 'function': - -! -! -! ... -! -! -! -! -! -! -! ... - -or more fuzzy by a device class alias: - -! -! -! ... -! -! -! -! -! -! ... - - -Non PCI devices, as the PS2 controller are named by a "device" node in the policy: - -! -! -! -! -! -! -! -! -! ... -! -! -! ... - -The managing_system attribute is evaluated by init. If set to "yes" it -permits a component, the platform driver, to restrict the allocation of memory to -specific physical RAM ranges. The platform driver uses this feature to ensure that -the allocation of DMA capable memory consider several restrictions. For -example, some drivers, as the UHCI controller, requires a -physical memory address below 4G. Another example is that on 32bit hosts -physical to virtual identical mappings of DMA memory for the device_pd -(required when IOMMU is used) must be below the kernel memory boundary (3G). -On some systems, e.g., base-hw kernel on certain ARM platforms, it allows the -platform driver to call system management firmware via kernel syscalls. - -The platform driver waits on startup on the first valid ACPI report, typically -provided dynamically by the acpi driver. -The report contains further information about the hardware the platform driver can -not discover (e.g. IRQ re-routing information, PCI ECAM/MMCONF information). - -A specific route to a report_rom service named 'acpi_report_rom' looks as -in the following: - -! -! ... -! -! -! -! -! ... -! -! ... - -Synchronize ACPI startup and platform driver --------------------------------------------- - -If the config attribute 'acpi_ready' is set to 'yes', the platform driver -monitors a ROM in XML format named 'acpi_ready'. - -! -! - -The platform driver will announce its service not as 'Platform', but instead -as 'Acpi' first. - -An ACPI application like acpica can connect to the platform driver and may -reconfigure hardware devices according to the ACPI table findings. If the -system state changes to "acpi_ready in the XML ROM 'acpi_ready': - -! - -the platform driver will announce the platform session as 'Platform', so -that drivers may start to operate with the platform driver. - -Supported PCI class aliases ---------------------------- - -The following class names are supported which correspond to the -specified PCI base class (B), sub class (S) and programming interface -(P) combinations. ('-' matches all devices in the category) - -alias B S P - -ALL - - - -AHCI 01 06 - -AUDIO 04 01 - -ETHERNET 02 00 - -HDAUDIO 04 03 - -ISABRIDGE 06 01 - -NVME 01 08 02 -USB 0c 03 00 10 20 30 -USB4 0c 03 40 -VGA 03 00 00 -WIFI 02 80 - - -Fixups for insufficient PCI BAR configuration ---------------------------------------------- - -If PCI devices happen to miss complete configuration after boot, the -platform driver supports nodes for concrete devices -(specified by bus-device-functions tuples). As depicted below, the - node instructs the platform driver to remap BAR id 0 to address -0x4017002000, which amends the BIOS configuration and is stringently -required for BARs with address 0. - -! -! -! - - -Supported non PCI devices -------------------------- - -The driver provides for the PS2 and PIT device the IO_PORT and IRQ resources. - -! -! -! -! -! -! -! -! -! -! -! -! -! -! -! -! -! -! -! -! -! -! -! diff --git a/repos/os/src/drivers/platform/legacy/x86/acpi_devices.cc b/repos/os/src/drivers/platform/legacy/x86/acpi_devices.cc deleted file mode 100644 index ae1cf74d85..0000000000 --- a/repos/os/src/drivers/platform/legacy/x86/acpi_devices.cc +++ /dev/null @@ -1,207 +0,0 @@ -/* - * \brief ACPI device information from config - * \author Christian Helmuth - * \date 2022-05-16 - */ - -/* - * Copyright (C) 2022 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 "acpi_devices.h" - -namespace Platform { namespace Acpi { - struct Device_impl; - - typedef String<16> Str; -}} - - -void Platform::Acpi::Device::Resource::print(Output &o) const -{ - using Genode::print; - switch (type) { - case Type::IRQ: - print(o, "IRQ [", base); - print(o, " ", irq == Irq::EDGE ? "edge" : irq == Irq::LEVEL_LOW ? "level-low" : "level-high"); - print(o, "]"); - break; - case Type::IOMEM: - print(o, "IOMEM "); - print(o, "[", Hex(base, Hex::Prefix::OMIT_PREFIX, Hex::PAD)); - print(o, "-", Hex(base + (size - 1), Hex::Prefix::OMIT_PREFIX, Hex::PAD)); - print(o, "]"); - break; - case Type::IOPORT: - print(o, "IOPORT "); - print(o, "[", Hex((unsigned short)base, Hex::Prefix::OMIT_PREFIX, Hex::PAD)); - print(o, "-", Hex((unsigned short)(base + (size - 1)), Hex::Prefix::OMIT_PREFIX, Hex::PAD)); - print(o, "]"); - break; - } -} - - -class Platform::Acpi::Device_impl : private Registry::Element, - public Platform::Acpi::Device -{ - private: - - Hid _hid; /* ACPI Spec 6.1.5 Hardware ID */ - - struct Resource_element : Registry::Element - { - unsigned id; - Resource res; - - Resource_element(Registry ®istry, - unsigned id, - Resource res) - : - Registry::Element(registry, *this), - id(id), res(res) - { } - }; - - Registry _resource_registry { }; - - Resource_result _lookup_resource(Resource::Type type, unsigned const id) const - { - Resource const *res = nullptr; - _resource_registry.for_each([&] (Resource_element const &e) { - if (e.res.type == type && e.id == id) - res = &e.res; - }); - - if (res) - return *res; - else - return Invalid_resource { }; - } - - unsigned _max_irq_id { 0 }; - unsigned _max_iomem_id { 0 }; - unsigned _max_ioport_id { 0 }; - - public: - - Device_impl(Registry ®istry, - Allocator &heap, Xml_node config) - : - Registry::Element(registry, *this), - _hid(config.attribute_value("name", Hid("ACPI0000"))) - { - config.for_each_sub_node("irq", [&] (Xml_node node) { - auto irq = [&] (Str const &mode, Str const &polarity) { - if (mode == "level") { - if (polarity == "high") - return Resource::Irq::LEVEL_HIGH; - else - return Resource::Irq::LEVEL_LOW; - } else { - return Resource::Irq::EDGE; - } - }; - new (heap) - Resource_element { - _resource_registry, - _max_irq_id++, - Resource { - .type = Resource::Type::IRQ, - .base = node.attribute_value("number", addr_t(0)), - .irq = irq(node.attribute_value("mode", Str("unchanged")), - node.attribute_value("polarity", Str("unchanged"))) } }; - }); - config.for_each_sub_node("io_mem", [&] (Xml_node node) { - new (heap) - Resource_element { - _resource_registry, - _max_iomem_id++, - Resource { - .type = Resource::Type::IOMEM, - .base = node.attribute_value("address", addr_t(0)), - .size = node.attribute_value("size", size_t(0)) } }; - }); - config.for_each_sub_node("io_port_range", [&] (Xml_node node) { - new (heap) - Resource_element { - _resource_registry, - _max_ioport_id++, - Resource { - .type = Resource::Type::IOPORT, - .base = node.attribute_value("address", addr_t(0)), - .size = node.attribute_value("size", size_t(0)) } }; - }); - } - - ~Device_impl() { error("unexpected call of ", __func__); } - - /* Platform::Acpi::Device interface */ - - Hid hid() const override { return _hid; } - - Resource_result resource(unsigned idx) const override - { - /* - * Index of all IOMEM and IOPORT resources - no IRQ! - * - * first _max_iomem_id IOMEM, then _max_ioport_id IOPORT - */ - if (idx < _max_iomem_id) - return iomem(idx); - else if (idx < _max_iomem_id + _max_ioport_id) - return ioport(idx - _max_iomem_id); - else - return Invalid_resource { }; - } - - Resource_result irq(unsigned id) const override - { - return _lookup_resource(Resource::Type::IRQ, id); - } - - Resource_result iomem(unsigned id) const override - { - return _lookup_resource(Resource::Type::IOMEM, id); - } - - Resource_result ioport(unsigned id) const override - { - return _lookup_resource(Resource::Type::IOPORT, id); - } -}; - - -Platform::Acpi::Device_registry::Lookup_result -Platform::Acpi::Device_registry::lookup(Platform::Acpi::Device::Hid hid) const -{ - Device const *found = nullptr; - - this->for_each([&] (Device const &device) { - if (device.hid() == hid) - found = &device; - }); - - if (found) - return found; - else - return Lookup_failed { }; -} - - -void Platform::Acpi::Device_registry::init_devices(Allocator &heap, Xml_node config) -{ - /* init only once */ - if (_initialized) - return; - - config.for_each_sub_node("device", [&] (Xml_node node) { - if (node.attribute_value("type", Str()) == "acpi") - new (heap) Device_impl(*this, heap, node); - }); - - _initialized = true; -} diff --git a/repos/os/src/drivers/platform/legacy/x86/acpi_devices.h b/repos/os/src/drivers/platform/legacy/x86/acpi_devices.h deleted file mode 100644 index 89e7aa98e3..0000000000 --- a/repos/os/src/drivers/platform/legacy/x86/acpi_devices.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * \brief ACPI device information from config - * \author Christian Helmuth - * \date 2022-05-16 - */ - -/* - * Copyright (C) 2022 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 -#include -#include -#include - - -namespace Platform { namespace Acpi { - using namespace Genode; - - class Device; - - class Device_registry; -} } - - -struct Platform::Acpi::Device : Interface -{ - typedef String<10> Hid; /* ACPI Spec 6.1.5 Hardware ID */ - - struct Resource - { - enum class Type { IRQ, IOMEM, IOPORT }; - - enum class Irq { EDGE, LEVEL_LOW, LEVEL_HIGH }; - - Type type; - addr_t base; - - union { - size_t size; - Irq irq; - }; - - void print(Output &o) const; - }; - - enum struct Invalid_resource { }; - typedef Attempt Resource_result; - - virtual Hid hid() const = 0; - virtual Resource_result resource(unsigned idx) const = 0; - virtual Resource_result irq(unsigned id) const = 0; - virtual Resource_result iomem(unsigned id) const = 0; - virtual Resource_result ioport(unsigned id) const = 0; -}; - - -struct Platform::Acpi::Device_registry : Genode::Registry -{ - bool _initialized { false }; - - void init_devices(Allocator &heap, Xml_node config); - - enum struct Lookup_failed { }; - typedef Attempt Lookup_result; - - Lookup_result lookup(Device::Hid name) const; -}; diff --git a/repos/os/src/drivers/platform/legacy/x86/device_pd.cc b/repos/os/src/drivers/platform/legacy/x86/device_pd.cc deleted file mode 100644 index 455a9f3342..0000000000 --- a/repos/os/src/drivers/platform/legacy/x86/device_pd.cc +++ /dev/null @@ -1,117 +0,0 @@ -/* - * \brief Pci device protection domain service for platform driver - * \author Alexander Boettcher - * \date 2013-02-10 - */ - -/* - * Copyright (C) 2013-2017 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 -#include -#include -#include - -#include - -#include "device_pd.h" - -void Platform::Device_pd::attach_dma_mem(Dataspace_capability ds_cap, - addr_t const dma_addr) -{ - using namespace Genode; - - Dataspace_client ds_client(ds_cap); - - size_t const size = ds_client.size(); - - addr_t page = ~0UL; - - using Attach_dma_error = Pd_session::Attach_dma_error; - - bool retry = false; - - do { - _pd.attach_dma(ds_cap, dma_addr).with_result( - - [&] (Pd_session::Attach_dma_ok) { - - page = dma_addr; - - /* trigger eager mapping of memory */ - _pd.map(page, size); - retry = false; - }, - [&] (Attach_dma_error e) { - switch (e) { - case Attach_dma_error::OUT_OF_RAM: - _address_space.upgrade_ram(); - retry = true; - break; - case Attach_dma_error::OUT_OF_CAPS: - _address_space.upgrade_caps(); - retry = true; - break; - case Attach_dma_error::DENIED: - warning("Pd_session::attach_dma denied"); - page = dma_addr; - retry = false; - break; - } - } - ); - } while (retry); - - /* sanity check */ - if ((page == ~0UL) || (page != dma_addr)) { - if (page != ~0UL) - _address_space.detach(page); - - error(_label, ": attachment of DMA memory @ ", - Hex(dma_addr), "+", Hex(size), " " "failed page=", Hex(page)); - return; - } -} - -void Platform::Device_pd::assign_pci(Io_mem_dataspace_capability const io_mem_cap, - addr_t const offset, uint16_t const rid) -{ - Dataspace_client ds_client(io_mem_cap); - - addr_t page = _address_space.attach(io_mem_cap, 0x1000, offset); - - /* sanity check */ - if (!page) - throw Region_map::Region_conflict(); - - /* trigger eager mapping of memory */ - _pd.map(page, 0x1000); - - /* utility to print rid value */ - struct Rid - { - uint16_t const v; - explicit Rid(uint16_t rid) : v(rid) { } - void print(Output &out) const - { - using Genode::print; - print(out, Hex((uint8_t)(v >> 8), Hex::Prefix::OMIT_PREFIX, Hex::PAD), ":", - Hex((uint8_t)((v >> 3) & 0x1f), Hex::Prefix::OMIT_PREFIX, Hex::PAD), ".", - Hex(v & 0x7, Hex::Prefix::OMIT_PREFIX)); - } - }; - - /* try to assign pci device to this protection domain */ - if (!_pd.assign_pci(page, rid)) - error(_label, ": assignment of PCI device ", Rid(rid), " failed ", - "virt=", Hex(page)); - else - log(_label,": assignment of PCI device ", Rid(rid), " succeeded"); - - /* we don't need the mapping anymore */ - _address_space.detach(page); -} diff --git a/repos/os/src/drivers/platform/legacy/x86/device_pd.h b/repos/os/src/drivers/platform/legacy/x86/device_pd.h deleted file mode 100644 index 366aaac867..0000000000 --- a/repos/os/src/drivers/platform/legacy/x86/device_pd.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * \brief Device PD handling for the platform driver - * \author Alexander Boettcher - * \date 2015-11-05 - */ - -/* - * Copyright (C) 2015-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. - */ - -#ifndef _DEVICE_PD_H_ -#define _DEVICE_PD_H_ - -/* base */ -#include -#include -#include -#include -#include - -/* os */ -#include - -namespace Platform { class Device_pd; } - - -class Platform::Device_pd -{ - private: - - Pd_connection _pd; - Session_label const &_label; - - /** - * Custom handling of PD-session depletion during attach operations - * - * The default implementation of 'env.rm()' automatically issues a resource - * request if the PD session quota gets exhausted. For the device PD, we don't - * want to issue resource requests but let the platform driver reflect this - * condition to its client. - */ - struct Expanding_region_map_client : Region_map_client - { - Env &_env; - Pd_connection &_pd; - Ram_quota_guard &_ram_guard; - Cap_quota_guard &_cap_guard; - - Expanding_region_map_client(Env &env, - Pd_connection &pd, - Ram_quota_guard &ram_guard, - Cap_quota_guard &cap_guard) - : - Region_map_client(pd.address_space()), _env(env), _pd(pd), - _ram_guard(ram_guard), _cap_guard(cap_guard) - { } - - Local_addr attach(Dataspace_capability ds, - size_t size = 0, off_t offset = 0, - bool use_local_addr = false, - Local_addr local_addr = (void *)0, - bool executable = false, - bool writeable = true) override - { - return retry( - [&] () { - return retry( - [&] () { - return Region_map_client::attach(ds, size, offset, - use_local_addr, - local_addr, - executable, - writeable); }, - [&] () { - upgrade_caps(); - } - ); - }, - [&] () { - upgrade_ram(); - } - ); - } - - void upgrade_ram() - { - enum { UPGRADE_RAM_QUOTA = 4096 }; - Ram_quota const ram { UPGRADE_RAM_QUOTA }; - _ram_guard.withdraw(ram); - _env.pd().transfer_quota(_pd.rpc_cap(), ram); - } - - void upgrade_caps() - { - enum { UPGRADE_CAP_QUOTA = 2 }; - Cap_quota const caps { UPGRADE_CAP_QUOTA }; - _cap_guard.withdraw(caps); - _env.pd().transfer_quota(_pd.rpc_cap(), caps); - } - } _address_space; - - public: - - Device_pd(Env &env, - Session_label const &label, - Ram_quota_guard &ram_guard, - Cap_quota_guard &cap_guard) - : - _pd(env, Pd_connection::Device_pd()), - _label(label), - _address_space(env, _pd, ram_guard, cap_guard) - { - _pd.ref_account(env.pd_session_cap()); - } - - void attach_dma_mem(Dataspace_capability, addr_t dma_addr); - void assign_pci(Io_mem_dataspace_capability const, - addr_t const, uint16_t const); -}; - -#endif /* _DEVICE_PD_H_ */ diff --git a/repos/os/src/drivers/platform/legacy/x86/irq.cc b/repos/os/src/drivers/platform/legacy/x86/irq.cc deleted file mode 100644 index 609142475d..0000000000 --- a/repos/os/src/drivers/platform/legacy/x86/irq.cc +++ /dev/null @@ -1,296 +0,0 @@ -/* - * \brief Implementation of shared IRQs in platform driver - * \author Alexander Boettcher - * \date 2015-03-27 - */ - -/* - * Copyright (C) 2015-2017 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. - */ - -/* Genode includes */ -#include -#include -#include - -/* Platform driver include */ -#include "irq.h" -#include "pci_session_component.h" - - -namespace Platform { - class Irq_component; - class Irq_allocator; -} - - -/** - * A simple allocator implementation used by the Irq_proxy - */ -class Platform::Irq_allocator -{ - private: - - /* - * We partition the IRQ space (128 GSIs) into 40 legacy IRQs and 64 MSIs (and - * hope the partitions will never overlap on any bizarre platform.) - */ - enum { LEGACY = 40, MSI = 64, LEGACY_ARRAY = 64 }; - - Bit_array _legacy { }; - Bit_allocator _msi { }; - - public: - - Irq_allocator() - { - /* reserve the last 24 legacy IRQs - 40 IRQs remaining */ - _legacy.set(LEGACY, LEGACY_ARRAY - LEGACY); - } - - unsigned alloc_msi() - { - try { - return _msi.alloc(); - } catch (Bit_allocator::Out_of_indices) { return ~0U; } - } - - void free_msi(unsigned msi) { _msi.free(msi); } - - bool alloc_irq(addr_t addr) - { - try { - _legacy.set(addr, 1); - return true; - } catch (...) { - return false; - } - } -}; - - -/** - * One allocator for managing in use IRQ numbers and one IRQ thread waiting - * for Genode signals of all hardware IRQs. - */ -static Platform::Irq_allocator irq_alloc; - - -/** - * Irq_proxy interface implementation - */ -class Platform::Irq_component : public Platform::Irq_proxy -{ - private: - - Irq_connection _irq; - Signal_handler _irq_dispatcher; - - bool _associated; - - public: - - void _ack_irq() { - /* - * Associate handler only when required, because our partner may - * also implement shared irq and would expect to get ack_irq() - * form us even if we have no client ... - */ - if (!_associated) { - _associated = true; - /* register signal handler on irq_session */ - _irq.sigh(_irq_dispatcher); - } - - _irq.ack_irq(); - } - - virtual bool remove_sharer(Platform::Irq_sigh *s) override { - if (!Irq_proxy::remove_sharer(s)) - return false; - - /* De-associate handler. */ - _associated = false; - _irq.sigh(Signal_context_capability()); - return true; - } - - public: - - Irq_component(Env &env, unsigned gsi, - Irq_session::Trigger trigger, - Irq_session::Polarity polarity) - : - Irq_proxy(gsi), - _irq(env, gsi, trigger, polarity), - _irq_dispatcher(env.ep(), *this, &Platform::Irq_proxy::notify_about_irq), - _associated(false) - { } - - static Irq_component *get_irq_proxy(unsigned irq_number, - Irq_allocator *irq_alloc = nullptr, - Irq_session::Trigger trigger = Irq_session::TRIGGER_UNCHANGED, - Irq_session::Polarity polarity = Irq_session::POLARITY_UNCHANGED, - Env *env = nullptr, - Allocator *heap = nullptr) - { - static List proxies; - static Mutex proxies_mutex; - - Mutex::Guard mutex_guard(proxies_mutex); - - /* lookup proxy in database */ - for (Irq_proxy *p = proxies.first(); p; p = p->next()) - if (p->irq_number() == irq_number) - return static_cast(p); - - /* try to create proxy */ - if (!irq_alloc || !env || !heap || !irq_alloc->alloc_irq(irq_number)) - return 0; - - Irq_component *new_proxy = new (heap) Irq_component(*env, irq_number, trigger, - polarity); - proxies.insert(new_proxy); - return new_proxy; - } -}; - - - -/******************************* - ** PCI IRQ session component ** - *******************************/ - -void Platform::Irq_session_component::ack_irq() -{ - if (msi()) { - _msi_conn->ack_irq(); - return; - } - - /* shared irq handling */ - Irq_component *irq_obj = Irq_component::get_irq_proxy(_gsi); - if (!irq_obj) { - error("expected to find IRQ proxy for IRQ ", Hex(_gsi)); - return; - } - - if (irq_obj->ack_irq()) - irq_obj->_ack_irq(); -} - - -Platform::Irq_session_component::Irq_session_component(unsigned irq, - addr_t pci_config_space, - Env &env, - Allocator &heap, - Irq_session::Trigger trigger, - Irq_session::Polarity polarity) -: - _gsi(irq) -{ - if (pci_config_space != ~0UL) { - /* msi way */ - unsigned msi = irq_alloc.alloc_msi(); - if (msi != ~0U) { - try { - using namespace Genode; - - _msi_conn.construct(env, msi, Irq_session::TRIGGER_UNCHANGED, - Irq_session::POLARITY_UNCHANGED, - pci_config_space); - - _msi_info = _msi_conn->info(); - if (_msi_info.type == Irq_session::Info::Type::MSI) { - _gsi = msi; - return; - } - } catch (Service_denied) { } - - irq_alloc.free_msi(msi); - } - } - - /* invalid irq number for pci_devices */ - if (_gsi >= INVALID_IRQ) - return; - - _gsi = Platform::Irq_override::irq_override(_gsi, trigger, polarity); - if (_gsi != irq || trigger != Irq_session::TRIGGER_UNCHANGED || - polarity != POLARITY_UNCHANGED) { - - log("IRQ override ", irq, "->", _gsi, ", " - "trigger mode: ", trigger, ", ", "polarity: ", polarity); - } - - try { - /* check if shared IRQ object was used before */ - if (Irq_component::get_irq_proxy(_gsi, &irq_alloc, trigger, - polarity, &env, &heap)) - return; - } catch (Service_denied) { } - - error("unavailable IRQ ", Hex(_gsi), " requested"); -} - - -Platform::Irq_session_component::~Irq_session_component() -{ - if (msi()) { - _msi_conn->sigh(Signal_context_capability()); - - irq_alloc.free_msi(_gsi); - return; - } - - /* shared irq handling */ - Irq_component *irq_obj = Irq_component::get_irq_proxy(_gsi); - if (!irq_obj) return; - - if (_irq_sigh.valid()) - irq_obj->remove_sharer(&_irq_sigh); -} - - -void Platform::Irq_session_component::sigh(Signal_context_capability sigh) -{ - if (_msi_conn.constructed()) { - /* register signal handler for msi directly at parent */ - _msi_conn->sigh(sigh); - return; - } - - /* shared irq handling */ - Irq_component *irq_obj = Irq_component::get_irq_proxy(_gsi); - if (!irq_obj) { - error("signal handler got not registered - irq object unavailable"); - return; - } - - Signal_context_capability old = _irq_sigh; - - if (old.valid() && !sigh.valid()) - irq_obj->remove_sharer(&_irq_sigh); - - _irq_sigh = sigh; - - if (!old.valid() && sigh.valid()) - irq_obj->add_sharer(&_irq_sigh); -} - - -unsigned short Platform::Irq_routing::rewrite(Pci::Bdf const bdf, unsigned char pin) -{ - unsigned const bridge_bdf_bus = Platform::bridge_bdf(bdf.bus); - - for (Irq_routing *i = list()->first(); i; i = i->next()) { - if ((bdf.device == i->_device) && (pin - 1 == i->_device_pin) && - (i->_bridge_bdf == bridge_bdf_bus)) - return i->_gsi; - } - - return 0; -} diff --git a/repos/os/src/drivers/platform/legacy/x86/irq.h b/repos/os/src/drivers/platform/legacy/x86/irq.h deleted file mode 100644 index 55c2402a96..0000000000 --- a/repos/os/src/drivers/platform/legacy/x86/irq.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * \brief IRQ session interface - * \author Alexander Boettcher - * \date 2015-03-25 - */ - -/* - * Copyright (C) 2015-2017 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. - */ - -#ifndef _X86__IRQ_H_ -#define _X86__IRQ_H_ - -#include -#include -#include -#include - -/* platform local includes */ -#include -#include - - -namespace Platform { - class Irq_session_component; - class Irq_override; - class Irq_routing; -} - - -class Platform::Irq_session_component : public Rpc_object, - private List::Element -{ - private: - - friend class List; - - unsigned _gsi; - Platform::Irq_sigh _irq_sigh { }; - Irq_session::Info _msi_info { }; - - Constructible _msi_conn { }; - - public: - - enum { INVALID_IRQ = 0xffU }; - - Irq_session_component(unsigned, addr_t, Env &, Allocator &heap, - Trigger trigger = TRIGGER_UNCHANGED, - Polarity polarity = POLARITY_UNCHANGED); - - ~Irq_session_component(); - - bool msi() - { - return _msi_conn.constructed() && - _msi_info.type == Irq_session::Info::Type::MSI; - } - - unsigned gsi() { return _gsi; } - - unsigned long msi_address() const { return _msi_info.address; } - unsigned long msi_data() const { return _msi_info.value; } - - /*************************** - ** Irq session interface ** - ***************************/ - - void ack_irq() override; - void sigh(Signal_context_capability) override; - - Info info() override - { - return { .type = Info::Type::INVALID, .address = 0, .value = 0 }; - } -}; - - -/** - * List that holds interrupt override information - */ -class Platform::Irq_override : public List::Element -{ - private: - - unsigned short const _irq; /* source IRQ */ - unsigned short const _gsi; /* target GSI */ - Irq_session::Trigger const _trigger; /* interrupt trigger mode */ - Irq_session::Polarity const _polarity; /* interrupt polarity */ - - Irq_session::Trigger _mode2trigger(unsigned mode) - { - enum { EDGE = 0x4, LEVEL = 0xc }; - - switch (mode & 0xc) { - case EDGE: - return Irq_session::TRIGGER_EDGE; - case LEVEL: - return Irq_session::TRIGGER_LEVEL; - default: - return Irq_session::TRIGGER_UNCHANGED; - } - } - - Irq_session::Polarity _mode2polarity(unsigned mode) - { - using namespace Genode; - enum { HIGH = 0x1, LOW = 0x3 }; - - switch (mode & 0x3) { - case HIGH: - return Irq_session::POLARITY_HIGH; - case LOW: - return Irq_session::POLARITY_LOW; - default: - return Irq_session::POLARITY_UNCHANGED; - } - } - - public: - - Irq_override(unsigned irq, unsigned gsi, unsigned mode) - : - _irq(irq), _gsi(gsi), - _trigger(_mode2trigger(mode)), _polarity(_mode2polarity(mode)) - { } - - static List *list() - { - static List _list; - return &_list; - } - - unsigned short irq() const { return _irq; } - unsigned short gsi() const { return _gsi; } - Irq_session::Trigger trigger() const { return _trigger; } - Irq_session::Polarity polarity() const { return _polarity; } - - static unsigned irq_override(unsigned irq, - Irq_session::Trigger &trigger, - Irq_session::Polarity &polarity) - { - for (Irq_override *i = list()->first(); i; i = i->next()) - if (i->irq() == irq) { - trigger = i->trigger(); - polarity = i->polarity(); - return i->gsi(); - } - - /* trigger and polarity not touched in this case! */ - return irq; - } -}; - - -/** - * List that holds interrupt rewrite information - */ -class Platform::Irq_routing : public List::Element -{ - private: - - unsigned short _gsi; - unsigned short _bridge_bdf; - unsigned short _device; - unsigned char _device_pin; - - public: - - static List *list() - { - static List _list; - return &_list; - } - - Irq_routing(unsigned short gsi, unsigned short bridge_bdf, - unsigned char device, unsigned char device_pin) - : - _gsi(gsi), _bridge_bdf(bridge_bdf), _device(device), - _device_pin(device_pin) - { } - - static unsigned short rewrite(Pci::Bdf, unsigned char pin); -}; - -#endif /* _X86__IRQ_H_ */ diff --git a/repos/os/src/drivers/platform/legacy/x86/irq_proxy.h b/repos/os/src/drivers/platform/legacy/x86/irq_proxy.h deleted file mode 100644 index c4971e435f..0000000000 --- a/repos/os/src/drivers/platform/legacy/x86/irq_proxy.h +++ /dev/null @@ -1,141 +0,0 @@ -/** - * \brief Shared-interrupt support - * \author Christian Helmuth - * \author Sebastian Sumpf - * \date 2009-12-15 - */ - -/* - * Copyright (C) 2009-2020 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. - */ - -#ifndef _DRIVERS__PLATFORM__SPEC__X86__IRQ_PROXY_H_ -#define _DRIVERS__PLATFORM__SPEC__X86__IRQ_PROXY_H_ - -#include - -namespace Platform { - class Irq_sigh; - class Irq_proxy; -} - - -class Platform::Irq_sigh : public Signal_context_capability, - public List::Element -{ - public: - - Irq_sigh & operator= (Signal_context_capability const &cap) - { - Signal_context_capability::operator=(cap); - return *this; - } - - Irq_sigh() { } - - void notify() { Signal_transmitter(*this).submit(1); } -}; - - -/* - * Proxy thread that associates to the interrupt and unblocks waiting irqctrl - * threads. - * - * XXX resources are not accounted as the interrupt is shared - */ -class Platform::Irq_proxy : private List::Element -{ - private: - - friend class List; - - protected: - - unsigned const _irq_number; - - List _sigh_list { }; - - Mutex _mutex { }; /* protects this object */ - int _num_sharers = 0; /* number of clients sharing this IRQ */ - int _num_acknowledgers = 0; /* number of currently blocked clients */ - bool _woken_up = false; /* client decided to wake me up - - this prevents multiple wakeups - to happen during initialization */ - public: - - using List::Element::next; - - Irq_proxy(unsigned irq_number) : _irq_number(irq_number) { } - - virtual ~Irq_proxy() { } - - /** - * Acknowledgements of clients - */ - virtual bool ack_irq() - { - Mutex::Guard mutex_guard(_mutex); - - _num_acknowledgers++; - - /* - * The proxy thread has to be woken up if no client woke it up - * before and this client is the last aspired acknowledger. - */ - if (!_woken_up && _num_acknowledgers == _num_sharers) { - _woken_up = true; - } - - return _woken_up; - } - - /** - * Notify all clients about irq - */ - void notify_about_irq() - { - Mutex::Guard mutex_guard(_mutex); - - /* reset acknowledger state */ - _num_acknowledgers = 0; - _woken_up = false; - - /* inform blocked clients */ - for (Irq_sigh * s = _sigh_list.first(); s ; s = s->next()) - s->notify(); - } - - unsigned irq_number() const { return _irq_number; } - - virtual bool add_sharer(Irq_sigh *s) - { - Mutex::Guard mutex_guard(_mutex); - - ++_num_sharers; - _sigh_list.insert(s); - - return true; - } - - virtual bool remove_sharer(Irq_sigh *s) - { - Mutex::Guard mutex_guard(_mutex); - - _sigh_list.remove(s); - --_num_sharers; - - if (_woken_up) - return _num_sharers == 0; - - if (_num_acknowledgers == _num_sharers) { - _woken_up = true; - } - - return _num_sharers == 0; - } -}; - -#endif /* _DRIVERS__PLATFORM__SPEC__X86__IRQ_PROXY_H_ */ diff --git a/repos/os/src/drivers/platform/legacy/x86/main.cc b/repos/os/src/drivers/platform/legacy/x86/main.cc deleted file mode 100644 index 58c3e5e777..0000000000 --- a/repos/os/src/drivers/platform/legacy/x86/main.cc +++ /dev/null @@ -1,215 +0,0 @@ -/* - * \brief Platform driver for x86 - * \author Norman Feske - * \author Christian Helmuth - * \date 2008-01-28 - */ - -/* - * Copyright (C) 2008-2017 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 -#include -#include - -#include - -#include "pci_session_component.h" -#include "pci_device_config.h" -#include "device_pd.h" -#include "acpi_devices.h" - -namespace Platform { - struct Main; - - namespace Nonpci { void acpi_device_registry(Acpi::Device_registry &); } -}; - -struct Platform::Main -{ - Env &_env; - - Heap _heap { _env.ram(), _env.rm() }; - - Acpi::Device_registry _acpi_device_registry { }; - - /* - * Use sliced heap to allocate each session component at a separate - * dataspace. - */ - Sliced_heap sliced_heap { _env.ram(), _env.rm() }; - - Attached_rom_dataspace _config { _env, "config" }; - - Constructible acpi_rom { }; - Constructible root { }; - - Constructible system_state { }; - Constructible acpi_ready { }; - - Signal_handler
_acpi_report { _env.ep(), *this, - &Main::acpi_update }; - Signal_handler
_system_report { _env.ep(), *this, - &Main::system_update }; - Signal_handler
_config_handler { _env.ep(), *this, - &Main::config_update }; - - Capability > root_cap { }; - - bool _acpi_ready = false; - - void _attempt_acpi_reset(); - - void acpi_update() - { - if (!root.constructed()) { - acpi_rom->update(); - - if (!acpi_rom->valid()) - return; - - bool msi_platform = false; - bool acpi_platform = false; - - try { - Attached_rom_dataspace info { _env, "platform_info" }; - info.xml().with_optional_sub_node("kernel", [&] (Xml_node const &node) { - acpi_platform = node.attribute_value("acpi", acpi_platform); - msi_platform = node.attribute_value("msi" , msi_platform); - }); - } catch (...) { } - - root.construct(_env, _heap, sliced_heap, _config, - acpi_rom->local_addr(), acpi_platform, - msi_platform); - } - - if (root_cap.valid()) - return; - - /* don't announce service if no policy entry is available */ - if (!root->config_with_policy()) - return; - - root_cap = _env.ep().manage(*root); - - if (_acpi_ready) { - Parent::Service_name announce_for_acpi("Acpi"); - _env.parent().announce(announce_for_acpi, root_cap); - } else - _env.parent().announce(root_cap); - } - - void system_update() - { - if (acpi_ready.constructed()) - acpi_ready->update(); - - if (!root.constructed()) - return; - - if (acpi_ready.constructed() && acpi_ready->valid()) { - Xml_node system(acpi_ready->local_addr(), acpi_ready->size()); - - typedef String<16> Value; - const Value state = system.attribute_value("state", Value("unknown")); - - if (state == "acpi_ready" && root_cap.valid()) { - _env.parent().announce(root_cap); - root_cap = Capability > (); - } - } - } - - void config_update() - { - _config.update(); - - if (!_config.valid()) - return; - - if (!root_cap.valid()) - acpi_update(); - - bool const system_state_was_constructed = system_state.constructed(); - - system_state.conditional(_config.xml().attribute_value("system", false), - _env, "system"); - - if (system_state.constructed() && !system_state_was_constructed) - system_state->sigh(_config_handler); - - if (system_state.constructed()) { - system_state->update(); - if (system_state->xml().attribute_value("state", String<16>()) == "reset") - _attempt_acpi_reset(); - } - - if (root.constructed()) { - root->generate_pci_report(); - root->config_update(); - } - - _acpi_device_registry.init_devices(_heap, _config.xml()); - } - - Main(Env &env) : _env(env) - { - _config.sigh(_config_handler); - - if (_config.valid()) - _acpi_ready = _config.xml().attribute_value("acpi_ready", false); - - if (_acpi_ready) { - acpi_ready.construct(env, "acpi_ready"); - acpi_ready->sigh(_system_report); - } - - /* wait for the first valid acpi report */ - acpi_rom.construct(env, "acpi"); - acpi_rom->sigh(_acpi_report); - - /* check if already valid */ - config_update(); - acpi_update(); - system_update(); - - Nonpci::acpi_device_registry(_acpi_device_registry); - } -}; - - -void Platform::Main::_attempt_acpi_reset() -{ - if (!acpi_rom.constructed()) - return; - - acpi_rom->xml().with_optional_sub_node("reset", [&] (Xml_node reset) { - - uint16_t const io_port = reset.attribute_value("io_port", (uint16_t)0); - uint8_t const value = reset.attribute_value("value", (uint8_t)0); - - log("trigger reset by writing value ", value, " to I/O port ", Hex(io_port)); - - try { - Io_port_connection reset_port { _env, io_port, 1 }; - reset_port.outb(io_port, value); - } - catch (...) { - error("unable to access reset I/O port ", Hex(io_port)); - } - }); -} - - -void Component::construct(Genode::Env &env) -{ - /* XXX execute constructors of global statics */ - env.exec_static_constructors(); - - static Platform::Main main(env); -} diff --git a/repos/os/src/drivers/platform/legacy/x86/nonpci_devices.cc b/repos/os/src/drivers/platform/legacy/x86/nonpci_devices.cc deleted file mode 100644 index 550883b19b..0000000000 --- a/repos/os/src/drivers/platform/legacy/x86/nonpci_devices.cc +++ /dev/null @@ -1,363 +0,0 @@ -/* - * \brief Non PCI devices, e.g. PS2 - * \author Alexander Boettcher - * \author Christian Helmuth - * \date 2015-04-17 - */ - -/* - * Copyright (C) 2015-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 "pci_session_component.h" -#include "irq.h" -#include "acpi_devices.h" - -namespace Platform { namespace Nonpci { class Ps2; class Pit; } } - - -class Platform::Nonpci::Ps2 : public Device_component -{ - private: - - enum { - IRQ_KEYBOARD = 1, - IRQ_MOUSE = 12, - - ACCESS_WIDTH = 1, - REG_DATA = 0x60, - REG_STATUS = 0x64, - }; - - Rpc_entrypoint &_ep; - Platform::Irq_session_component _irq_mouse; - Io_port_connection _data; - Io_port_connection _status; - - public: - - Ps2(Env &env, - Attached_io_mem_dataspace &pciconf, - Session_component &session, - Allocator &heap_for_irq, - Pci::Config::Delayer &delayer, - Device_bars_pool &devices_bars) - : - Device_component(env, pciconf, session, IRQ_KEYBOARD, - heap_for_irq, delayer, devices_bars), - _ep(env.ep().rpc_ep()), - _irq_mouse(IRQ_MOUSE, ~0UL, env, heap_for_irq), - _data(env, REG_DATA, ACCESS_WIDTH), - _status(env, REG_STATUS, ACCESS_WIDTH) - { - _ep.manage(&_irq_mouse); - } - - ~Ps2() { _ep.dissolve(&_irq_mouse); } - - Irq_session_capability irq(uint8_t virt_irq) override - { - switch (virt_irq) { - case 0: - log("PS2 uses IRQ, vector ", Hex(IRQ_KEYBOARD)); - return Device_component::irq(virt_irq); - case 1: - log("PS2 uses IRQ, vector ", Hex(IRQ_MOUSE)); - return _irq_mouse.cap(); - default: - return Irq_session_capability(); - } - } - - Io_port_session_capability io_port(uint8_t io_port) override - { - if (io_port == 0) - return _data.cap(); - if (io_port == 1) - return _status.cap(); - - return Io_port_session_capability(); - } - - Io_mem_session_capability io_mem(uint8_t, Cache, addr_t, size_t) override - { - return Io_mem_session_capability(); - } - - Device_name_string name() const override { return "PS2"; } -}; - - -class Platform::Nonpci::Pit : public Device_component -{ - private: - - enum { - IRQ_PIT = 0, - - PIT_PORT = 0x40, - PORTS_WIDTH = 4 - }; - - Io_port_connection _ports; - - public: - - Pit(Env &env, - Attached_io_mem_dataspace &pciconf, - Session_component &session, - Allocator &heap_for_irq, - Pci::Config::Delayer &delayer, - Device_bars_pool &devices_bars) - : - Device_component(env, pciconf, session, IRQ_PIT, - heap_for_irq, delayer, devices_bars), - _ports(env, PIT_PORT, PORTS_WIDTH) - { } - - Io_port_session_capability io_port(uint8_t io_port) override - { - if (io_port == 0) - return _ports.cap(); - - return Io_port_session_capability(); - } - - Device_name_string name() const override { return "PIT"; } -}; - - -namespace Platform { namespace Nonpci { - class Acpi; - - void acpi_device_registry(Platform::Acpi::Device_registry &); -} } - - -static Platform::Acpi::Device_registry *_acpi_device_registry; - -void Platform::Nonpci::acpi_device_registry(Platform::Acpi::Device_registry ®istry) -{ - _acpi_device_registry = ®istry; -} - - -class Platform::Nonpci::Acpi : public Device_component -{ - private: - - Env &_env; - - Allocator &_session_heap; - - Platform::Acpi::Device const &_acpi_device; - - Irq_session_component *_irq0 = nullptr; - - /* - * Noncopyable - */ - Acpi(Acpi const &) = delete; - Acpi &operator = (Acpi const &) = delete; - - public: - - Acpi(Platform::Acpi::Device const &acpi_device, - Env &env, - Attached_io_mem_dataspace &pciconf, - Session_component &session, - Allocator &session_heap, - Allocator &global_heap, - Pci::Config::Delayer &delayer, - Device_bars_pool &devices_bars) - : - Device_component(env, pciconf, session, 0, - global_heap, delayer, devices_bars), - _env(env), _session_heap(session_heap), _acpi_device(acpi_device) - { } - - Device_name_string name() const override { return _acpi_device.hid(); } - - /* Platform::Device interface */ - - void bus_address(unsigned char *bus, unsigned char *dev, - unsigned char *fn) override - { - *bus = 0; *dev = 0; *fn = 0; - } - - unsigned short vendor_id() override { return ~0; } - - unsigned short device_id() override { return ~0; } - - unsigned class_code() override { return ~0; } - - Resource resource(int resource_id) override - { - using Acpi_device = Platform::Acpi::Device; - - return _acpi_device.resource(resource_id).convert( - [&] (Acpi_device::Resource r) { - /* craft artificial BAR values from resource info */ - switch (r.type) { - case Acpi_device::Resource::Type::IOMEM: - return Resource((r.base & 0xfffffff0) | 0b0000, r.size); - - case Acpi_device::Resource::Type::IOPORT: - return Resource((r.base & 0xfffffffc) | 0b01, r.size); - - case Acpi_device::Resource::Type::IRQ: - return Resource(); - } - return Resource(); - }, - [&] (Acpi_device::Invalid_resource) { return Resource(); }); - } - - unsigned config_read(unsigned char, Access_size) override - { - warning("ignore config_read from ACPI device ", _acpi_device.hid()); - return 0; - } - - void config_write(unsigned char, unsigned, Access_size) override - { - warning("ignore config_write to ACPI device ", _acpi_device.hid()); - } - - Irq_session_capability irq(uint8_t v_id) override - { - using Acpi_device = Platform::Acpi::Device; - - /* TODO more than one IRQ */ - if (v_id != 0) { - warning("ACPI device with more than one IRQ not supported (requested id ", v_id, ")"); - return Irq_session_capability(); - } - if (_irq0) return _irq0->cap(); - - /* TODO needs try see pci_device.cc ::iomem() */ - return _acpi_device.irq(v_id).convert( - [&] (Acpi_device::Resource r) { - Platform::Irq_session_component &irq = - *new(_session_heap) - Platform::Irq_session_component(r.base, ~0UL, _env, _session_heap, - Irq_session::TRIGGER_LEVEL, - Irq_session::POLARITY_LOW); - _env.ep().manage(irq); - _irq0 = &irq; - return irq.cap(); - }, - [&] (Acpi_device::Invalid_resource) { return Irq_session_capability(); }); - } - - Io_port_session_capability io_port(uint8_t v_id) override - { - using Acpi_device = Platform::Acpi::Device; - - /* TODO needs try see pci_device.cc ::iomem() */ - - return _acpi_device.ioport(v_id).convert( - [&] (Acpi_device::Resource r) { - Io_port_connection &ioport = - *new (_session_heap) Io_port_connection(_env, r.base, r.size); - return ioport.cap(); - }, - [&] (Acpi_device::Invalid_resource) { return Io_port_session_capability(); }); - } - - Io_mem_session_capability io_mem(uint8_t v_id, - Cache /* ignored */, - addr_t /* ignored */, - size_t /* ignored */) override - { - using Acpi_device = Platform::Acpi::Device; - - /* TODO needs try see pci_device.cc ::iomem() */ - - return _acpi_device.iomem(v_id).convert( - [&] (Acpi_device::Resource r) { - Io_mem_connection &iomem = - *new (_session_heap) Io_mem_connection(_env, r.base, r.size); - return iomem.cap(); - }, - [&] (Acpi_device::Invalid_resource) { return Io_mem_session_capability(); }); - } -}; - - -/** - * Platform session component devices which are non PCI devices, e.g. PS2 - */ -Platform::Device_capability Platform::Session_component::device(Device_name const &name) -{ - if (!name.valid_string()) - return Device_capability(); - - Device_name_string const device_name { name.string() }; - - enum class Type { UNKNOWN, PS2, PIT, ACPI } device_type { Type::UNKNOWN }; - - Platform::Acpi::Device const *acpi_device = nullptr; - - if (device_name == "PS2") - device_type = Type::PS2; - - else if (device_name == "PIT") - device_type = Type::PIT; - - else if (_acpi_device_registry) - device_type = _acpi_device_registry->lookup(device_name).convert( - [&] (Acpi::Device const *device) { - acpi_device = device; - return Type::ACPI; - }, - [&] (Acpi::Device_registry::Lookup_failed) { return Type::UNKNOWN; }); - - bool const found = device_type != Type::UNKNOWN; - - if (!found) { - error("unknown device name '", device_name, "'"); - return Device_capability(); - } - - if (!permit_device(device_name.string())) { - error("denied access to device '", device_name, "' for " - "session '", _label, "'"); - return Device_capability(); - } - - try { - Device_component * dev = nullptr; - - switch (device_type) { - case Type::PS2: - dev = new (_md_alloc) Nonpci::Ps2(_env, _pciconf, *this, - _global_heap, _delayer, - _devices_bars); - break; - case Type::PIT: - dev = new (_md_alloc) Nonpci::Pit(_env, _pciconf, *this, - _global_heap, _delayer, - _devices_bars); - break; - case Type::ACPI: - dev = new (_md_alloc) Nonpci::Acpi(*acpi_device, - _env, _pciconf, *this, - _md_alloc, - _global_heap, _delayer, - _devices_bars); - break; - default: - return Device_capability(); - } - - _device_list.insert(dev); - return _env.ep().rpc_ep().manage(dev); - } - catch (Out_of_ram) { throw; } - catch (Service_denied) { return Device_capability(); } -} diff --git a/repos/os/src/drivers/platform/legacy/x86/pci_bridge.h b/repos/os/src/drivers/platform/legacy/x86/pci_bridge.h deleted file mode 100644 index 92ba968e46..0000000000 --- a/repos/os/src/drivers/platform/legacy/x86/pci_bridge.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * \brief PCI bridge discovery - * \author Sebastian Sumpf - * \date 2012-02-25 - */ - - /* - * Copyright (C) 2009-2017 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. - */ - -#ifndef _PCI_BRIDGE_H_ -#define _PCI_BRIDGE_H_ - -#include - -namespace Platform { class Bridge; } - - -/** - * List of PCI-bridge devices - */ -class Platform::Bridge : public List::Element -{ - private: - - /* PCI config space fields of bridge */ - unsigned char _bus; - unsigned char _dev; - unsigned char _fun; - - unsigned char _secondary_bus; - unsigned char _subordinate_bus; - - public: - - Bridge(unsigned char bus, unsigned char dev, unsigned char fun, - unsigned char secondary_bus, unsigned char subordinate_bus) - : - _bus(bus), _dev(dev), _fun(fun), _secondary_bus(secondary_bus), - _subordinate_bus(subordinate_bus) - { } - - bool part_of (unsigned char bus) const - { - return _secondary_bus <= bus && bus <= _subordinate_bus; - } - - unsigned short bdf() - { - unsigned short bdf = _bus; - bdf = (bdf << 8) | ((_dev & 0x1f) << 3) | (_fun & 0x7); - return bdf; - } - - enum { INVALID_ROOT_BRIDGE = 0x10000U }; - static unsigned root_bridge_bdf; -}; - -#endif /* _PCI_BRIDGE_H_ */ diff --git a/repos/os/src/drivers/platform/legacy/x86/pci_config_access.h b/repos/os/src/drivers/platform/legacy/x86/pci_config_access.h deleted file mode 100644 index ed22e1af0c..0000000000 --- a/repos/os/src/drivers/platform/legacy/x86/pci_config_access.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * \brief PCI configuration access for the platform driver - * \author Norman Feske - * \date 2008-01-28 - */ - -/* - * Copyright (C) 2008-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. - */ - -#ifndef _X86_PCI_CONFIG_ACCESS_H_ -#define _X86_PCI_CONFIG_ACCESS_H_ - -#include -#include -#include -#include -#include - -namespace Platform { namespace Pci { struct Bdf; struct Config; } } - - -struct Platform::Pci::Bdf -{ - unsigned bus, device, function; - - static Bdf from_value(uint16_t const bdf) - { - return Bdf { .bus = (bdf >> 8) & 0xffu, - .device = (bdf >> 3) & 0x1fu, - .function = bdf & 0x07u }; - } - - static Bdf from_xml(Xml_node node) - { - return Bdf { .bus = node.attribute_value("bus", 0U), - .device = node.attribute_value("device", 0U), - .function = node.attribute_value("function", 0U) }; - } - - - uint16_t value() const { - return ((bus & 0xff) << 8) | ((device & 0x1f) << 3) | (function & 7); } - - bool operator == (Bdf const &other) const { - return value() == other.value(); } - - void print(Output &out) const - { - using Genode::print; - print(out, Hex((uint8_t)bus, Hex::Prefix::OMIT_PREFIX, Hex::Pad::PAD), - ":", Hex((uint8_t)device, Hex::Prefix::OMIT_PREFIX, Hex::Pad::PAD), - ".", Hex(function, Hex::Prefix::OMIT_PREFIX)); - } -}; - - -namespace Platform { - - class Config_access - { - private: - - Attached_io_mem_dataspace &_pciconf; - - size_t const _pciconf_size; - - /** - * Calculate device offset from BDF - * - * \return device base address - */ - unsigned _dev_base(Pci::Bdf const bdf) - { - return unsigned(bdf.value()) << 12; - } - - Bit_array<256> _used { }; - - void _use_register(unsigned char addr, unsigned short width) - { - for (unsigned i = 0; i < width; i++) - if (!_used.get(addr + i, 1)) - _used.set(addr + i, 1); - } - - public: - - class Invalid_mmio_access : Exception { }; - - Config_access(Attached_io_mem_dataspace &pciconf) - : - _pciconf(pciconf), - _pciconf_size(Dataspace_client(_pciconf.cap()).size()) - { } - - Config_access(Config_access &c) - : _pciconf(c._pciconf), _pciconf_size(c._pciconf_size) { } - - /** - * Read value from config space of specified device/function - * - * \param bdf target PCI bus, device & function ID - * \param addr target byte within targeted PCI config space - * \param size bit width of read access - * - * \return value read from specified config-space address - * - * There is no range check for the input values. - */ - unsigned read(Pci::Bdf const bdf, unsigned char const addr, - Device::Access_size const size, bool const track = true) - { - unsigned const offset = _dev_base(bdf) + addr; - char const * const field_ptr = _pciconf.local_addr() + offset; - - if (offset >= _pciconf_size) - throw Invalid_mmio_access(); - - switch (size) { - - case Device::ACCESS_8BIT: - if (track) - _use_register(addr, 1); - return *(uint8_t const *)field_ptr; - - case Device::ACCESS_16BIT: - if (track) - _use_register(addr, 2); - return *(uint16_t const *)field_ptr; - - case Device::ACCESS_32BIT: - if (track) - _use_register(addr, 4); - return *(uint32_t const *)field_ptr; - } - return ~0U; - } - - /** - * Write to config space of specified device/function - * - * \param bdf target PCI bus, device & function ID - * \param addr target byte within targeted PCI config space - * \param value value to be written - * \param size bit width of write access - * - * There is no range check for the input values. - */ - void write(Pci::Bdf const bdf, unsigned char const addr, - unsigned const value, Device::Access_size const size, - bool const track = true) - { - unsigned const offset = _dev_base(bdf) + addr; - char * const field_ptr = _pciconf.local_addr() + offset; - - if (offset >= _pciconf_size) - throw Invalid_mmio_access(); - - /* - * Write value to targeted address, see read() comment above - * for an explanation of the assembly templates - */ - switch (size) { - - case Device::ACCESS_8BIT: - if (track) - _use_register(addr, 1); - *(uint8_t volatile *)field_ptr = value; - break; - - case Device::ACCESS_16BIT: - if (track) - _use_register(addr, 2); - *(uint16_t volatile *)field_ptr = value; - break; - - case Device::ACCESS_32BIT: - if (track) - _use_register(addr, 4); - *(uint32_t volatile *)field_ptr = value; - break; - } - } - - bool reg_in_use(unsigned char addr, Device::Access_size size) - { - switch (size) { - case Device::ACCESS_8BIT: - return _used.get(addr, 1); - case Device::ACCESS_16BIT: - return _used.get(addr, 2); - case Device::ACCESS_32BIT: - return _used.get(addr, 4); - default: - return true; - } - } - }; -} - -/** - * Type-safe, fine-grained access to a PCI config space of a device - * - * It is similar to Genode::Mmio but uses Config_access as backend. - */ -struct Platform::Pci::Config: Register_set -{ - private: - - friend Register_set_plain_access; - - Config_access &_config; - Pci::Bdf _bdf; - uint16_t _cap; - - template - inline ACCESS_T _read(off_t const &offset) const - { - addr_t const cap = _cap + offset; - - if (sizeof(ACCESS_T) == 1) - return _config.read(_bdf, cap, Device::ACCESS_8BIT); - if (sizeof(ACCESS_T) == 2) - return _config.read(_bdf, cap, Device::ACCESS_16BIT); - if (sizeof(ACCESS_T) == 4) - return _config.read(_bdf, cap, Device::ACCESS_32BIT); - - warning("unsupported read ", sizeof(ACCESS_T)); - return 0; - } - - template - inline void _write(off_t const offset, ACCESS_T const value) - { - addr_t const cap = _cap + offset; - - switch (sizeof(ACCESS_T)) { - case 1 : - _config.write(_bdf, cap, value, Device::ACCESS_8BIT); - break; - case 2 : - _config.write(_bdf, cap, value, Device::ACCESS_16BIT); - break; - case 4 : - _config.write(_bdf, cap, value, Device::ACCESS_32BIT); - break; - default: - warning("unsupported write ", sizeof(ACCESS_T)); - } - } - - public: - - Config(Config_access &config, Pci::Bdf const &bdf, uint16_t cap) - : - Register_set(*this), _config(config), _bdf(bdf), _cap(cap) - { } - -}; - -#endif /* _X86_PCI_CONFIG_ACCESS_H_ */ diff --git a/repos/os/src/drivers/platform/legacy/x86/pci_device.cc b/repos/os/src/drivers/platform/legacy/x86/pci_device.cc deleted file mode 100644 index 30aa26399b..0000000000 --- a/repos/os/src/drivers/platform/legacy/x86/pci_device.cc +++ /dev/null @@ -1,341 +0,0 @@ -/* - * \brief PCI device component implementation - * \author Alexander Boettcher - * \author Christian Helmuth - * \date 2022-06-24 - */ - -/* - * Copyright (C) 2015-2017 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 "pci_session_component.h" -#include "pci_device_component.h" - - -Genode::Io_port_session_capability Platform::Device_component::io_port(uint8_t const v_id) -{ - uint8_t const max = sizeof(_io_port_conn) / sizeof(_io_port_conn[0]); - uint8_t r_id = 0; - - for (unsigned i = 0; i < max; ++i) { - Pci::Resource res = _device_config.resource(i); - - if (!res.valid() || res.mem()) - continue; - - if (v_id != r_id) { - ++r_id; - continue; - } - - if (_io_port_conn[v_id] != nullptr) - return _io_port_conn[v_id]->cap(); - - try { - _io_port_conn[v_id] = new (_slab_ioport) - Io_port_connection(_env, res.base(), res.size()); - return _io_port_conn[v_id]->cap(); - } catch (...) { - return Io_port_session_capability(); - } - } - - return Io_port_session_capability(); -} - -Genode::Io_mem_session_capability Platform::Device_component::io_mem(uint8_t const v_id, - Cache const caching, - addr_t const offset, - size_t const size) -{ - uint8_t max = sizeof(_io_mem) / sizeof(_io_mem[0]); - uint8_t r_id = 0; - - for (unsigned i = 0; i < max; ++i) { - Pci::Resource res = _device_config.resource(i); - - if (!res.valid() || !res.mem()) - continue; - - if (v_id != r_id) { - ++r_id; - continue; - } - - /* limit IO_MEM session size to resource size */ - size_t const res_size = min(size, res.size()); - - if (offset >= res.size() || offset > res.size() - res_size) - return Io_mem_session_capability(); - - /* error if MEM64 resource base address above 4G on 32-bit */ - if (res.base() > ~(addr_t)0) { - error("request for MEM64 resource of ", _device_config, - " at ", Hex(res.base()), " not supported on 32-bit system"); - return Io_mem_session_capability(); - } - - try { - bool const wc = caching == Cache::WRITE_COMBINED; - Io_mem * io_mem = new (_slab_iomem) Io_mem(_env, - res.base() + offset, - res_size, wc); - _io_mem[i].insert(io_mem); - return io_mem->cap(); - } - catch (Out_of_caps) { - warning("Out_of_caps in Device_component::io_mem"); - throw; - } - catch (Out_of_ram) { - warning("Out_of_ram in Device_component::io_mem"); - throw; - } - catch (...) { - warning("unhandled exception in 'Device_component::io_mem'"); - return Io_mem_session_capability(); - } - } - - return Io_mem_session_capability(); -} - - -unsigned Platform::Device_component::config_read(unsigned char address, Access_size size) -{ - if (pci_device()) - return _device_config.read(_config_access, address, size, - _device_config.DONT_TRACK_ACCESS); - - return ~0; -} - - -void Platform::Device_component::config_write(unsigned char address, - unsigned value, - Access_size size) -{ - if (!pci_device()) - return; - - /* white list of ports which we permit to write */ - switch (address) { - case 0x40 ... 0xff: - /* allow access to device-specific registers if not used by us */ - if (!_device_config.reg_in_use(_config_access, address, size)) - break; - - error(_device_config, " write access to " - "address=", Hex(address), " " - "value=", Hex(value), " " - "size=", Hex(size), " " - "denied - it is used by the platform driver."); - return; - case Device_config::PCI_CMD_REG: /* COMMAND register - first byte */ - if (size == Access_size::ACCESS_16BIT) - break; - [[fallthrough]]; - case Device_config::PCI_CMD_REG + 1: /* COMMAND register - second byte */ - case 0xd: /* Latency timer */ - if (size == Access_size::ACCESS_8BIT) - break; - [[fallthrough]]; - default: - warning(_device_config, " write access to " - "address=", Hex(address), " " - "value=", Hex(value), " " - "size=", Hex(size), " " - "got dropped"); - return; - } - - /* assign device to device_pd */ - if (!_device_assigned && - address == Device_config::PCI_CMD_REG && - (value & Device_config::PCI_CMD_DMA)) { - - try { _session.assign_device(this); } - catch (Out_of_ram) { throw; } - catch (Out_of_caps) { throw; } - catch (...) { - error("assignment to device failed"); - } - _device_assigned = true; - _device_used = true; - } - - _device_config.write(_config_access, address, value, size, - _device_config.DONT_TRACK_ACCESS); -} - -Genode::Irq_session_capability Platform::Device_component::irq(uint8_t id) -{ - if (id != 0) - return Irq_session_capability(); - - if (_irq_session) - return _irq_session->cap(); - - if (!pci_device()) { - /* Non PCI devices */ - _irq_session = construct_at(_mem_irq_component, - _irq_line, ~0UL, - _env, - _global_heap); - - _env.ep().rpc_ep().manage(_irq_session); - return _irq_session->cap(); - } - - uint16_t const msi_cap = _msi_cap(); - uint16_t const msix_cap = _msix_cap(); - bool const try_msi_msix = (_session.msi_usage() && msi_cap) || - (_session.msix_usage() && msix_cap); - _irq_session = construct_at(_mem_irq_component, - _configure_irq(_irq_line, msi_cap, msix_cap), - try_msi_msix ? _config_space : ~0UL, - _env, _global_heap); - _env.ep().rpc_ep().manage(_irq_session); - - bool msix_used = false; - bool msi_used = false; - - if (_irq_session->msi()) { - if (_session.msix_usage() && msix_cap) - msix_used = _setup_msix(msix_cap); - if (!msix_used && msi_cap) - msi_used = _setup_msi(msi_cap); - } - - if (_irq_session->msi()) - log(_device_config, " uses ", - msix_used ? "MSI-X " : "", - (msix_used && msi_cap) ? "(supports MSI) " : "", - msi_used ? "MSI ": "", - (msi_used && msix_cap) ? "(supports MSI-X) " : "", - (!msi_used && !msix_used) ? "no MSI/-X/IRQ " : "", - "vector ", Hex(_irq_session->msi_data()), ", " - "address ", Hex(_irq_session->msi_address())); - else - log(_device_config, " uses IRQ, vector ", - Hex(_irq_line), - (msi_cap || msix_cap) ? ", supports:" : "", - msi_cap ? " MSI" : "", - msix_cap ? " MSI-X" : ""); - - return _irq_session->cap(); -} - -bool Platform::Device_component::_setup_msi(uint16_t const msi_cap) -{ - try { - addr_t const msi_address = _irq_session->msi_address(); - uint32_t const msi_value = _irq_session->msi_data(); - - uint16_t msi = _read_config_16(msi_cap + 2); - - _write_config_32(msi_cap + 0x4, msi_address); - - if (msi & CAP_MSI_64) { - uint32_t upper_address = sizeof(msi_address) > 4 - ? uint64_t(msi_address) >> 32 - : 0UL; - - _write_config_16(msi_cap + 0x8, upper_address); - _write_config_16(msi_cap + 0xc, msi_value); - } else - _write_config_16(msi_cap + 0x8, msi_value); - - /* enable MSI */ - _device_config.write(_config_access, msi_cap + 2, - msi ^ MSI_ENABLED, - Platform::Device::ACCESS_8BIT); - - msi = _read_config_16(msi_cap + 2); - - return msi & MSI_ENABLED; - } catch (...) { } - - return false; -} - -bool Platform::Device_component::_setup_msix(uint16_t const msix_cap) -{ - try { - struct Table_pba : Register<32> - { - struct Bir : Bitfield<0, 3> { }; - struct Offset : Bitfield<3, 29> { }; - }; - - addr_t const msi_address = _irq_session->msi_address(); - uint32_t const msi_value = _irq_session->msi_data(); - - uint16_t ctrl = _read_config_16(msix_cap + 2); - - uint32_t const slots = Msix_ctrl::Slots::get(ctrl) + 1; - - uint32_t const table = _read_config_32(msix_cap + 4); - uint8_t const table_bir = Table_pba::Bir::masked(table); - uint32_t const table_off = Table_pba::Offset::masked(table); - - enum { SIZEOF_MSI_TABLE_ENTRY = 16, SIZE_IOMEM = 0x1000 }; - - Pci::Resource res = _device_config.resource(table_bir); - if (!slots || !res.valid() || res.size() < SIZE_IOMEM || - table_off > res.size() - SIZE_IOMEM) - return false; - - if (slots * SIZEOF_MSI_TABLE_ENTRY > SIZE_IOMEM) - return false; - - uint64_t const msix_table_phys = res.base() + table_off; - - apply_msix_table(res, msix_table_phys, SIZE_IOMEM, - [&](addr_t const msix_table) - { - struct Msi_entry : public Mmio { - Msi_entry(addr_t const base) : Mmio(base) { } - - struct Address_low : Register<0x0, 32> { }; - struct Address_high : Register<0x4, 32> { }; - struct Value : Register<0x8, 32> { }; - struct Vector : Register<0xc, 32> { - struct Mask : Bitfield <0, 1> { }; - }; - } msi_entry_0 (msix_table); - - /* setup first msi-x table entry */ - msi_entry_0.write(msi_address & ~(0x3UL)); - msi_entry_0.write(sizeof(msi_address) == 4 ? 0 : msi_address >> 32); - msi_entry_0.write(msi_value); - msi_entry_0.write(0); - - /* disable all msi-x table entries beside the first one */ - for (unsigned i = 1; i < slots; i++) { - struct Msi_entry unused (msix_table + SIZEOF_MSI_TABLE_ENTRY * i); - unused.write(1); - } - - /* enable MSI-X */ - Msix_ctrl::Fmask::set(ctrl, 0); - Msix_ctrl::Enable::set(ctrl, 1); - _write_config_16(msix_cap + 2, ctrl); - }); - - /* check back that MSI-X got enabled */ - ctrl = _read_config_16(msix_cap + 2); - - return Msix_ctrl::Enable::get(ctrl); - } catch (Out_of_caps) { - warning("Out_of_caps during MSI-X enablement"); } - catch (Out_of_ram) { - warning("Out_of_ram during MSI-X enablement"); } - catch (...) { warning("MSI-X enablement failed"); } - - return false; -} diff --git a/repos/os/src/drivers/platform/legacy/x86/pci_device_component.h b/repos/os/src/drivers/platform/legacy/x86/pci_device_component.h deleted file mode 100644 index db3d92da36..0000000000 --- a/repos/os/src/drivers/platform/legacy/x86/pci_device_component.h +++ /dev/null @@ -1,608 +0,0 @@ -/* - * \brief platform device component - * \author Norman Feske - * \author Christian Helmuth - * \date 2008-01-28 - */ - -/* - * Copyright (C) 2008-2017 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. - */ - -#ifndef _PCI_DEVICE_COMPONENT_H_ -#define _PCI_DEVICE_COMPONENT_H_ - -/* base */ -#include -#include -#include -#include -#include -#include - -/* os */ -#include - -/* local */ -#include "pci_device_config.h" -#include "irq.h" - -namespace Platform { - class Device_component; - class Session_component; - - typedef String<10> Device_name_string; - - typedef Registry > Device_bars_pool; -} - - -class Platform::Device_component : public Rpc_object, - private List::Element -{ - private: - - friend class List; - - /* - * Noncopyable - */ - Device_component(Device_component const &); - Device_component &operator = (Device_component const &); - - Env &_env; - Pci::Config::Delayer &_delayer; - Device_bars_pool &_devices_bars; - Device_config _device_config { }; - addr_t _config_space; - Config_access _config_access; - Platform::Session_component &_session; - Irq_session_component *_irq_session = nullptr; - unsigned short _irq_line; - bool _device_used { false }; - bool _device_assigned { false }; - Allocator &_global_heap; - - class Io_mem : public Io_mem_connection, - private List::Element - { - private: - - friend class List; - friend class Platform::Device_component; - - public: - - addr_t const base; - size_t const size; - - Io_mem(Env &env, addr_t base, size_t size, bool wc) - : - Io_mem_connection(env, base, size, wc), - base(base), size(size) - { } - }; - - enum { - IO_BLOCK_SIZE = sizeof(Io_port_connection) * - Device::NUM_RESOURCES + 32 + 8 * sizeof(void *), - IO_MEM_SIZE = sizeof(Io_mem) * - Device::NUM_RESOURCES + 32 + 8 * sizeof(void *), - PCI_IRQ_LINE = 0x3c, - PCI_IRQ_PIN = 0x3d, - - CAP_MSI_64 = 0x80, - MSI_ENABLED = 0x1 - }; - - struct Msix_ctrl : Register<16> - { - struct Slots : Bitfield< 0, 10> { }; - struct Fmask : Bitfield<14, 1> { }; - struct Enable : Bitfield<15, 1> { }; - }; - - struct Pci_express : Pci::Config - { - Pci_express(Device_component &dev, uint16_t cap) - : Pci::Config(dev._config_access, dev._device_config.bdf(), cap) { } - - struct Capabilities : Register<0x04, 32> { - struct Reset : Bitfield< 28, 1> { }; }; - struct Control: Register<0x08, 16> { - struct Reset : Bitfield< 15, 1> { }; }; - struct Status: Register<0x0a, 16> { - struct Pending : Bitfield< 5, 1> { }; }; - struct Capabilities2 : Register<0x24, 32> { - struct Readiness : Bitfield<31, 1> { }; }; - struct Status2 : Register<0x32, 16> { - struct Readiness_status : Bitfield<15, 1> { }; }; - }; - - struct Pci_power: Pci::Config - { - Pci_power(Device_component &dev, uint16_t cap) - : Pci::Config(dev._config_access, dev._device_config.bdf(), cap) { } - - struct Capabilities : Register<0x02, 16> - { - struct Specific_init : Bitfield< 5, 1> { }; - }; - struct Control : Register<0x04, 16> - { - struct D0_3 : Bitfield< 0, 2> { }; - struct No_soft_reset : Bitfield< 3, 1> { }; - }; - }; - - - Tslab _slab_ioport; - char _slab_ioport_block_data[IO_BLOCK_SIZE]; - - Tslab _slab_iomem; - char _slab_iomem_block_data[IO_MEM_SIZE]; - - char _mem_irq_component[sizeof(Irq_session_component)]; - - Io_port_connection *_io_port_conn[Device::NUM_RESOURCES]; - - /* list of requested resource chunks per BAR */ - List _io_mem[Device::NUM_RESOURCES]; - - struct Status : Register<8> - { - struct Capabilities : Bitfield<4,1> { }; - - inline static access_t read(uint8_t t) { return t; } - }; - - /** - * Convenience functions to increase readability of code - */ - uint16_t _read_config_16(uint16_t const cap) - { - return _device_config.read(_config_access, cap, - Platform::Device::ACCESS_16BIT); - } - - void _write_config_16(uint16_t const cap, uint16_t const value) - { - _device_config.write(_config_access, cap, value, - Platform::Device::ACCESS_16BIT); - } - - uint32_t _read_config_32(uint16_t const cap) - { - return _device_config.read(_config_access, cap, - Platform::Device::ACCESS_32BIT); - } - - void _write_config_32(uint16_t const cap, uint32_t const value) - { - _device_config.write(_config_access, cap, value, - Platform::Device::ACCESS_32BIT); - } - - /** - * Read out msi capabilities of the device. - */ - uint16_t _msi_cap() - { - enum { CAP_MSI = 0x5 }; - return _lookup_cap(CAP_MSI); - } - - uint16_t _msix_cap() - { - enum { CAP_MSI_X = 0x11 }; - return _lookup_cap(CAP_MSI_X); - } - - uint16_t _power_cap() - { - enum { CAP_POWER = 0x1 }; - return _lookup_cap(CAP_POWER); - } - - /* PCI express cap (not PCI express extended cap!) */ - uint16_t _pcie_cap() - { - enum { CAP_PCIE = 0x10 }; - return _lookup_cap(CAP_PCIE); - } - - uint16_t _lookup_cap(uint16_t const target_cap) - { - enum { PCI_STATUS = 0x6, PCI_CAP_OFFSET = 0x34 }; - - Status::access_t status = Status::read(_read_config_16(PCI_STATUS)); - if (!Status::Capabilities::get(status)) - return 0; - - uint8_t cap = _read_config_16(PCI_CAP_OFFSET); - - for (uint16_t val = 0; cap; cap = val >> 8) { - val = _read_config_16(cap); - if ((val & 0xff) != target_cap) - continue; - - return cap; - } - - return 0; - } - - - /** - * Disable MSI/MSI-X if already enabled. - */ - unsigned _configure_irq(unsigned irq, uint16_t const msi_cap, - uint16_t const msix_cap) - { - uint8_t pin = _device_config.read(_config_access, PCI_IRQ_PIN, - Platform::Device::ACCESS_8BIT); - if (!pin) - return Irq_session_component::INVALID_IRQ; - - /* lookup rewrite information as provided by acpi table */ - uint16_t irq_r = Irq_routing::rewrite(_device_config.bdf(), pin); - if (irq_r) { - log(_device_config, " adjust IRQ as reported by ACPI: ", - irq, " -> ", irq_r); - - _irq_line = irq = irq_r; - } - - if (msi_cap) { - uint16_t msi = _read_config_16(msi_cap + 2); - - if (msi & MSI_ENABLED) - /* disable MSI */ - _device_config.write(_config_access, msi_cap + 2, - msi ^ MSI_ENABLED, - Platform::Device::ACCESS_8BIT); - } - - if (msix_cap) { - uint16_t msix = _read_config_16(msix_cap + 2); - - if (Msix_ctrl::Enable::get(msix)) { - Msix_ctrl::Enable::set(msix, 0); - - _write_config_16(msix_cap + 2, msix); - } - } - - return irq; - } - - - /** - * Disable bus master dma if already enabled. - */ - void _disable_bus_master_dma() - { - /* - * Disabling a bridge may make the devices behind non-functional, - * as we have no driver which will switch it on again - */ - if (_device_config.pci_bridge() || - _device_config.bdf() == Pci::Bdf::from_value(Platform::Bridge::root_bridge_bdf)) - return; - - _device_config.disable_bus_master_dma(_config_access); - } - - bool _setup_msi(uint16_t); - bool _setup_msix(uint16_t); - - template - void apply_msix_table(Pci::Resource const &lookup, - addr_t const msix_table_phys, - size_t const msix_table_size, - FUNC const &fn) - { - uint8_t max = sizeof(_io_mem) / sizeof(_io_mem[0]); - for (unsigned i = 0; i < max; ++i) { - Pci::Resource res = _device_config.resource(i); - - if (!res.valid() || !res.mem()) - continue; - - if (res.base() != lookup.base() || res.size() != lookup.size()) - continue; - - for (Io_mem * io_mem = _io_mem[i].first(); io_mem; io_mem = io_mem->next()) { - - if (!(io_mem->base <= msix_table_phys && - msix_table_phys + msix_table_size <= io_mem->base + io_mem->size)) - continue; - - size_t const offset = msix_table_phys - io_mem->base; - - Attached_dataspace mem_io(_env.rm(), io_mem->dataspace()); - - fn(reinterpret_cast(mem_io.local_addr()) + offset); - - return; - } - } - - /* requested io_mem not allocated by Pci::Resource - try direct */ - Io_mem io_mem(_env, msix_table_phys, msix_table_size, false); - Attached_dataspace mem_io(_env.rm(), io_mem.dataspace()); - addr_t const offset = msix_table_phys & 0xfffull; - addr_t const msix_table = reinterpret_cast(mem_io.local_addr()) + offset; - - fn(msix_table); - } - - void _device_reset() - { - uint16_t const cap = _pcie_cap(); - if (!cap) - return; - - Pci_express pci_cap(*this, cap); - - if (!pci_cap.read()) - return; - - log(_device_config, " reset function"); - - pci_cap.write(1); - - try { - /* optional use FLR Time if available instead of heuristic */ - pci_cap.wait_for(Pci::Config::Attempts(100), - Pci::Config::Microseconds(10000), _delayer, - Pci_express::Status::Pending::Equal(0)); - } catch (Pci::Config::Polling_timeout) { - warning(_device_config, " reset timeout raised"); - } - } - - void _power_off() - { - /* don't touch unused device */ - if (!_device_used) - return; - - uint16_t const cap = _power_cap(); - if (!cap) { - _disable_bus_master_dma(); - return; - } - - /* - * PCI Power Management - 8.2.2 D3 State - * - * "If the device driver is not capable of fully reinitializing" - * "a function, the operating system should not put the function" - * "into D3" - * - * Actually, at this point we don't know about the capabilities of - * the actual driver. - */ - log(_device_config, " power off"); - - /* - * "When placing a function into D3, the operating system software" - * "is required to disable I/O and memory space as well as bus" - * "mastering via the PCI Command register. - */ - Device_config::Pci_header header (_config_access, _device_config.bdf()); - - auto command = header.read(); - Device_config::Pci_header::Command::Dma::set(command, 0); - Device_config::Pci_header::Command::Memory::set(command, 0); - Device_config::Pci_header::Command::Ioport::set(command, 0); - - header.write(command); - - /* power off */ - Pci_power pci_cap(*this, cap); - pci_cap.write(3); - } - - void _power_on() - { - uint16_t const cap = _power_cap(); - if (!cap) - return; - - Pci_power pci_cap(*this, cap); - - if (pci_cap.read() == 0) - return; - - /* since it was off before, it got used by powering it on */ - _device_used = true; - - log(_device_config, " power on", - pci_cap.read() ? ", no_soft_reset" : "", - pci_cap.read() ? ", specific_init_required" : ""); - - /* power on */ - pci_cap.write(0); - - /* - * PCI Express 4.3 - 5.3.1.4. D3 State - * - * "Unless Readiness Notifications mechanisms are used ..." - * "a minimum recovery time following a D3 hot → D0 transition of" - * "at least 10 ms ..." - */ - _delayer.usleep(10'000); - - /* - * PCI Power Management - 3.2.4 - PMCSR Power Management Control/Status - * - * "no additional operating system intervention is required ..." - * "beyond writing the PowerState" - */ - if (pci_cap.read()) - return; - - _device_reset(); - - _devices_bars.for_each([&](auto const &bars) { - if (!(bars.bdf == _device_config.bdf())) - return; - - _device_config.restore_bars(_config_access, bars); - }); - - /* re-read the resources which set to valid ones after power on */ - _device_config = Device_config(_device_config.bdf(), - &_config_access); - } - - public: - - /** - * Constructor for PCI devices - */ - Device_component(Env &env, - Device_config device_config, addr_t addr, - Config_access &config_access, - Platform::Session_component &session, - Allocator &md_alloc, - Allocator &global_heap, - Pci::Config::Delayer &delayer, - Device_bars_pool &devices_bars) - : - _env(env), - _delayer(delayer), - _devices_bars(devices_bars), - _device_config(device_config), _config_space(addr), - _config_access(config_access), - _session(session), - _irq_line(_device_config.read(_config_access, PCI_IRQ_LINE, - Platform::Device::ACCESS_8BIT)), - _global_heap(global_heap), - _slab_ioport(&md_alloc, &_slab_ioport_block_data), - _slab_iomem(&md_alloc, &_slab_iomem_block_data) - { - for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) { - _io_port_conn[i] = nullptr; - } - - _power_on(); - } - - /** - * Constructor for non PCI devices - */ - Device_component(Env &env, - Attached_io_mem_dataspace &pciconf, - Platform::Session_component &session, unsigned irq, - Allocator &global_heap, - Pci::Config::Delayer &delayer, - Device_bars_pool &devices_bars) - : - _env(env), - _delayer(delayer), - _devices_bars(devices_bars), - _config_space(~0UL), - _config_access(pciconf), - _session(session), - _irq_line(irq), - _global_heap(global_heap), - _slab_ioport(nullptr, &_slab_ioport_block_data), - _slab_iomem(nullptr, &_slab_iomem_block_data) - { - for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) - _io_port_conn[i] = nullptr; - } - - /** - * De-constructor - */ - ~Device_component() - { - if (_irq_session) { - _env.ep().rpc_ep().dissolve(_irq_session); - _irq_session->~Irq_session_component(); - } - - for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) { - if (_io_port_conn[i]) - destroy(_slab_ioport, _io_port_conn[i]); - - while (Io_mem * io_mem = _io_mem[i].first()) { - _io_mem[i].remove(io_mem); - destroy(_slab_iomem, io_mem); - } - } - - if (!pci_device()) - return; - - _power_off(); - } - - /* distinct non-PCI and PCI devices */ - bool pci_device() const { return _device_config.valid(); } - - /**************************************** - ** Methods used solely by pci session ** - ****************************************/ - - Device_config device_config() const { return _device_config; } - addr_t config_space() const { return _config_space; } - - virtual Device_name_string name() const { return "PCI"; } - - template - void for_each_device(FUNC const &fn) const - { - fn(*this); - - for (auto *dev = this; dev; dev = dev->next()) { - fn(*dev); } - } - - /************************** - ** PCI-device interface ** - **************************/ - - void bus_address(unsigned char *bus, unsigned char *dev, - unsigned char *fn) override - { - *bus = _device_config.bdf().bus; - *dev = _device_config.bdf().device; - *fn = _device_config.bdf().function; - } - - unsigned short vendor_id() override { return _device_config.vendor_id(); } - - unsigned short device_id() override { return _device_config.device_id(); } - - unsigned class_code() override { return _device_config.class_code(); } - - Resource resource(int resource_id) override - { - if (pci_device()) - return _device_config.resource(resource_id).api_resource(); - - /* return invalid resource if device is invalid */ - return Resource(0, 0); - } - - unsigned config_read(unsigned char address, Access_size size) override; - - void config_write(unsigned char address, unsigned value, - Access_size size) override; - - Irq_session_capability irq(uint8_t) override; - - Io_port_session_capability io_port(uint8_t) override; - - Io_mem_session_capability io_mem(uint8_t, Cache, addr_t, size_t) override; -}; - -#endif /* _PCI_DEVICE_COMPONENT_H_ */ diff --git a/repos/os/src/drivers/platform/legacy/x86/pci_device_config.h b/repos/os/src/drivers/platform/legacy/x86/pci_device_config.h deleted file mode 100644 index 0478bc988b..0000000000 --- a/repos/os/src/drivers/platform/legacy/x86/pci_device_config.h +++ /dev/null @@ -1,458 +0,0 @@ -/* - * \brief PCI device configuration - * \author Norman Feske - * \author Christian Helmuth - * \date 2008-01-29 - */ - -/* - * Copyright (C) 2008-2017 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. - */ - -#ifndef _X86__PCI_DEVICE_CONFIG_H_ -#define _X86__PCI_DEVICE_CONFIG_H_ - -#include -#include -#include -#include "pci_config_access.h" - - -namespace Platform { namespace Pci { struct Resource; } } - - -class Platform::Pci::Resource -{ - public: - - struct Bar : Register<32> - { - struct Space : Bitfield<0,1> { enum { MEM = 0, PORT = 1 }; }; - - struct Mem_type : Bitfield<1,2> { enum { MEM32 = 0, MEM64 = 2 }; }; - struct Mem_prefetch : Bitfield<3,1> { }; - struct Mem_address_mask : Bitfield<4,28> { }; - struct Port_address_mask : Bitfield<2,14> { }; - - static bool mem(access_t r) { return Space::get(r) == Space::MEM; } - static bool mem64(access_t r) { return mem(r) - && Mem_type::get(r) == Mem_type::MEM64; } - static uint64_t mem_address(access_t r0, uint64_t r1) { return (r1 << 32) | Mem_address_mask::masked(r0); } - static uint64_t mem_size(access_t r0, uint64_t r1) { return ~mem_address(r0, r1) + 1; } - - static uint16_t port_address(access_t r) { return Port_address_mask::masked(r); } - static uint16_t port_size(access_t r) { return ~port_address(r) + 1; } - }; - - private: - - uint32_t _bar[2] { 0, 0 }; /* contains two consecutive BARs for MEM64 */ - uint64_t _size { 0 }; - - public: - - /* invalid resource */ - Resource() { } - - /* PORT or MEM32 resource */ - Resource(uint32_t bar, uint32_t size) - : - _bar{bar, 0}, _size(mem() ? Bar::mem_size(size, ~0) : Bar::port_size(size)) - { } - - /* MEM64 resource */ - Resource(uint32_t bar0, uint32_t size0, uint32_t bar1, uint32_t size1) - : _bar{bar0, bar1}, _size(Bar::mem_size(size0, size1)) - { } - - bool valid() const { return !!_bar[0]; } /* no base address -> invalid */ - bool mem() const { return Bar::mem(_bar[0]); } - bool mem64() const { return mem() && Bar::mem64(_bar[0]); } - uint64_t base() const { return mem() ? Bar::mem_address(_bar[0], _bar[1]) - : Bar::port_address(_bar[0]); } - uint64_t size() const { return _size; } - - Platform::Device::Resource api_resource() - { - /* - * The API type limits to 32-bit currently (defined in - * spec/x86/platform_device/platform_device.h) - */ - return Device::Resource((unsigned)_bar[0], (unsigned)_size); - } - - void print(Output &out) const - { - Genode::print(out, Hex_range(base(), size())); - Genode::print(out, " ("); - Genode::print(out, valid() ? mem() ? Bar::mem64(_bar[0]) ? "MEM64" : "MEM" : "IO" : "invalid"); - Genode::print(out, ")"); - } -}; - - -namespace Platform { - - class Device_config - { - private: - - Pci::Bdf _bdf; - - /* - * Information provided by the PCI config space - */ - unsigned _vendor_id = 0, _device_id = 0; - unsigned _class_code = 0; - unsigned _header_type = 0; - - /* - * Header type definitions - */ - enum { - HEADER_FUNCTION = 0, - HEADER_PCI_TO_PCI = 1, - HEADER_CARD_BUS = 2 - }; - - Platform::Pci::Resource _resource[Device::NUM_RESOURCES]; - - bool _resource_id_is_valid(int resource_id) const - { - /* - * The maximum number of PCI resources depends on the - * header type of the device. - */ - int max_num = _header_type == HEADER_FUNCTION ? Device::NUM_RESOURCES - : _header_type == HEADER_PCI_TO_PCI ? 2 - : 0; - - return resource_id >= 0 && resource_id < max_num; - } - - enum { INVALID_VENDOR = 0xffffU }; - - public: - - enum { MAX_BUSES = 256, MAX_DEVICES = 32, MAX_FUNCTIONS = 8 }; - - enum { - PCI_CMD_REG = 0x4, - PCI_CMD_MASK = 0x7, /* IOPORT (1), MEM(2), DMA(4) */ - PCI_CMD_DMA = 0x4, - }; - - struct Pci_header : Pci::Config - { - Pci_header(Config_access &access, Pci::Bdf const bdf) - : Pci::Config(access, bdf, 0 /* from start */) { } - - struct Command : Register<0x04, 16> - { - struct Ioport : Bitfield< 0, 1> { }; - struct Memory : Bitfield< 1, 1> { }; - struct Dma : Bitfield< 2, 1> { }; - }; - }; - - struct Device_bars - { - Pci::Bdf bdf; - - uint32_t bar_addr[Device::NUM_RESOURCES] { }; - - bool all_invalid() const - { - for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) { - if (bar_addr[i] != 0 && bar_addr[i] != ~0U) - return false; - } - return true; - } - - Device_bars(Pci::Bdf bdf) : bdf(bdf) { } - virtual ~Device_bars() { }; - }; - - /** - * Constructor - */ - Device_config() : _bdf({ .bus = 0, .device = 0, .function = 0 }) { - _vendor_id = INVALID_VENDOR; } - - Device_config(Pci::Bdf bdf) : _bdf(bdf) { } - - Device_config(Pci::Bdf bdf, Config_access *pci_config) : _bdf(bdf) - { - _vendor_id = pci_config->read(bdf, 0, Device::ACCESS_16BIT); - - /* break here if device is invalid */ - if (_vendor_id == INVALID_VENDOR) - return; - - _device_id = pci_config->read(bdf, 2, Device::ACCESS_16BIT); - _class_code = pci_config->read(bdf, 8, Device::ACCESS_32BIT) >> 8; - _class_code &= 0xffffff; - _header_type = pci_config->read(bdf, 0xe, Device::ACCESS_8BIT); - _header_type &= 0x7f; - - /* - * We prevent scanning function 1-7 of non-multi-function - * devices by checking bit 7 (mf bit) of function 0 of the - * device. Note, the mf bit of function 1-7 is not significant - * and may be set or unset. - */ - if (bdf.function != 0) { - Pci::Bdf const dev { .bus = bdf.bus, .device = bdf.device, .function = 0 }; - if (!(pci_config->read(dev, 0xe, Device::ACCESS_8BIT) & 0x80)) { - _vendor_id = INVALID_VENDOR; - return; - } - } - - /* - * We iterate over all BARs but check for 64-bit memory - * resources, which are stored in two consecutive BARs. The - * MEM64 information is stored in the first resource entry and - * the second resource is marked invalid. - */ - int i = 0; - while (_resource_id_is_valid(i)) { - - using Pci::Resource; - - /* index of base-address register in configuration space */ - unsigned const bar_idx = 0x10 + 4 * i; - - /* First, save initial base-address register value. */ - unsigned const bar_value = pci_config->read(bdf, bar_idx, Device::ACCESS_32BIT); - - /* - * Second, determine resource size (and validity) by writing - * a magic value (all bits set) to the base-address - * register. In response, the device clears a number of - * lowest-significant bits corresponding to the resource - * size. - */ - pci_config->write(bdf, bar_idx, ~0, Device::ACCESS_32BIT); - unsigned const bar_size = pci_config->read(bdf, bar_idx, Device::ACCESS_32BIT); - - /* skip invalid resource BARs */ - if (bar_value == ~0U || bar_size == 0U) { - _resource[i] = Resource(); - ++i; - continue; - } - - /* - * Finally, we write back the bar-address value as assigned - * by the BIOS. - */ - pci_config->write(bdf, bar_idx, bar_value, Device::ACCESS_32BIT); - - if (!Resource::Bar::mem64(bar_value)) { - _resource[i] = Resource(bar_value, bar_size); - ++i; - } else { - /* also consume next BAR for MEM64 */ - unsigned const bar2_idx = bar_idx + 4; - unsigned const bar2_value = - pci_config->read(bdf, bar2_idx, Device::ACCESS_32BIT); - pci_config->write(bdf, bar2_idx, ~0, Device::ACCESS_32BIT); - unsigned const bar2_size = - pci_config->read(bdf, bar2_idx, Device::ACCESS_32BIT); - pci_config->write(bdf, bar2_idx, bar2_value, Device::ACCESS_32BIT); - - /* combine into first resource and mark second as invalid */ - _resource[i] = Resource(bar_value, bar_size, - bar2_value, bar2_size); - ++i; - _resource[i] = Resource(); - ++i; - } - } - } - - /** - * Accessor function for device location - */ - Pci::Bdf bdf() const { return _bdf; } - - void print(Output &out) const { Genode::print(out, bdf()); } - - /** - * Accessor functions for device information - */ - unsigned short device_id() { return _device_id; } - unsigned short vendor_id() { return _vendor_id; } - unsigned int class_code() { return _class_code; } - - /** - * Return true if device is a PCI bridge - */ - bool pci_bridge() const { return _header_type == HEADER_PCI_TO_PCI; } - - /** - * Return true if device is valid - */ - bool valid() const { return _vendor_id != INVALID_VENDOR; } - - /** - * Return resource description by resource ID - */ - Platform::Pci::Resource resource(int resource_id) - { - /* return invalid resource if sanity check fails */ - if (!_resource_id_is_valid(resource_id)) - return Platform::Pci::Resource(); - - return _resource[resource_id]; - } - - void remap_resource(Config_access &config, int const id, - uint64_t const base_address) - { - if (!_resource_id_is_valid(id)) - return; - - using Pci::Resource; - - Resource &res = _resource[id]; - - log(*this, " remap BAR", id, " ", res, " to ", Hex(base_address)); - - struct Resource_params { uint32_t bar; uint32_t size; }; - - auto update_bar = [&] (int const id, uint32_t const address) { - unsigned const off = 0x10 + 4 * id; - - config.write(_bdf, off, ~0U, Device::ACCESS_32BIT); - - uint32_t const size = config.read(_bdf, off, Device::ACCESS_32BIT); - - config.write(_bdf, off, address, Device::ACCESS_32BIT); - - return Resource_params { - .bar = config.read(_bdf, off, Device::ACCESS_32BIT), - .size = size - }; - }; - - Resource_params const bar0 = update_bar(id, base_address & 0xffffffff); - - if (!res.mem64()) { - res = Resource(bar0.bar, bar0.size); - return; - } - - Resource_params const bar1 = update_bar(id + 1, (base_address >> 32) & 0xffffffff); - - res = Resource(bar0.bar, bar0.size, bar1.bar, bar1.size); - } - - template void for_each_resource(FN const &fn) const - { - for (unsigned r = 0; r < Device::NUM_RESOURCES; r++) { - if (!_resource_id_is_valid(r)) - break; - - if (_resource[r].valid()) - fn(r, _resource[r]); - } - } - - /** - * Read configuration space - */ - enum { DONT_TRACK_ACCESS = false }; - unsigned read(Config_access &pci_config, unsigned char address, - Device::Access_size size, bool track = true) - { - return pci_config.read(_bdf, address, size, track); - } - - /** - * Write configuration space - */ - void write(Config_access &pci_config, unsigned char address, - unsigned long value, Device::Access_size size, - bool track = true) - { - pci_config.write(_bdf, address, value, size, track); - } - - bool reg_in_use(Config_access &pci_config, unsigned char address, - Device::Access_size size) { - return pci_config.reg_in_use(address, size); } - - void disable_bus_master_dma(Config_access &pci_config) - { - Pci_header header (pci_config, _bdf); - - if (header.read()) - header.write(0); - } - - Device_bars save_bars() - { - Device_bars bars (_bdf); - - for (unsigned r = 0; r < Device::NUM_RESOURCES; r++) { - if (!_resource_id_is_valid(r)) - break; - - bars.bar_addr[r] = _resource[r].base(); - } - - return bars; - }; - - void restore_bars(Config_access &config, Device_bars const &bars) - { - for (unsigned r = 0; r < Device::NUM_RESOURCES; r++) { - if (!_resource_id_is_valid(r)) - break; - - /* index of base-address register in configuration space */ - unsigned const bar_idx = 0x10 + 4 * r; - - /* PCI protocol to write address after requesting size */ - config.write(_bdf, bar_idx, ~0U, Device::ACCESS_32BIT); - config.read (_bdf, bar_idx, Device::ACCESS_32BIT); - config.write(_bdf, bar_idx, bars.bar_addr[r], - Device::ACCESS_32BIT); - } - } - }; - - class Config_space : private List::Element - { - private: - - friend class List; - - uint32_t _bdf_start; - uint32_t _func_count; - addr_t _base; - - public: - - using List::Element::next; - - Config_space(uint32_t bdf_start, uint32_t func_count, addr_t base) - : - _bdf_start(bdf_start), _func_count(func_count), _base(base) {} - - addr_t lookup_config_space(Pci::Bdf const bdf) - { - if ((_bdf_start <= bdf.value()) && (bdf.value() <= _bdf_start + _func_count - 1)) - return _base + (unsigned(bdf.value()) << 12); - return 0; - } - }; -} - -#endif /* _X86__PCI_DEVICE_CONFIG_H_ */ diff --git a/repos/os/src/drivers/platform/legacy/x86/pci_session_component.h b/repos/os/src/drivers/platform/legacy/x86/pci_session_component.h deleted file mode 100644 index ddf2828faa..0000000000 --- a/repos/os/src/drivers/platform/legacy/x86/pci_session_component.h +++ /dev/null @@ -1,1224 +0,0 @@ -/* - * \brief Platform session component - * \author Norman Feske - * \author Christian Helmuth - * \date 2008-01-28 - */ - -/* - * Copyright (C) 2008-2017 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. - */ - -#ifndef _PCI_SESSION_COMPONENT_H_ -#define _PCI_SESSION_COMPONENT_H_ - -/* base */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* os */ -#include -#include -#include -#include - -/* local */ -#include "device_pd.h" -#include "pci_bridge.h" -#include "pci_config_access.h" -#include "pci_device_component.h" - -namespace Platform { - - unsigned short bridge_bdf(unsigned char bus); - - class Pci_buses; - class Ram_dataspace; - class Rmrr; - class Root; - class Session_component; -} - - -class Platform::Ram_dataspace : public List::Element -{ - private: - - Ram_dataspace_capability const _cap; - - public: - - Ram_dataspace(Ram_dataspace_capability c) : _cap(c) { } - - bool match(const Ram_dataspace_capability &cap) const { - return cap.local_name() == _cap.local_name(); } - - Ram_dataspace_capability cap() const { return _cap; } -}; - - -class Platform::Rmrr : public List::Element -{ - public: - - class Bdf : public List::Element - { - private: - - uint8_t _bus, _dev, _func; - - public: - - Bdf(uint8_t bus, uint8_t dev, uint8_t func) - : _bus(bus), _dev(dev), _func(func) { } - - bool match(Pci::Bdf const bdf) - { - return bdf.bus == _bus && bdf.device == _dev && - bdf.function == _func; - } - }; - - private: - - uint64_t const _start, _end; - - Io_mem_dataspace_capability _cap { }; - - List _bdf_list { }; - - Constructible _io_mem { }; - - public: - - Rmrr(uint64_t start, uint64_t end) : _start(start), _end(end) { } - - Io_mem_dataspace_capability match(Env &env, Device_config config) - { - for (Bdf *bdf = _bdf_list.first(); bdf; bdf = bdf->next()) { - if (!bdf->match(config.bdf())) - continue; - - if (_cap.valid()) - return _cap; - - _io_mem.construct(env, _start, _end - _start + 1); - _cap = _io_mem->dataspace(); - return _cap; - } - return Io_mem_dataspace_capability(); - } - - addr_t start() const { return _start; } - - void add(Bdf * bdf) { _bdf_list.insert(bdf); } - - static List *list() - { - static List _list; - return &_list; - } -}; - - -class Platform::Pci_buses -{ - private: - - Bit_array _valid { }; - - void _scan_bus(Config_access &, Allocator &, Device_bars_pool &, - unsigned char bus, Xml_node const &config); - - bool _bus_valid(int bus) - { - if (bus >= Device_config::MAX_BUSES) - return false; - - return _valid.get(bus, 1); - } - - public: - - Pci_buses(Allocator &heap, - Attached_io_mem_dataspace &pciconf, - Device_bars_pool &devices_bars, - Xml_node const &config_node) - { - Config_access c(pciconf); - _scan_bus(c, heap, devices_bars, 0 /* root bus */, config_node); - } - - /** - * Scan PCI buses for a device - * - * \param bus start scanning at bus number - * \param device start scanning at device number - * \param function start scanning at function number - * \param out_device_config device config information of the - * found device - * \param config_access interface for accessing the PCI - * configuration - * space - * - * \retval true device was found - * \retval false no device was found - */ - bool find_next(unsigned bus, unsigned device, unsigned function, - Device_config *out_device_config, - Config_access *config_access) - { - for (; bus < Device_config::MAX_BUSES; bus++) { - if (!_bus_valid(bus)) - continue; - - for (; device < Device_config::MAX_DEVICES; device++) { - for (; function < Device_config::MAX_FUNCTIONS; function++) { - - /* read config space */ - Pci::Bdf const bdf { .bus = bus, .device = device, .function = function }; - Device_config config(bdf, config_access); - - if (config.valid()) { - *out_device_config = config; - return true; - } - } - function = 0; /* init value for next device */ - } - device = 0; /* init value for next bus */ - } - return false; - } -}; - - -class Platform::Session_component : public Rpc_object -{ - private: - - Env &_env; - Attached_rom_dataspace &_config; - Attached_io_mem_dataspace &_pciconf; - addr_t const _pciconf_base; - Ram_quota_guard _ram_guard; - Cap_quota_guard _cap_guard; - Constrained_ram_allocator _env_ram { _env.pd(), _ram_guard, _cap_guard }; - Heap _md_alloc; - Session_label const _label; - List _device_list { }; - Platform::Pci_buses &_pci_bus; - Allocator &_global_heap; - Pci::Config::Delayer &_delayer; - Device_bars_pool &_devices_bars; - bool const _iommu; - bool const _msi_avail; - bool _msi_usage { true }; - bool _msix_usage { true }; - - /** - * Registry of RAM dataspaces allocated by the session - */ - List _ram_caps { }; - - void _insert(Ram_dataspace_capability cap) { - _ram_caps.insert(new (_md_alloc) Platform::Ram_dataspace(cap)); } - - bool _owned(Ram_dataspace_capability cap) - { - for (Ram_dataspace *ds = _ram_caps.first(); ds; ds = ds->next()) - if (ds->match(cap)) - return true; - - return false; - } - - bool _remove(Ram_dataspace_capability cap) - { - for (Platform::Ram_dataspace *ds = _ram_caps.first(); ds; - ds = ds->next()) { - - if (!ds->match(cap)) - continue; - - _ram_caps.remove(ds); - destroy(_md_alloc, ds); - return true; - } - return false; - } - - Platform::Device_pd _device_pd { _env, _label, _ram_guard, _cap_guard }; - - enum { MAX_PCI_DEVICES = Device_config::MAX_BUSES * - Device_config::MAX_DEVICES * - Device_config::MAX_FUNCTIONS }; - - static Bit_array bdf_in_use; - - /** - * List containing extended PCI config space information - */ - static List &config_space_list() - { - static List config_space; - return config_space; - } - - /** - * Find for a given PCI device described by the bus:dev:func triple - * the corresponding extended 4K PCI config space address. - * A io mem dataspace is created and returned. - */ - addr_t lookup_config_space(Pci::Bdf const bdf) - { - addr_t config_space = ~0UL; /* invalid */ - - Config_space *e = config_space_list().first(); - for (; e && (config_space == ~0UL); e = e->next()) - config_space = e->lookup_config_space(bdf); - - return config_space; - } - - typedef String<32> Alias_name; - - /* - * List of aliases for PCI base class, sub class, and - * programming interface triples supported in XML config - */ - bool valid_alias(Alias_name const &name, unsigned const class_code = ~0U) - { - /* wildcard 0xff matches all codes */ - auto wildcard = [] (uint8_t v) { return v == 0xff; }; - - static struct Alias { - const char *name; - uint8_t b, s, p; /* base class, sub class, progif */ - } const aliases [] = { - { "ALL" , 0xff, 0xff, 0xff}, - { "AHCI" , 0x01, 0x06, 0xff}, - { "AUDIO" , 0x04, 0x01, 0xff}, - { "ETHERNET" , 0x02, 0x00, 0xff}, - { "HDAUDIO" , 0x04, 0x03, 0xff}, - { "ISABRIDGE", 0x06, 0x01, 0xff}, - { "NVME" , 0x01, 0x08, 0x02}, - { "USB" , 0x0c, 0x03, 0x00}, /* UHCI */ - { "USB" , 0x0c, 0x03, 0x10}, /* OHCI */ - { "USB" , 0x0c, 0x03, 0x20}, /* EHCI */ - { "USB" , 0x0c, 0x03, 0x30}, /* XHCI */ - { "USB4" , 0x0c, 0x03, 0x40}, /* USB4 NHI/Thunderbolt */ - { "VGA" , 0x03, 0x00, 0x00}, - { "WIFI" , 0x02, 0x80, 0xff}, - }; - - uint8_t const b = (class_code >> 16) & 0xff; - uint8_t const s = (class_code >> 8) & 0xff; - uint8_t const p = class_code & 0xff; - - for (Alias const &alias : aliases) { - if (name != alias.name) - continue; - - if ((wildcard(b) || wildcard(alias.b) || b == alias.b) - && (wildcard(s) || wildcard(alias.s) || s == alias.s) - && (wildcard(p) || wildcard(alias.p) || p == alias.p)) - return true; - } - - return false; - } - - /** - * Check device usage according to session policy - */ - bool permit_device(const char * name) - { - Session_policy const policy { _label, _config.xml() }; - - try { - policy.for_each_sub_node("device", [&] (Xml_node dev) { - - /* enforce restriction based on name */ - if (dev.attribute_value("name", Device_name_string()) == name) - /* found identical match - permit access */ - throw true; - }); - } catch (bool result) { return result; } - - return false; - } - - static bool _bdf_exactly_specified(Xml_node node) - { - return node.has_attribute("bus") - && node.has_attribute("device") - && node.has_attribute("function"); - } - - static bool _bdf_attributes_in_valid_range(Xml_node const &node) - { - return _bdf_exactly_specified(node) - && (node.attribute_value("bus", 0U) < Device_config::MAX_BUSES) - && (node.attribute_value("device", 0U) < Device_config::MAX_DEVICES) - && (node.attribute_value("function", 0U) < Device_config::MAX_FUNCTIONS); - } - - static bool _bdf_matches(Xml_node const &node, Pci::Bdf const &bdf) - { - return Pci::Bdf::from_xml(node) == bdf; - } - - /** - * Check according session policy device usage - */ - bool permit_device(Pci::Bdf const bdf, unsigned const class_code) - { - try { - Session_policy const policy { _label, _config.xml() }; - - policy.for_each_sub_node("pci", [&] (Xml_node node) { - - if (_bdf_exactly_specified(node)) { - if (_bdf_matches(node, bdf)) - throw true; - /* check also for class entry */ - } - - if (!node.has_attribute("class")) - return; - - /* enforce restriction based upon classes */ - auto alias = node.attribute_value("class", Alias_name()); - - if (!valid_alias(alias, class_code)) - return; - - /* if this bdf is used by some policy - deny */ - if (alias != "ALL" && find_dev_in_policy(bdf)) - return; - - throw true; - }); - } catch (bool result) { return result; } - - return false; - } - - /** - * Lookup a given device name. - */ - bool find_dev_in_policy(const char * dev_name, bool once = true) - { - try { - _config.xml().for_each_sub_node("policy", [&] (Xml_node policy) { - policy.for_each_sub_node("device", [&] (Xml_node device) { - - if (device.attribute_value("name", Device_name_string()) == dev_name) { - - if (once) - throw true; - once = true; - } - }); - }); - } catch (bool result) { return result; } - - return false; - } - - /** - * Lookup a given device name. - */ - bool find_dev_in_policy(Pci::Bdf const bdf, bool once = true) - { - try { - Xml_node xml = _config.xml(); - xml.for_each_sub_node("policy", [&] (Xml_node policy) { - policy.for_each_sub_node("pci", [&] (Xml_node node) { - - if (_bdf_exactly_specified(node)) { - - if (_bdf_matches(node, bdf)) { - - if (once) - throw true; - once = true; - } - } - }); - }); - } catch (bool result) { return result; } - - return false; - } - - public: - - /** - * Constructor - */ - Session_component(Env &env, - Attached_rom_dataspace &config, - Attached_io_mem_dataspace &pciconf, - addr_t pciconf_base, - Platform::Pci_buses &buses, - Allocator &global_heap, - Pci::Config::Delayer &delayer, - Device_bars_pool &devices_bars, - char const *args, - bool const iommu, - bool const msi) - : - _env(env), - _config(config), - _pciconf(pciconf), - _pciconf_base(pciconf_base), - _ram_guard(ram_quota_from_args(args)), - _cap_guard(cap_quota_from_args(args)), - _md_alloc(_env_ram, env.rm()), - _label(label_from_args(args)), - _pci_bus(buses), - _global_heap(global_heap), - _delayer(delayer), - _devices_bars(devices_bars), - _iommu(iommu), - _msi_avail(msi) - { - /* subtract the RPC session and session dataspace capabilities */ - _cap_guard.withdraw(Cap_quota{2}); - - check_for_policy(); - } - - void check_for_policy() - { - Session_policy const policy { _label, _config.xml() }; - - if (_msi_avail) { - _msi_usage = policy.attribute_value("msi", _msi_usage); - _msix_usage = _msi_usage && - policy.attribute_value("msix", _msix_usage); - } else - _msi_usage = _msix_usage = false; - - /* check policy for non-pci devices */ - policy.for_each_sub_node("device", [&] (Xml_node device_node) { - - if (!device_node.has_attribute("name")) { - error("'", _label, "' - device node " "misses 'name' attribute"); - throw Service_denied(); - } - - Device_name_string const name = - device_node.attribute_value("name", Device_name_string()); - - enum { DOUBLET = false }; - if (find_dev_in_policy(name.string(), DOUBLET)) { - error("'", _label, "' - device '", name, "' " - "is part of more than one policy"); - throw Service_denied(); - } - }); - - /* pci devices */ - policy.for_each_sub_node("pci", [&] (Xml_node node) { - - enum { INVALID_CLASS = 0x1000000U }; - - /** - * Valid input is either a triple of 'bus', 'device', - * 'function' attributes or a single 'class' attribute. - * All other attribute names are traded as wrong. - */ - if (node.has_attribute("class")) { - - Alias_name const alias = node.attribute_value("class", Alias_name()); - - if (!valid_alias(alias)) { - error("'", _label, "' - invalid 'class' ", - "attribute '", alias, "'"); - throw Service_denied(); - } - - /* sanity check that 'class' is the only attribute */ - try { - node.attribute(1); - error("'", _label, "' - attributes beside 'class' detected"); - throw Service_denied(); - } - catch (Xml_attribute::Nonexistent_attribute) { } - - /* we have a class and it is the only attribute */ - return; - } - - /* no 'class' attribute - now check for valid bdf triple */ - try { - node.attribute(3); - error("'", _label, "' - " "invalid number of pci node attributes"); - throw Service_denied(); - - } catch (Xml_attribute::Nonexistent_attribute) { } - - if (_bdf_exactly_specified(node)) { - - if (!_bdf_attributes_in_valid_range(node)) { - error("'", _label, "' - " - "invalid pci node attributes for bdf"); - throw Service_denied(); - } - - Pci::Bdf const bdf = Pci::Bdf::from_xml(node); - - enum { DOUBLET = false }; - if (find_dev_in_policy(bdf, DOUBLET)) { - error("'", _label, "' - device '", bdf, "' " - "is part of more than one policy"); - throw Service_denied(); - } - } - }); - } - - bool policy_valid() - { - try { - /* check that policy is available */ - check_for_policy(); - } catch (...) { - return false; - } - - /* check that device entries in policy are still permitted */ - if (!_device_list.first()) - return true; - - bool result = true; - - _device_list.first()->for_each_device([&](auto const &dev) { - - /* Non PCI devices */ - if (!dev.pci_device()) { - if (!permit_device(dev.name().string())) - result = false; - - return; - } - - /* PCI devices */ - if (!permit_device(dev.device_config().bdf(), - dev.device_config().class_code())) - result = false; - }); - - return result; - } - - /** - * Destructor - */ - ~Session_component() - { - /* release all elements of the session's device list */ - while (_device_list.first()) - release_device(_device_list.first()->cap()); - - while (Platform::Ram_dataspace *ds = _ram_caps.first()) { - _ram_caps.remove(ds); - _env_ram.free(ds->cap()); - destroy(_md_alloc, ds); - } - } - - - void upgrade_resources(Session::Resources resources) - { - _ram_guard.upgrade(resources.ram_quota); - _cap_guard.upgrade(resources.cap_quota); - } - - - static void add_config_space(uint32_t bdf_start, - uint32_t func_count, - addr_t base, - Allocator &heap) - { - Config_space * space = - new (heap) Config_space(bdf_start, func_count, base); - config_space_list().insert(space); - } - - - /** - * Check whether msi usage was explicitly switched off - */ - bool msi_usage() const { return _msi_usage; } - - - /** - * Check whether msi-x usage was explicitly switched off - */ - bool msix_usage() const { return _msix_usage; } - - /*************************** - ** PCI session interface ** - ***************************/ - - Device_capability first_device(unsigned device_class, - unsigned class_mask) override { - return next_device(Device_capability(), device_class, class_mask); } - - Device_capability next_device(Device_capability prev_device, - unsigned device_class, - unsigned class_mask) override - { - /* - * Create the interface to the PCI config space. - */ - Config_access config_access(_pciconf); - - /* lookup device component for previous device */ - auto lambda = [&] (Device_component *prev) - { - - /* - * Start bus scanning after the previous device's location. - * If no valid device was specified for 'prev_device', - * start at the beginning. - */ - int bus = 0, device = 0, function = -1; - - if (prev) { - Device_config config = prev->device_config(); - bus = config.bdf().bus; - device = config.bdf().device; - function = config.bdf().function; - } - - /* - * Scan buses for devices. - * If no device is found, return an invalid capability. - */ - Device_config config; - - while (true) { - function += 1; - if (!_pci_bus.find_next(bus, device, function, &config, - &config_access)) - return Device_capability(); - - /* get new bdf values */ - bus = config.bdf().bus; - device = config.bdf().device; - function = config.bdf().function; - - /* if filter of driver don't match skip and continue */ - if ((config.class_code() ^ device_class) & class_mask) - continue; - - /* check that policy permit access to the matched device */ - if (permit_device(Pci::Bdf { (unsigned)bus, - (unsigned)device, - (unsigned)function }, - config.class_code())) - break; - } - - /* lookup if we have a extended pci config space */ - addr_t config_space = lookup_config_space(config.bdf()); - - /* - * A device was found. Create a new device component for the - * device and return its capability. - */ - Device_component * dev = new (_md_alloc) - Device_component(_env, config, config_space, config_access, - *this, _md_alloc, _global_heap, _delayer, - _devices_bars); - - _device_list.insert(dev); - - try { - /* if more than one driver uses the device - warn about */ - if (bdf_in_use.get(config.bdf().value(), 1)) - error("Device ", config, " is used by more than one driver - " - "session '", _label, "'."); - else - bdf_in_use.set(config.bdf().value(), 1); - - return _env.ep().rpc_ep().manage(dev); - } catch (...) { - _device_list.remove(dev); - destroy(_md_alloc, dev); - throw; - } - }; - return _env.ep().rpc_ep().apply(prev_device, lambda); - } - - void release_device(Device_capability device_cap) override - { - Device_component * device = nullptr; - auto lambda = [&] (Device_component *d) - { - device = d; - if (!device) - return; - - if (device->pci_device()) { - if (bdf_in_use.get(device->device_config().bdf().value(), 1)) - bdf_in_use.clear(device->device_config().bdf().value(), 1); - } - - _device_list.remove(device); - _env.ep().rpc_ep().dissolve(device); - }; - - /* lookup device component */ - _env.ep().rpc_ep().apply(device_cap, lambda); - - if (device) - destroy(_md_alloc, device); - } - - void assign_device(Device_component * device) - { - if (!device || device->config_space() == ~0UL || !_iommu) - return; - - try { - addr_t const base_ecam = _pciconf_base; - addr_t const base_offset = 0x1000UL * device->device_config().bdf().value(); - - if (base_ecam + base_offset != device->config_space()) - throw 1; - - for (Rmrr *r = Rmrr::list()->first(); r; r = r->next()) { - Io_mem_dataspace_capability rmrr_cap = r->match(_env, device->device_config()); - if (rmrr_cap.valid()) - _device_pd.attach_dma_mem(rmrr_cap, r->start()); - } - - _device_pd.assign_pci(_pciconf.cap(), base_offset, - device->device_config().bdf().value()); - - } catch (...) { - error("assignment to device pd or of RMRR region failed"); - } - } - - /** - * De-/Allocation of dma capable dataspaces - */ - - Ram_dataspace_capability alloc_dma_buffer(size_t const size, Cache cache) override - { - /* - * Check available quota beforehand and reflect the state back - * to the client because the 'Expanding_pd_session_client' will - * ask its parent otherwise. - */ - enum { WATERMARK_CAP_QUOTA = 8, }; - if (_env.pd().avail_caps().value < WATERMARK_CAP_QUOTA) - throw Out_of_caps(); - - enum { WATERMARK_RAM_QUOTA = 4096, }; - if (_env.pd().avail_ram().value < WATERMARK_RAM_QUOTA) - throw Out_of_ram(); - - if (!size) - return {}; - - Ram_dataspace_capability ram_cap = _env_ram.alloc(size, cache); - addr_t const dma_addr = _env.pd().dma_addr(ram_cap); - - if (!ram_cap.valid()) - return ram_cap; - - try { - _device_pd.attach_dma_mem(ram_cap, dma_addr); - _insert(ram_cap); - } catch (Out_of_ram) { - _env_ram.free(ram_cap); - throw Out_of_ram(); - } catch (Out_of_caps) { - _env_ram.free(ram_cap); - throw Out_of_caps(); - } - - return ram_cap; - } - - void free_dma_buffer(Ram_dataspace_capability ram_cap) override - { - if (!ram_cap.valid() || !_remove(ram_cap)) - return; - - _env_ram.free(ram_cap); - } - - addr_t dma_addr(Ram_dataspace_capability ram_cap) override - { - if (!ram_cap.valid() || !_owned(ram_cap)) - return 0; - - return _env.pd().dma_addr(ram_cap); - } - - /* non-PCI devices */ - Device_capability device(Device_name const &name) override; -}; - - -class Platform::Root : public Root_component -{ - private: - - Env &_env; - Allocator &_heap; - Attached_rom_dataspace &_config; - - Constructible _pci_confspace { }; - addr_t _pci_confspace_base = 0; - Constructible _pci_reporter { }; - - Device_bars_pool _devices_bars { }; - - Constructible _buses { }; - - bool _iommu { false }; - bool _pci_reported { false }; - bool _msi_platform; - - struct Timer_delayer : Pci::Config::Delayer, Timer::Connection - { - Timer_delayer(Env &env) : Timer::Connection(env) { } - - void usleep(uint64_t us) override { Timer::Connection::usleep(us); } - } _delayer { _env }; - - Registry > _sessions { }; - - void _parse_report_rom(Env &env, const char * acpi_rom, - bool acpi_platform) - { - Xml_node xml_acpi(acpi_rom); - if (!xml_acpi.has_type("acpi")) - throw 1; - - xml_acpi.for_each_sub_node("bdf", [&] (Xml_node &node) { - - uint32_t const bdf_start = node.attribute_value("start", 0U); - uint32_t const func_count = node.attribute_value("count", 0U); - addr_t const base = node.attribute_value("base", 0UL); - - Session_component::add_config_space(bdf_start, func_count, - base, _heap); - - Device_config const bdf_first(Pci::Bdf::from_value(bdf_start)); - Device_config const bdf_last(Pci::Bdf::from_value(bdf_start + - func_count - 1)); - - addr_t const memory_size = 0x1000UL * func_count; - - /* Simplification: Only consider first config space and - * check if it is for domain 0 */ - if (bdf_start || _pci_confspace.constructed()) { - warning("ECAM/MMCONF range ", - bdf_first, "-", bdf_last, " - addr ", - Hex_range(base, memory_size), " ignored"); - return; - } - - log("ECAM/MMCONF range ", bdf_first, "-", bdf_last, " - addr ", - Hex_range(base, memory_size)); - - _pci_confspace_base = base; - _pci_confspace.construct(env, base, memory_size); - }); - - if (!_pci_confspace.constructed()) - throw 2; - - Config_access config_access(*_pci_confspace); - - for (unsigned i = 0; i < xml_acpi.num_sub_nodes(); i++) { - Xml_node node = xml_acpi.sub_node(i); - - if (node.has_type("bdf") || node.has_type("reset")) - continue; - - if (node.has_type("irq_override")) { - unsigned const irq = node.attribute_value("irq", 0xffU); - unsigned const gsi = node.attribute_value("gsi", 0xffU); - unsigned const flags = node.attribute_value("flags", 0xffU); - - if (!acpi_platform) { - warning("MADT IRQ ", irq, "-> GSI ", gsi, " flags ", - flags, " ignored"); - continue; - } - - using Platform::Irq_override; - Irq_override * o = new (_heap) Irq_override(irq, gsi, - flags); - Irq_override::list()->insert(o); - continue; - } - - if (node.has_type("drhd") || node.has_type("ivdb")) { - _iommu = true; - continue; - } - - if (node.has_type("rmrr")) { - uint64_t const - mem_start = node.attribute_value("start", (uint64_t)0), - mem_end = node.attribute_value("end", (uint64_t)0); - - if (node.num_sub_nodes() == 0) - throw 3; - - Rmrr * rmrr = new (_heap) Rmrr(mem_start, mem_end); - Rmrr::list()->insert(rmrr); - - for (unsigned s = 0; s < node.num_sub_nodes(); s++) { - Xml_node scope = node.sub_node(s); - if (!scope.num_sub_nodes() || !scope.has_type("scope")) - throw 4; - - unsigned bus = 0, dev = 0, func = 0; - scope.attribute("bus_start").value(bus); - - for (unsigned p = 0; p < scope.num_sub_nodes(); p++) { - Xml_node path = scope.sub_node(p); - if (!path.has_type("path")) - throw 5; - - path.attribute("dev") .value(dev); - path.attribute("func").value(func); - - Pci::Bdf const bdf = { .bus = bus, .device = dev, - .function = func }; - - Device_config bridge(bdf, &config_access); - if (bridge.pci_bridge()) - /* PCI bridge spec 3.2.5.3, 3.2.5.4 */ - bus = bridge.read(config_access, 0x19, - Device::ACCESS_8BIT); - } - - rmrr->add(new (_heap) Rmrr::Bdf(bus, dev, func)); - } - continue; - } - - if (node.has_type("root_bridge")) { - node.attribute("bdf").value(Platform::Bridge::root_bridge_bdf); - continue; - } - - if (!node.has_type("routing")) { - error ("unsupported node '", node.type(), "'"); - throw __LINE__; - } - - unsigned const gsi = node.attribute_value("gsi", 0U), - bridge_bdf = node.attribute_value("bridge_bdf", 0U), - device = node.attribute_value("device", 0U), - device_pin = node.attribute_value("device_pin", 0U); - - /* drop routing information on non ACPI platform */ - if (!acpi_platform) - continue; - - Irq_routing * r = new (_heap) Irq_routing(gsi, bridge_bdf, - device, device_pin); - Irq_routing::list()->insert(r); - } - } - - void _construct_buses() - { - Dataspace_client ds_pci_mmio(_pci_confspace->cap()); - - uint64_t const phys_addr = _pci_confspace_base; - uint64_t const phys_size = ds_pci_mmio.size(); - uint64_t mmio_size = 0x10000000UL; /* max MMCONF memory */ - - /* try surviving wrong ACPI ECAM/MMCONF table information */ - while (true) { - try { - _buses.construct(_heap, *_pci_confspace, _devices_bars, _config.xml()); - /* construction and scan succeeded */ - break; - } catch (Platform::Config_access::Invalid_mmio_access) { - - error("ECAM/MMCONF MMIO access out of bounds - " - "ACPI table information is wrong!"); - - _pci_confspace.destruct(); - - while (mmio_size > phys_size) { - try { - error(" adjust size from ", Hex(phys_size), - "->", Hex(mmio_size)); - _pci_confspace.construct(_env, phys_addr, mmio_size); - /* got memory - try again */ - break; - } catch (Service_denied) { - /* decrease by one bus memory size */ - mmio_size -= 0x1000UL * 32 * 8; - } - } - if (mmio_size <= phys_size) - /* broken machine - you're lost */ - throw; - } - } - } - - protected: - - Session_component *_create_session(const char *args) override - { - try { - return new (md_alloc()) - Registered(_sessions, _env, _config, - *_pci_confspace, - _pci_confspace_base, - *_buses, _heap, _delayer, - _devices_bars, args, _iommu, - _msi_platform); - } - catch (Session_policy::No_policy_defined) { - error("Invalid session request, no matching policy for ", - "'", label_from_args(args).string(), "'"); - throw Service_denied(); - } - } - - void _upgrade_session(Session_component *s, const char *args) override { - s->upgrade_resources(session_resources_from_args(args)); } - - public: - - /** - * Constructor - * - * \param ep entry point to be used for serving the PCI session - * and PCI device interface - * \param md_alloc meta-data allocator for allocating PCI-session - * components and PCI-device components - */ - Root(Env &env, Allocator &heap, Allocator &md_alloc, Attached_rom_dataspace &config, - char const *acpi_rom, bool acpi_platform, bool msi_platform) - : - Root_component(&env.ep().rpc_ep(), &md_alloc), - _env(env), - _heap(heap), - _config(config), - _msi_platform(msi_platform) - { - try { - _parse_report_rom(env, acpi_rom, acpi_platform); - } catch (...) { - error("ACPI report parsing error."); - throw; - } - - if (Platform::Bridge::root_bridge_bdf < Platform::Bridge::INVALID_ROOT_BRIDGE) { - Device_config config(Pci::Bdf::from_value(Platform::Bridge::root_bridge_bdf)); - log("Root bridge: ", config); - } else { - warning("Root bridge: unknown"); - } - - _construct_buses(); - - generate_pci_report(); - } - - void generate_pci_report() - { - if (!_pci_reported && _config.valid() && - _config.xml().has_sub_node("report") && - _config.xml().sub_node("report").attribute_value("pci", false)) { - - _pci_reported = true; - - _pci_reporter.construct(_env, "pci", "pci"); - - Config_access config_access(*_pci_confspace); - Device_config config; - - _pci_reporter->generate([&] (Reporter::Xml_generator &xml) { - int bus = 0, device = 0, function = -1; - - /* iterate over pci devices */ - while (true) { - function += 1; - if (!(*_buses).find_next(bus, device, function, &config, - &config_access)) - return; - - bus = config.bdf().bus; - device = config.bdf().device; - function = config.bdf().function; - - xml.node("device", [&] () { - xml.attribute("bus" , String<5>(Hex(bus))); - xml.attribute("device" , String<5>(Hex(device))); - xml.attribute("function" , String<5>(Hex(function))); - xml.attribute("vendor_id" , String<8>(Hex(config.vendor_id()))); - xml.attribute("device_id" , String<8>(Hex(config.device_id()))); - xml.attribute("class_code", String<12>(Hex(config.class_code()))); - xml.attribute("bridge" , config.pci_bridge() ? "yes" : "no"); - - enum { PCI_STATUS = 0x6, PCI_CAP_OFFSET = 0x34 }; - - try { - config.read(config_access, PCI_STATUS, Platform::Device::ACCESS_16BIT); - - uint8_t cap = config.read(config_access, - PCI_CAP_OFFSET, - Platform::Device::ACCESS_8BIT); - - for (uint16_t val = 0; cap; cap = val >> 8) { - val = config.read(config_access, cap, Platform::Device::ACCESS_16BIT); - xml.attribute("cap", String<8>(Hex(val & 0xff))); - } - } catch (...) { - xml.attribute("cap", "failed to read"); - } - }); - } - }); - } - } - - bool config_with_policy() const { - return _config.valid() && _config.xml().has_sub_node("policy"); } - - void config_update() - { - _sessions.for_each([&](auto &session) { - if (!session.policy_valid()) - destroy(session); - }); - } -}; - -#endif /* _PCI_SESSION_COMPONENT_H_ */ diff --git a/repos/os/src/drivers/platform/legacy/x86/session.cc b/repos/os/src/drivers/platform/legacy/x86/session.cc deleted file mode 100644 index c08901dbbd..0000000000 --- a/repos/os/src/drivers/platform/legacy/x86/session.cc +++ /dev/null @@ -1,161 +0,0 @@ -/* - * \brief platform session component - * \author Norman Feske - * \date 2008-01-28 - */ - -/* - * Copyright (C) 2008-2017 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 "pci_session_component.h" -#include "pci_bridge.h" - - -/* set during ACPI ROM parsing to valid value */ -unsigned Platform::Bridge::root_bridge_bdf = INVALID_ROOT_BRIDGE; - - -static Genode::List *bridges() -{ - static Genode::List list; - return &list; -} - - -unsigned short Platform::bridge_bdf(unsigned char bus) -{ - for (Platform::Bridge *bridge = bridges()->first(); bridge; - bridge = bridge->next()) - { - if (bridge->part_of(bus)) - return bridge->bdf(); - } - /* XXX Ideally, this case should never happen */ - return Platform::Bridge::root_bridge_bdf; -} - -void Platform::Pci_buses::_scan_bus(Config_access &config_access, - Allocator &heap, - Device_bars_pool &devices_bars, - unsigned char bus, - Xml_node const &config_node) -{ - for (unsigned dev = 0; dev < Device_config::MAX_DEVICES; ++dev) { - for (unsigned fun = 0; fun < Device_config::MAX_FUNCTIONS; ++fun) { - - Pci::Bdf const bdf { .bus = bus, .device = dev, .function = fun }; - - /* read config space */ - Device_config config(bdf, &config_access); - - if (!config.valid()) - continue; - - /* apply fixups to BAR memory resources */ - config.for_each_resource([&] (int const id, Platform::Pci::Resource const res) - { - uint64_t remap_address = 0; - config_node.for_each_sub_node("pci-fixup", [&] (Xml_node node) { - if (!node.has_attribute("bus") - || !node.has_attribute("device") - || !node.has_attribute("function") - || !(bdf == Pci::Bdf::from_xml(node))) - return; - - node.for_each_sub_node("bar", [&] (Xml_node node) { - if (node.attribute_value("id", (long)-1) == id) - remap_address = node.attribute_value("address", (uint64_t)0); - }); - }); - - if (remap_address) { - config.remap_resource(config_access, id, 0x4017002000); - return; - } - - if (!res.base() && res.mem()) - warning(bdf, " BAR", id, " ", res, - " has invalid base address - consider "); - }); - - /* remember Device BARs required after power off and/or reset */ - Device_config::Device_bars bars = config.save_bars(); - if (!bars.all_invalid()) - new (heap) Registered(devices_bars, bars); - - /* - * Switch off PCI bus master DMA for some classes of devices, - * which caused trouble. - * Some devices are enabled by BIOS/UEFI or/and bootloaders and - * aren't switch off when handing over to the kernel and Genode. - * By disabling bus master DMA they should stop to issue DMA - * operations and IRQs. IRQs are problematic, if it is a shared - * IRQ - e.g. Ethernet and graphic card share a GSI IRQ. If the - * graphic card driver is started without a Ethernet driver, - * the graphic card may ack all IRQs. We may end up in a endless - * IRQ/ACK loop, since no Ethernet driver acknowledge/disable IRQ - * generation on the Ethernet device. - * - * Switching off PCI bus master DMA in general is a bad idea, - * since some device classes require a explicit handover protocol - * between BIOS/UEFI and device, e.g. USB. Violating such protocols - * lead to hard hangs on some machines. - */ - if (config.class_code() >> 8) { - uint16_t classcode = config.class_code() >> 16; - uint16_t subclass = (config.class_code() >> 8) & 0xff; - - if ((classcode == 0x2 && subclass == 0x00) /* ETHERNET */) { - config.disable_bus_master_dma(config_access); - } - } - - /* - * There is at least one device on the current bus, so - * we mark it as valid. - */ - if (!_valid.get(bus, 1)) - _valid.set(bus, 1); - - /* scan behind bridge */ - if (config.pci_bridge()) { - /* PCI bridge spec 3.2.5.3, 3.2.5.4 */ - unsigned char sec_bus = config.read(config_access, 0x19, - Device::ACCESS_8BIT); - unsigned char sub_bus = config.read(config_access, 0x20, - Device::ACCESS_8BIT); - - bridges()->insert(new (heap) Bridge(bus, dev, fun, sec_bus, - sub_bus)); - - uint16_t cmd = config.read(config_access, - Device_config::PCI_CMD_REG, - Platform::Device::ACCESS_16BIT); - - const bool enabled = (cmd & Device_config::PCI_CMD_MASK) - == Device_config::PCI_CMD_MASK; - - if (!enabled) { - config.write(config_access, Device_config::PCI_CMD_REG, - cmd | Device_config::PCI_CMD_MASK, - Platform::Device::ACCESS_16BIT); - } - - log(config, " - bridge ", - Hex(sec_bus, Hex::Prefix::OMIT_PREFIX, Hex::Pad::PAD), - ":00.0", !enabled ? " enabled" : ""); - - _scan_bus(config_access, heap, devices_bars, sec_bus, config_node); - } - } - } -} - - -using Platform::Session_component; - -Genode::Bit_array Session_component::bdf_in_use; diff --git a/repos/os/src/drivers/platform/legacy/x86/target.mk b/repos/os/src/drivers/platform/legacy/x86/target.mk deleted file mode 100644 index d9ab3786c1..0000000000 --- a/repos/os/src/drivers/platform/legacy/x86/target.mk +++ /dev/null @@ -1,9 +0,0 @@ -TARGET = legacy_pc_platform_drv -REQUIRES = x86 -SRC_CC = main.cc irq.cc pci_device.cc nonpci_devices.cc session.cc -SRC_CC += device_pd.cc acpi_devices.cc -LIBS = base - -INC_DIR = $(PRG_DIR) - -CC_CXX_WARN_STRICT_CONVERSION =