FreeNOS
MemoryContext.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Niek Linnenbank
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #pragma clang optimize off
19 #pragma GCC push_options
20 #pragma GCC optimize ("O0")
21 
22 #include <FreeNOS/System.h>
23 #include <SplitAllocator.h>
24 #include "MemoryContext.h"
25 
27 
29  : m_alloc(alloc)
30  , m_map(map)
31  , m_mapRangeSparseCallback(this, &MemoryContext::mapRangeSparseCallback)
32  , m_savedRange(ZERO)
33  , m_numSparsePages(ZERO)
34 {
35 }
36 
38 {
39 }
40 
42 {
43  return m_current;
44 }
45 
47 {
48  Result r = Success;
49 
50  // Allocate a block of contiguous physical pages, if needed.
51  if (!range->phys)
52  {
53  Allocator::Range alloc_args;
54  alloc_args.address = 0;
55  alloc_args.size = range->size;
56  alloc_args.alignment = PAGESIZE;
57 
58  if (m_alloc->allocate(alloc_args) != Allocator::Success)
59  return OutOfMemory;
60 
61  range->phys = alloc_args.address;
62  }
63 
64  // Insert virtual page(s)
65  for (Size i = 0; i < range->size; i += PAGESIZE)
66  {
67  if ((r = map(range->virt + i,
68  range->phys + i,
69  range->access)) != Success)
70  break;
71  }
72 
73  return r;
74 }
75 
77 {
78  Allocator::Range alloc_args;
79 
80  // Allocate a set of physical pages (non-contiguous)
81  m_savedRange = range;
82  m_numSparsePages = 0;
83 
84  alloc_args.address = 0;
85  alloc_args.size = range->size;
86  alloc_args.alignment = 0;
87 
88  // This invokes our callback for each new page that is allocated
90  return OutOfMemory;
91 
92  return Success;
93 }
94 
96 {
97  Result r = Success;
98 
99  for (Size i = 0; i < range->size; i += PAGESIZE)
100  if ((r = unmap(range->virt + i)) != Success)
101  break;
102 
103  return r;
104 }
105 
107 {
108  Address phys;
109  Result result = lookup(virt, &phys);
110 
111  if (result == Success)
112  m_alloc->release(phys);
113 
114  return result;
115 }
116 
118 {
119  Memory::Range r = m_map->range(region);
120  Size currentSize = 0;
121  Address addr = r.virt, currentAddr = r.virt, tmp;
122 
123  while (addr < r.virt+r.size && currentSize < size)
124  {
125  if (lookup(addr, &tmp) == InvalidAddress)
126  {
127  currentSize += PAGESIZE;
128  }
129  else
130  {
131  currentSize = 0;
132  currentAddr = addr + PAGESIZE;
133  }
134  addr += PAGESIZE;
135  }
136 
137  if (currentSize >= size)
138  {
139  *virt = currentAddr;
140  return Success;
141  }
142  else
143  return OutOfMemory;
144 }
145 
147 {
148  Result r = Success;
149 
150  for (Size i = 0; i < 8U * PAGESIZE; i += PAGESIZE)
151  {
152  r = map(m_savedRange->virt + m_numSparsePages, (*phys) + i, m_savedRange->access);
153  if (r != Success)
154  break;
155 
157  }
158 
159  assert(r == Success);
160 }
MemoryContext::m_savedRange
Memory::Range * m_savedRange
Saved range input for use in the mapRangeSparse Callback.
Definition: MemoryContext.h:239
SplitAllocator::allocate
virtual Result allocate(Range &args)
Allocate physical memory.
Definition: SplitAllocator.cpp:35
Memory::Range
Memory range.
Definition: Memory.h:55
SplitAllocator.h
MemoryContext
Virtual memory abstract interface.
Definition: MemoryContext.h:42
MemoryContext::unmapRange
virtual Result unmapRange(Memory::Range *range)
Unmaps a range of virtual memory.
Definition: MemoryContext.cpp:95
MemoryContext::MemoryContext
MemoryContext(MemoryMap *map, SplitAllocator *alloc)
Constructor.
Definition: MemoryContext.cpp:28
MemoryContext::release
virtual Result release(Address virt)
Release a memory page mapping.
Definition: MemoryContext.cpp:106
PAGESIZE
#define PAGESIZE
ARM uses 4K pages.
Definition: ARMConstant.h:97
MemoryContext::map
virtual Result map(Address virt, Address phys, Memory::Access access)=0
Map a physical page to a virtual address.
Address
unsigned long Address
A memory address.
Definition: Types.h:131
Allocator::Range::address
Address address
Starting address of the memory range.
Definition: Allocator.h:67
MemoryContext::unmap
virtual Result unmap(Address virt)=0
Unmap a virtual address.
Allocator::Range::alignment
Size alignment
Alignment in bytes or ZERO for default alignment.
Definition: Allocator.h:69
MemoryContext::InvalidAddress
@ InvalidAddress
Definition: MemoryContext.h:52
Allocator::Range::size
Size size
Amount of memory in bytes.
Definition: Allocator.h:68
SplitAllocator
Allocator which separates kernel mapped memory at virtual and physical addresses.
Definition: SplitAllocator.h:37
MemoryContext::lookup
virtual Result lookup(Address virt, Address *phys) const =0
Translate virtual address to physical address.
MemoryContext::m_mapRangeSparseCallback
Callback< MemoryContext, Address > m_mapRangeSparseCallback
Callback object for mapRangeSparseCallback function.
Definition: MemoryContext.h:236
Allocator::Success
@ Success
Definition: Allocator.h:55
Memory::Range::phys
Address phys
Physical address.
Definition: Memory.h:58
MemoryContext::Result
Result
Result codes.
Definition: MemoryContext.h:49
MemoryMap::range
Memory::Range range(Region region) const
Get memory range for the given region.
Definition: MemoryMap.cpp:36
MemoryContext::mapRangeSparseCallback
virtual void mapRangeSparseCallback(Address *phys)
Callback to provide intermediate Range object during mapRangeSparse()
Definition: MemoryContext.cpp:146
MemoryContext::Success
@ Success
Definition: MemoryContext.h:51
MemoryContext::findFree
virtual Result findFree(Size size, MemoryMap::Region region, Address *virt) const
Find unused memory.
Definition: MemoryContext.cpp:117
MemoryMap
Describes virtual memory map layout.
Definition: MemoryMap.h:38
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
MemoryMap::Region
Region
Memory regions.
Definition: MemoryMap.h:52
MemoryContext::OutOfMemory
@ OutOfMemory
Definition: MemoryContext.h:55
MemoryContext::getCurrent
static MemoryContext * getCurrent()
Get currently active MemoryContext.
Definition: MemoryContext.cpp:41
Allocator::Range
Describes a range of memory.
Definition: Allocator.h:65
MemoryContext::m_numSparsePages
Size m_numSparsePages
Number of pages allocated via mapRangeSparse Callback.
Definition: MemoryContext.h:242
assert
#define assert(exp)
Insert program diagnostics.
Definition: assert.h:60
SplitAllocator::release
virtual Result release(const Address addr)
Release memory page.
Definition: SplitAllocator.cpp:89
MemoryContext::m_current
static MemoryContext * m_current
The currently active MemoryContext.
Definition: MemoryContext.h:233
MemoryContext::~MemoryContext
virtual ~MemoryContext()
Destructor.
Definition: MemoryContext.cpp:37
Memory::Range::virt
Address virt
Virtual address.
Definition: Memory.h:57
MemoryContext.h
Memory::Range::size
Size size
Size in number of bytes.
Definition: Memory.h:59
Memory::Range::access
Access access
Page access flags.
Definition: Memory.h:60
ZERO
#define ZERO
Zero value.
Definition: Macros.h:43
MemoryContext::m_alloc
SplitAllocator * m_alloc
Physical memory allocator.
Definition: MemoryContext.h:227
MemoryContext::mapRangeContiguous
virtual Result mapRangeContiguous(Memory::Range *range)
Map a range of contiguous physical pages to virtual addresses.
Definition: MemoryContext.cpp:46
MemoryContext::mapRangeSparse
virtual Result mapRangeSparse(Memory::Range *range)
Map and allocate a range of sparse (non-contiguous) physical pages to virtual addresses.
Definition: MemoryContext.cpp:76
MemoryContext::m_map
MemoryMap * m_map
Virtual memory layout.
Definition: MemoryContext.h:230
SplitAllocator::allocateSparse
Result allocateSparse(const Range &range, CallbackFunction *function)
Allocate sparse (non-contiguous) physical memory.
Definition: SplitAllocator.cpp:40