FreeNOS
VMCtl.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 #include <FreeNOS/System.h>
19 #include <FreeNOS/ProcessManager.h>
20 #include <SplitAllocator.h>
21 #include "VMCtl.h"
22 #include "ProcessID.h"
23 
25  const MemoryOperation op,
26  Memory::Range *range)
27 {
31  Process *proc = ZERO;
32 
33  DEBUG("");
34 
35  // Find the given process
36  if (procID == SELF)
37  proc = procs->current();
38  else if (!(proc = procs->get(procID)))
39  {
40  return API::NotFound;
41  }
42 
43  // Retrieve memory context
44  MemoryContext *mem = proc->getMemoryContext();
45 
46  // Perform operation
47  switch (op)
48  {
49  case LookupVirtual:
50  // Translate virtual address to physical address (page boundary)
51  memResult = mem->lookup(range->virt, &range->phys);
52  if (memResult != MemoryContext::Success)
53  {
54  ERROR("failed to lookup virtual address " << (void *) range->virt <<
55  ": " << (int) memResult);
56  return API::AccessViolation;
57  }
58  assert(!(range->phys & ~PAGEMASK));
59 
60  // Add offset within the page
61  range->phys += range->virt & ~PAGEMASK;
62  break;
63 
64  case MapContiguous:
65  case MapSparse:
66  if (!range->virt)
67  {
68  memResult = mem->findFree(range->size, MemoryMap::UserPrivate, &range->virt);
69  if (memResult != MemoryContext::Success)
70  {
71  ERROR("failed to find free virtual address in UserPrivate: " <<
72  (int) memResult);
73  return API::IOError;
74  }
75  range->virt += range->phys & ~PAGEMASK;
76  }
77  if (op == MapContiguous)
78  memResult = mem->mapRangeContiguous(range);
79  else
80  memResult = mem->mapRangeSparse(range);
81 
82  if (memResult != MemoryContext::Success)
83  {
84  ERROR("failed to map memory range " << (void *)range->virt << "->" <<
85  (void *) range->phys << ": " << (int) memResult);
86  return API::IOError;
87  }
88  break;
89 
90  case UnMap:
91  memResult = mem->unmapRange(range);
92  if (memResult != MemoryContext::Success)
93  {
94  ERROR("failed to unmap range at virtual address " << (void *)range->virt <<
95  ": " << (int) memResult);
96  return API::IOError;
97  }
98  break;
99 
100  case Release:
101  memResult = mem->releaseRange(range);
102  if (memResult != MemoryContext::Success)
103  {
104  ERROR("failed to release range at virtual address " << (void *)range->virt <<
105  ": " << (int) memResult);
106  return API::IOError;
107  }
108  break;
109 
110  case ReleaseSections:
111  memResult = mem->releaseSection(*range);
112  if (memResult != MemoryContext::Success)
113  {
114  ERROR("failed to release sections at virtual address " << (void *)range->virt <<
115  ": " << (int) memResult);
116  return API::IOError;
117  }
118  break;
119 
120  case CacheClean: {
121  Arch::Cache cache;
122  cache.cleanData(range->virt);
123  break;
124  }
125 
126  case CacheInvalidate: {
127  Arch::Cache cache;
128  const Cache::Result r = cache.invalidateAddress(Cache::Data, range->virt);
129  if (r != Cache::Success)
130  {
131  ERROR("failed to invalidate cache at address " << (void *) range->virt <<
132  ": result = " << (int) r);
133  return API::IOError;
134  }
135  break;
136  }
137 
138  case CacheCleanInvalidate: {
139  Arch::Cache cache;
141  break;
142  }
143 
144  case Access: {
145  const MemoryContext::Result mr = mem->access(range->virt, &range->access);
146  if (mr == MemoryContext::Success)
147  ret = API::Success;
148  else
149  ret = API::AccessViolation;
150  break;
151  }
152 
153  case ReserveMem:
154  {
157 
158  for (Size i = 0; i < range->size; i += PAGESIZE)
159  {
160  const Address addr = range->phys + i;
161 
162  if (alloc->isAllocated(addr))
163  {
164  ERROR("address " << (void *)addr << " is already allocated");
165  return API::InvalidArgument;
166  }
167  else if ((allocResult = alloc->allocate(addr)) != Allocator::Success)
168  {
169  ERROR("failed to allocate " << (void *)addr << ", result = " << (int)allocResult);
170  return API::IOError;
171  }
172  }
173  break;
174  }
175 
176  default:
177  ret = API::InvalidArgument;
178  break;
179  }
180 
181  // Done
182  return ret;
183 }
ARMCacheV6::cleanInvalidate
virtual Result cleanInvalidate(Type type)
Clean and invalidate entire cache.
Definition: ARMCacheV6.cpp:41
SplitAllocator::allocate
virtual Result allocate(Range &args)
Allocate physical memory.
Definition: SplitAllocator.cpp:35
Memory::Range
Memory range.
Definition: Memory.h:55
SplitAllocator.h
ProcessManager
Represents a process which may run on the host.
Definition: ProcessManager.h:44
MemoryContext
Virtual memory abstract interface.
Definition: MemoryContext.h:42
API::Result
Result
Enumeration of generic kernel API result codes.
Definition: API.h:68
CacheClean
@ CacheClean
Definition: VMCtl.h:46
MemoryContext::unmapRange
virtual Result unmapRange(Memory::Range *range)
Unmaps a range of virtual memory.
Definition: MemoryContext.cpp:95
MemoryContext::access
virtual Result access(Address virt, Memory::Access *access) const =0
Get Access flags for a virtual address.
MapSparse
@ MapSparse
Definition: VMCtl.h:38
MemoryContext::releaseRange
virtual Result releaseRange(Memory::Range *range)=0
Release a range of physical memory by its virtual memory pages.
Process
Represents a process which may run on the host.
Definition: Process.h:44
API::InvalidArgument
@ InvalidArgument
Definition: API.h:74
PAGEMASK
#define PAGEMASK
Mask to find the page.
Definition: ARMConstant.h:121
PAGESIZE
#define PAGESIZE
ARM uses 4K pages.
Definition: ARMConstant.h:97
ProcessID.h
API::AccessViolation
@ AccessViolation
Definition: API.h:71
Cache::Data
@ Data
Definition: Cache.h:56
ProcessID
u32 ProcessID
Process Identification Number.
Definition: Types.h:140
Address
unsigned long Address
A memory address.
Definition: Types.h:131
Kernel::getAllocator
SplitAllocator * getAllocator()
Get physical memory allocator.
Definition: Kernel.cpp:138
CacheInvalidate
@ CacheInvalidate
Definition: VMCtl.h:47
Cache::Success
@ Success
Definition: Cache.h:44
UnMap
@ UnMap
Definition: VMCtl.h:39
Kernel::getProcessManager
ProcessManager * getProcessManager()
Get process manager.
Definition: Kernel.cpp:143
CacheCleanInvalidate
@ CacheCleanInvalidate
Definition: VMCtl.h:48
API::IOError
@ IOError
Definition: API.h:76
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.
SELF
#define SELF
Definition: ProcessID.h:35
DEBUG
#define DEBUG(msg)
Output a debug message to standard output.
Definition: Log.h:89
Process::getMemoryContext
MemoryContext * getMemoryContext()
Get MMU memory context.
Definition: Process.cpp:95
Release
@ Release
Definition: VMCtl.h:40
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
ARMCacheV6
ARMv6 cache management implementation.
Definition: ARMCacheV6.h:42
Access
@ Access
Definition: VMCtl.h:43
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
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
WeakSingleton< Kernel >::instance
static Kernel * instance()
Retrieve the instance.
Definition: Singleton.h:86
Cache::cleanData
virtual Result cleanData(Address addr)
Clean one data page.
Definition: Cache.cpp:20
MemoryMap::UserPrivate
@ UserPrivate
< User private dynamic memory mappings
Definition: MemoryMap.h:59
ProcessManager::get
Process * get(const ProcessID id)
Retrieve a Process by it's ID.
Definition: ProcessManager.cpp:95
LookupVirtual
@ LookupVirtual
Definition: VMCtl.h:42
ARMCacheV6::invalidateAddress
virtual Result invalidateAddress(Type type, Address addr)
Invalidate one memory page.
Definition: ARMCacheV6.cpp:113
MemoryOperation
MemoryOperation
Memory operations which may be used as an argument to VMCtl().
Definition: VMCtl.h:35
VMCtlHandler
API::Result VMCtlHandler(const ProcessID procID, const MemoryOperation op, Memory::Range *range)
Kernel handler prototype.
Definition: VMCtl.cpp:24
API::NotFound
@ NotFound
Definition: API.h:73
assert
#define assert(exp)
Insert program diagnostics.
Definition: assert.h:60
ERROR
#define ERROR(msg)
Output an error message.
Definition: Log.h:61
ReleaseSections
@ ReleaseSections
Definition: VMCtl.h:41
API::Success
@ Success
Definition: API.h:70
Cache::Result
Result
Result codes.
Definition: Cache.h:42
Memory::Range::virt
Address virt
Virtual address.
Definition: Memory.h:57
Memory::Range::size
Size size
Size in number of bytes.
Definition: Memory.h:59
ProcessManager::current
Process * current()
Current process running.
Definition: ProcessManager.cpp:203
VMCtl.h
MemoryContext::releaseSection
virtual Result releaseSection(const Memory::Range &range, const bool tablesOnly=false)=0
Release memory sections.
Memory::Range::access
Access access
Page access flags.
Definition: Memory.h:60
ZERO
#define ZERO
Zero value.
Definition: Macros.h:43
MapContiguous
@ MapContiguous
Definition: VMCtl.h:37
SplitAllocator::isAllocated
bool isAllocated(const Address page) const
Check if a physical page is allocated.
Definition: SplitAllocator.cpp:106
ReserveMem
@ ReserveMem
Definition: VMCtl.h:44
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
Allocator::Result
Result
Allocation results.
Definition: Allocator.h:53