l4re-base-25.08.0

This commit is contained in:
2025-09-12 15:55:45 +02:00
commit d959eaab98
37938 changed files with 9382688 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
requires: libloader stdlibs libkproxy
maintainer: adam@os.inf.tu-dresden.de warg@os.inf.tu-dresden.de

View File

@@ -0,0 +1,9 @@
PKGDIR ?= .
L4DIR ?= $(PKGDIR)/../..
# the default is to build the listed directories, provided that they
# contain a Makefile. If you need to change this, uncomment the following
# line and adapt it.
# TARGET = idl include src lib server examples doc
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ..
L4DIR ?= $(PKGDIR)/../..
# the default is to build the listed directories, provided that they
# contain a Makefile. If you need to change this, uncomment the following
# line and adapt it.
# TARGET = idl src lib server examples doc
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,14 @@
PKGDIR ?= ../..
L4DIR ?= $(PKGDIR)/../..
TARGET = loader
SRC_CC = main.cc slab_alloc.cc \
region.cc app_task.cc name_space.cc \
log.cc global.cc \
sched_proxy.cc alloc.cc
LDFLAGS +=
#CPPFLAGS += -fPIC
REQUIRES_LIBS := libloader libkproxy cxx_libc_io cxx_io
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,136 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/cxx/exceptions>
#include <l4/cxx/l4iostream>
#include <l4/sys/factory>
#include <l4/re/util/meta>
#include <cstdlib>
#include "obj_reg.h"
#include "alloc.h"
//#include "globals.h"
//#include "slab_alloc.h"
#include "region.h"
#include "name_space.h"
#include "log.h"
#include "sched_proxy.h"
Allocator::~Allocator()
{
}
class LLog : public Ldr::Log
{
public:
LLog(char const *t, int l, unsigned char col) : Log()
{
if (l > 32)
l = 32;
set_tag(cxx::String(t, l));
set_color(col);
}
virtual ~LLog() {}
};
static L4::Ipc::Cap<void> new_cap(L4::Epiface *o)
{
Gate_alloc::registry.register_obj(o);
return L4::Ipc::make_cap(o->obj_cap(), L4_CAP_FPAGE_RWSD);
}
int
Allocator::op_create(L4::Factory::Rights, L4::Ipc::Cap<void> &res,
long type, L4::Ipc::Varg_list<> &&args)
{
switch (type)
{
case L4Re::Namespace::Protocol:
res = new_cap(new Ldr::Name_space());
return L4_EOK;
case L4Re::Rm::Protocol:
res = new_cap(new Region_map());
return L4_EOK;
case L4_PROTO_LOG:
{
L4::Ipc::Varg tag = args.pop_front();
if (!tag.is_of<char const *>())
return -L4_EINVAL;
L4::Ipc::Varg col = args.pop_front();
int color;
if (col.is_of<char const *>())
color = LLog::color_value(cxx::String(col.value<char const*>(),
col.length()));
else if(col.is_of_int()) // ignore sign
color = col.value<long>();
else
color = 7;
Ldr::Log *l = new LLog(tag.value<char const*>(), tag.length(), color);
res = new_cap(l);
return L4_EOK;
}
case L4::Scheduler::Protocol:
{
if (!_sched_prio_limit)
return -L4_ENODEV;
L4::Ipc::Varg p_max = args.pop_front(),
p_base = args.pop_front(),
cpus = args.pop_front();
if (!p_max.is_of_int() || !p_base.is_of_int()) // ignore sign
return -L4_EINVAL;
if (p_max.value<l4_mword_t>() > _sched_prio_limit
|| p_base.value<l4_mword_t>() > _sched_prio_limit)
return -L4_ERANGE;
if (p_max.value<l4_umword_t>() <= p_base.value<l4_umword_t>())
return -L4_EINVAL;
l4_umword_t cpu_mask = ~0UL;
if (!cpus.is_of<void>() && cpus.is_of_int())
cpu_mask = cpus.value<l4_umword_t>();
Sched_proxy *o = new Sched_proxy();
o->set_prio(p_base.value<l4_mword_t>(), p_max.value<l4_mword_t>());
o->restrict_cpus(cpu_mask);
res = new_cap(o);
return L4_EOK;
}
default:
return -L4_ENODEV;
}
}
Allocator *
Allocator::root_allocator()
{
static Allocator ra(300000);
return &ra;
}

View File

