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,6 @@
PKGDIR = ..
L4DIR ?= $(PKGDIR)/../../..
TARGET = $(wildcard [a-z]*)
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,6 @@
PKGDIR = ../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = $(wildcard [a-z]*)
include $(L4DIR)/mk/subdir.mk

View File

@@ -0,0 +1,8 @@
PKGDIR ?= ../../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_l4re_ma+rm_cc
SRC_CC = ma+rm.cc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,112 @@
/**
* \file
* \brief Example of coarse grained memory allocation, in C++.
*/
/*
* (c) 2009 Adam Lackorzynski <adam@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/mem_alloc>
#include <l4/re/rm>
#include <l4/re/env>
#include <l4/re/dataspace>
#include <l4/re/util/cap_alloc>
#include <l4/sys/err.h>
#include <cstdio>
#include <cstring>
/**
* \brief Allocate memory, given in bytes in the granularity of pages.
*
* \param size_in_bytes Size to allocate, in bytes, will be truncates to
* whole pages (L4_PAGESIZE).
* \param flags Flags to control memory allocation:
* L4Re::Mem_alloc::Continuous: Physically continuous memory
* L4Re::Mem_alloc::Pinned: Pinned memory
* L4Re::Mem_alloc::Super_pages: Use big pages
* \retval virt_addr Virtual address the memory is accessible under,
* undefined if return code != 0
*
* \return 0 on success, error code otherwise
*/
static int allocate_mem(unsigned long size_in_bytes, unsigned long flags,
void **virt_addr)
{
int r;
L4::Cap<L4Re::Dataspace> d;
/* Allocate a free capability index for our data space */
d = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
if (!d.is_valid())
return -L4_ENOMEM;
size_in_bytes = l4_trunc_page(size_in_bytes);
/* Allocate memory via a dataspace */
if ((r = L4Re::Env::env()->mem_alloc()->alloc(size_in_bytes, d, flags)))
return r;
/* Make the dataspace visible in our address space */
*virt_addr = 0;
if ((r = L4Re::Env::env()->rm()->attach(virt_addr, size_in_bytes,
L4Re::Rm::F::Search_addr | L4Re::Rm::F::RW,
L4::Ipc::make_cap_rw(d), 0,
flags & L4Re::Mem_alloc::Super_pages
? L4_SUPERPAGESHIFT : L4_PAGESHIFT)))
return r;
/* Done, virtual address is in virt_addr */
return 0;
}
/**
* \brief Free previously allocated memory.
*
* \param virt_addr Virtual address return by allocate_mem
*
* \return 0 on success, error code otherwise
*/
static int free_mem(void *virt_addr)
{
int r;
L4::Cap<L4Re::Dataspace> ds;
/* Detach memory from our address space */
if ((r = L4Re::Env::env()->rm()->detach(virt_addr, &ds)))
return r;
/* Release and return capability slot to allocator */
L4Re::Util::cap_alloc.free(ds, L4Re::Env::env()->task().cap());
/* All went ok */
return 0;
}
int main(void)
{
void *virt;
/* Allocate memory: 16k Bytes (usually) */
if (allocate_mem(4 * L4_PAGESIZE, 0, &virt))
return 1;
printf("Allocated memory.\n");
/* Do something with the memory */
memset(virt, 0x12, 4 * L4_PAGESIZE);
printf("Touched memory.\n");
/* Free memory */
if (free_mem(virt))
return 2;
printf("Freed and done. Bye.\n");
return 0;
}

View File

