mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 21:57:55 +00:00
acpi_drv: report Intel opregion copy
acpica and the Intel display driver tries to use the Intel Opregion simultaneously on Genode, which is not supported nor wanted for IO_MEM region as which it is handled. Attempts to remove the access to the region was not successful, since some SSDT table contains ACPI AML code which is executed regularly and read/write the Opregion. The patch adds support to make a copy of the Intel Opregion and report it as is. The copy was sufficient to make the Intel display driver working to find and lookup the Intel VBT (video bios table) information to setup all connectors on a Fujitsu U7411 docking station. Issue #4531
This commit is contained in:
parent
b1195508ba
commit
c2d9fbca9b
@ -11,7 +11,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2017 Genode Labs GmbH
|
* Copyright (C) 2009-2022 Genode Labs GmbH
|
||||||
*
|
*
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU Affero General Public License version 3.
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include "acpi.h"
|
#include "acpi.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "intel_opregion.h"
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
@ -412,6 +413,95 @@ class Pci_config_space : public List<Pci_config_space>::Element
|
|||||||
static List<Pci_config_space> _list;
|
static List<Pci_config_space> _list;
|
||||||
return &_list;
|
return &_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Config_space : Mmio
|
||||||
|
{
|
||||||
|
struct Vendor : Register<0x00, 16> { enum { INTEL = 0x8086 }; };
|
||||||
|
struct Class : Register<0x0b, 8> { enum { DISPLAY = 0x3 }; };
|
||||||
|
struct Asls : Register<0xfc, 32> { };
|
||||||
|
|
||||||
|
Config_space(addr_t mmio) : Mmio(mmio) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Opregion : Mmio
|
||||||
|
{
|
||||||
|
struct Minor : Register<0x16, 8> { };
|
||||||
|
struct Major : Register<0x17, 8> { };
|
||||||
|
struct MBox : Register<0x58, 32> {
|
||||||
|
struct Asle : Bitfield<2, 1> { };
|
||||||
|
};
|
||||||
|
struct Asle_ardy : Register<0x300, 32> { };
|
||||||
|
struct Asle_rvda : Register<0x3ba, 64> { };
|
||||||
|
struct Asle_rvds : Register<0x3c2, 32> { };
|
||||||
|
|
||||||
|
Opregion(addr_t mmio) : Mmio(mmio) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void intel_opregion(Env &env)
|
||||||
|
{
|
||||||
|
for (auto *e = list()->first(); e; e = e->next()) {
|
||||||
|
if (e->_bdf_start != 0u) /* BDF 0:0.0 */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto const config_offset = 8u * 2; /* BDF 0:2.0 */
|
||||||
|
auto const config_size = 4096;
|
||||||
|
|
||||||
|
if (e->_func_count <= config_offset)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Attached_io_mem_dataspace pci_config(env, e->_base +
|
||||||
|
config_offset * config_size,
|
||||||
|
config_size);
|
||||||
|
Config_space device((addr_t)pci_config.local_addr<void>());
|
||||||
|
|
||||||
|
if ((device.read<Config_space::Vendor>() != Config_space::Vendor::INTEL) ||
|
||||||
|
(device.read<Config_space::Class>() != Config_space::Class::DISPLAY))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
OPREGION_SIZE = 2 * 4096
|
||||||
|
};
|
||||||
|
|
||||||
|
addr_t const phys_asls = device.read<Config_space::Asls>();
|
||||||
|
if (!phys_asls)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
addr_t asls_size = OPREGION_SIZE;
|
||||||
|
|
||||||
|
{
|
||||||
|
Attached_io_mem_dataspace map_asls(env, phys_asls, asls_size);
|
||||||
|
Opregion opregion((addr_t)map_asls.local_addr<void>());
|
||||||
|
|
||||||
|
auto const rvda = opregion.read<Opregion::Asle_rvda>();
|
||||||
|
auto const rvds = opregion.read<Opregion::Asle_rvds>();
|
||||||
|
|
||||||
|
if (opregion.read<Opregion::MBox::Asle>() &&
|
||||||
|
opregion.read<Opregion::Major>() >= 2 && rvda && rvds) {
|
||||||
|
|
||||||
|
/* 2.0 rvda is physical, 2.1+ rvda is relative offset */
|
||||||
|
if (opregion.read<Opregion::Major>() > 2 ||
|
||||||
|
opregion.read<Opregion::Minor>() >= 1) {
|
||||||
|
|
||||||
|
if (rvda > asls_size)
|
||||||
|
asls_size += rvda - asls_size;
|
||||||
|
asls_size += opregion.read<Opregion::Asle_rvds>();
|
||||||
|
} else {
|
||||||
|
warning("rvda/rvds unsupported case");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Intel_opregion requires access to the opregion memory later
|
||||||
|
* on used by acpica. Therefore the code must be executed here
|
||||||
|
* and finished, before the acpi report is sent.
|
||||||
|
* With a valid acpi report the acpica driver starts to run
|
||||||
|
* and would collide with Intel_opregion.
|
||||||
|
*/
|
||||||
|
static Acpi::Intel_opregion opregion_report { env, phys_asls,
|
||||||
|
asls_size };
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1580,5 +1670,11 @@ void Acpi::generate_report(Genode::Env &env, Genode::Allocator &alloc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Intel opregion lookup & parsing must be finished before acpi
|
||||||
|
* report is sent, therefore the invocation is placed exactly here.
|
||||||
|
*/
|
||||||
|
Pci_config_space::intel_opregion(env);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
57
repos/os/src/drivers/acpi/intel_opregion.cc
Normal file
57
repos/os/src/drivers/acpi/intel_opregion.cc
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* \brief Lookup Intel opregion region and report it as is (plain data)
|
||||||
|
* \author Alexander Boettcher
|
||||||
|
* \date 2022-05-25
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 <base/attached_io_mem_dataspace.h>
|
||||||
|
#include <base/attached_ram_dataspace.h>
|
||||||
|
#include <os/reporter.h>
|
||||||
|
|
||||||
|
#include "intel_opregion.h"
|
||||||
|
|
||||||
|
void Acpi::Intel_opregion::generate_report(Genode::Env &env,
|
||||||
|
addr_t const region_phys,
|
||||||
|
addr_t const region_size)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
addr_t const phys_addr_offset = region_phys & 0xffful;
|
||||||
|
addr_t const memory_size = region_size + phys_addr_offset;
|
||||||
|
|
||||||
|
/* create ram dataspace with space for io_mem address + size */
|
||||||
|
Attached_io_mem_dataspace io_mem { env, region_phys, memory_size };
|
||||||
|
Attached_ram_dataspace report_mem { env.ram(), env.rm(),
|
||||||
|
memory_size + sizeof(addr_t) * 2 };
|
||||||
|
|
||||||
|
auto mem_local = report_mem.local_addr<char>();
|
||||||
|
|
||||||
|
/* copy io_mem to ram dataspace and preserve offset */
|
||||||
|
memcpy(mem_local + phys_addr_offset, io_mem.local_addr<char>(),
|
||||||
|
region_size);
|
||||||
|
|
||||||
|
Dataspace_client report_ds(report_mem.cap());
|
||||||
|
|
||||||
|
/* report also io_mem address and io_mem size (!equal to ds size) */
|
||||||
|
auto report_phys_ptr = (addr_t*)(mem_local + report_ds.size() - sizeof(addr_t) * 2);
|
||||||
|
auto report_phys_size = (addr_t*)(mem_local + report_ds.size() - sizeof(addr_t));
|
||||||
|
|
||||||
|
*report_phys_ptr = region_phys;
|
||||||
|
*report_phys_size = region_size;
|
||||||
|
|
||||||
|
/* create report */
|
||||||
|
_report.construct(env, "intel_opregion", "intel_opregion",
|
||||||
|
report_ds.size());
|
||||||
|
_report->enabled(true);
|
||||||
|
_report->report(report_mem.local_addr<void>(), report_ds.size());
|
||||||
|
|
||||||
|
} catch (...) {
|
||||||
|
Genode::warning("Intel opregion region copy failed");
|
||||||
|
}
|
||||||
|
}
|
41
repos/os/src/drivers/acpi/intel_opregion.h
Normal file
41
repos/os/src/drivers/acpi/intel_opregion.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* \brief Lookup Intel opregion and report it as is (plain data)
|
||||||
|
* \author Alexander Boettcher
|
||||||
|
* \date 2022-05-25
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INTEL_OPREGION_REPORTER_H_
|
||||||
|
#define _INTEL_OPREGION_REPORTER_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <os/reporter.h>
|
||||||
|
|
||||||
|
namespace Acpi {
|
||||||
|
class Intel_opregion;
|
||||||
|
using namespace Genode;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Acpi::Intel_opregion
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
Constructible<Reporter> _report { };
|
||||||
|
|
||||||
|
void generate_report(Env &env, addr_t, addr_t);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Intel_opregion(Env &env, addr_t phys_base, addr_t size)
|
||||||
|
{
|
||||||
|
generate_report(env, phys_base, size);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _INTEL_OPREGION_REPORTER_H_ */
|
@ -1,6 +1,6 @@
|
|||||||
TARGET = acpi_drv
|
TARGET = acpi_drv
|
||||||
REQUIRES = x86
|
REQUIRES = x86
|
||||||
SRC_CC = main.cc acpi.cc smbios_table_reporter.cc
|
SRC_CC = main.cc acpi.cc smbios_table_reporter.cc intel_opregion.cc
|
||||||
LIBS = base
|
LIBS = base
|
||||||
|
|
||||||
INC_DIR = $(PRG_DIR)/../..
|
INC_DIR = $(PRG_DIR)/../..
|
||||||
@ -8,5 +8,6 @@ INC_DIR = $(PRG_DIR)/../..
|
|||||||
vpath main.cc $(PRG_DIR)/../..
|
vpath main.cc $(PRG_DIR)/../..
|
||||||
vpath acpi.cc $(PRG_DIR)/../..
|
vpath acpi.cc $(PRG_DIR)/../..
|
||||||
vpath smbios_table_reporter.cc $(PRG_DIR)/../..
|
vpath smbios_table_reporter.cc $(PRG_DIR)/../..
|
||||||
|
vpath intel_opregion.cc $(PRG_DIR)/../..
|
||||||
|
|
||||||
CC_CXX_WARN_STRICT_CONVERSION =
|
CC_CXX_WARN_STRICT_CONVERSION =
|
||||||
|
Loading…
Reference in New Issue
Block a user