@@ -0,0 +1,35 @@
/*
* (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/re/mem_alloc>
#include <l4/sys/cxx/ipc_epiface>
#include <l4/cxx/list>
class Allocator : public L4::Epiface_t<Allocator, L4Re::Mem_alloc>
{
private:
long _sched_prio_limit;
l4_umword_t _sched_cpu_mask;
public:
explicit Allocator(unsigned prio_limit = 0)
: _sched_prio_limit(prio_limit), _sched_cpu_mask(~0UL)
{}
virtual ~Allocator();
int op_create(L4::Factory::Rights r, L4::Ipc::Cap<void> &res,
long type, L4::Ipc::Varg_list<> &&args);
long op_info(L4Re::Mem_alloc::Rights, L4Re::Mem_alloc::Stats &)
{ return L4_EOK; }
static Allocator *root_allocator();
};

View File

@@ -0,0 +1,84 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include "app_task.h"
//#include "slab_alloc.h"
//#include "globals.h"
#include <l4/re/error_helper>
#include <l4/re/util/cap_alloc>
#include <l4/cxx/iostream>
#include "obj_reg.h"
using L4Re::Util::cap_alloc;
using L4Re::Dataspace;
#if 0
static Slab_alloc<App_task> *alloc()
{
static Slab_alloc<App_task> a;
return &a;
}
#endif
#if 0
void *App_task::operator new (size_t) throw()
{ return alloc()->alloc(); }
void App_task::operator delete (void *m) throw()
{ alloc()->free((App_task*)m); }
#endif
int
App_task::op_signal(L4Re::Parent::Rights, unsigned long sig, unsigned long val)
{
switch (sig)
{
case 0: // exit
{
L4Re::Util::cap_alloc.free(obj_cap());
delete this;
if (val != 0)
L4::cout << "LDR: task " << this << " exited with " << val
<< '\n';
return -L4_ENOREPLY;
}
default: break;
}
return L4_EOK;
}
App_task::App_task()
: _task(L4::Cap<L4::Task>::Invalid),
_thread(L4::Cap<L4::Thread>::Invalid)
{
//object_pool.cap_alloc()->alloc(&_alloc);
Gate_alloc::registry.register_obj(&_rm);
_rm.init();
//object_pool.cap_alloc()->alloc(&log);
}
App_task::~App_task()
{
//object_pool.cap_alloc()->free(&_alloc);
Gate_alloc::registry.unregister_obj(&_rm);
//object_pool.cap_alloc()->free(&log);
if (_thread.is_valid())
cap_alloc.free(_thread);
if (_task.is_valid())
cap_alloc.free(_task);
if (_sched.obj_cap().is_valid())
cap_alloc.free(_sched.obj_cap());
Gate_alloc::registry.unregister_obj(this);
}

View File

@@ -0,0 +1,45 @@
/*
* (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/re/log>
#include <l4/re/env>
#include "region.h"
#include "sched_proxy.h"
#include <l4/sys/cxx/ipc_epiface>
class App_task : public L4::Epiface_t<App_task, L4Re::Parent>
{
private:
L4::Cap<L4::Task> _task;
L4::Cap<L4::Thread> _thread;
L4::Cap<L4::Log> _log;
Region_map _rm;
public:
Sched_proxy _sched;
App_task();
static L4::Cap<L4Re::Mem_alloc> allocator()
{ return L4Re::Env::env()->mem_alloc(); }
int op_signal(L4Re::Parent::Rights, unsigned long sig, unsigned long val);
Region_map *rm() { return &_rm; }
void task_cap(L4::Cap<L4::Task> const &c) { _task = c; }
void thread_cap(L4::Cap<L4::Thread> const &c) { _thread = c; }
L4::Cap<L4::Task> task_cap() const { return _task; }
L4::Cap<L4::Thread> thread_cap() const { return _thread; }
virtual ~App_task();
};

View File

@@ -0,0 +1,43 @@
/*
* (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>,
* Björn Döbel <doebel@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/re/util/debug>
class Err : public L4Re::Util::Err
{
public:
explicit
Err(Level l = Normal) : L4Re::Util::Err(l, "Ldr") {}
};
class Dbg : public L4Re::Util::Dbg
{
public:
enum Level
{
Info = 1,
Warn = 2,
Boot = 4,
Server = 0x10,
Exceptions = 0x20,
Cmd_line = 0x40,
Loader = 0x80,
Parser = 0x100,
Name_space = 0x400,
};
explicit
Dbg(unsigned long mask, char const *subs = 0)
: L4Re::Util::Dbg(mask, "Ldr", subs)
{}
};

View File

@@ -0,0 +1,14 @@
/*
* (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include "global.h"
namespace Glbl {
extern L4::Cap<void> rcv_cap;
char log_buffer[1024];
}

View File

@@ -0,0 +1,15 @@
/*
* (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/sys/capability>
namespace Glbl {
extern char log_buffer[1024];
}

View File

@@ -0,0 +1,10 @@
/*
* (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once

View File

@@ -0,0 +1,152 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>,
* Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/re/log>
#include <l4/re/log-sys.h>
#include <l4/sys/kdebug.h>
#include <l4/cxx/minmax>
#include "log.h"
#include "global.h"
#include "obj_reg.h"
#include <cstdio>
#include <unistd.h>
static Ldr::Log *last_log = 0;
static void my_outnstring(char const *s, unsigned long len)
{
write(1, s, len);
}
static void mycpy(char **buf, unsigned int *rem, char const *s, unsigned int l)
{
int o = cxx::min(*rem, l);
memcpy(*buf, s, o);
*rem -= o;
*buf += o;
}
static char msgbuf[4096];
l4_msgtag_t
Ldr::Log::op_dispatch(l4_utcb_t *utcb, l4_msgtag_t tag, L4::Vcon::Rights)
{
if (tag.words() < 2)
return l4_msgtag(-L4_EINVAL, 0, 0, 0);
l4_msg_regs_t *m = l4_utcb_mr_u(utcb);
L4::Opcode op = m->mr[0];
// we only have one opcode
if (op != L4Re::Log_::Print)
return l4_msgtag(-L4_ENOSYS, 0, 0, 0);
char *msg = Glbl::log_buffer;
unsigned long len_msg = sizeof(Glbl::log_buffer);
if (len_msg > (tag.words() - 2) * sizeof(l4_umword_t))
len_msg = (tag.words() - 2) * sizeof(l4_umword_t);
if (len_msg > m->mr[1])
len_msg = m->mr[1];
memcpy(msg, &m->mr[2], len_msg);
unsigned int rem = sizeof(msgbuf);
while (len_msg > 0 && msg[0])
{
char *obuf = msgbuf;
#if 1
if (color())
{
int n = snprintf(obuf, rem, "\033[%s3%dm",
(color() & 8) ? "01;" : "", (color() & 7));
obuf = obuf + n;
rem -= n;
}
else
mycpy(&obuf, &rem, "\033[0m", 4);
#endif
if (last_log != this)
{
if (last_log != 0)
my_outnstring("\n", 1);
mycpy(&obuf, &rem, _tag, cxx::min<unsigned long>(_l, Max_tag));
if (_l < Max_tag)
mycpy(&obuf, &rem, " ", Max_tag-_l);
if (_in_line)
mycpy(&obuf, &rem, ": ", 2);
else
mycpy(&obuf, &rem, "| ", 2);
}
unsigned long i;
for (i = 0; i < len_msg; ++i)
if (msg[i] == '\n' || msg[i] == 0)
break;
mycpy(&obuf, &rem, msg, i);
if (i <len_msg && msg[i] == '\n')
{
if (color())
mycpy(&obuf, &rem, "\033[0m", 4);
mycpy(&obuf, &rem, "\n", 1);
_in_line = false;
last_log = 0;
++i;
}
else
{
last_log = this;
_in_line = true;
}
my_outnstring(msgbuf, obuf-msgbuf);
msg += i;
len_msg -= i;
}
if (_in_line && color())
my_outnstring("\033[0m", 4);
// and finally done
return l4_msgtag(-L4_ENOREPLY, 0, 0, 0);
}
int
Ldr::Log::color_value(cxx::String const &col)
{
int c = 0, bright = 0;
if (col.empty())
return 0;
switch(col[0])
{
case 'N': bright = 1; /* FALLTHRU */ case 'n': c = 0; break;
case 'R': bright = 1; /* FALLTHRU */ case 'r': c = 1; break;
case 'G': bright = 1; /* FALLTHRU */ case 'g': c = 2; break;
case 'Y': bright = 1; /* FALLTHRU */ case 'y': c = 3; break;
case 'B': bright = 1; /* FALLTHRU */ case 'b': c = 4; break;
case 'M': bright = 1; /* FALLTHRU */ case 'm': c = 5; break;
case 'C': bright = 1; /* FALLTHRU */ case 'c': c = 6; break;
case 'W': bright = 1; /* FALLTHRU */ case 'w': c = 7; break;
default: c = 0;
}
return (bright << 3) | c;
}

