X-Git-Url: http://git.buserror.net/cgi-bin/gitweb.cgi?p=polintos%2Fscott%2Fpriv.git;a=blobdiff_plain;f=kernel%2Fmem%2Faddrspace.cc;h=20a46fb04d09c6997e87ee2669e94cabefb494b6;hp=324421f7f2b1f7fd1be271fb7f6c210c662cdb29;hb=b4bfc871337ca32ce83407916a87db2524729ca9;hpb=7da27a216a7f4bb3331fe315cdbec69bfcf2c762 diff --git a/kernel/mem/addrspace.cc b/kernel/mem/addrspace.cc index 324421f..20a46fb 100644 --- a/kernel/mem/addrspace.cc +++ b/kernel/mem/addrspace.cc @@ -9,34 +9,19 @@ // // This software is copyright (c) 2006 Scott Wood . // -// 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 #include +#include #include #include #include @@ -46,7 +31,7 @@ extern int roshared_start, roshared_page_end; extern int rwshared_start, rwshared_page_end; namespace Mem { - extern IMappable physmem; + extern IMappable physmem, anonmem; class AddrSpaceFactory { public: @@ -59,7 +44,7 @@ namespace Mem { void create(Object *obj) { - *obj = static_cast(*(new AddrSpace(false))); + *obj = static_cast(*(new AddrSpace)); } }; @@ -74,7 +59,7 @@ namespace Mem { void create(Object *obj) { - AddrSpace *as = new AddrSpace(true); + AddrSpace *as = new ProcAddrSpace; Region region; MapFlags mf = 0; u64 vstart; @@ -86,8 +71,7 @@ namespace Mem { mf.access_IDLNS_Read = 1; mf.access_IDLNS_Exec = 1; - as->map(physmem, region, &vstart, mf, - true, AddrSpace::map_protected); + as->map(physmem, region, &vstart, mf, AddrSpace::map_protected); region.start = kvirt_to_phys(&rwshared_start); region.end = kvirt_to_phys(&rwshared_page_end); @@ -96,14 +80,16 @@ namespace Mem { mf.access_IDLNS_Write = 1; mf.CopyOnWrite = 1; - as->map(physmem, region, &vstart, mf, - true, AddrSpace::map_protected); + as->map(physmem, region, &vstart, mf, AddrSpace::map_protected); - AllocFlags af = 0; - vstart = Arch::stack_bottom; - as->alloc_and_map(Arch::stack_top - vstart + 1, &vstart, af, mf); + // 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(*(as)); + *obj = static_cast(*as); } }; @@ -113,34 +99,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(true); - else + if (!ptbl) page_table = new PageTableImpl(false); cached_free_region = Arch::user_start + Arch::page_size; } + ProcAddrSpace::ProcAddrSpace() : + AddrSpace(new PageTableImpl(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(ptbl_toplevel)) { - init_iface(); + // FIXME: set cached_free_region to kernel virtual space is_process = true; - page_table = new PageTableImpl(ptbl_toplevel); - - // FIXME: should be kernel virtual space - cached_free_region = Arch::user_start + Arch::page_size; } void AddrSpace::get_mappable(IMappable *ma) @@ -154,12 +138,6 @@ namespace Mem { *addrspace = NULL; } - void AddrSpace::alloc_and_map(u64 len, u64 *vstart, - AllocFlags aflags, MapFlags mflags) - { - // FIXME: implement - } - bool AddrSpace::handle_fault(ulong vaddr, bool write, bool exec, bool user) { if (lock.held_by_curthread()) @@ -499,9 +477,9 @@ namespace Mem { new_page->release(); } - void ASpaceMappable::get_entry(u64 vaddr, u64 *phys, PTEFlags *flags) + void ASpaceMappable::get_mapping(u64 vaddr, u64 *phys, PTEFlags *flags) { - aspace->page_table->get_entry(vaddr, phys, flags); + aspace->page_table->get_mapping(vaddr, phys, flags); } bool AddrSpace::map(VirtualArea *va, u64 vaddr, PTEFlags reqflags) @@ -511,7 +489,7 @@ namespace Mem { u64 phys; PTEFlags flags; - va->ma->get_entry(vaddr + va->offset, &phys, &flags); + va->ma->get_mapping(vaddr + va->offset, &phys, &flags); PTEFlags newflags = flags & va->flags; newflags.FaultOnWrite = flags.FaultOnWrite | va->flags.FaultOnWrite; @@ -526,7 +504,7 @@ namespace Mem { u64 oldphys; PTEFlags oldflags; - page_table->get_entry(vaddr, &oldphys, &oldflags); + page_table->get_mapping(vaddr, &oldphys, &oldflags); if (oldflags.Valid && !(reqflags.Writeable && oldflags.FaultOnWrite)) @@ -542,6 +520,7 @@ namespace Mem { // gets its copy-on-write broken. assert((oldflags & reqflags) == reqflags); + assert(!va->flags.FaultOnWrite || oldphys == phys); return true; } @@ -580,7 +559,7 @@ namespace Mem { } void AddrSpace::map(IMappable ma, Region region, u64 *vstart, - MapFlags mflags, bool from_kernel, int map_type) + MapFlags mflags, int map_type) { // FIXME: check alignment for VIPT caches // FIXME: Implement the "Replace" map flag @@ -614,7 +593,7 @@ namespace Mem { if (*vstart != System::Mem::AddrSpace_ns::unspecified_start) { vregion.start = *vstart; - vregion.end = vregion.start + region.end - region.start + 1; + vregion.end = vregion.start + region.end - region.start; if (is_process) { if (!valid_addr(vregion.start)) @@ -631,7 +610,7 @@ namespace Mem { } if (*vstart == System::Mem::AddrSpace_ns::unspecified_start) { - if (fixed) + if (fixed) throw_idl(ResourceBusy, 2, countarray("varea overlap")); if (!get_free_region(region.end - region.start + 1, vregion, prev)) @@ -769,6 +748,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) { @@ -822,11 +806,9 @@ 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_entry(u64 addr, u64 *phys, PTEFlags *flags) + void get_mapping(u64 addr, u64 *phys, PTEFlags *flags) { *phys = addr; *flags = 0; @@ -840,6 +822,43 @@ namespace Mem { PhysMem real_physmem; IMappable physmem = real_physmem; + + class AnonMem : public Mappable { + public: + void get_size(u64 *size) + { + if (sizeof(long) == 8) + *size = 1ULL << (64 - Arch::page_shift); + else + *size = 1ULL << (32 - Arch::page_shift); + } + + void pagein(u64 vaddr, PTEFlags reqflags) + { + } + + void get_mapping(u64 addr, u64 *phys, PTEFlags *flags) + { + Page *page = PageAlloc::alloc(1); + + // OPT: Only zero if it was asked for. + // OPT: Eventually, have separate pagelists for zeroed and + // unzeroed memory, and a low-priority background thread + // that zeroes pages and moves them to the zeroed list. + bzero(page_to_kvirt(page), Arch::page_size); + + *phys = page_to_phys(page); + *flags = 0; + flags->Valid = 1; + flags->Readable = 1; + flags->Writeable = 1; + flags->Executable = 1; + flags->User = 1; + } + }; + + AnonMem real_anonmem; + IMappable anonmem = real_anonmem; } #include