@@ -0,0 +1,8 @@
PKGDIR ?= ../../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_periodic_task
SRC_CC = main.cc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,70 @@
/**
* (c) 2014 Steffen Liebergeld <steffen.liebergeld@kernkonzept.com>
*
* This file is licensed under the terms of the GNU General Public License 2.
* See the file COPYING-GPL-2 for details.
*/
#include <l4/re/error_helper>
#include <l4/re/util/object_registry>
#include <l4/cxx/ipc_timeout_queue>
#include <cstdio>
class My_loop_hooks :
public L4::Ipc_svr::Timeout_queue_hooks<My_loop_hooks>,
public L4::Ipc_svr::Ignore_errors
{
public:
/**
* This function is required by Timeout_queue_hooks to get current time.
*/
l4_kernel_clock_t now()
{
return l4_kip_clock(l4re_kip());
}
};
L4Re::Util::Registry_server<My_loop_hooks> server;
/**
* This class implements the code that needs to be run periodically.
*/
class Periodic_task : public L4::Ipc_svr::Timeout_queue::Timeout
{
public:
Periodic_task(int iterations, L4::Ipc_svr::Server_iface *sif)
: _iterations(iterations), _sif(sif)
{
// Add this to the IPC server's Timeout_queue with an absolute timeout.
// The timeout will expire in 5 seconds from now.
_sif->add_timeout(this, l4_kip_clock(l4re_kip()) + 5000000);
}
/**
* This function is called by the Timeout_queue when its timeout expired.
*/
void expired()
{
printf("Timeout expired.\n");
if (!--_iterations)
printf("Bye bye from ex_periodic_task!\n");
else
// We add ourselves back into the Timeout_queue with a new absolute timeout
// that is 5 seconds after the previous timeout.
_sif->add_timeout(this, timeout() + 5000000);
}
private:
int _iterations;
L4::Ipc_svr::Server_iface *_sif;
};
static Periodic_task task(5, &server);
int main()
{
printf("Hello from ex_periodic_task\n");
server.loop();
}

View File

@@ -0,0 +1,7 @@
PKGDIR ?= ../../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_l4re_physmem_cc
SRC_CC = physmem.cc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,132 @@
/**
* \file
* \brief Example of getting memory and it physical address
*/
/*
* (c) 2020 Adam Lackorzynski <adam@l4re.org>
*
* This file is part of L4Re and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
#include <l4/re/mem_alloc>
#include <l4/re/rm>
#include <l4/re/env>
#include <l4/re/dataspace>
#include <l4/re/dma_space>
#include <l4/re/protocols.h>
#include <l4/re/error_helper>
#include <l4/re/util/unique_cap>
#include <l4/sys/err.h>
#include <l4/sys/factory>
#include <cstdio>
#include <cstring>
#include <cassert>
static int allocate_mem(unsigned long size_in_bytes, unsigned long flags,
unsigned long phys_align, void **virt_addr,
L4Re::Util::Unique_cap<L4Re::Dma_space> &dmaspace,
L4Re::Dma_space::Dma_addr *phys_addr)
{
int r;
L4::Cap<L4Re::Dataspace> d;
/* Allocate a free capability index for our data space */
d = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
if (!d.is_valid())
return -L4_ENOMEM;
size_in_bytes = l4_trunc_page(size_in_bytes);
flags |= L4Re::Mem_alloc::Continuous;
/* Allocate memory via a dataspace */
if ((r = L4Re::Env::env()->mem_alloc()->alloc(size_in_bytes, d,
flags, phys_align)))
return r;
/* Make the dataspace visible in our address space, uncached */
*virt_addr = 0;
if ((r = L4Re::Env::env()->rm()->attach(virt_addr, size_in_bytes,
L4Re::Rm::F::Search_addr
| L4Re::Rm::F::RW
| L4Re::Rm::F::Cache_uncached,
L4::Ipc::make_cap_rw(d), 0,
flags & L4Re::Mem_alloc::Super_pages
? L4_SUPERPAGESHIFT : L4_PAGESHIFT)))
return r;
/* The the physical memory address of the allocated memory */
if ((r = dmaspace->associate(L4::Ipc::Cap<L4::Task>(),
L4Re::Dma_space::Phys_space)))
return r;
l4_size_t ps = size_in_bytes;
if ((r = dmaspace->map(L4::Ipc::make_cap_rw(d), 0, &ps,
L4Re::Dma_space::Attributes::None,
L4Re::Dma_space::Bidirectional, phys_addr)))
return r;
// The memory is L4Re::Mem_alloc::Continuous, i.e., there is only
// one size.
assert(ps == size_in_bytes);
/* Done, virtual address is in virt_addr */
return 0;
}
static int free_mem(void *virt_addr)
{
int r;
L4::Cap<L4Re::Dataspace> ds;
/* Detach memory from our address space */
if ((r = L4Re::Env::env()->rm()->detach(virt_addr, &ds)))
return r;
/* Release and return capability slot to allocator */
L4Re::Util::cap_alloc.free(ds, L4Re::Env::env()->task().cap());
/* All went ok */
return 0;
}
int main(void)
{
L4Re::Env const *e = L4Re::Env::env();
void *virt;
auto dmaspace = L4Re::chkcap(L4Re::Util::make_unique_cap<L4Re::Dma_space>());
L4Re::Dma_space::Dma_addr phys;
int r;
if ((r = l4_error(e->user_factory()->create(dmaspace.get()))))
return r;
/* Allocate memory: 16k Bytes (usually) */
if (allocate_mem(4 * L4_PAGESIZE, // size
0, // flags
2 + L4_PAGESHIFT, // 16 KByte aligned
&virt, dmaspace, &phys))
{
printf("The memory allocation failed\n");
return 1;
}
printf("Allocated memory, virtual address: %p\n", virt);
printf("Physical / DMA address: %llx\n", phys);
/* Do something with the memory */
memset(virt, 0x12, 4 * L4_PAGESIZE);
/* Free memory */
if (free_mem(virt))
return 2;
dmaspace->disassociate();
printf("Freed and done. Bye.\n");
return 0;
}