View File

@@ -0,0 +1,68 @@
/*
* (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/sys/capability>
#include <l4/sys/vcon>
#include <l4/sys/cxx/ipc_epiface>
#include <l4/cxx/string>
#include "local_service.h"
#include <cstring>
namespace Ldr {
class Log : public L4::Epiface_t<Log, L4::Vcon>
{
private:
enum { Max_tag = 8 };
char _tag[Max_tag];
unsigned char _l;
unsigned char _color;
bool _in_line;
public:
Log() : _l(0), _color(0), _in_line(false) {}
void set_tag(cxx::String const &tag)
{
_l = cxx::min<unsigned long>(tag.len(), Max_tag);
memcpy(_tag, tag.start(), _l);
}
void set_color(unsigned char color)
{ _color = color; }
char const *tag() const { return _tag; }
unsigned char color() const { return _color; }
int op_bind(L4::Icu::Rights, l4_umword_t,
L4::Ipc::Snd_fpage)
{ return -L4_ENOSYS; }
int op_unbind(L4::Icu::Rights, l4_umword_t,
L4::Ipc::Snd_fpage)
{ return -L4_ENOSYS; }
int op_info(L4::Icu::Rights, L4::Icu::_Info &)
{ return -L4_ENOSYS; }
int op_msi_info(L4::Icu::Rights, unsigned, l4_uint64_t,
l4_icu_msi_info_t &)
{ return -L4_ENOSYS; }
int op_mask(L4::Icu::Rights, l4_umword_t)
{ return -L4_ENOSYS; }
int op_unmask(L4::Icu::Rights, l4_umword_t)
{ return -L4_ENOSYS; }
int op_set_mode(L4::Icu::Rights, l4_umword_t, l4_umword_t)
{ return -L4_ENOSYS; }
l4_msgtag_t op_dispatch(l4_utcb_t *utcb, l4_msgtag_t tag, L4::Vcon::Rights);
static int color_value(cxx::String const &col);
virtual ~Log() {}
};
}

View File

@@ -0,0 +1,127 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/sys/ipc.h>
#include <stdio.h>
#include <l4/re/l4aux.h>
#include <l4/re/error_helper>
#include <l4/re/util/br_manager>
#include <l4/sys/scheduler>
#include <l4/sys/thread>
#include <l4/cxx/iostream>
#include <typeinfo>
#include "debug.h"
#include "region.h"
#include "global.h"
#include "log.h"
#include "obj_reg.h"
#include "alloc.h"
using L4Re::chksys;
static Dbg info(Dbg::Info);
static Dbg boot_info(Dbg::Boot);
l4re_aux_t* l4re_aux;
template< typename Reg >
class My_dispatcher
{
private:
Reg r;
public:
l4_msgtag_t dispatch(l4_msgtag_t tag, l4_umword_t obj, l4_utcb_t *utcb)
{
typename Reg::Value *o = 0;
Dbg dbg(Dbg::Server);
dbg.printf("tag=%lx (proto=%ld) obj=%lx", tag.raw,
tag.label(), obj);
if (tag.is_exception())
{
dbg.cprintf("\n");
Dbg(Dbg::Warn).printf("unhandled exception...\n");
return l4_msgtag(-L4_ENOREPLY, 0, 0, 0);
}
else
{
o = r.find(obj & ~3UL);
if (!o)
{
dbg.cprintf(": invalid object\n");
return l4_msgtag(-L4_ENOENT, 0, 0, 0);
}
dbg.cprintf(": object is a %s\n", typeid(*o).name());
l4_msgtag_t res = o->dispatch(tag, obj, utcb);
dbg.printf("reply = %ld\n", res.label());
return res;
}
Dbg(Dbg::Warn).printf("Invalid message (tag.label=%ld)\n", tag.label());
return l4_msgtag(-L4_ENOSYS, 0, 0, 0);
}
};
static L4::Server<L4Re::Util::Br_manager_hooks> server;
namespace Gate_alloc {
L4Re::Util::Object_registry registry(&server);
}
int
main(int argc, char **argv)
{
try {
Dbg::set_level(0); //Dbg::Info | Dbg::Boot);
info.printf("Hello from loader\n");
boot_info.printf("cmdline: ");
for (int i = 0; i < argc; ++i)
boot_info.cprintf("'%s'", argv[i]);
boot_info.cprintf("\n");
l4_umword_t *auxp = (l4_umword_t*)&argv[argc] + 1;
while (*auxp)
++auxp;
++auxp;
l4re_aux = 0;
while (*auxp)
{
info.printf("aux: %lx\n", *auxp);
if (*auxp == 0xf0)
l4re_aux = (l4re_aux_t*)auxp[1];
auxp += 2;
}
Region_map::global_init();
L4Re::chkcap(Gate_alloc::registry.register_obj(Allocator::root_allocator(), "loader"));
server.loop<L4::Runtime_error>(My_dispatcher<L4::Basic_registry>());
}
catch (L4::Runtime_error const &e)
{
L4::cout << "Got exception\n";
L4::cout << e << "\n";
}
return 1;
}

View File

@@ -0,0 +1,122 @@
/*
* (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/cxx/iostream>
#include "name_space.h"
#include "debug.h"
#include "obj_reg.h"
#include "global.h"
#include <l4/cxx/minmax>
#include <l4/re/consts>
#include <cstring>
#include <cstdlib>
#include <cassert>
namespace Ldr {
static Dbg dbg(Dbg::Name_space, "ns");
Name_space::Name_space()
: L4Re::Util::Names::Name_space(dbg, Err())
{
Gate_alloc::registry.register_obj(this);
}
Name_space::~Name_space()
{
Gate_alloc::registry.unregister_obj(this);
}
Entry *
Name_space::alloc_dynamic_entry(Names::Name const &name, unsigned flags)
{
char *na = (char*)malloc(name.len());
if (!na)
return 0;
memcpy(na, name.start(), name.len());
Names::Name new_name(na, name.len());
Entry *e = new Ldr::Entry(new_name, Names::Obj(flags), true);
if (e)
return e;
free(na);
return 0;
}
void
Name_space::free_dynamic_entry(Names::Entry *n)
{
free(const_cast<char*>(n->name().start()));
delete static_cast<Ldr::Entry*>(n);
}
int
Name_space::get_epiface(l4_umword_t data, bool is_local, L4::Epiface **lo)
{
if (is_local)
return -L4_EINVAL;
*lo = L4::Basic_registry::find(data);
return (*lo) ? L4_EOK : -L4_EINVAL;
}
int
Name_space::copy_receive_cap(L4::Cap<void> *cap)
{
*cap = server_iface()->get_rcv_cap(0);
return server_iface()->realloc_rcv_cap(0);
}
void
Name_space::free_capability(L4::Cap<void> cap)
{
L4Re::Util::cap_alloc.free(cap);
}
void
Name_space::free_epiface(L4::Epiface *)
{ /* nothing to do */ }
}
// dump stuff
#include <l4/cxx/iostream>
namespace L4Re { namespace Util { namespace Names {
void
Name_space::dump(bool rec, int indent) const
{
Name_space const *n;
//L4::cout << "loader: Name space dump (" << obj_cap() << ")\n";
for (Const_iterator i = begin(); i != end(); ++i)
{
for (int x = 0; x < indent; ++x)
L4::cout << " ";
L4::cout << " " << i->name() << " -> "
<< i->obj()->cap().cap()
<< " o=" << (void*)i->obj()->obj() << " f="
<< i->obj()->flags() << '\n';
if (rec && i->obj()->is_valid()
&& (n = dynamic_cast<Name_space const *>(i->obj()->obj())))
n->dump(rec, indent + 1);
}
}
}}}

