From a258caa7abd8f9d34c4ddb94b4d18182efbcda05 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Fri, 8 Jan 2016 16:21:48 +0100 Subject: [PATCH] nova: propagate bdf for assign_pci properly Now, the right PCI bus:device:function (BDF) is reported to the kernel during assign_pci syscall - beforehand it was ever 0:0.0. The BDF is needed to lookup the correct DMAR unit the kernel has to configure. This was revealed as the DMAR unit for Intel graphics on x201 is not the same as for all other PCI devices we have drivers for on this platform. Fixes #1848 --- repos/base-nova/include/pd_session/client.h | 4 ++-- repos/base-nova/include/pd_session/pd_session.h | 12 ++++++++++-- .../src/core/include/pd_session_component.h | 2 +- .../base-nova/src/core/pd_session_extension.cc | 4 ++-- .../drivers/platform/spec/x86/device_pd/main.cc | 8 +++++--- .../platform/spec/x86/pci_device_config.h | 3 +++ .../platform/spec/x86/pci_device_pd_ipc.h | 17 ++++++++++------- .../platform/spec/x86/pci_session_component.h | 8 +++----- 8 files changed, 36 insertions(+), 22 deletions(-) diff --git a/repos/base-nova/include/pd_session/client.h b/repos/base-nova/include/pd_session/client.h index 18f78dc7e..9a29860dd 100644 --- a/repos/base-nova/include/pd_session/client.h +++ b/repos/base-nova/include/pd_session/client.h @@ -33,8 +33,8 @@ namespace Genode { return call(parent); } - bool assign_pci(addr_t pci_config_memory_address) { - return call(pci_config_memory_address); } + bool assign_pci(addr_t pci_config_memory_address, uint16_t bdf) { + return call(pci_config_memory_address, bdf); } }; } diff --git a/repos/base-nova/include/pd_session/pd_session.h b/repos/base-nova/include/pd_session/pd_session.h index 41e3e7776..efa573acc 100644 --- a/repos/base-nova/include/pd_session/pd_session.h +++ b/repos/base-nova/include/pd_session/pd_session.h @@ -49,7 +49,15 @@ namespace Genode { virtual int assign_parent(Parent_capability parent) = 0; - virtual bool assign_pci(addr_t) = 0; + /** + * Assign PCI device to a protection domain. + * + * \param pci_config_space virtual address of the 4K PCI config + * space extended memory of the device + * \param bdf bus/device/function of the PCI device + * \return true on success, or false in case of an error + */ + virtual bool assign_pci(addr_t pci_config_space, uint16_t bdf) = 0; /********************* ** RPC declaration ** @@ -57,7 +65,7 @@ namespace Genode { GENODE_RPC(Rpc_bind_thread, int, bind_thread, Thread_capability); GENODE_RPC(Rpc_assign_parent, int, assign_parent, Parent_capability); - GENODE_RPC(Rpc_assign_pci, bool, assign_pci, addr_t); + GENODE_RPC(Rpc_assign_pci, bool, assign_pci, addr_t, uint16_t); GENODE_RPC_INTERFACE(Rpc_bind_thread, Rpc_assign_parent, Rpc_assign_pci); diff --git a/repos/base-nova/src/core/include/pd_session_component.h b/repos/base-nova/src/core/include/pd_session_component.h index 67152bde8..57fb318b9 100644 --- a/repos/base-nova/src/core/include/pd_session_component.h +++ b/repos/base-nova/src/core/include/pd_session_component.h @@ -70,7 +70,7 @@ namespace Genode { int bind_thread(Thread_capability); int assign_parent(Parent_capability); - bool assign_pci(addr_t); + bool assign_pci(addr_t, uint16_t); }; } diff --git a/repos/base-nova/src/core/pd_session_extension.cc b/repos/base-nova/src/core/pd_session_extension.cc index a0f38f025..f90c3de2c 100644 --- a/repos/base-nova/src/core/pd_session_extension.cc +++ b/repos/base-nova/src/core/pd_session_extension.cc @@ -17,8 +17,8 @@ using namespace Genode; -bool Pd_session_component::assign_pci(addr_t pci_config_memory) +bool Pd_session_component::assign_pci(addr_t pci_config_memory, uint16_t bdf) { - uint8_t res = Nova::assign_pci(_pd.pd_sel(), pci_config_memory, 0); + uint8_t res = Nova::assign_pci(_pd.pd_sel(), pci_config_memory, bdf); return res == Nova::NOVA_OK; } diff --git a/repos/os/src/drivers/platform/spec/x86/device_pd/main.cc b/repos/os/src/drivers/platform/spec/x86/device_pd/main.cc index 0c30e20ce..8d4f206f9 100644 --- a/repos/os/src/drivers/platform/spec/x86/device_pd/main.cc +++ b/repos/os/src/drivers/platform/spec/x86/device_pd/main.cc @@ -127,7 +127,7 @@ void Platform::Device_pd_component::attach_dma_mem(Genode::Dataspace_capability } } -void Platform::Device_pd_component::assign_pci(Genode::Io_mem_dataspace_capability io_mem_cap) +void Platform::Device_pd_component::assign_pci(Genode::Io_mem_dataspace_capability io_mem_cap, Genode::uint16_t rid) { using namespace Genode; @@ -143,8 +143,10 @@ void Platform::Device_pd_component::assign_pci(Genode::Io_mem_dataspace_capabili PERR("assignment of PCI device failed - %lx", page); /* try to assign pci device to this protection domain */ - if (!env()->pd_session()->assign_pci(page)) - PERR("assignment of PCI device failed"); + if (!env()->pd_session()->assign_pci(page, rid)) + PERR("assignment of PCI device %x:%x.%x failed phys=%lx virt=%lx", + rid >> 8, (rid >> 3) & 0x1f, rid & 0x7, + ds_client.phys_addr(), page); /* we don't need the mapping anymore */ rm_session()->detach(page); diff --git a/repos/os/src/drivers/platform/spec/x86/pci_device_config.h b/repos/os/src/drivers/platform/spec/x86/pci_device_config.h index bab1f2d3a..e3c0f36b7 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_device_config.h +++ b/repos/os/src/drivers/platform/spec/x86/pci_device_config.h @@ -143,6 +143,9 @@ namespace Platform { int device_number() { return _device; } int function_number() { return _function; } + Genode::uint16_t bdf () { + return (_bus << 8) | (_device << 3) | (_function & 0x7); } + /** * Accessor functions for device information */ diff --git a/repos/os/src/drivers/platform/spec/x86/pci_device_pd_ipc.h b/repos/os/src/drivers/platform/spec/x86/pci_device_pd_ipc.h index 6cf7bcde0..097095977 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_device_pd_ipc.h +++ b/repos/os/src/drivers/platform/spec/x86/pci_device_pd_ipc.h @@ -5,7 +5,7 @@ */ /* - * Copyright (C) 2013-2015 Genode Labs GmbH + * Copyright (C) 2013-2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. @@ -18,6 +18,7 @@ #include namespace Platform { + struct Device_pd; struct Device_pd_client; struct Device_pd_component; @@ -33,7 +34,7 @@ struct Platform::Device_pd : Genode::Session GENODE_RPC_THROW(Rpc_assign_pci, void, assign_pci, GENODE_TYPE_LIST(Genode::Rm_session::Out_of_metadata, Genode::Rm_session::Region_conflict), - Genode::Io_mem_dataspace_capability); + Genode::Io_mem_dataspace_capability, Genode::uint16_t); GENODE_RPC_INTERFACE(Rpc_attach_dma_mem, Rpc_assign_pci); }; @@ -41,19 +42,21 @@ struct Platform::Device_pd : Genode::Session struct Platform::Device_pd_client : Genode::Rpc_client { Device_pd_client(Capability cap) - : - Rpc_client(cap) { } + : Rpc_client(cap) { } void attach_dma_mem(Genode::Dataspace_capability cap) { call(cap); } - void assign_pci(Genode::Io_mem_dataspace_capability cap) { - call(cap); } + void assign_pci(Genode::Io_mem_dataspace_capability cap, + Genode::uint16_t bdf) + { + call(cap, bdf); + } }; struct Platform::Device_pd_component : Genode::Rpc_object { void attach_dma_mem(Genode::Dataspace_capability); - void assign_pci(Genode::Io_mem_dataspace_capability); + void assign_pci(Genode::Io_mem_dataspace_capability, Genode::uint16_t); }; diff --git a/repos/os/src/drivers/platform/spec/x86/pci_session_component.h b/repos/os/src/drivers/platform/spec/x86/pci_session_component.h index c7487a722..acca4edc8 100644 --- a/repos/os/src/drivers/platform/spec/x86/pci_session_component.h +++ b/repos/os/src/drivers/platform/spec/x86/pci_session_component.h @@ -266,12 +266,10 @@ namespace Platform { * A io mem dataspace is created and returned. */ Genode::addr_t - lookup_config_space(Genode::uint8_t bus, Genode::uint8_t dev, - Genode::uint8_t func) + lookup_config_space(Genode::uint16_t const bdf) { using namespace Genode; - uint32_t bdf = (bus << 8) | ((dev & 0x1f) << 3) | (func & 0x7); addr_t config_space = ~0UL; /* invalid */ Config_space *e = config_space_list().first(); @@ -670,7 +668,7 @@ namespace Platform { /* lookup if we have a extended pci config space */ Genode::addr_t config_space = - lookup_config_space(bus, device, function); + lookup_config_space(config.bdf()); /* * A device was found. Create a new device component for the @@ -753,7 +751,7 @@ namespace Platform { return; try { - _device_pd->child.assign_pci(io_mem); + _device_pd->child.assign_pci(io_mem, device->config().bdf()); for (Rmrr *r = Rmrr::list()->first(); r; r = r->next()) { Io_mem_dataspace_capability rmrr_cap = r->match(device->config());