]> git.buserror.net Git - polintos/scott/priv.git/blobdiff - kernel/mem/addrspace.cc
update
[polintos/scott/priv.git] / kernel / mem / addrspace.cc
index f014c5458c621d97b08a5efe3787d342852dd533..78cbe5e6b573aa5c2429fcbd70ee5392cf478d9b 100644 (file)
@@ -9,38 +9,25 @@
 //
 // 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;
@@ -59,7 +46,7 @@ namespace Mem {
                
                void create(Object *obj)
                {
-                       *obj = static_cast<IAddrSpace>(*(new AddrSpace(false)));
+                       *obj = static_cast<IAddrSpace>(*(new AddrSpace));
                }
        };
 
@@ -74,7 +61,7 @@ namespace Mem {
                
                void create(Object *obj)
                {
-                       AddrSpace *as = new AddrSpace(true);
+                       AddrSpace *as = new ProcAddrSpace;
                        Region region;
                        MapFlags mf = 0;
                        u64 vstart;
@@ -86,7 +73,8 @@ namespace Mem {
                        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);
@@ -95,16 +83,16 @@ namespace Mem {
                        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);
                }
        };
        
@@ -114,34 +102,32 @@ namespace Mem {
        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)
@@ -155,7 +141,7 @@ namespace Mem {
                *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;
@@ -180,12 +166,10 @@ namespace Mem {
                }
 
                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)
@@ -424,10 +408,10 @@ namespace Mem {
                        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;
@@ -576,7 +560,7 @@ namespace Mem {
        }
        
        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
@@ -641,12 +625,13 @@ namespace Mem {
                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;
 
@@ -765,6 +750,11 @@ namespace Mem {
        {
                *min_align = Arch::page_mapping_min_align;
        }
+
+       void AddrSpace::get_size(u64 *size)
+       {
+               page_table->get_size(size);
+       }
        
        void Mappable::map(VirtualArea *varea)
        {
@@ -803,9 +793,6 @@ namespace Mem {
                        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)
@@ -818,8 +805,6 @@ namespace Mem {
        
                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)
@@ -831,6 +816,7 @@ namespace Mem {
                        flags->Writeable = 1;
                        flags->Executable = 1;
                        flags->User = 1;
+                       flags->AddressOnly = 1;
                }
        };
        
@@ -849,8 +835,6 @@ namespace Mem {
        
                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)