View File

@@ -0,0 +1,63 @@
/*
* (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/re/util/name_space_svr>
#include <l4/sys/cxx/ipc_epiface>
namespace Ldr {
namespace Names { using namespace L4Re::Util::Names; }
class Entry : public Names::Entry
{
public:
Entry(Names::Name const &n, Names::Obj const &o, bool dyn = false)
: Names::Entry(n, o, dyn) {}
void * operator new (size_t s) { return ::operator new(s); }
void operator delete(void *b) { ::operator delete(b); }
};
class Name_space : public L4::Epiface_t<Name_space, L4Re::Namespace>,
public Names::Name_space
{
public:
Name_space();
~Name_space();
// server support ----------------------------------------
int get_epiface(l4_umword_t data, bool is_local, L4::Epiface **lo) override;
int copy_receive_cap(L4::Cap<void> *cap) override;
void free_capability(L4::Cap<void> cap) override;
void free_epiface(L4::Epiface *epiface) override;
Entry *alloc_dynamic_entry(Names::Name const &n, unsigned flags) override;
void free_dynamic_entry(Names::Entry *e) override;
// internally used to register bootfs files, name spaces...
int register_obj(Names::Name const &name, Names::Obj const &o,
bool dyn = false)
{
Entry *n = new Entry(name, o, dyn);
int err = insert(n);
if (err < 0)
delete n;
return err;
}
};
}
inline
L4::BasicOStream &operator << (L4::BasicOStream &s, L4Re::Util::Names::Name const &n)
{
for (int l = 0; l < n.len(); ++l)
s << n.name()[l];
return s;
}

View File

@@ -0,0 +1,25 @@
/*
* (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/sys/task>
#include <l4/sys/factory>
#include <l4/sys/types.h>
#include <l4/re/util/cap_alloc>
#include <l4/re/env>
#include <l4/re/util/object_registry>
namespace Gate_alloc {
extern L4Re::Util::Object_registry registry;
}

View File

@@ -0,0 +1,177 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>,
* Björn Döbel <doebel@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include "region.h"
#include <l4/sys/kip>
#include <l4/re/dataspace>
#include <l4/re/rm>
#include <l4/re/rm-sys.h>
#include <l4/re/env>
#include <l4/sys/task>
#include <l4/cxx/iostream>
#include <l4/cxx/l4iostream>
#include "global.h"
#include "debug.h"
#include <cstdio>
using L4Re::Rm;
using L4Re::Dataspace;
using L4Re::Util::Region;
Region_map::Region_map()
: Base(0,0)
{}
void
Region_map::init()
{
for (auto const &m: L4::Kip::Mem_desc::all(l4_kip()))
{
if (!m.is_virtual())
continue;
l4_addr_t start = m.start();
l4_addr_t end = m.end();
switch (m.type())
{
case L4::Kip::Mem_desc::Conventional:
set_limits(start, end);
break;
case L4::Kip::Mem_desc::Reserved:
attach_area(start, end - start + 1, L4Re::Rm::F::Reserved);
break;
default:
break;
}
}
// reserve page at 0
attach_area(0, L4_PAGESIZE);
}
static l4_addr_t map_area;
static l4_addr_t map_end;
void Region_map::global_init()
{
L4Re::chksys(L4Re::Env::env()->rm()->reserve_area(&map_area, L4_PAGESIZE,
L4Re::Rm::F::Reserved | L4Re::Rm::F::Search_addr));
map_end = map_area + L4_PAGESIZE -1;
Dbg(Dbg::Boot, "rm").printf("map area %lx-%lx\n", map_area, map_end);
}
int
Region_ops::map(Region_handler const *h, l4_addr_t local_adr,
Region const &r, bool need_w, L4::Ipc::Snd_fpage *result)
{
auto f = h->flags();
if ((f & Rm::F::Reserved) || !h->memory().is_valid())
return -L4_ENOENT;
if (f & Rm::F::Pager)
return -L4_ENOENT;
auto mf = map_flags(f);
if (!need_w)
mf = mf & ~L4Re::Dataspace::F::W;
l4_addr_t offset = local_adr - r.start() + h->offset();
L4::Cap<L4Re::Dataspace> ds = L4::cap_cast<L4Re::Dataspace>(h->memory());
if (int err = ds->map(offset, mf, map_area, map_area, map_end))
return err;
*result = L4::Ipc::Snd_fpage::mem(map_area, L4_PAGESHIFT, L4_FPAGE_RWX,
local_adr, L4::Ipc::Snd_fpage::Grant);
return L4_EOK;
}
void Region_ops::unmap(Region_handler const * /*h*/, l4_addr_t /*vaddr*/,
l4_addr_t /*offs*/, unsigned long /*size*/)
{
}
void
Region_ops::take(Region_handler const * /*h*/)
{
}
void
Region_ops::release(Region_handler const * /*h*/)
{
}
int
Region_ops::map_info(Region_handler const *h, l4_addr_t *start_addr,
l4_addr_t *end_addr)
{
auto f = h->flags();
if ((f & Rm::F::Reserved) || !h->memory().is_valid())
return -L4_ENOENT;
if (f & Rm::F::Pager)
return 0;
L4::Cap<L4Re::Dataspace> ds = L4::cap_cast<L4Re::Dataspace>(h->memory());
return ds->map_info(start_addr, end_addr);
}
void
Region_map::debug_dump(unsigned long /*function*/) const
{
printf("Region maping: limits [%lx-%lx]\n", min_addr(), max_addr());
printf(" Area map:\n");
for (Region_map::Const_iterator i = area_begin(); i != area_end(); ++i)
printf(" [%10lx-%10lx] -> flags=%x\n",
i->first.start(), i->first.end(),
i->second.flags());
printf(" Region map:\n");
for (Region_map::Const_iterator i = begin(); i != end(); ++i)
printf(" [%10lx-%10lx] -> (offs=%llx, ds=%lx, flags=%x)\n",
i->first.start(), i->first.end(),
i->second.offset(), i->second.memory().cap(),
i->second.flags());
}
void
Region_ops::free(Region_handler const *h, l4_addr_t start, unsigned long size)
{
if (h->is_ro())
return;
if ((h->flags() & Rm::F::Reserved) || !h->memory().is_valid())
return;
if (h->flags() & Rm::F::Pager)
return;
L4::Cap<L4Re::Dataspace> ds = L4::cap_cast<L4Re::Dataspace>(h->memory());
ds->clear(start + h->offset(), size);
}
long
Region_map::op_io_page_fault(L4::Io_pager::Rights,
l4_fpage_t io_pfa, l4_umword_t pc,
L4::Ipc::Opt<L4::Ipc::Snd_fpage> &)
{
Err().printf("IO-port-fault: port=0x%lx size=%d pc=0x%lx\n",
l4_fpage_ioport(io_pfa), 1 << l4_fpage_size(io_pfa), pc);
return -L4_ENOMEM;
}