View File

@@ -0,0 +1,8 @@
PKGDIR ?= ../../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_l4re_ds_clnt ex_l4re_ds_srv
SRC_CC_ex_l4re_ds_clnt = ds_clnt.cc
SRC_CC_ex_l4re_ds_srv = ds_srv.cc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,110 @@
/*
* (c) 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/re/util/cap_alloc> // L4::Cap
#include <l4/re/dataspace> // L4Re::Dataspace
#include <l4/re/rm> // L4::Rm
#include <l4/re/env> // L4::Env
#include <l4/sys/cache.h>
#include <cstring>
#include <cstdio>
#include <unistd.h>
#include "interface.h"
int main()
{
/*
* Try to get server interface cap.
*/
L4::Cap<My_interface> svr = L4Re::Env::env()->get_cap<My_interface>("shm");
if (!svr.is_valid())
{
printf("Could not get the server capability\n");
return 1;
}
/*
* Alloc data space cap slot
*/
L4::Cap<L4Re::Dataspace> ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
if (!ds.is_valid())
{
printf("Could not get capability slot!\n");
return 1;
}
/*
* Alloc server notifier IRQ cap slot
*/
L4::Cap<L4::Irq> irq = L4Re::Util::cap_alloc.alloc<L4::Irq>();
if (!irq.is_valid())
{
printf("Could not get capability slot!\n");
return 1;
}
/*
* Request shared data-space cap.
*/
if (svr->get_shared_buffer(ds, irq))
{
printf("Could not get shared memory dataspace!\n");
return 1;
}
/*
* Attach to arbitrary region
*/
char *addr = 0;
int err = L4Re::Env::env()->rm()->attach(&addr, ds->size(),
L4Re::Rm::F::Search_addr | L4Re::Rm::F::RW,
L4::Ipc::make_cap_rw(ds));
if (err < 0)
{
printf("Error attaching data space: %s\n", l4sys_errtostr(err));
return 1;
}
printf("Content: %s\n", addr);
// wait a bit for the demo effect
printf("Sleeping a bit...\n");
sleep(1);
/*
* Fill in new stuff
*/
memset(addr, 0, ds->size());
char const * const msg = "Hello from client, too!";
printf("Setting new content in shared memory\n");
snprintf(addr, strlen(msg)+1, msg);
l4_cache_clean_data((unsigned long)addr,
(unsigned long)addr + strlen(msg) + 1);
// notify the server
irq->trigger();
/*
* Detach region containing addr, result should be Detached_ds (other results
* only apply if we split regions etc.).
*/
err = L4Re::Env::env()->rm()->detach(addr, 0);
if (err)
printf("Failed to detach region\n");
/* Free objects and capabilties, just for completeness. */
L4Re::Util::cap_alloc.free(ds, L4Re::This_task);
L4Re::Util::cap_alloc.free(irq, L4Re::This_task);
return 0;
}

