acpi: transition to the new base API

Issue #1987
This commit is contained in:
Josef Söntgen 2016-05-28 10:52:26 +02:00 committed by Christian Helmuth
parent 833c9e01f5
commit c77f146e72
3 changed files with 111 additions and 98 deletions

View File

@ -11,7 +11,7 @@
*/ */
/* /*
* Copyright (C) 2009-2015 Genode Labs GmbH * Copyright (C) 2009-2016 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 General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -19,6 +19,7 @@
/* base includes */ /* base includes */
#include <io_mem_session/connection.h> #include <io_mem_session/connection.h>
#include <util/misc_math.h>
#include <util/mmio.h> #include <util/mmio.h>
/* os includes */ /* os includes */
@ -137,10 +138,10 @@ struct Dmar_struct_header : Generic
} while (addr < dmar_entry_end()); } while (addr < dmar_entry_end());
} }
struct Dmar_struct_header * clone() struct Dmar_struct_header * clone(Genode::Allocator &alloc)
{ {
size_t const size = dmar_entry_end() - reinterpret_cast<addr_t>(this); size_t const size = dmar_entry_end() - reinterpret_cast<addr_t>(this);
char * clone = new (env()->heap()) char[size]; char * clone = new (&alloc) char[size];
memcpy(clone, this, size); memcpy(clone, this, size);
return reinterpret_cast<Dmar_struct_header *>(clone); return reinterpret_cast<Dmar_struct_header *>(clone);
@ -371,7 +372,7 @@ class Table_wrapper
/** /**
* Parse override structures * Parse override structures
*/ */
void parse_madt() void parse_madt(Genode::Allocator &alloc)
{ {
Apic_struct *apic = _table->apic_struct(); Apic_struct *apic = _table->apic_struct();
for (; apic < _table->end(); apic = apic->next()) { for (; apic < _table->end(); apic = apic->next()) {
@ -382,12 +383,12 @@ class Table_wrapper
PINF("MADT IRQ %u -> GSI %u flags: %x", o->irq, o->gsi, o->flags); PINF("MADT IRQ %u -> GSI %u flags: %x", o->irq, o->gsi, o->flags);
Irq_override::list()->insert(new (env()->heap()) Irq_override::list()->insert(new (&alloc)
Irq_override(o->irq, o->gsi, o->flags)); Irq_override(o->irq, o->gsi, o->flags));
} }
} }
void parse_mcfg() const void parse_mcfg(Genode::Allocator &alloc) const
{ {
Mcfg_struct *mcfg = _table->mcfg_struct(); Mcfg_struct *mcfg = _table->mcfg_struct();
for (; mcfg < _table->mcfg_end(); mcfg = mcfg->next()) { for (; mcfg < _table->mcfg_end(); mcfg = mcfg->next()) {
@ -400,11 +401,11 @@ class Table_wrapper
uint32_t bus_start = mcfg->pci_bus_start * 32 * 8; uint32_t bus_start = mcfg->pci_bus_start * 32 * 8;
Pci_config_space::list()->insert( Pci_config_space::list()->insert(
new (env()->heap()) Pci_config_space(bus_start, func_count, mcfg->base)); new (&alloc) Pci_config_space(bus_start, func_count, mcfg->base));
} }
} }
void parse_dmar() const void parse_dmar(Genode::Allocator &alloc) const
{ {
Dmar_struct_header *head = _table->dmar_header(); Dmar_struct_header *head = _table->dmar_header();
PLOG("%u bit DMA physical addressable%s\n", head->width + 1, PLOG("%u bit DMA physical addressable%s\n", head->width + 1,
@ -415,7 +416,7 @@ class Table_wrapper
PLOG("DMA remapping structure type=%u", dmar.read<Dmar_common::Type>()); PLOG("DMA remapping structure type=%u", dmar.read<Dmar_common::Type>());
}); });
Dmar_entry::list()->insert(new (env()->heap()) Dmar_entry(head->clone())); Dmar_entry::list()->insert(new (&alloc) Dmar_entry(head->clone(alloc)));
} }
Table_wrapper(addr_t base) : _base(base), _table(0) Table_wrapper(addr_t base) : _base(base), _table(0)
@ -487,14 +488,14 @@ class Element : public List<Element>::Element
uint8_t _type; /* the type of this element */ uint8_t _type; /* the type of this element */
uint32_t _size; /* size in bytes */ uint32_t _size; /* size in bytes */
uint32_t _size_len; /* length of size in bytes */ uint32_t _size_len; /* length of size in bytes */
char *_name; /* name of element */ char _name[64]; /* name of element */
uint32_t _name_len; /* length of name in bytes */ uint32_t _name_len; /* length of name in bytes */
uint32_t _bdf; /* bus device function */ uint32_t _bdf; /* bus device function */
uint8_t const *_data; /* pointer to the data section */ uint8_t const *_data; /* pointer to the data section */
uint32_t _para_len; /* parameters to be skipped */ uint32_t _para_len; /* parameters to be skipped */
bool _valid; /* true if this is a valid element */ bool _valid; /* true if this is a valid element */
bool _routed; /* has the PCI information been read */ bool _routed; /* has the PCI information been read */
List<Pci_routing> *_pci; /* list of PCI routing elements for this element */ List<Pci_routing> _pci; /* list of PCI routing elements for this element */
/* packages we are looking for */ /* packages we are looking for */
enum { DEVICE = 0x5b, SUB_DEVICE = 0x82, DEVICE_NAME = 0x8, SCOPE = 0x10, METHOD = 0x14, PACKAGE_OP = 0x12 }; enum { DEVICE = 0x5b, SUB_DEVICE = 0x82, DEVICE_NAME = 0x8, SCOPE = 0x10, METHOD = 0x14, PACKAGE_OP = 0x12 };
@ -655,8 +656,7 @@ class Element : public List<Element>::Element
/* is absolute name */ /* is absolute name */
if (*name == ROOT_PREFIX || !parent) { if (*name == ROOT_PREFIX || !parent) {
_name = (char *)env()->heap()->alloc(_name_len); memcpy(_name, name + prefix_len, min(sizeof(_name), _name_len));
memcpy(_name, name + prefix_len, _name_len);
} }
else { else {
/* skip parts */ /* skip parts */
@ -665,7 +665,11 @@ class Element : public List<Element>::Element
/* skip parent prefix */ /* skip parent prefix */
for (uint32_t p = 0; name[p] == PARENT_PREFIX; p++, parent_len -= NAME_LEN) ; for (uint32_t p = 0; name[p] == PARENT_PREFIX; p++, parent_len -= NAME_LEN) ;
_name = (char *)env()->heap()->alloc(_name_len + parent_len);
if (_name_len + parent_len > sizeof(_name)) {
PERR("name is not large enough");
throw -1;
}
memcpy(_name, parent->_name, parent_len); memcpy(_name, parent->_name, parent_len);
memcpy(_name + parent_len, name + prefix_len, _name_len); memcpy(_name + parent_len, name + prefix_len, _name_len);
@ -747,7 +751,7 @@ class Element : public List<Element>::Element
* Try to locate _PRT table and its GSI values for device * Try to locate _PRT table and its GSI values for device
* (data has to be located within the device data) * (data has to be located within the device data)
*/ */
void _direct_prt(Element *dev) void _direct_prt(Genode::Allocator &alloc, Element *dev)
{ {
uint32_t len = 0; uint32_t len = 0;
@ -771,11 +775,11 @@ class Element : public List<Element>::Element
} }
if (i == 4) { if (i == 4) {
Pci_routing * r = new (env()->heap()) Pci_routing(val[0], val[1], val[3]); Pci_routing * r = new (&alloc) Pci_routing(val[0], val[1], val[3]);
/* set _ADR, _PIN, _GSI */ /* set _ADR, _PIN, _GSI */
dev->pci_list()->insert(r); dev->pci_list().insert(r);
dev->pci_list()->first()->dump(); dev->pci_list().first()->dump();
} }
len = len ? (e.data() - (_data + offset)) + e.size() : 1; len = len ? (e.data() - (_data + offset)) + e.size() : 1;
@ -785,7 +789,7 @@ class Element : public List<Element>::Element
/** /**
* Search for _PRT outside of device * Search for _PRT outside of device
*/ */
void _indirect_prt(Element *dev) void _indirect_prt(Genode::Allocator &alloc, Element *dev)
{ {
uint32_t name_len; uint32_t name_len;
uint32_t found = 0; uint32_t found = 0;
@ -805,7 +809,7 @@ class Element : public List<Element>::Element
for (uint32_t skip = 0; skip <= dev->_name_len / NAME_LEN; skip++) { for (uint32_t skip = 0; skip <= dev->_name_len / NAME_LEN; skip++) {
Element *e = dev->_compare(name, skip * NAME_LEN); Element *e = dev->_compare(name, skip * NAME_LEN);
if (e) if (e)
e->_direct_prt(dev); e->_direct_prt(alloc, dev);
} }
} }
else else
@ -815,9 +819,11 @@ class Element : public List<Element>::Element
Element(uint8_t const *data = 0, bool package_op4 = false) Element(uint8_t const *data = 0, bool package_op4 = false)
: :
_type(0), _size(0), _size_len(0), _name(0), _name_len(0), _bdf(0), _type(0), _size(0), _size_len(0), _name_len(0), _bdf(0),
_data(data), _para_len(0), _valid(false), _routed(false), _pci(0) _data(data), _para_len(0), _valid(false), _routed(false)
{ {
_name[0] = '\0';
if (!data) if (!data)
return; return;
@ -900,18 +906,14 @@ class Element : public List<Element>::Element
_type = other._type; _type = other._type;
_size = other._size; _size = other._size;
_size_len = other._size_len; _size_len = other._size_len;
memcpy(_name, other._name, sizeof(_name));
_name_len = other._name_len; _name_len = other._name_len;
_bdf = other._bdf; _bdf = other._bdf;
_data = other._data; _data = other._data;
_para_len = other._para_len;
_valid = other._valid; _valid = other._valid;
_routed = other._routed; _routed = other._routed;
_pci = other._pci; _pci = other._pci;
_para_len = other._para_len;
if (other._name) {
_name = (char *)env()->heap()->alloc(other._name_len);
memcpy(_name, other._name, _name_len);
}
} }
bool is_device_name() { return _type == DEVICE_NAME; } bool is_device_name() { return _type == DEVICE_NAME; }
@ -933,11 +935,7 @@ class Element : public List<Element>::Element
public: public:
virtual ~Element() virtual ~Element() { }
{
if (_name)
env()->heap()->free(_name, _name_len);
}
/** /**
* Accessors * Accessors
@ -969,7 +967,7 @@ class Element : public List<Element>::Element
return &_list; return &_list;
} }
static void clean_list() static void clean_list(Genode::Allocator &alloc)
{ {
unsigned long freed_up = 0; unsigned long freed_up = 0;
@ -985,7 +983,7 @@ class Element : public List<Element>::Element
Element * next = element->next(); Element * next = element->next();
Element::list()->remove(element); Element::list()->remove(element);
destroy(env()->heap(), element); destroy(&alloc, element);
element = next; element = next;
} }
@ -996,17 +994,12 @@ class Element : public List<Element>::Element
/** /**
* Return list of PCI information for this element * Return list of PCI information for this element
*/ */
List<Pci_routing> *pci_list() List<Pci_routing> & pci_list() { return _pci; }
{
if (!_pci)
_pci = new (env()->heap()) List<Pci_routing>();
return _pci;
}
/** /**
* Parse elements of table * Parse elements of table
*/ */
static void parse(Generic *table) static void parse(Genode::Allocator &alloc, Generic *table)
{ {
uint8_t const *data = table->data(); uint8_t const *data = table->data();
for (; data < table->data() + table->size; data++) { for (; data < table->data() + table->size; data++) {
@ -1018,7 +1011,7 @@ class Element : public List<Element>::Element
if (data + e.size() > table->data() + table->size) if (data + e.size() > table->data() + table->size)
break; break;
Element *i = new (env()->heap()) Element(e); Element *i = new (&alloc) Element(e);
list()->insert(i); list()->insert(i);
/* skip header */ /* skip header */
@ -1031,13 +1024,13 @@ class Element : public List<Element>::Element
data += e._para_len; data += e._para_len;
} }
parse_bdf(); parse_bdf(alloc);
} }
/** /**
* Parse BDF and GSI information * Parse BDF and GSI information
*/ */
static void parse_bdf() static void parse_bdf(Genode::Allocator &alloc)
{ {
for (Element *e = list()->first(); e; e = e->next()) { for (Element *e = list()->first(); e; e = e->next()) {
@ -1064,8 +1057,8 @@ class Element : public List<Element>::Element
if (verbose) if (verbose)
PDBG("Scanning device %x", e->_bdf); PDBG("Scanning device %x", e->_bdf);
prt->_direct_prt(e); prt->_direct_prt(alloc, e);
prt->_indirect_prt(e); prt->_indirect_prt(alloc, e);
} }
e->_routed = true; e->_routed = true;
@ -1083,7 +1076,7 @@ class Element : public List<Element>::Element
if (!e->is_device() || e->_bdf != bridge_bdf) if (!e->is_device() || e->_bdf != bridge_bdf)
continue; continue;
Pci_routing *r = e->pci_list()->first(); Pci_routing *r = e->pci_list().first();
for (; r; r = r->next()) { for (; r; r = r->next()) {
if (r->match_bdf(device_bdf) && r->pin() == pin) { if (r->match_bdf(device_bdf) && r->pin() == pin) {
if (verbose) PDBG("Found GSI: %u device : %x pin %u", if (verbose) PDBG("Found GSI: %u device : %x pin %u",
@ -1104,6 +1097,9 @@ class Acpi_table
{ {
private: private:
Genode::Env &env;
Genode::Allocator &alloc;
/* BIOS range to scan for RSDP */ /* BIOS range to scan for RSDP */
enum { BIOS_BASE = 0xe0000, BIOS_SIZE = 0x20000 }; enum { BIOS_BASE = 0xe0000, BIOS_SIZE = 0x20000 };
@ -1118,7 +1114,7 @@ class Acpi_table
if (!io_ds.valid()) if (!io_ds.valid())
throw -1; throw -1;
uint8_t *ret = env()->rm_session()->attach(io_ds, size); uint8_t *ret = env.rm().attach(io_ds, size);
cap = io_mem.cap(); cap = io_mem.cap();
return ret; return ret;
} }
@ -1146,25 +1142,25 @@ class Acpi_table
try { try {
area = _search_rsdp(_map_io(BIOS_BASE, BIOS_SIZE, cap)); area = _search_rsdp(_map_io(BIOS_BASE, BIOS_SIZE, cap));
return area; return area;
} catch (...) { env()->parent()->close(cap); } } catch (...) { env.parent().close(cap); }
/* search EBDA (BIOS addr + 0x40e) */ /* search EBDA (BIOS addr + 0x40e) */
try { try {
area = _map_io(0x0, 0x1000, cap); area = _map_io(0x0, 0x1000, cap);
if (area) { if (area) {
unsigned short base = (*reinterpret_cast<unsigned short *>(area + 0x40e)) << 4; unsigned short base = (*reinterpret_cast<unsigned short *>(area + 0x40e)) << 4;
env()->parent()->close(cap); env.parent().close(cap);
area = _map_io(base, 1024, cap); area = _map_io(base, 1024, cap);
area = _search_rsdp(area); area = _search_rsdp(area);
} }
return area; return area;
} catch (...) { env()->parent()->close(cap); } } catch (...) { env.parent().close(cap); }
return 0; return 0;
} }
template <typename T> template <typename T>
void _parse_tables(T * entries, uint32_t count) void _parse_tables(Genode::Allocator &alloc, T * entries, uint32_t count)
{ {
/* search for SSDT and DSDT tables */ /* search for SSDT and DSDT tables */
for (uint32_t i = 0; i < count; i++) { for (uint32_t i = 0; i < count; i++) {
@ -1181,23 +1177,23 @@ class Acpi_table
if (verbose) if (verbose)
PDBG("Found %s", table.name()); PDBG("Found %s", table.name());
Element::parse(table.table()); Element::parse(alloc, table.table());
} }
if (table.is_madt()) { if (table.is_madt()) {
PDBG("Found MADT"); PDBG("Found MADT");
table.parse_madt(); table.parse_madt(alloc);
} }
if (table.is_mcfg()) { if (table.is_mcfg()) {
PDBG("Found MCFG"); PDBG("Found MCFG");
table.parse_mcfg(); table.parse_mcfg(alloc);
} }
if (table.is_dmar()) { if (table.is_dmar()) {
PDBG("Found DMAR"); PDBG("Found DMAR");
table.parse_dmar(); table.parse_dmar(alloc);
} }
} }
@ -1207,7 +1203,7 @@ class Acpi_table
if (verbose) if (verbose)
PDBG("Found dsdt %s", table.name()); PDBG("Found dsdt %s", table.name());
Element::parse(table.table()); Element::parse(alloc, table.table());
} }
} }
} }
@ -1216,7 +1212,8 @@ class Acpi_table
public: public:
Acpi_table() Acpi_table(Genode::Env &env, Genode::Allocator &alloc)
: env(env), alloc(alloc)
{ {
Io_mem_session_capability io_mem; Io_mem_session_capability io_mem;
@ -1255,22 +1252,22 @@ class Acpi_table
addr_t const xsdt = rsdp->xsdt; addr_t const xsdt = rsdp->xsdt;
uint8_t const acpi_revision = rsdp->revision; uint8_t const acpi_revision = rsdp->revision;
/* drop rsdp io_mem mapping since rsdt/xsdt may overlap */ /* drop rsdp io_mem mapping since rsdt/xsdt may overlap */
env()->parent()->close(io_mem); env.parent().close(io_mem);
if (acpi_revision != 0 && xsdt && sizeof(addr_t) != sizeof(uint32_t)) { if (acpi_revision != 0 && xsdt && sizeof(addr_t) != sizeof(uint32_t)) {
/* running 64bit and xsdt is valid */ /* running 64bit and xsdt is valid */
Table_wrapper table(xsdt); Table_wrapper table(xsdt);
uint64_t * entries = reinterpret_cast<uint64_t *>(table.table() + 1); uint64_t * entries = reinterpret_cast<uint64_t *>(table.table() + 1);
_parse_tables(entries, table.entry_count(entries)); _parse_tables(alloc, entries, table.entry_count(entries));
} else { } else {
/* running (32bit) or (64bit and xsdt isn't valid) */ /* running (32bit) or (64bit and xsdt isn't valid) */
Table_wrapper table(rsdt); Table_wrapper table(rsdt);
uint32_t * entries = reinterpret_cast<uint32_t *>(table.table() + 1); uint32_t * entries = reinterpret_cast<uint32_t *>(table.table() + 1);
_parse_tables(entries, table.entry_count(entries)); _parse_tables(alloc, entries, table.entry_count(entries));
} }
/* free up memory of elements not of any use */ /* free up memory of elements not of any use */
Element::clean_list(); Element::clean_list(alloc);
/* free up io memory */ /* free up io memory */
acpi_memory().free_io_memory(); acpi_memory().free_io_memory();
@ -1278,15 +1275,6 @@ class Acpi_table
}; };
/**
* Parse acpi table
*/
static void init_acpi_table()
{
static Acpi_table table;
}
static void attribute_hex(Xml_generator &xml, char const *name, static void attribute_hex(Xml_generator &xml, char const *name,
unsigned long long value) unsigned long long value)
{ {
@ -1296,9 +1284,10 @@ static void attribute_hex(Xml_generator &xml, char const *name,
} }
void Acpi::generate_report() void Acpi::generate_report(Genode::Env &env, Genode::Allocator &alloc)
{ {
init_acpi_table(); /* parse table */
Acpi_table acpi_table(env, alloc);
enum { REPORT_SIZE = 4 * 4096 }; enum { REPORT_SIZE = 4 * 4096 };
static Reporter acpi("acpi", "acpi", REPORT_SIZE); static Reporter acpi("acpi", "acpi", REPORT_SIZE);
@ -1373,7 +1362,7 @@ void Acpi::generate_report()
if (!e->is_device()) if (!e->is_device())
continue; continue;
Pci_routing *r = e->pci_list()->first(); Pci_routing *r = e->pci_list().first();
for (; r; r = r->next()) { for (; r; r = r->next()) {
xml.node("routing", [&] () { xml.node("routing", [&] () {
attribute_hex(xml, "gsi", r->gsi()); attribute_hex(xml, "gsi", r->gsi());

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2009-2013 Genode Labs GmbH * Copyright (C) 2009-2016 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 General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -14,12 +14,16 @@
#ifndef _ACPI_H_ #ifndef _ACPI_H_
#define _ACPI_H_ #define _ACPI_H_
/* Genode includes */
#include <base/env.h>
namespace Acpi namespace Acpi
{ {
/** /**
* Generate report rom * Generate report rom
*/ */
void generate_report(); void generate_report(Genode::Env&, Genode::Allocator&);
} }
#endif /* _ACPI_H_ */ #endif /* _ACPI_H_ */

View File

@ -5,33 +5,53 @@
*/ */
/* /*
* Copyright (C) 2009-2015 Genode Labs GmbH * Copyright (C) 2009-2016 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 General Public License version 2. * under the terms of the GNU General Public License version 2.
*/ */
#include <base/printf.h> /* Genode includes */
#include <base/sleep.h> #include <base/component.h>
#include <base/heap.h>
#include <base/log.h>
#include <util/xml_generator.h>
#include <os/reporter.h> /* local includes */
#include <acpi.h>
#include "acpi.h"
int main(int argc, char **argv) namespace Acpi {
{
using namespace Genode; using namespace Genode;
struct Main;
}
struct Acpi::Main
{
Genode::Env &env;
Genode::Heap heap { env.ram(), env.rm() };
Main(Env &env) : env(env)
{
try { try {
Acpi::generate_report(); Acpi::generate_report(env, heap);
} catch (Genode::Xml_generator::Buffer_exceeded) { } catch (Genode::Xml_generator::Buffer_exceeded) {
PERR("ACPI report too large - failure"); Genode::error("ACPI report too large - failure");
throw; throw;
} catch (...) { } catch (...) {
PERR("Unknown exception occured - failure"); Genode::error("Unknown exception occured - failure");
throw; throw;
} }
}
};
Genode::sleep_forever();
return 0; /***************
** Component **
***************/
namespace Component {
Genode::size_t stack_size() { return 2*1024*sizeof(long); }
void construct(Genode::Env &env) { static Acpi::Main main(env); }
} }