View File

@@ -0,0 +1,91 @@
/*
* (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/sys/capability>
#include <l4/re/dataspace>
#include <l4/re/util/region_mapping>
#include <l4/re/util/region_mapping_svr_2>
#include <l4/sys/cxx/ipc_epiface>
#include <l4/re/util/item_alloc>
#include <l4/re/util/cap_alloc>
#include <l4/re/error_helper>
#include "slab_alloc.h"
#include "debug.h"
class Region_ops;
typedef L4Re::Util::Region_handler<L4::Cap<L4Re::Dataspace>, Region_ops> Region_handler;
class Region_ops
{
public:
typedef L4::Ipc::Snd_fpage Map_result;
static int map(Region_handler const *h, l4_addr_t addr,
L4Re::Util::Region const &r, bool writable,
L4::Ipc::Snd_fpage *result);
static void unmap(Region_handler const *h, l4_addr_t vaddr,
l4_addr_t offs, unsigned long size);
static void free(Region_handler const *h, l4_addr_t start, unsigned long size);
static void take(Region_handler const *h);
static void release(Region_handler const *h);
static int map_info(Region_handler const *h, l4_addr_t *start_addr,
l4_addr_t *end_addr);
};
class Region_map
: public L4Re::Util::Region_map<Region_handler, Slab_alloc>,
public L4Re::Util::Rm_server<Region_map, Dbg>,
public L4::Epiface_t<Region_map, L4Re::Rm>
{
private:
typedef L4Re::Util::Region_map<Region_handler, Slab_alloc> Base;
public:
typedef L4::Cap<L4Re::Dataspace> Dataspace;
enum { Have_find = true };
static int validate_ds(L4::Ipc_svr::Server_iface *sif,
L4::Ipc::Snd_fpage const & /*ds_cap*/,
L4Re::Rm::Flags,
L4::Cap<L4Re::Dataspace> *ds)
{
// XXX: must check that ds is from trusted allocator!
L4::Cap<L4Re::Dataspace> c = sif->rcv_cap<L4Re::Dataspace>(0);
if (!c)
return -L4_EINVAL;
sif->realloc_rcv_cap(0);
*ds = c;
return L4_EOK;
}
static l4_umword_t find_res(L4::Cap<void> const &ds) { return ds.cap(); }
static void global_init();
Region_map();
long op_io_page_fault(L4::Io_pager::Rights,
l4_fpage_t io_pfa, l4_umword_t pc,
L4::Ipc::Opt<L4::Ipc::Snd_fpage> &);
virtual ~Region_map() {}
void init();
void debug_dump(unsigned long function) const;
};