View File

@@ -0,0 +1,220 @@
/*
* (c) 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/re/env>
#include <l4/re/error_helper>
#include <l4/re/namespace>
#include <l4/re/util/cap_alloc>
#include <l4/re/util/object_registry>
#include <l4/re/dataspace>
#include <l4/cxx/ipc_server>
#include <l4/util/util.h>
#include <l4/sys/typeinfo_svr>
#include <cstring>
#include <cstdio>
#include <unistd.h>
#include <pthread.h>
#include <pthread-l4.h>
#include <thread>
#include "interface.h"
/**
* A very simple server object, just providing the
* shared memory data space and an IRQ object to send a notification.
*/
class My_server_obj : public L4::Server_object_t<L4::Kobject>
{
private:
/**
* The capability to the shared memory.
*/
L4::Cap<L4Re::Dataspace> _shm;
L4::Cap<L4::Irq> _irq;
public:
/**
* Create a new object for the given data space.
*/
explicit My_server_obj(L4::Cap<L4Re::Dataspace> shm, L4::Cap<L4::Irq> irq)
: _shm(shm), _irq(irq)
{}
/**
* Dispatch function, dealing with remote requests.
*/
int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
};
int My_server_obj::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
{
// we don't care about the original object reference, however
// we could read out the access rights from the lowest 2 bits
(void) obj;
l4_msgtag_t t;
ios >> t; // extract the tag
switch (t.label())
{
case L4::Meta::Protocol:
// handle the meta protocol requests, implementing the
// runtime dynamic type system for L4 objects.
return L4::Util::handle_meta_request<My_interface>(ios);
case 0:
// since we have just one operation we have no opcode dispatch,
// and just return the data-space and the notifier IRQ capabilities
ios << _shm << _irq;
return 0;
default:
// every other protocol is not supported.
return -L4_EBADPROTO;
}
}
/**
* A simple Server object attached to a notifier IRQ.
* This provides a kind of interrupt handler integrated in our
* server.
*/
class Shm_observer : public L4::Irq_handler_object
{
private:
/**
* The pointer to the shared memory.
*/
char *_shm;
public:
/**
* Create a new object for the given shared memory.
*/
explicit Shm_observer(char *shm)
: _shm(shm)
{}
/**
* Dispatch function, dealing with remote requests.
* This is the ISR.
*/
int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
};
int Shm_observer::dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
{
// We don't care about the original object reference, however
// we could read out the access rights from the lowest 2 bits
(void)obj;
// Since we end up here in this function, we got a 'message' from the IRQ
// that is bound to us. The 'ios' stream won't contain any valuable info.
(void)ios;
printf("Client sent us: %s\n", _shm);
return 0;
}
enum
{
DS_SIZE = 4 << 12,
};
static char *get_ds(L4::Cap<L4Re::Dataspace> *_ds)
{
*_ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
if (!(*_ds).is_valid())
{
printf("Dataspace allocation failed.\n");
return 0;
}
int err = L4Re::Env::env()->mem_alloc()->alloc(DS_SIZE, *_ds, 0);
if (err < 0)
{
printf("mem_alloc->alloc() failed.\n");
L4Re::Util::cap_alloc.free(*_ds);
return 0;
}
/*
* Attach DS to local address space
*/
char *_addr = 0;
err = L4Re::Env::env()->rm()->attach(&_addr, (*_ds)->size(),
L4Re::Rm::F::Search_addr | L4Re::Rm::F::RW,
L4::Ipc::make_cap_rw(*_ds));
if (err < 0)
{
printf("Error attaching data space: %s\n", l4sys_errtostr(err));
L4Re::Util::cap_alloc.free(*_ds);
return 0;
}
/*
* Success! Write something to DS.
*/
printf("Attached DS\n");
static char const * const msg = "[DS] Hello from server!";
snprintf(_addr, strlen(msg) + 1, msg);
return _addr;
}
static void *server_thread(void *)
{
L4::Cap<L4::Thread> l4_thread = Pthread::L4::cap(pthread_self());
L4Re::Util::Registry_server<> server(l4_thread, L4Re::Env::env()->factory());
L4::Cap<L4Re::Dataspace> ds;
char *addr;
if (!(addr = get_ds(&ds)))
return nullptr;
// First the IRQ handler, because we need it in the My_server_obj object
Shm_observer observer(addr);
// Registering the observer as an IRQ handler, this allocates an
// IRQ object using the factory of our server.
L4::Cap<L4::Irq> irq = server.registry()->register_irq_obj(&observer);
// Now the initial server object shared with the client via our parent.
// it provides the data-space and the IRQ capabilities to a client.
My_server_obj server_obj(ds, irq);
// Registering the server object to the capability 'shm' in our the L4Re::Env.
// This capability must be provided by the parent. (see the shared_ds.lua)
server.registry()->register_obj(&server_obj, "shm");
// Run our server loop.
server.loop();
}
int main()
{
pthread_attr_t pattr;
if (pthread_attr_init(&pattr))
L4Re::throw_error(-L4_ENOMEM, "Initialize pthread attributes");
pthread_t thr;
L4Re::chksys(pthread_create(&thr, &pattr, server_thread, nullptr),
"Create server thread");
L4Re::chksys(pthread_attr_destroy(&pattr), "Destroy pthread attributes");
l4_sleep_forever();
return 0;
}

