Files
moslab-code/src/fiasco/src/abi/kip.cpp
2025-09-12 15:55:45 +02:00

281 lines
7.3 KiB
C++

INTERFACE:
#include <cxx/static_vector>
class Mem_desc
{
public:
enum Mem_type
{
Undefined = 0x0,
Conventional = 0x1,
Reserved = 0x2,
Dedicated = 0x3,
Shared = 0x4,
Kernel_tmp = 0x7,
Info = 0xd,
Bootloader = 0xe,
Arch = 0xf,
};
enum Ext_type_info
{
Info_acpi_rsdp = 0
};
private:
Mword _l, _h;
};
//----------------------------------------------------------------------------
INTERFACE:
#include "types.h"
#include "global_data.h"
class Kip
{
public:
enum : Cpu_time
{
Clock_1_second = 1000000ULL,
Clock_1_hour = 3600ULL * Clock_1_second,
Clock_1_day = 24ULL * Clock_1_hour,
Clock_1_year = 365UL * Clock_1_day,
};
void print() const;
char const *version_string() const;
Cpu_time clock() const;
void set_clock(Cpu_time c);
void add_to_clock(Cpu_time plus);
/* 0x00 */
Unsigned32 magic;
Unsigned32 version;
Unsigned8 offset_version_strings;
Unsigned8 _fill0[3];
Unsigned8 kip_sys_calls;
Unsigned8 node;
Unsigned8 _fill1[2];
/* 0x10 */
Unsigned64 sigma0_ip; ///< Sigma0 instruction pointer
Unsigned64 root_ip; ///< Root task instruction pointer
/* 0x20 */
volatile Cpu_time _clock; // don't access directly, use clock() instead!
// not updated in certain configurations
Unsigned64 frequency_cpu; ///< CPU frequency in kHz
/* 0x30 */
Unsigned64 acpi_rsdp_addr; ///< ACPI RSDP/XSDP
Unsigned64 dt_addr; ///< Device Tree
/* 0x40 */
Unsigned64 user_ptr; ///< l4-mod-info pointer
Unsigned64 mbt_counter; // only used for model-based testing
/* 0x50 */
Unsigned32 sched_granularity; ///< for rounding time slices
Unsigned32 _mem_descs; ///< memory descriptors relative to Kip
Unsigned32 _mem_descs_num; ///< number of memory descriptors
Unsigned32 _res1[1]; ///< \internal
/* 0x60: */
Unsigned64 _res2[2]; ///< \internal - spare space
/* 0x70:
* Platform_info. */
/* 0x70 + sizeof(Platform_info):
* - Memory descriptors (2 Mwords per descriptor),
* - kernel version string ('\0'-terminated),
* - feature strings ('\0'-terminated)
* - terminating '\0'. */
/* 0x800-0x900:
* Code for syscall invocation. */
/* 0x900-0x97F:
* Code for reading the system clock with microsecond resolution. Depending on
* the configuration, this clock might or might not be synchronized with the
* KIP clock. */
/* 0x980-0x9FF:
* Code for reading the system clock with nanosecond resolution. Depending on
* the configuration, this clock might or might not be synchronized with the
* KIP clock. */
private:
static Global_data<Kip *> global_kip;
};
#define L4_KERNEL_INFO_MAGIC (0x4BE6344CL) /* "L4µK" */
//============================================================================
IMPLEMENTATION:
#include "assert.h"
#include "config.h"
#include "mem.h"
#include "panic.h"
#include "version.h"
PUBLIC inline
Mem_desc::Mem_desc(Address start, Address end, Mem_type t, bool v = false,
unsigned st = 0)
: _l((start & ~0x3ffUL) | (t & 0x0f) | ((st << 4) & 0x0f0)
| (v?0x0200:0x0)),
_h(end)
{}
PUBLIC inline ALWAYS_INLINE
Address Mem_desc::start() const
{ return _l & ~0x3ffUL; }
PUBLIC inline ALWAYS_INLINE
Address Mem_desc::end() const
{ return _h | 0x3ffUL; }
PUBLIC inline ALWAYS_INLINE
Address Mem_desc::size() const
{ return end() - start() + 1; }
PUBLIC inline ALWAYS_INLINE
void
Mem_desc::type(Mem_type t)
{ _l = (_l & ~0x0f) | (t & 0x0f); }
PUBLIC inline ALWAYS_INLINE
Mem_desc::Mem_type Mem_desc::type() const
{ return static_cast<Mem_type>(_l & 0x0f); }
PUBLIC inline
unsigned Mem_desc::ext_type() const
{ return (_l >> 4) & 0x0f; }
PUBLIC inline ALWAYS_INLINE
unsigned Mem_desc::is_virtual() const
{ return _l & 0x200; }
PUBLIC inline ALWAYS_INLINE
unsigned Mem_desc::eager_map() const
{ return _l & 0x100; }
PUBLIC inline
bool Mem_desc::contains(Address addr) const
{
return start() <= addr && end() >= addr;
}
PUBLIC inline ALWAYS_INLINE
bool Mem_desc::valid() const
{ return type() && start() < end(); }
PRIVATE inline ALWAYS_INLINE
Mem_desc *Kip::mem_descs()
{ return offset_cast<Mem_desc*>(this, _mem_descs); }
PRIVATE inline
Mem_desc const *Kip::mem_descs() const
{ return offset_cast<Mem_desc const *>(this, _mem_descs); }
PUBLIC inline ALWAYS_INLINE
unsigned Kip::num_mem_descs() const
{ return _mem_descs_num; }
PUBLIC inline NEEDS[Kip::num_mem_descs, Kip::mem_descs] ALWAYS_INLINE
cxx::static_vector<Mem_desc>
Kip::mem_descs_a()
{ return cxx::static_vector<Mem_desc>(mem_descs(), num_mem_descs()); }
PUBLIC inline NEEDS[Kip::num_mem_descs, Kip::mem_descs] ALWAYS_INLINE
cxx::static_vector<Mem_desc const>
Kip::mem_descs_a() const
{ return cxx::static_vector<Mem_desc const>(mem_descs(), num_mem_descs()); }
PUBLIC inline
void Kip::num_mem_descs(unsigned n)
{ _mem_descs_num = n; }
PUBLIC
Mem_desc *Kip::add_mem_region(Mem_desc const &md)
{
for (auto &m: mem_descs_a())
if (m.type() == Mem_desc::Undefined)
{
m = md;
return &m;
}
// Add mem region failed -- must be a Fiasco startup problem. Bail out.
panic("Too few memory descriptors in KIP");
}
DEFINE_GLOBAL Global_data<Kip *> Kip::global_kip;
PUBLIC static inline ALWAYS_INLINE NEEDS["config.h"]
void
Kip::init_global_kip(Kip *kip)
{
global_kip = kip;
kip->platform_info.is_mp = Config::Max_num_cpus > 1;
kip->sched_granularity = Config::Scheduler_granularity;
// check that the KIP has actually been set up
//assert(kip->sigma0_ip && kip->root_ip && kip->user_ptr);
}
PUBLIC static inline Kip *Kip::k() { return global_kip; }
IMPLEMENT
char const *Kip::version_string() const
{
static_assert((sizeof(Kip) & 0xf) == 0, "Invalid KIP structure size");
return reinterpret_cast <char const *> (this) + (offset_version_strings << 4);
}
#ifdef TARGET_NAME
#define TARGET_NAME_PHRASE " for " TARGET_NAME
#else
#define TARGET_NAME_PHRASE
#endif
asm(".section .initkip.version, \"a\", %progbits \n"
".string \"" CONFIG_KERNEL_VERSION_STRING "\" \n"
".previous \n");
asm(".section .initkip.features.end, \"a\", %progbits \n"
".string \"\" \n"
".previous \n");
//----------------------------------------------------------------------------
IMPLEMENTATION[!sync_clock]:
IMPLEMENT inline NEEDS["mem.h"]
Cpu_time
Kip::clock() const
{ return Mem::read64_consistent(const_cast<Cpu_time const *>(&_clock)); }
IMPLEMENT inline
void
Kip::set_clock(Cpu_time c)
{ _clock = c; }
IMPLEMENT inline NEEDS["mem.h"]
void
Kip::add_to_clock(Cpu_time plus)
{
// This function does not force a full atomic update. The caller needs to be
// aware about this: Either the update is performed by a single specific CPU
// (the boot CPU) or the callers have to use a lock.
// However, on ARM < v7, the update of the 64-bit clock can be observed in
// any order defeating the user-level retry loop for reading the clock which
// assumes that low word is written before the high word.
Mem::write64_consistent(const_cast<Cpu_time *>(&_clock), _clock + plus);
}