Changeset c520034 in mainline for kernel/arch/ia32/src/mm


Ignore:
Timestamp:
2011-12-31T18:19:35Z (14 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
295f658, 77c2b02, 96cd5b4
Parents:
852052d (diff), 22f0561 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Support for kernel non-identity mappings, phase I.

  • identity/non-identity kernel memory split on all architectures
  • low/high physical memory split on all architectures
  • frame allocator understands low/high memory
  • high physical memory currently unused (Phase II)
  • more compact frame_t
  • zone conf frames, pte_t, kernel stacks allocated from low memory
  • lockless TLB-miss handlers everywhere (newly sparc64, ia64)
  • preallocate PTL1 page tables for non-identity and prevent their deallocation
  • hw_map() unification
  • new resource allocator used for allocating kernel virtual addresses

Breakage:

  • sparc64/sun4v creates too large kernel identity; not fixed because of lack of testing hw
  • ppc32's tlb_refill() seems wrong as it creates too large kernel identity, but appears unused and the architecture works normally

Not implemented yet (phase II):

  • allow high memory to be used for common kernel allocations
Location:
kernel/arch/ia32/src/mm
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/ia32/src/mm/frame.c

    r852052d rc520034  
    4646#include <print.h>
    4747
    48 #define PHYSMEM_LIMIT32  UINT64_C(0x07c000000)
    49 #define PHYSMEM_LIMIT64  UINT64_C(0x200000000)
    50 
    5148size_t hardcoded_unmapped_ktext_size = 0;
    5249size_t hardcoded_unmapped_kdata_size = 0;
    5350
    54 uintptr_t last_frame = 0;
    55 
    56 static void init_e820_memory(pfn_t minconf)
     51static void init_e820_memory(pfn_t minconf, bool low)
    5752{
    5853        unsigned int i;
    5954       
    6055        for (i = 0; i < e820counter; i++) {
    61                 uint64_t base = e820table[i].base_address;
    62                 uint64_t size = e820table[i].size;
     56                uintptr_t base = (uintptr_t) e820table[i].base_address;
     57                size_t size = (size_t) e820table[i].size;
    6358               
    64 #ifdef __32_BITS__
    65                 /*
    66                  * XXX FIXME:
    67                  *
    68                  * Ignore zones which start above PHYSMEM_LIMIT32
    69                  * or clip zones which go beyond PHYSMEM_LIMIT32.
    70                  *
    71                  * The PHYSMEM_LIMIT32 (2 GB - 64 MB) is a rather
    72                  * arbitrary constant which allows to have at
    73                  * least 64 MB in the kernel address space to
    74                  * map hardware resources.
    75                  *
    76                  * The kernel uses fixed 1:1 identity mapping
    77                  * of the physical memory with 2:2 GB split.
    78                  * This is a severe limitation of the current
    79                  * kernel memory management.
    80                  *
    81                  */
    82                
    83                 if (base > PHYSMEM_LIMIT32)
     59                if (!frame_adjust_zone_bounds(low, &base, &size))
    8460                        continue;
    85                
    86                 if (base + size > PHYSMEM_LIMIT32)
    87                         size = PHYSMEM_LIMIT32 - base;
    88 #endif
    89                
    90 #ifdef __64_BITS__
    91                 /*
    92                  * XXX FIXME:
    93                  *
    94                  * Ignore zones which start above PHYSMEM_LIMIT64
    95                  * or clip zones which go beyond PHYSMEM_LIMIT64.
    96                  *
    97                  * The PHYSMEM_LIMIT64 (8 GB) is the size of the
    98                  * fixed 1:1 identically mapped physical memory
    99                  * accessible during the bootstrap process.
    100                  * This is a severe limitation of the current
    101                  * kernel memory management.
    102                  *
    103                  */
    104                
    105                 if (base > PHYSMEM_LIMIT64)
    106                         continue;
    107                
    108                 if (base + size > PHYSMEM_LIMIT64)
    109                         size = PHYSMEM_LIMIT64 - base;
    110 #endif
    11161               
    11262                if (e820table[i].type == MEMMAP_MEMORY_AVAILABLE) {
     
    11666                            FRAME_SIZE);
    11767                       
     68                        size_t count = SIZE2FRAMES(new_size);
    11869                        pfn_t pfn = ADDR2PFN(new_base);
    119                         size_t count = SIZE2FRAMES(new_size);
     70                        pfn_t conf;
    12071                       
    121                         pfn_t conf;
    122                         if ((minconf < pfn) || (minconf >= pfn + count))
    123                                 conf = pfn;
    124                         else
    125                                 conf = minconf;
    126                        
    127                         zone_create(pfn, count, conf, ZONE_AVAILABLE);
    128                        
    129                         // XXX this has to be removed
    130                         if (last_frame < ALIGN_UP(new_base + new_size, FRAME_SIZE))
    131                                 last_frame = ALIGN_UP(new_base + new_size, FRAME_SIZE);
     72                        if (low) {
     73                                if ((minconf < pfn) || (minconf >= pfn + count))
     74                                        conf = pfn;
     75                                else
     76                                        conf = minconf;
     77                                zone_create(pfn, count, conf,
     78                                    ZONE_AVAILABLE | ZONE_LOWMEM);
     79                        } else {
     80                                conf = zone_external_conf_alloc(count);
     81                                zone_create(pfn, count, conf,
     82                                    ZONE_AVAILABLE | ZONE_HIGHMEM);
     83                        }
    13284                } else if ((e820table[i].type == MEMMAP_MEMORY_ACPI) ||
    13385                    (e820table[i].type == MEMMAP_MEMORY_NVS)) {
     
    179131
    180132
    181 void frame_arch_init(void)
     133void frame_low_arch_init(void)
    182134{
    183135        pfn_t minconf;
     
    192144#endif
    193145               
    194                 init_e820_memory(minconf);
     146                init_e820_memory(minconf, true);
    195147               
    196148                /* Reserve frame 0 (BIOS data) */
     
    206158}
    207159
     160void frame_high_arch_init(void)
     161{
     162        if (config.cpu_active == 1)
     163                init_e820_memory(0, false);
     164}
     165
    208166/** @}
    209167 */
  • kernel/arch/ia32/src/mm/page.c

    r852052d rc520034  
    4949#include <print.h>
    5050#include <interrupt.h>
     51#include <macros.h>
    5152
    5253void page_arch_init(void)
     
    5556        int flags;
    5657       
    57         if (config.cpu_active == 1) {
    58                 page_mapping_operations = &pt_mapping_operations;
     58        if (config.cpu_active > 1) {
     59                /* Fast path for non-boot CPUs */
     60                write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
     61                paging_on();
     62                return;
     63        }
     64
     65        page_mapping_operations = &pt_mapping_operations;
    5966       
    60                 /*
    61                  * PA2KA(identity) mapping for all frames until last_frame.
    62                  */
    63                 page_table_lock(AS_KERNEL, true);
    64                 for (cur = 0; cur < last_frame; cur += FRAME_SIZE) {
    65                         flags = PAGE_CACHEABLE | PAGE_WRITE;
    66                         if ((PA2KA(cur) >= config.base) && (PA2KA(cur) < config.base + config.kernel_size))
    67                                 flags |= PAGE_GLOBAL;
    68                         page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
    69                 }
    70                 page_table_unlock(AS_KERNEL, true);
     67        /*
     68         * PA2KA(identity) mapping for all low-memory frames.
     69         */
     70        page_table_lock(AS_KERNEL, true);
     71        for (cur = 0; cur < min(config.identity_size, config.physmem_end);
     72            cur += FRAME_SIZE) {
     73                flags = PAGE_CACHEABLE | PAGE_WRITE;
     74                if ((PA2KA(cur) >= config.base) &&
     75                    (PA2KA(cur) < config.base + config.kernel_size))
     76                        flags |= PAGE_GLOBAL;
     77                page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
     78        }
     79        page_table_unlock(AS_KERNEL, true);
    7180               
    72                 exc_register(14, "page_fault", true, (iroutine_t) page_fault);
    73                 write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
    74         } else
    75                 write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
     81        exc_register(14, "page_fault", true, (iroutine_t) page_fault);
     82        write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
    7683       
    7784        paging_on();
    78 }
    79 
    80 
    81 uintptr_t hw_map(uintptr_t physaddr, size_t size)
    82 {
    83         if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH))
    84                 panic("Unable to map physical memory %p (%zu bytes).",
    85                     (void *) physaddr, size);
    86        
    87         uintptr_t virtaddr = PA2KA(last_frame);
    88         pfn_t i;
    89         page_table_lock(AS_KERNEL, true);
    90         for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++) {
    91                 uintptr_t addr = PFN2ADDR(i);
    92                 page_mapping_insert(AS_KERNEL, virtaddr + addr, physaddr + addr, PAGE_NOT_CACHEABLE | PAGE_WRITE);
    93         }
    94         page_table_unlock(AS_KERNEL, true);
    95        
    96         last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE);
    97        
    98         return virtaddr;
    9985}
    10086
Note: See TracChangeset for help on using the changeset viewer.