//
// This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of
-// this software and associated documentation files (the "Software"), to deal with
-// the Software without restriction, including without limitation the rights to
-// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-// of the Software, and to permit persons to whom the Software is furnished to do
-// so, subject to the following conditions:
+// This software is provided 'as-is', without any express or implied warranty.
+// In no event will the authors or contributors be held liable for any damages
+// arising from the use of this software.
//
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimers.
-//
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimers in the
-// documentation and/or other materials provided with the distribution.
-//
-// * The names of the Software's authors and/or contributors
-// may not be used to endorse or promote products derived from
-// this Software without specific prior written permission.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
-// SOFTWARE.
+// Permission is hereby granted to everyone, free of charge, to use, copy,
+// modify, prepare derivative works of, publish, distribute, perform,
+// sublicense, and/or sell copies of the Software, provided that the above
+// copyright notice and disclaimer of warranty be included in all copies or
+// substantial portions of this software.
#include <kern/mem.h>
#include <kern/paging.h>
+#include <kern/generic-pagetable.h>
#include <kern/pagetable.h>
#include <kern/pagealloc.h>
#include <kern/generic-pte.h>
#include <kern/compiler.h>
+#include <kern/process.h>
+#include <kern/thread.h>
extern int roshared_start, roshared_page_end;
extern int rwshared_start, rwshared_page_end;
void create(Object *obj)
{
- *obj = static_cast<IAddrSpace>(*(new AddrSpace(false)));
+ *obj = static_cast<IAddrSpace>(*(new AddrSpace));
}
};
void create(Object *obj)
{
- AddrSpace *as = new AddrSpace(true);
+ AddrSpace *as = new ProcAddrSpace;
Region region;
MapFlags mf = 0;
u64 vstart;
mf.access_IDLNS_Read = 1;
mf.access_IDLNS_Exec = 1;
- as->map(physmem, region, &vstart, mf, AddrSpace::map_protected);
+ as->map(physmem, region, &vstart, mf,
+ PTEFlags::protectedmap | PTEFlags::addressonly);
region.start = kvirt_to_phys(&rwshared_start);
region.end = kvirt_to_phys(&rwshared_page_end);
mf.access_IDLNS_Write = 1;
mf.CopyOnWrite = 1;
- as->map(physmem, region, &vstart, mf, AddrSpace::map_protected);
+ as->map(physmem, region, &vstart, mf,
+ PTEFlags::protectedmap | PTEFlags::addressonly);
// Leave the stack no-exec by default.
region.start = vstart = Arch::stack_bottom;
region.end = Arch::stack_top;
mf.CopyOnWrite = 0;
- printf("vstart %llx\n", vstart);
as->map(anonmem, region, &vstart, mf);
- *obj = static_cast<IAddrSpace>(*(as));
+ *obj = static_cast<IAddrSpace>(*as);
}
};
AddrSpaceFactory real_addrspace_factory;
Factory addr_space_factory = real_addrspace_factory;
- AddrSpace::AddrSpace(bool process) : mappable(this)
+ AddrSpace::AddrSpace(PageTable *ptbl) : mappable(this)
{
init_iface();
- is_process = process;
+ is_process = false;
+ page_table = ptbl;
- // OPT: Allow optional use of the native PTE for stacked aspaces,
- // either because the native PTE is 64-bit, or because it's an
- // embedded system which does not need 64-bit storage.
-
- if (process)
- page_table = new PageTableImpl<Arch::PTE>(true);
- else
+ if (!ptbl)
page_table = new PageTableImpl<GenPTE>(false);
cached_free_region = Arch::user_start + Arch::page_size;
}
+ ProcAddrSpace::ProcAddrSpace() :
+ AddrSpace(new PageTableImpl<Arch::PTE>(true))
+ {
+ is_process = true;
+ }
+
// This should only be used once during bootup to initialize the
// kernel's address space with a static initial page table.
- AddrSpace::AddrSpace(void *ptbl_toplevel) : mappable(this)
+ ProcAddrSpace::ProcAddrSpace(void *ptbl_toplevel) :
+ AddrSpace(new PageTableImpl<Arch::PTE>(ptbl_toplevel))
{
- init_iface();
+ // FIXME: set cached_free_region to kernel virtual space
is_process = true;
- page_table = new PageTableImpl<Arch::PTE>(ptbl_toplevel);
-
- // FIXME: should be kernel virtual space
- cached_free_region = Arch::user_start + Arch::page_size;
}
void AddrSpace::get_mappable(IMappable *ma)
*addrspace = NULL;
}
- bool AddrSpace::handle_fault(ulong vaddr, bool write, bool exec, bool user)
+ int AddrSpace::handle_fault(ulong vaddr, bool write, bool exec, bool user)
{
if (lock.held_by_curthread())
return false;
}
catch (BadPageFault &bpf) {
- // FIXME: retain info about nature of bpf
- // to throw to user?
- return false;
+ return bpf.cause;
}
- return true;
+ return -1;
}
bool AddrSpace::check_overlap(Region region, VirtualArea *&va)
VirtualArea *va = aspace->varea_tree.find(vaddr);
if (!va)
- throw BadPageFault();
+ throw BadPageFault(MemoryFault_ns::Cause::Unmapped);
if ((va->flags & reqflags) != reqflags)
- throw BadPageFault();
+ throw BadPageFault(MemoryFault_ns::Cause::Protected);
if (aspace->map(va, vaddr, reqflags))
break;
}
void AddrSpace::map(IMappable ma, Region region, u64 *vstart,
- MapFlags mflags, int map_type)
+ MapFlags mflags, PTEFlags set, PTEFlags clear)
{
// FIXME: check alignment for VIPT caches
// FIXME: Implement the "Replace" map flag
if (mflags.Replace)
throw_idl(InvalidArgument, 3,
- countarray("Replace unimplemented"));
+ countarray<ORBMM>("Replace unimplemented"));
Mappable *cma = Mappable::classptr(ma);
if (!cma) {
mflags.Fixed = 1;
if (!page_aligned(region.start))
- throw_idl(InvalidArgument, 1, countarray("unaligned start"));
+ throw_idl(InvalidArgument, 1, countarray<ORBMM>("unaligned start"));
if (!page_aligned(region.end + 1))
- throw_idl(InvalidArgument, 1, countarray("unaligned end"));
+ throw_idl(InvalidArgument, 1, countarray<ORBMM>("unaligned end"));
Lock::AutoLock autolock(lock);
Region vregion;
if (is_process) {
if (!valid_addr(vregion.start))
throw_idl(InvalidArgument, 2,
- countarray("invalid virtual start"));
+ countarray<ORBMM>("invalid virtual start"));
if (!valid_addr(vregion.end))
throw_idl(InvalidArgument, 2,
- countarray("invalid virtual end"));
+ countarray<ORBMM>("invalid virtual end"));
}
if (check_overlap(vregion, prev))
if (*vstart == System::Mem::AddrSpace_ns::unspecified_start) {
if (fixed)
- throw_idl(ResourceBusy, 2, countarray("varea overlap"));
+ throw_idl(ResourceBusy, 2, countarray<ORBMM>("varea overlap"));
if (!get_free_region(region.end - region.start + 1, vregion, prev))
- throw_idl(OutOfSpace, countarray("out of vspace"));
+ throw_idl(OutOfSpace, countarray<ORBMM>("out of vspace"));
*vstart = vregion.start;
}
newva->region() = vregion;
newva->flags.Valid = 1;
- newva->flags.User = map_type != map_kernel;
+ newva->flags.User = 1;
newva->flags.Readable = mflags.access_IDLNS_Read;
newva->flags.Writeable = mflags.access_IDLNS_Write;
newva->flags.Executable = mflags.access_IDLNS_Exec;
newva->flags.FaultOnWrite = mflags.CopyOnWrite;
- newva->flags.Protected = map_type != map_user;
+ newva->flags.raw |= set;
+ newva->flags.raw &= ~clear;
newva->ma = cma;
newva->offset = region.start - vregion.start;
{
*min_align = Arch::page_mapping_min_align;
}
+
+ void AddrSpace::get_size(u64 *size)
+ {
+ page_table->get_size(size);
+ }
void Mappable::map(VirtualArea *varea)
{
oldpage->release();
}
- // FIXME: Add a special PTE flag to indicate that PhysMem mappings
- // don't mess with page refcounts.
-
class PhysMem : public Mappable {
public:
void get_size(u64 *size)
void pagein(u64 vaddr, PTEFlags reqflags)
{
- // Doesn't need to do anything yet, though it may later
- // once high memory support is added.
}
void get_mapping(u64 addr, u64 *phys, PTEFlags *flags)
flags->Writeable = 1;
flags->Executable = 1;
flags->User = 1;
+ flags->AddressOnly = 1;
}
};
void pagein(u64 vaddr, PTEFlags reqflags)
{
- // Doesn't need to do anything yet, though it may later
- // once high memory support is added.
}
void get_mapping(u64 addr, u64 *phys, PTEFlags *flags)