View File

@@ -0,0 +1,42 @@
#pragma once
#include <l4/sys/capability>
#include <l4/re/dataspace>
#include <l4/cxx/ipc_stream>
/**
* Interface class for remote object.
*
* Inherits from L4::Kobject, via the L4::Kobject_t helper
* template that generates the dynamic type information for the meta
* protocol.
*/
class My_interface : public L4::Kobject_t<My_interface, L4::Kobject>
{
// Disable instantiation and copy, because we just work via
// L4::Cap<...> references.
L4_KOBJECT(My_interface)
public:
/**
* The single method of our object.
* Requesting the data space and the IRQ to notify the server.
*/
int get_shared_buffer(L4::Cap<L4Re::Dataspace> ds, L4::Cap<L4::Irq> irq) throw();
};
inline
int
My_interface::get_shared_buffer(L4::Cap<L4Re::Dataspace> ds, L4::Cap<L4::Irq> irq) throw()
{
L4::Ipc::Iostream s(l4_utcb());
// we have just a single operation, so no opcode needed
// s << Opcode;
// put receive buffer for data-space cap and the irq cap into the stream
s << L4::Ipc::Small_buf(ds)
<< L4::Ipc::Small_buf(irq);
return l4_error(s.call(cap()));
}

View File

@@ -0,0 +1,27 @@
-- Include L4 functionality
local L4 = require("L4");
-- Create a channel from the client to the server
local channel = L4.default_loader:new_channel();
-- Start the server, giving the channel with full server rights.
-- The server will have a yellow log output.
L4.default_loader:start(
{
caps = { shm = channel:svr() },
log = { "server", "yellow" }
},
"rom/ex_l4re_ds_srv"
);
-- Start the client, giving it the channel with read only rights. The
-- log output will be green.
L4.default_loader:start(
{
caps = { shm = channel },
log = { "client", "green" },
l4re_dbg = L4.Dbg.Warn
},
"rom/ex_l4re_ds_clnt"
);

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_l4re_ma+rm_c
SRC_C = ma+rm.c
REQUIRES_LIBS = l4re_c-util
DEPENDS_PKGS = $(REQUIRES_LIBS)
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,113 @@
/**
* \file
* \brief Example of coarse grained memory allocation, in C.
*/
/*
* (c) 2009 Adam Lackorzynski <adam@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/c/mem_alloc.h>
#include <l4/re/c/rm.h>
#include <l4/re/c/util/cap_alloc.h>
#include <l4/sys/err.h>
#include <stdio.h>
#include <string.h>
/**
* \brief Allocate memory, given in bytes in the granularity of pages.
*
* \param size_in_bytes Size to allocate, in bytes, will be truncates to
* whole pages (L4_PAGESIZE).
* \param flags Flags to control memory allocation:
* L4RE_MA_CONTINUOUS: Physically continuous memory
* L4RE_MA_PINNED: Pinned memory
* L4RE_MA_SUPER_PAGES: Use big pages
* \retval virt_addr Virtual address the memory is accessible under,
* undefined if return code != 0
*
* \return 0 on success, error code otherwise
*/
static int allocate_mem(unsigned long size_in_bytes, unsigned long flags,
void **virt_addr)
{
int r;
l4re_ds_t ds;
/* Allocate a free capability index for our data space */
ds = l4re_util_cap_alloc();
if (l4_is_invalid_cap(ds))
return -L4_ENOMEM;
size_in_bytes = l4_trunc_page(size_in_bytes);
/* Allocate memory via a dataspace */
if ((r = l4re_ma_alloc(size_in_bytes, ds, flags)))
return r;
/* Make the dataspace visible in our address space */
*virt_addr = 0;
if ((r = l4re_rm_attach(virt_addr, size_in_bytes,
L4RE_RM_F_SEARCH_ADDR | L4RE_RM_F_RWX, ds, 0,
flags & L4RE_MA_SUPER_PAGES
? L4_SUPERPAGESHIFT : L4_PAGESHIFT)))
{
/* Free dataspace again */
l4re_util_cap_free_um(ds);
return r;
}
/* Done, virtual address is in virt_addr */
return 0;
}
/**
* \brief Free previously allocated memory.
*
* \param virt_addr Virtual address return by allocate_mem
*
* \return 0 on success, error code otherwise
*/
static int free_mem(void *virt_addr)
{
int r;
l4re_ds_t ds;
/* Detach memory from our address space */
if ((r = l4re_rm_detach_ds(virt_addr, &ds)))
return r;
/* Free memory at our memory allocator */
l4re_util_cap_free_um(ds);
/* All went ok */
return 0;
}
int main(void)
{
void *virt;
/* Allocate memory: 16k Bytes (usually) */
if (allocate_mem(4 * L4_PAGESIZE, 0, &virt))
return 1;
printf("Allocated memory.\n");
/* Do something with the memory */
memset(virt, 0x12, 4 * L4_PAGESIZE);
printf("Touched memory.\n");
/* Free memory */
if (free_mem(virt))
return 2;
printf("Freed and done. Bye.\n");
return 0;
}