View File

@@ -0,0 +1,219 @@
/*
* (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include "sched_proxy.h"
#include "global.h"
#include "debug.h"
#include "obj_reg.h"
#include <algorithm>
#include <l4/re/env>
#include <l4/sys/scheduler>
//#include <cstdio>
static
l4_sched_cpu_set_t
blow_up(l4_sched_cpu_set_t const &src, unsigned char gran)
{
l4_sched_cpu_set_t n;
gran &= sizeof(l4_umword_t) * 8 - 1;
unsigned char og = src.granularity() & (sizeof(l4_umword_t) * 8 - 1);
n.set(gran, src.offset() & (~0UL << og));
n.map = 0;
for (unsigned i = 0; i < sizeof(l4_umword_t) * 8; ++i)
if (src.map & (1UL << (i >> (og - gran))))
n.map |= 1UL << i;
return n;
}
static
l4_sched_cpu_set_t operator & (l4_sched_cpu_set_t const &a, l4_sched_cpu_set_t const &b)
{
l4_sched_cpu_set_t _a, _b;
unsigned char const ga = a.granularity() & (sizeof(l4_umword_t) * 8 - 1);
unsigned char const gb = b.granularity() & (sizeof(l4_umword_t) * 8 - 1);
if (ga < gb)
{
_b = blow_up(b, ga);
_a = a;
}
else if (ga == gb)
{
_a = a;
_b = b;
}
else
{
_a = blow_up(a, gb);
_b = b;
}
long ofs_dif = _a.offset() - _b.offset();
long unsigned abs_ofs_dif;
if (ofs_dif < 0)
abs_ofs_dif = -ofs_dif;
else
abs_ofs_dif = ofs_dif;
if (abs_ofs_dif >= sizeof(l4_umword_t) * 8)
return l4_sched_cpu_set(0,0,0);
if (ofs_dif < 0)
{
_b.map &= (_a.map >> abs_ofs_dif);
return _b;
}
else
{
_a.map &= (_b.map >> abs_ofs_dif);
return _a;
}
}
Sched_proxy::List Sched_proxy::_list;
Sched_proxy::Sched_proxy() : L4kproxy::Scheduler_svr(this),
_real_cpus(l4_sched_cpu_set(0,0,0)), _cpu_mask(_real_cpus),
_max_cpus(0), _sched_classes(0),
_prio_offset(0), _prio_limit(0)
{
rescan_cpus_and_classes();
_list.push_front(this);
}
void
Sched_proxy::rescan_cpus_and_classes()
{
l4_sched_cpu_set_t c;
l4_umword_t max = 0;
c.map = 0;
c.gran_offset = 0;
l4_umword_t sc = 0;
int e = l4_error(L4Re::Env::env()->scheduler()->info(&max, &c, &sc));
if (e < 0)
return;
_max_cpus = std::min<unsigned>(sizeof(l4_umword_t) * 8, max);
_real_cpus = c;
_cpus = _real_cpus & _cpu_mask;
_sched_classes = sc;
}
Sched_proxy::~Sched_proxy()
{
_list.remove(this);
}
int
Sched_proxy::info(l4_umword_t *cpu_max, l4_sched_cpu_set_t *cpus,
l4_umword_t *sched_classes)
{
*cpu_max = _max_cpus;
unsigned char g = cpus->granularity() & (sizeof(l4_umword_t) * 8 - 1);
l4_umword_t offs = cpus->offset() & (~0UL << g);
if (offs >= _max_cpus)
return -L4_ERANGE;
cpus->map = 0;
unsigned b = 0;
for (unsigned i = offs; i < _max_cpus && b < sizeof(l4_umword_t) * 8;)
{
if (_cpus.map & (1UL << i))
cpus->map |= 1UL << b;
++i;
if (!(i & ~(~0UL << g)))
++b;
}
if (sched_classes)
*sched_classes = _sched_classes;
return L4_EOK;
}
int
Sched_proxy::run_thread(L4::Cap<L4::Thread> thread, l4_sched_param_t const &sp)
{
l4_sched_param_t s = sp;
s.prio = std::min(sp.prio + _prio_offset, (l4_umword_t)_prio_limit);
s.affinity = sp.affinity & _cpus;
#if 0
printf("loader[%p] run_thread: o=%u scheduler affinity = %lx sp.m=%lx sp.o=%u sp.g=%u\n",
this, _cpus.offset, _cpus.map, sp.affinity.map, (unsigned)sp.affinity.offset, (unsigned)sp.affinity.granularity);
printf("loader[%p] sp.m=%lx sp.o=%u sp.g=%u\n",
this, s.affinity.map, (unsigned)s.affinity.offset, (unsigned)s.affinity.granularity);
#endif
return l4_error(L4Re::Env::env()->scheduler()->run_thread(thread, s));
}
int
Sched_proxy::idle_time(l4_sched_cpu_set_t const &, l4_kernel_clock_t &)
{ return -L4_ENOSYS; }
L4::Cap<L4::Thread>
Sched_proxy::received_thread(L4::Ipc::Snd_fpage const &fp)
{
if (!fp.cap_received())
return L4::Cap<L4::Thread>::Invalid;
return server_iface()->rcv_cap<L4::Thread>(0);
}
void
Sched_proxy::restrict_cpus(l4_umword_t cpus)
{
_cpu_mask = l4_sched_cpu_set(0, 0, cpus);
_cpus = _real_cpus & _cpu_mask;
}
class Cpu_hotplug_server : public L4::Irqep_t<Cpu_hotplug_server>
{
public:
void handle_irq()
{
typedef Sched_proxy::List List;
for (List::Const_iterator i = Sched_proxy::_list.begin();
i != Sched_proxy::_list.end();
++i)
{
i->rescan_cpus_and_classes();
i->hotplug_event();
}
}
Cpu_hotplug_server()
{
L4::Cap<L4::Irq> irq = Gate_alloc::registry.register_irq_obj(this);
if (!irq)
{
Err(Err::Fatal).printf("Could not allocate IRQ for CPU hotplug\n");
return;
}
if (l4_error(L4Re::Env::env()->scheduler()->bind(0, irq)) < 0)
{
Err(Err::Fatal).printf("Could not bind CPU hotplug IRQ to scheduler\n");
return;
}
}
};
static Cpu_hotplug_server _cpu_hotplug_server;

View File

@@ -0,0 +1,59 @@
/*
* (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/cxx/hlist>
#include <l4/sys/cxx/ipc_epiface>
#include <l4/libkproxy/scheduler_svr>
#include "global.h"
class Sched_proxy :
public L4::Epiface_t<Sched_proxy, L4::Scheduler>,
public L4kproxy::Scheduler_svr,
public L4kproxy::Scheduler_interface,
public cxx::H_list_item
{
public:
Sched_proxy();
~Sched_proxy();
// need this because of the wierd Scheduler_svr construction
Server_iface *server_iface() const
{ return L4::Epiface::server_iface(); }
int info(l4_umword_t *cpu_max, l4_sched_cpu_set_t *cpus,
l4_umword_t *sched_classes = nullptr) override;
int run_thread(L4::Cap<L4::Thread> thread, l4_sched_param_t const &sp)
override;
int idle_time(l4_sched_cpu_set_t const &cpus, l4_kernel_clock_t &)
override;
void set_prio(unsigned offs, unsigned limit)
{ _prio_offset = offs; _prio_limit = limit; }
L4::Cap<L4::Thread> received_thread(L4::Ipc::Snd_fpage const &fp);
void restrict_cpus(l4_umword_t cpus);
void rescan_cpus_and_classes();
private:
friend class Cpu_hotplug_server;
l4_sched_cpu_set_t _cpus, _real_cpus, _cpu_mask;
unsigned _max_cpus;
l4_umword_t _sched_classes;
unsigned _prio_offset, _prio_limit;
typedef cxx::H_list_bss<Sched_proxy> List;
static List _list;
};

View File

@@ -0,0 +1,79 @@
/*
* (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/re/util/item_alloc>
#include <l4/re/util/cap_alloc>
#include <l4/re/error_helper>
#include <l4/re/env>
#include <l4/re/mem_alloc>
#include <l4/re/rm>
#include <l4/re/dataspace>
#include "slab_alloc.h"
using L4::Cap;
using L4Re::Util::cap_alloc;
using L4Re::Dataspace;
using L4Re::chksys;
using L4Re::Env;
using L4Re::Rm;
class Single_page_alloc_static
{
private:
enum { Num_pages = 1024 };
L4Re::Util::Item_alloc<Num_pages> _page_map;
l4_addr_t _blob;
Cap<Dataspace> _mem;
public:
Single_page_alloc_static()
{
//L4::cerr << "Hello from alloc\n";
_mem = cap_alloc.alloc<Dataspace>();
if (!_mem.is_valid())
chksys(-L4_ENOMEM, "could not allocate capability");
unsigned long size = Num_pages * L4_PAGESIZE;
chksys(Env::env()->mem_alloc()->alloc(size, _mem),
"backend storage data space");
chksys(Env::env()->rm()
->attach(&_blob, size, Rm::F::Search_addr | Rm::F::RW,
L4::Ipc::make_cap_rw(_mem)),
"attaching backend storage data space");
}
void *alloc()
{
//L4::cerr << "PA:alloc...\n";
long p = _page_map.alloc();
if (p < 0)
return 0;
//L4::cerr << "PA: ok\n";
return (void*)(_blob + (p * L4_PAGESIZE));
}
void free(void *p)
{
if (!p)
return;
l4_addr_t offset = l4_addr_t(p) - _blob;
_mem->clear(offset, L4_PAGESIZE);
_page_map.free(offset / L4_PAGESIZE);
}
};
static Single_page_alloc_static _pa;
void *Single_page_alloc_base::_alloc() { return _pa.alloc(); }
void Single_page_alloc_base::_free(void *o) { _pa.free(o); }

View File

@@ -0,0 +1,34 @@
/*
* (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#pragma once
#include <l4/cxx/slab_alloc>
class Single_page_alloc_base
{
protected:
void *_alloc();
void _free(void *p);
};
template<typename A>
class Single_page_alloc : public Single_page_alloc_base
{
public:
enum { can_free = true };
A *alloc() { return reinterpret_cast<A*>(_alloc()); }
void free(A *o) { _free(o); }
};
template< typename Type >
class Slab_alloc
: public cxx::Slab_static<Type, L4_PAGESIZE, 2, Single_page_alloc>
{};