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
This commit is contained in:
Alexander Boettcher 2016-01-08 16:21:48 +01:00 committed by Christian Helmuth
parent eb16ad3ad9
commit a258caa7ab
8 changed files with 36 additions and 22 deletions

View File

@ -33,8 +33,8 @@ namespace Genode {
return call<Rpc_assign_parent>(parent);
}
bool assign_pci(addr_t pci_config_memory_address) {
return call<Rpc_assign_pci>(pci_config_memory_address); }
bool assign_pci(addr_t pci_config_memory_address, uint16_t bdf) {
return call<Rpc_assign_pci>(pci_config_memory_address, bdf); }
};
}

View File

@ -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);

View File

@ -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);
};
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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
*/

View File

@ -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 <io_mem_session/capability.h>
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>
{
Device_pd_client(Capability<Device_pd> cap)
:
Rpc_client<Device_pd>(cap) { }
: Rpc_client<Device_pd>(cap) { }
void attach_dma_mem(Genode::Dataspace_capability cap) {
call<Rpc_attach_dma_mem>(cap); }
void assign_pci(Genode::Io_mem_dataspace_capability cap) {
call<Rpc_assign_pci>(cap); }
void assign_pci(Genode::Io_mem_dataspace_capability cap,
Genode::uint16_t bdf)
{
call<Rpc_assign_pci>(cap, bdf);
}
};
struct Platform::Device_pd_component : Genode::Rpc_object<Device_pd,
Device_pd_component>
{
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);
};

View File

@ -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());