View File

@@ -0,0 +1,9 @@
PKGDIR ?= ../..
L4DIR ?= $(PKGDIR)/../../..
TARGET = ex_smap-server ex_smap-client
SRC_CC_ex_smap-server = server.cc
SRC_CC_ex_smap-client = client.cc
include $(L4DIR)/mk/prog.mk

View File

@@ -0,0 +1,70 @@
/*
* (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/err.h>
#include <l4/sys/types.h>
#include <l4/re/env>
#include <l4/re/util/cap_alloc>
#include <l4/cxx/ipc_stream>
#include <stdio.h>
#include "shared.h"
static int
func_smap_call(L4::Cap<void> const &server)
{
L4::Ipc::Iostream s(l4_utcb());
l4_addr_t addr = 0;
int err;
if ((err = L4Re::Env::env()->rm()->reserve_area(&addr, L4_PAGESIZE,
L4Re::Rm::F::Search_addr)))
{
printf("The reservation of one page within our virtual memory failed with %d\n", err);
return 1;
}
s << L4::Opcode(Mapper::Do_map)
<< (l4_addr_t)addr;
s << L4::Ipc::Rcv_fpage::mem((l4_addr_t)addr, L4_PAGESHIFT, 0);
int r = l4_error(s.call(server.cap(), Mapper::Protocol));
if (r)
return r; // failure
printf("String sent by server: %s\n", (char *)addr);
return 0; // ok
}
int
main()
{
L4::Cap<void> server = L4Re::Env::env()->get_cap<void>("smap");
if (!server.is_valid())
{
printf("Could not get capability slot!\n");
return 1;
}
printf("Asking for page from server\n");
if (func_smap_call(server))
{
printf("Error talking to server\n");
return 1;
}
printf("It worked!\n");
L4Re::Util::cap_alloc.free(server, L4Re::This_task);
return 0;
}

View File

@@ -0,0 +1,76 @@
/*
* (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 <stdio.h>
#include <l4/re/env>
#include <l4/re/util/cap_alloc>
#include <l4/re/util/object_registry>
#include <l4/cxx/ipc_server>
#include "shared.h"
static char page_to_map[L4_PAGESIZE] __attribute__((aligned(L4_PAGESIZE)));
static L4Re::Util::Registry_server<> server;
class Smap_server : public L4::Server_object_t<Mapper>
{
public:
int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios);
};
int
Smap_server::dispatch(l4_umword_t, L4::Ipc::Iostream &ios)
{
l4_msgtag_t t;
ios >> t;
// We're only talking the Map_example protocol
if (t.label() != Mapper::Protocol)
return -L4_EBADPROTO;
L4::Opcode opcode;
ios >> opcode;
switch (opcode)
{
case Mapper::Do_map:
l4_addr_t snd_base;
ios >> snd_base;
// put something into the page to read it out at the other side
snprintf(page_to_map, sizeof(page_to_map), "Hello from the server!");
printf("Sending to client\n");
// send page
ios << L4::Ipc::Snd_fpage::mem((l4_addr_t)page_to_map, L4_PAGESHIFT,
L4_FPAGE_RO, snd_base);
return L4_EOK;
default:
return -L4_ENOSYS;
}
}
int
main()
{
static Smap_server smap;
// Register server
if (!server.registry()->register_obj(&smap, "smap").is_valid())
{
printf("Could not register my service, read-only namespace?\n");
return 1;
}
printf("Welcome to the memory map example server!\n");
// Wait for client requests
server.loop();
return 0;
}

View File

@@ -0,0 +1,17 @@
/*
* (c) 2008-2009 Adam Lackorzynski <adam@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>
struct Mapper : public L4::Kobject_t<Mapper, L4::Kobject>
{
enum Opcodes { Do_map };
};

View File

@@ -0,0 +1,21 @@
-- vim:set ft=lua:
-- Include L4 functionality
local L4 = require("L4");
-- Channel for the communication between the server and the client.
local smap_channel = L4.default_loader:new_channel();
-- The server program, using the 'smap' channel in server
-- mode. The log prefix will be 'server', colored yellow.
L4.default_loader:start({ caps = { smap = smap_channel:svr() },
log = { "server", "yellow" }},
"rom/ex_smap-server");
-- The client program.
-- It is given the 'smap' channel to be able to talk to the server.
-- The log prefix will be 'client', colored green.
L4.default_loader:start({ caps = { smap = smap_channel },
log = { "client", "green" } },
"rom/ex_smap-client");