1.1 --- a/Makefile Tue Jan 19 23:26:49 2021 +0100
1.2 +++ b/Makefile Wed Jan 20 01:37:12 2021 +0100
1.3 @@ -21,7 +21,10 @@
1.4
1.5 SERVER_INTERFACES_SRC_CC = $(call interfaces_to_server_cc,$(SERVER_INTERFACES_CC))
1.6
1.7 -PLAIN_SRC_CC = dstest_server.cc flexpage.cc memory_utils.cc region.cc
1.8 +PLAIN_SRC_CC = \
1.9 + dstest_server.cc flexpage.cc \
1.10 + memory.cc memory_map.cc memory_utils.cc \
1.11 + region.cc resource.cc simple_pager.cc
1.12
1.13 # Normal definitions.
1.14
2.1 --- a/dstest_server.cc Tue Jan 19 23:26:49 2021 +0100
2.2 +++ b/dstest_server.cc Wed Jan 20 01:37:12 2021 +0100
2.3 @@ -1,7 +1,7 @@
2.4 /*
2.5 * Test dataspace operations.
2.6 *
2.7 - * Copyright (C) 2020 Paul Boddie <paul@boddie.org.uk>
2.8 + * Copyright (C) 2020, 2021 Paul Boddie <paul@boddie.org.uk>
2.9 *
2.10 * This program is free software; you can redistribute it and/or
2.11 * modify it under the terms of the GNU General Public License as
2.12 @@ -29,58 +29,19 @@
2.13 #include <ipc/server.h>
2.14
2.15 #include "dataspace_server.h"
2.16 -#include "flexpage.h"
2.17 +#include "simple_pager.h"
2.18
2.19
2.20
2.21 /* Component interface. */
2.22
2.23 -class DataspaceServer : public Dataspace
2.24 +class DataspaceServer : public SimplePager
2.25 {
2.26 -protected:
2.27 - Region *_region;
2.28 - offset_t _start, _size;
2.29 -
2.30 public:
2.31 - explicit DataspaceServer(char *addr, offset_t size)
2.32 - {
2.33 - _region = new Region((offset_t) addr, (offset_t) addr + size);
2.34 - _start = 0;
2.35 - _size = size;
2.36 -
2.37 - offset_t i;
2.38 - int j;
2.39 -
2.40 - for (i = 0, j = 0; i < size; i += PAGE_SIZE, j++)
2.41 - memset((void *) (addr + i), (int) 'a' + j, PAGE_SIZE);
2.42 - }
2.43 -
2.44 - virtual long map(unsigned long offset, l4_addr_t hot_spot, unsigned long flags, l4_snd_fpage_t *region)
2.45 + explicit DataspaceServer(Memory *memory)
2.46 + : SimplePager(memory)
2.47 {
2.48 - Flexpage flexpage(_region);
2.49 - offset_t max_offset = _start + _size;
2.50 -
2.51 - printf("map(%ld, %lx, %lx, ...)\n", offset, hot_spot, flags);
2.52 -
2.53 - flexpage.reset(_start + offset);
2.54 -
2.55 - SendFlexpage send_flexpage = flexpage.to_send(offset, hot_spot, max_offset);
2.56 -
2.57 - printf("send %lx -> %lx -> {%lx, %d}\n", _region->start, flexpage.base_addr, send_flexpage.base_addr, send_flexpage.order);
2.58 -
2.59 - /* Send the flexpage explicitly. */
2.60 -
2.61 - region->fpage = l4_fpage(send_flexpage.base_addr, send_flexpage.order,
2.62 - (flags & L4RE_DS_MAP_FLAG_RW) ? L4_FPAGE_RW
2.63 - : L4_FPAGE_RO);
2.64 - region->snd_base = hot_spot;
2.65 -
2.66 - long err = complete_Dataspace_map(*region);
2.67 -
2.68 - if (err)
2.69 - return err;
2.70 -
2.71 - return IPC_MESSAGE_SENT;
2.72 + memset((void *) _region->start, (int) 'a', PAGE_SIZE);
2.73 }
2.74 };
2.75
2.76 @@ -90,17 +51,11 @@
2.77 {
2.78 /* Some memory. */
2.79
2.80 - char *memory;
2.81 -
2.82 - if (posix_memalign((void **) &memory, 40960, 40960))
2.83 - {
2.84 - printf("Could not allocate memory.\n");
2.85 - return 1;
2.86 - }
2.87 + Memory memory(10);
2.88
2.89 /* Dataspace encapsulation. */
2.90
2.91 - DataspaceServer obj(memory, 40960);
2.92 + DataspaceServer obj(&memory);
2.93
2.94 /* Server capability. */
2.95
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/memory.cc Wed Jan 20 01:37:12 2021 +0100
3.3 @@ -0,0 +1,80 @@
3.4 +#include "memory.h"
3.5 +#include "memory_map.h"
3.6 +
3.7 +
3.8 +
3.9 +/* Global memory allocator. */
3.10 +
3.11 +extern Allocator allocator;
3.12 +
3.13 +
3.14 +
3.15 +/* Initialise the memory pool with an optional 'limit' in pages. */
3.16 +
3.17 +Memory::Memory(unsigned int limit, offset_t region_size)
3.18 +: _limit(limit), _region_size(region_size)
3.19 +{
3.20 + _limited = true;
3.21 +}
3.22 +
3.23 +Memory::Memory()
3.24 +: _region_size(PAGE_SIZE)
3.25 +{
3.26 + _limited = false;
3.27 +}
3.28 +
3.29 +/* Allocate a new region of the given 'size' rounded to the nearest page. */
3.30 +
3.31 +Region *Memory::region(offset_t size)
3.32 +{
3.33 + std::lock_guard<std::mutex> guard(_lock);
3.34 +
3.35 + offset_t rounded = round(size, PAGE_SIZE);
3.36 + offset_t pages = rounded / PAGE_SIZE;
3.37 +
3.38 + /* Check for sufficient pages. */
3.39 +
3.40 + if (!_limited || (_limit >= pages))
3.41 + {
3.42 + /* Attempt to allocate aligned memory. */
3.43 +
3.44 + Region *region = allocator.region(rounded);
3.45 +
3.46 + if (region == NULL)
3.47 + return NULL;
3.48 +
3.49 + if (_limited)
3.50 + _limit -= pages;
3.51 +
3.52 + return region;
3.53 + }
3.54 +
3.55 + /* Return no region without sufficient pages. */
3.56 +
3.57 + else
3.58 + return NULL;
3.59 +}
3.60 +
3.61 +Region *Memory::region()
3.62 +{
3.63 + return region(_region_size);
3.64 +}
3.65 +
3.66 +/* Release the allocated 'region'. */
3.67 +
3.68 +void Memory::release(Region *region)
3.69 +{
3.70 + std::lock_guard<std::mutex> guard(_lock);
3.71 +
3.72 + offset_t rounded = round(region->size(), PAGE_SIZE);
3.73 + offset_t pages = rounded / PAGE_SIZE;
3.74 +
3.75 + if (_limited)
3.76 + _limit += pages;
3.77 +
3.78 + allocator.remove(region);
3.79 +
3.80 + delete region;
3.81 +}
3.82 +
3.83 +// vim: tabstop=4 expandtab shiftwidth=4
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/memory.h Wed Jan 20 01:37:12 2021 +0100
4.3 @@ -0,0 +1,35 @@
4.4 +#pragma once
4.5 +
4.6 +#include <list>
4.7 +#include <mutex>
4.8 +
4.9 +#include "memory_utils.h"
4.10 +#include "region.h"
4.11 +#include "types.h"
4.12 +
4.13 +
4.14 +
4.15 +/* A memory pool abstraction. */
4.16 +
4.17 +class Memory
4.18 +{
4.19 +protected:
4.20 + std::mutex _lock;
4.21 +
4.22 + unsigned int _limit;
4.23 + offset_t _region_size;
4.24 + bool _limited;
4.25 +
4.26 +public:
4.27 + explicit Memory(unsigned int limit, offset_t region_size=PAGE_SIZE);
4.28 +
4.29 + explicit Memory();
4.30 +
4.31 + Region *region(offset_t size);
4.32 +
4.33 + Region *region();
4.34 +
4.35 + void release(Region *region);
4.36 +};
4.37 +
4.38 +// vim: tabstop=4 expandtab shiftwidth=4
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/memory_map.cc Wed Jan 20 01:37:12 2021 +0100
5.3 @@ -0,0 +1,83 @@
5.4 +#include <stdlib.h>
5.5 +
5.6 +#include "memory_map.h"
5.7 +#include "memory_utils.h"
5.8 +
5.9 +
5.10 +
5.11 +/* Global memory allocator. */
5.12 +
5.13 +Allocator allocator;
5.14 +
5.15 +
5.16 +
5.17 +/* Region management. */
5.18 +
5.19 +void MemoryMap::insert(Region *region)
5.20 +{
5.21 + std::lock_guard<std::mutex> guard(_lock);
5.22 +
5.23 + _regions.insert(_MemoryMapEntry(region->start, region));
5.24 +}
5.25 +
5.26 +void MemoryMap::remove(Region *region)
5.27 +{
5.28 + std::lock_guard<std::mutex> guard(_lock);
5.29 +
5.30 + _MemoryMap::iterator entry = _regions.find(region->start);
5.31 +
5.32 + if (entry != _regions.end())
5.33 + _regions.erase(entry);
5.34 +}
5.35 +
5.36 +/* Show the memory state. */
5.37 +
5.38 +void MemoryMap::show(std::ostringstream &buffer)
5.39 +{
5.40 + std::lock_guard<std::mutex> guard(_lock);
5.41 +
5.42 + _MemoryMap::iterator it;
5.43 +
5.44 + buffer << "Mem: ";
5.45 +
5.46 + for (it = _regions.begin(); it != _regions.end(); it++)
5.47 + {
5.48 + it->second->state.show(buffer);
5.49 + buffer << " ";
5.50 + }
5.51 +
5.52 + buffer << std::endl;
5.53 +}
5.54 +
5.55 +
5.56 +
5.57 +/* Allocate a block of the given 'size'. */
5.58 +
5.59 +Region *Allocator::region(offset_t size)
5.60 +{
5.61 + /* Attempt to allocate aligned memory. */
5.62 +
5.63 + void *current;
5.64 +
5.65 + /* Make the size appropriate for the invocation. */
5.66 +
5.67 + size = round_multiple(size, PAGE_SIZE);
5.68 +
5.69 + if (posix_memalign(¤t, size, size))
5.70 + return NULL;
5.71 +
5.72 + Region *region = new Region((offset_t) current, (offset_t) current + size);
5.73 +
5.74 + insert(region);
5.75 + return region;
5.76 +}
5.77 +
5.78 +/* Release the allocated 'region'. */
5.79 +
5.80 +void Allocator::release(Region *region)
5.81 +{
5.82 + remove(region);
5.83 + delete region;
5.84 +}
5.85 +
5.86 +// vim: tabstop=4 expandtab shiftwidth=4
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/memory_map.h Wed Jan 20 01:37:12 2021 +0100
6.3 @@ -0,0 +1,51 @@
6.4 +#pragma once
6.5 +
6.6 +#include <map>
6.7 +#include <mutex>
6.8 +#include <sstream>
6.9 +
6.10 +#include "region.h"
6.11 +#include "types.h"
6.12 +
6.13 +
6.14 +
6.15 +/* Memory map entry. */
6.16 +
6.17 +typedef std::map<offset_t, Region *> _MemoryMap;
6.18 +typedef std::pair<offset_t, Region *> _MemoryMapEntry;
6.19 +
6.20 +
6.21 +
6.22 +/* Memory organised as a collection of regions. */
6.23 +
6.24 +class MemoryMap
6.25 +{
6.26 +protected:
6.27 + std::mutex _lock;
6.28 + _MemoryMap _regions;
6.29 +
6.30 +public:
6.31 + /* Region maintenance. */
6.32 +
6.33 + void insert(Region *region);
6.34 +
6.35 + void remove(Region *region);
6.36 +
6.37 + /* Debugging methods. */
6.38 +
6.39 + void show(std::ostringstream &buffer);
6.40 +};
6.41 +
6.42 +
6.43 +
6.44 +/* An allocator abstraction. */
6.45 +
6.46 +class Allocator : public MemoryMap
6.47 +{
6.48 +public:
6.49 + Region *region(offset_t size);
6.50 +
6.51 + void release(Region *region);
6.52 +};
6.53 +
6.54 +// vim: tabstop=4 expandtab shiftwidth=4
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/resource.cc Wed Jan 20 01:37:12 2021 +0100
7.3 @@ -0,0 +1,12 @@
7.4 +#include "resource.h"
7.5 +
7.6 +
7.7 +Resource::~Resource()
7.8 +{
7.9 +}
7.10 +
7.11 +void Resource::close()
7.12 +{
7.13 +}
7.14 +
7.15 +// vim: tabstop=4 expandtab shiftwidth=4
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/resource.h Wed Jan 20 01:37:12 2021 +0100
8.3 @@ -0,0 +1,15 @@
8.4 +#pragma once
8.5 +
8.6 +
8.7 +
8.8 +/* A resource interface. */
8.9 +
8.10 +class Resource
8.11 +{
8.12 +public:
8.13 + virtual ~Resource();
8.14 +
8.15 + virtual void close();
8.16 +};
8.17 +
8.18 +// vim: tabstop=4 expandtab shiftwidth=4
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/simple_pager.cc Wed Jan 20 01:37:12 2021 +0100
9.3 @@ -0,0 +1,55 @@
9.4 +#include <l4/re/c/dataspace.h>
9.5 +
9.6 +#include "dataspace_server.h"
9.7 +#include "simple_pager.h"
9.8 +
9.9 +
9.10 +
9.11 +SimplePager::SimplePager(Memory *memory)
9.12 +{
9.13 + if (memory == NULL)
9.14 + _memory = new Memory();
9.15 + else
9.16 + _memory = memory;
9.17 +
9.18 + _region = _memory->region();
9.19 +}
9.20 +
9.21 +void SimplePager::close()
9.22 +{
9.23 + if (_region != NULL)
9.24 + {
9.25 + _memory->release(_region);
9.26 + _region = NULL;
9.27 + }
9.28 +}
9.29 +
9.30 +/* Map a flexpage corresponding to the dataspace 'offset' involving a 'hot_spot'
9.31 + (flexpage offset). */
9.32 +
9.33 +long SimplePager::map(unsigned long offset, l4_addr_t hot_spot, unsigned long flags, l4_snd_fpage_t *region)
9.34 +{
9.35 + Flexpage flexpage(_region);
9.36 +
9.37 + flexpage.reset(offset);
9.38 +
9.39 + /* Issue the flexpage via the IPC system. */
9.40 +
9.41 + SendFlexpage send_flexpage = flexpage.to_send(offset, hot_spot);
9.42 +
9.43 + /* Send the flexpage explicitly. */
9.44 +
9.45 + region->fpage = l4_fpage(send_flexpage.base_addr, send_flexpage.order,
9.46 + (flags & L4RE_DS_MAP_FLAG_RW) ? L4_FPAGE_RW
9.47 + : L4_FPAGE_RO);
9.48 + region->snd_base = hot_spot;
9.49 +
9.50 + long err = complete_Dataspace_map(*region);
9.51 +
9.52 + if (err)
9.53 + return err;
9.54 +
9.55 + return IPC_MESSAGE_SENT;
9.56 +}
9.57 +
9.58 +// vim: tabstop=4 expandtab shiftwidth=4
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/simple_pager.h Wed Jan 20 01:37:12 2021 +0100
10.3 @@ -0,0 +1,28 @@
10.4 +#pragma once
10.5 +
10.6 +#include "dataspace_interface.h"
10.7 +#include "flexpage.h"
10.8 +#include "memory.h"
10.9 +#include "resource.h"
10.10 +
10.11 +
10.12 +
10.13 +/* A simple pager exposing a single memory region as a dataspace. */
10.14 +
10.15 +class SimplePager : public Dataspace, public Resource
10.16 +{
10.17 +protected:
10.18 + Memory *_memory;
10.19 + Region *_region;
10.20 +
10.21 +public:
10.22 + explicit SimplePager(Memory *memory=NULL);
10.23 +
10.24 + void close();
10.25 +
10.26 + /* Paging methods. */
10.27 +
10.28 + long map(unsigned long offset, l4_addr_t hot_spot, unsigned long flags, l4_snd_fpage_t *region);
10.29 +};
10.30 +
10.31 +// vim: tabstop=4 expandtab shiftwidth=4