Changes in / [1761268:7aaed09] in mainline


Ignore:
Files:
31 added
66 edited

Legend:

Unmodified
Added
Removed
  • kernel/Makefile

    r1761268 r7aaed09  
    229229        generic/src/syscall/syscall.c \
    230230        generic/src/syscall/copy.c \
     231        generic/src/mm/km.c \
    231232        generic/src/mm/reserve.c \
    232233        generic/src/mm/buddy.c \
     
    245246        generic/src/lib/str.c \
    246247        generic/src/lib/elf.c \
     248        generic/src/lib/ra.c \
    247249        generic/src/lib/rd.c \
    248250        generic/src/printf/printf_core.c \
  • kernel/arch/abs32le/Makefile.inc

    r1761268 r7aaed09  
    5757        arch/$(KARCH)/src/smp/smp.c \
    5858        arch/$(KARCH)/src/smp/ipi.c \
     59        arch/$(KARCH)/src/mm/km.c \
    5960        arch/$(KARCH)/src/mm/as.c \
    6061        arch/$(KARCH)/src/mm/frame.c \
  • kernel/arch/abs32le/include/mm/frame.h

    r1761268 r7aaed09  
    4141#include <typedefs.h>
    4242
    43 extern void frame_arch_init(void);
     43extern void frame_low_arch_init(void);
     44extern void frame_high_arch_init(void);
    4445extern void physmem_print(void);
    4546
  • kernel/arch/abs32le/src/mm/frame.c

    r1761268 r7aaed09  
    5050
    5151
    52 void frame_arch_init(void)
     52void frame_low_arch_init(void)
     53{
     54}
     55
     56void frame_high_arch_init(void)
    5357{
    5458}
  • kernel/arch/abs32le/src/mm/page.c

    r1761268 r7aaed09  
    5656}
    5757
    58 
    59 uintptr_t hw_map(uintptr_t physaddr, size_t size)
    60 {
    61         return physaddr;
    62 }
    63 
    6458void page_fault(unsigned int n __attribute__((unused)), istate_t *istate)
    6559{
  • kernel/arch/amd64/Makefile.inc

    r1761268 r7aaed09  
    8686        arch/$(KARCH)/src/bios/bios.c \
    8787        arch/$(KARCH)/src/interrupt.c \
     88        arch/$(KARCH)/src/mm/km.c \
    8889        arch/$(KARCH)/src/mm/as.c \
    8990        arch/$(KARCH)/src/mm/frame.c \
  • kernel/arch/amd64/include/mm/frame.h

    r1761268 r7aaed09  
    4343#include <typedefs.h>
    4444
    45 extern uintptr_t last_frame;
    46 extern void frame_arch_init(void);
     45extern void frame_low_arch_init(void);
     46extern void frame_high_arch_init(void);
    4747extern void physmem_print(void);
    4848
  • kernel/arch/amd64/src/mm/page.c

    r1761268 r7aaed09  
    4646#include <panic.h>
    4747#include <align.h>
     48#include <macros.h>
    4849
    4950void page_arch_init(void)
    5051{
    51         if (config.cpu_active == 1) {
    52                 uintptr_t cur;
    53                 unsigned int identity_flags =
    54                     PAGE_CACHEABLE | PAGE_EXEC | PAGE_GLOBAL | PAGE_WRITE;
     52        if (config.cpu_active > 1) {
     53                write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
     54                return;
     55        }
     56
     57        uintptr_t cur;
     58        unsigned int identity_flags =
     59            PAGE_CACHEABLE | PAGE_EXEC | PAGE_GLOBAL | PAGE_WRITE;
    5560               
    56                 page_mapping_operations = &pt_mapping_operations;
     61        page_mapping_operations = &pt_mapping_operations;
    5762               
    58                 page_table_lock(AS_KERNEL, true);
     63        page_table_lock(AS_KERNEL, true);
    5964               
    60                 /*
    61                  * PA2KA(identity) mapping for all frames.
    62                  */
    63                 for (cur = 0; cur < last_frame; cur += FRAME_SIZE)
    64                         page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, identity_flags);
     65        /*
     66         * PA2KA(identity) mapping for all low-memory frames.
     67         */
     68        for (cur = 0; cur < min(config.identity_size, config.physmem_end);
     69            cur += FRAME_SIZE)
     70                page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, identity_flags);
    6571               
    66                 page_table_unlock(AS_KERNEL, true);
     72        page_table_unlock(AS_KERNEL, true);
    6773               
    68                 exc_register(14, "page_fault", true, (iroutine_t) page_fault);
    69                 write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
    70         } else
    71                 write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
     74        exc_register(14, "page_fault", true, (iroutine_t) page_fault);
     75        write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
    7276}
    7377
     
    9498}
    9599
    96 uintptr_t hw_map(uintptr_t physaddr, size_t size)
    97 {
    98         if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH))
    99                 panic("Unable to map physical memory %p (%zu bytes).",
    100                     (void *) physaddr, size);
    101        
    102         uintptr_t virtaddr = PA2KA(last_frame);
    103         pfn_t i;
    104        
    105         page_table_lock(AS_KERNEL, true);
    106        
    107         for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++)
    108                 page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE | PAGE_WRITE);
    109        
    110         page_table_unlock(AS_KERNEL, true);
    111        
    112         last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE);
    113        
    114         return virtaddr;
    115 }
    116 
    117100/** @}
    118101 */
  • kernel/arch/arm32/Makefile.inc

    r1761268 r7aaed09  
    5353        arch/$(KARCH)/src/debug/stacktrace.c \
    5454        arch/$(KARCH)/src/debug/stacktrace_asm.S \
     55        arch/$(KARCH)/src/mm/km.c \
    5556        arch/$(KARCH)/src/mm/as.c \
    5657        arch/$(KARCH)/src/mm/frame.c \
  • kernel/arch/arm32/include/mach/integratorcp/integratorcp.h

    r1761268 r7aaed09  
    103103extern void icp_cpu_halt(void);
    104104extern void icp_irq_exception(unsigned int, istate_t *);
    105 extern void icp_get_memory_extents(uintptr_t *, uintptr_t *);
     105extern void icp_get_memory_extents(uintptr_t *, size_t *);
    106106extern void icp_frame_init(void);
    107107extern size_t icp_get_irq_count(void);
  • kernel/arch/arm32/include/mach/testarm/testarm.h

    r1761268 r7aaed09  
    7171extern void gxemul_cpu_halt(void);
    7272extern void gxemul_irq_exception(unsigned int, istate_t *);
    73 extern void gxemul_get_memory_extents(uintptr_t *, uintptr_t *);
     73extern void gxemul_get_memory_extents(uintptr_t *, size_t *);
    7474extern void gxemul_frame_init(void);
    7575extern size_t gxemul_get_irq_count(void);
  • kernel/arch/arm32/include/machine_func.h

    r1761268 r7aaed09  
    5050        void (*machine_timer_irq_start)(void);
    5151        void (*machine_cpu_halt)(void);
    52         void (*machine_get_memory_extents)(uintptr_t *, uintptr_t *);
     52        void (*machine_get_memory_extents)(uintptr_t *, size_t *);
    5353        void (*machine_irq_exception)(unsigned int, istate_t *);
    5454        void (*machine_frame_init)(void);
     
    8181 * @param size          Place to store memory size.
    8282 */
    83 extern void machine_get_memory_extents(uintptr_t *start, uintptr_t *size);
     83extern void machine_get_memory_extents(uintptr_t *start, size_t *size);
    8484
    8585/** Interrupt exception handler.
  • kernel/arch/arm32/include/mm/frame.h

    r1761268 r7aaed09  
    6161#endif
    6262
    63 extern uintptr_t last_frame;
    64 
    65 extern void frame_arch_init(void);
     63extern void frame_low_arch_init(void);
     64extern void frame_high_arch_init(void);
    6665extern void boot_page_table_free(void);
    6766#define physmem_print()
  • kernel/arch/arm32/include/mm/page.h

    r1761268 r7aaed09  
    5454
    5555/* Number of entries in each level. */
    56 #define PTL0_ENTRIES_ARCH       (2 << 12)       /* 4096 */
     56#define PTL0_ENTRIES_ARCH       (1 << 12)       /* 4096 */
    5757#define PTL1_ENTRIES_ARCH       0
    5858#define PTL2_ENTRIES_ARCH       0
    5959/* coarse page tables used (256 * 4 = 1KB per page) */
    60 #define PTL3_ENTRIES_ARCH       (2 << 8)        /* 256 */
     60#define PTL3_ENTRIES_ARCH       (1 << 8)        /* 256 */
    6161
    6262/* Page table sizes for each level. */
  • kernel/arch/arm32/src/mach/gta02/gta02.c

    r1761268 r7aaed09  
    6565static void gta02_timer_irq_start(void);
    6666static void gta02_cpu_halt(void);
    67 static void gta02_get_memory_extents(uintptr_t *start, uintptr_t *size);
     67static void gta02_get_memory_extents(uintptr_t *start, size_t *size);
    6868static void gta02_irq_exception(unsigned int exc_no, istate_t *istate);
    6969static void gta02_frame_init(void);
     
    123123 * @param size          Place to store memory size.
    124124 */
    125 static void gta02_get_memory_extents(uintptr_t *start, uintptr_t *size)
     125static void gta02_get_memory_extents(uintptr_t *start, size_t *size)
    126126{
    127127        *start = GTA02_MEMORY_START + GTA02_MEMORY_SKIP;
  • kernel/arch/arm32/src/mach/integratorcp/integratorcp.c

    r1761268 r7aaed09  
    220220 * @param size          Place to store memory size.
    221221 */
    222 void icp_get_memory_extents(uintptr_t *start, uintptr_t *size)
     222void icp_get_memory_extents(uintptr_t *start, size_t *size)
    223223{
    224224        *start = 0;
  • kernel/arch/arm32/src/mach/testarm/testarm.c

    r1761268 r7aaed09  
    202202 * @param size          Place to store memory size.
    203203 */
    204 void gxemul_get_memory_extents(uintptr_t *start, uintptr_t *size)
     204void gxemul_get_memory_extents(uintptr_t *start, size_t *size)
    205205{
    206206        *start = 0;
    207         *size = *((uintptr_t *) (GXEMUL_MP_ADDRESS + GXEMUL_MP_MEMSIZE_OFFSET));
     207        *size = *((uintptr_t *) (GXEMUL_MP_ADDRESS + GXEMUL_MP_MEMSIZE_OFFSET));
    208208}
    209209
  • kernel/arch/arm32/src/machine_func.c

    r1761268 r7aaed09  
    8585 * @param size          Place to store memory size.
    8686 */
    87 void machine_get_memory_extents(uintptr_t *start, uintptr_t *size)
     87void machine_get_memory_extents(uintptr_t *start, size_t *size)
    8888{
    8989        (machine_ops->machine_get_memory_extents)(start, size);
  • kernel/arch/arm32/src/mm/frame.c

    r1761268 r7aaed09  
    3939#include <config.h>
    4040#include <align.h>
     41#include <macros.h>
    4142
    42 /** Address of the last frame in the memory. */
    43 uintptr_t last_frame = 0;
     43static void frame_common_arch_init(bool low)
     44{
     45        uintptr_t base;
     46        size_t size;
    4447
    45 /** Creates memory zones. */
    46 void frame_arch_init(void)
     48        machine_get_memory_extents(&base, &size);
     49        base = ALIGN_UP(base, FRAME_SIZE);
     50        size = ALIGN_DOWN(size, FRAME_SIZE);
     51       
     52        if (!frame_adjust_zone_bounds(low, &base, &size))
     53                return;
     54
     55        if (low) {
     56                zone_create(ADDR2PFN(base), SIZE2FRAMES(size),
     57                    BOOT_PAGE_TABLE_START_FRAME +
     58                    BOOT_PAGE_TABLE_SIZE_IN_FRAMES,
     59                    ZONE_AVAILABLE | ZONE_LOWMEM);
     60        } else {
     61                pfn_t conf = zone_external_conf_alloc(SIZE2FRAMES(size));
     62
     63                zone_create(ADDR2PFN(base), SIZE2FRAMES(size), conf,
     64                    ZONE_AVAILABLE | ZONE_HIGHMEM);
     65        }
     66       
     67}
     68
     69/** Create low memory zones. */
     70void frame_low_arch_init(void)
    4771{
    48         uintptr_t mem_start, mem_size;
    49         uintptr_t first_frame;
    50         uintptr_t num_frames;
     72        frame_common_arch_init(true);
    5173
    52         machine_get_memory_extents(&mem_start, &mem_size);
    53         first_frame = ALIGN_UP(mem_start, FRAME_SIZE);
    54         last_frame = ALIGN_DOWN(mem_start + mem_size, FRAME_SIZE);
    55         num_frames = (last_frame - first_frame) >> FRAME_WIDTH;
    56        
    57         /* All memory as one zone */
    58         zone_create(first_frame >> FRAME_WIDTH, num_frames,
    59             BOOT_PAGE_TABLE_START_FRAME + BOOT_PAGE_TABLE_SIZE_IN_FRAMES, 0);
    60        
    6174        /* blacklist boot page table */
    6275        frame_mark_unavailable(BOOT_PAGE_TABLE_START_FRAME,
     
    6477
    6578        machine_frame_init();
     79}
     80
     81/** Create high memory zones. */
     82void frame_high_arch_init(void)
     83{
     84        frame_common_arch_init(false);
    6685}
    6786
  • kernel/arch/arm32/src/mm/page.c

    r1761268 r7aaed09  
    3737#include <genarch/mm/page_pt.h>
    3838#include <mm/page.h>
     39#include <arch/mm/frame.h>
    3940#include <align.h>
    4041#include <config.h>
     
    4243#include <typedefs.h>
    4344#include <interrupt.h>
    44 #include <arch/mm/frame.h>
     45#include <macros.h>
    4546
    4647/** Initializes page tables.
     
    5758       
    5859        uintptr_t cur;
     60
    5961        /* Kernel identity mapping */
    60         for (cur = PHYSMEM_START_ADDR; cur < last_frame; cur += FRAME_SIZE)
     62        for (cur = PHYSMEM_START_ADDR;
     63            cur < min(config.identity_size, config.physmem_end);
     64            cur += FRAME_SIZE)
    6165                page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
    6266       
    6367        /* Create mapping for exception table at high offset */
    6468#ifdef HIGH_EXCEPTION_VECTORS
     69        // XXX: fixme to use proper non-identity page
    6570        void *virtaddr = frame_alloc(ONE_FRAME, FRAME_KA);
    66         page_mapping_insert(AS_KERNEL, EXC_BASE_ADDRESS, KA2PA(virtaddr), flags);
     71        page_mapping_insert(AS_KERNEL, EXC_BASE_ADDRESS, KA2PA(virtaddr),
     72            flags);
    6773#else
    6874#error "Only high exception vector supported now"
     
    7884}
    7985
    80 /** Maps device into the kernel space.
    81  *
    82  * Maps physical address of device into kernel virtual address space (so it can
    83  * be accessed only by kernel through virtual address).
    84  *
    85  * @param physaddr Physical address where device is connected.
    86  * @param size Length of area where device is present.
    87  *
    88  * @return Virtual address where device will be accessible.
    89  */
    90 uintptr_t hw_map(uintptr_t physaddr, size_t size)
    91 {
    92         if (last_frame + ALIGN_UP(size, PAGE_SIZE) >
    93             KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH)) {
    94                 panic("Unable to map physical memory %p (%d bytes).",
    95                     (void *) physaddr, size);
    96         }
    97        
    98         uintptr_t virtaddr = PA2KA(last_frame);
    99         pfn_t i;
    100 
    101         page_table_lock(AS_KERNEL, true);
    102         for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++) {
    103                 page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i),
    104                     physaddr + PFN2ADDR(i),
    105                     PAGE_NOT_CACHEABLE | PAGE_READ | PAGE_WRITE | PAGE_KERNEL);
    106         }
    107         page_table_unlock(AS_KERNEL, true);
    108        
    109         last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE);
    110         return virtaddr;
    111 }
    112 
    11386/** @}
    11487 */
  • kernel/arch/ia32/Makefile.inc

    r1761268 r7aaed09  
    9999        arch/$(KARCH)/src/userspace.c \
    100100        arch/$(KARCH)/src/cpu/cpu.c \
     101        arch/$(KARCH)/src/mm/km.c \
    101102        arch/$(KARCH)/src/mm/as.c \
    102103        arch/$(KARCH)/src/mm/frame.c \
  • kernel/arch/ia32/include/mm/frame.h

    r1761268 r7aaed09  
    4343#include <typedefs.h>
    4444
    45 extern uintptr_t last_frame;
    46 
    47 extern void frame_arch_init(void);
     45extern void frame_low_arch_init(void);
     46extern void frame_high_arch_init(void);
    4847extern void physmem_print(void);
    4948
  • kernel/arch/ia32/src/mm/frame.c

    r1761268 r7aaed09  
    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

    r1761268 r7aaed09  
    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
  • kernel/arch/ia64/Makefile.inc

    r1761268 r7aaed09  
    5252        arch/$(KARCH)/src/ivt.S \
    5353        arch/$(KARCH)/src/interrupt.c \
     54        arch/$(KARCH)/src/mm/km.c \
    5455        arch/$(KARCH)/src/mm/as.c \
    5556        arch/$(KARCH)/src/mm/frame.c \
  • kernel/arch/ia64/include/mm/frame.h

    r1761268 r7aaed09  
    4343#include <typedefs.h>
    4444
    45 extern uintptr_t last_frame;
    46 
    47 extern void frame_arch_init(void);
     45extern void frame_low_arch_init(void);
     46extern void frame_high_arch_init(void);
    4847#define physmem_print()
    4948
  • kernel/arch/ia64/include/mm/page.h

    r1761268 r7aaed09  
    5757
    5858/* Firmware area (bellow 4GB in phys mem) */
    59 #define FW_OFFSET   0x00000000F0000000
     59#define FW_OFFSET   0x00000000F0000000  // FIXME: [non-ident]
    6060/* Legacy IO space */
    61 #define IO_OFFSET   0x0001000000000000
     61#define IO_OFFSET   0x0001000000000000  // FIXME: [non-ident]
    6262/* Videoram - now mapped to 0 as VGA text mode vram on 0xb8000 */
    63 #define VIO_OFFSET  0x0002000000000000
     63#define VIO_OFFSET  0x0002000000000000  // FIXME: [non-ident]
    6464
    6565
  • kernel/arch/ia64/src/mm/frame.c

    r1761268 r7aaed09  
    5151#define MINCONF 1
    5252
    53 uintptr_t last_frame = 0;
     53static void frame_common_arch_init(bool low)
     54{
     55        unsigned int i;
    5456
    55 void frame_arch_init(void)
    56 {
    57         if (config.cpu_active == 1) {
    58                 unsigned int i;
    59                 for (i = 0; i < bootinfo->memmap_items; i++) {
    60                         if (bootinfo->memmap[i].type == MEMMAP_FREE_MEM) {
    61                                 uint64_t base = bootinfo->memmap[i].base;
    62                                 uint64_t size = bootinfo->memmap[i].size;
    63                                 uint64_t abase = ALIGN_UP(base, FRAME_SIZE);
     57        for (i = 0; i < bootinfo->memmap_items; i++) {
     58                if (bootinfo->memmap[i].type != MEMMAP_FREE_MEM)
     59                        continue;
    6460
    65                                 if (size > FRAME_SIZE)
    66                                         size -= abase - base;
     61                uintptr_t base = bootinfo->memmap[i].base;
     62                size_t size = bootinfo->memmap[i].size;
     63                uintptr_t abase = ALIGN_UP(base, FRAME_SIZE);
    6764
    68                                 if (size > MIN_ZONE_SIZE) {
    69                                         zone_create(abase >> FRAME_WIDTH,
    70                                             size >> FRAME_WIDTH,
    71                                             max(MINCONF, abase >> FRAME_WIDTH),
    72                                             0);
    73                                 }
    74                                 if (abase + size > last_frame)
    75                                         last_frame = abase + size;
     65                if (size > FRAME_SIZE)
     66                        size -= abase - base;
     67
     68                if (!frame_adjust_zone_bounds(low, &abase, &size))
     69                        continue;
     70
     71                if (size > MIN_ZONE_SIZE) {
     72                        pfn_t pfn = ADDR2PFN(abase);
     73                        size_t count = SIZE2FRAMES(size);
     74
     75                        if (low) {
     76                                zone_create(pfn, count, max(MINCONF, pfn),
     77                                    ZONE_AVAILABLE | ZONE_LOWMEM);
     78                        } else {
     79                                pfn_t conf;
     80
     81                                conf = zone_external_conf_alloc(count);
     82                                zone_create(pfn, count, conf,
     83                                    ZONE_AVAILABLE | ZONE_HIGHMEM);
    7684                        }
    7785                }
    78                
    79                 /*
    80                  * Blacklist ROM regions.
    81                  */
    82                 frame_mark_unavailable(ADDR2PFN(ROM_BASE),
    83                     SIZE2FRAMES(ROM_SIZE));
     86        }
     87}
    8488
    85                 frame_mark_unavailable(ADDR2PFN(KERNEL_RESERVED_AREA_BASE),
    86                     SIZE2FRAMES(KERNEL_RESERVED_AREA_SIZE));
    87         }       
     89void frame_low_arch_init(void)
     90{
     91        if (config.cpu_active > 1)
     92                return;
     93       
     94        frame_common_arch_init(true);
     95       
     96        /*
     97         * Blacklist ROM regions.
     98         */
     99        frame_mark_unavailable(ADDR2PFN(ROM_BASE),
     100            SIZE2FRAMES(ROM_SIZE));
     101
     102        frame_mark_unavailable(ADDR2PFN(KERNEL_RESERVED_AREA_BASE),
     103            SIZE2FRAMES(KERNEL_RESERVED_AREA_SIZE));
     104}
     105
     106void frame_high_arch_init(void)
     107{
     108        if (config.cpu_active > 1)
     109                return;
     110       
     111        frame_common_arch_init(false);
    88112}
    89113
  • kernel/arch/ia64/src/mm/page.c

    r1761268 r7aaed09  
    255255}
    256256
    257 uintptr_t hw_map(uintptr_t physaddr, size_t size __attribute__ ((unused)))
    258 {
    259         /* THIS is a dirty hack. */
    260         return (uintptr_t)((uint64_t)(PA2KA(physaddr)) + VIO_OFFSET);
    261 }
    262 
    263257/** @}
    264258 */
  • kernel/arch/ia64/src/mm/tlb.c

    r1761268 r7aaed09  
    480480        va = istate->cr_ifa; /* faulting address */
    481481       
    482         page_table_lock(AS, true);
    483482        t = page_mapping_find(AS, va, true);
    484483        if (t) {
     
    488487                 */
    489488                itc_pte_copy(t);
    490                 page_table_unlock(AS, true);
    491489        } else {
    492490                /*
    493491                 * Forward the page fault to address space page fault handler.
    494492                 */
    495                 page_table_unlock(AS, true);
    496493                if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) {
    497494                        fault_if_from_uspace(istate, "Page fault at %p.",
     
    598595       
    599596       
    600         page_table_lock(AS, true);
    601597        pte_t *entry = page_mapping_find(AS, va, true);
    602598        if (entry) {
     
    606602                 */
    607603                dtc_pte_copy(entry);
    608                 page_table_unlock(AS, true);
    609604        } else {
    610                 page_table_unlock(AS, true);
    611605                if (try_memmap_io_insertion(va, istate))
    612606                        return;
     
    650644        va = istate->cr_ifa;  /* faulting address */
    651645       
    652         page_table_lock(AS, true);
    653646        t = page_mapping_find(AS, va, true);
    654647        ASSERT((t) && (t->p));
     
    667660                }
    668661        }
    669         page_table_unlock(AS, true);
    670662}
    671663
     
    683675        va = istate->cr_ifa;  /* faulting address */
    684676       
    685         page_table_lock(AS, true);
    686677        t = page_mapping_find(AS, va, true);
    687678        ASSERT((t) && (t->p));
     
    700691                }
    701692        }
    702         page_table_unlock(AS, true);
    703693}
    704694
     
    716706        va = istate->cr_ifa;  /* faulting address */
    717707       
    718         page_table_lock(AS, true);
    719708        t = page_mapping_find(AS, va, true);
    720709        ASSERT((t) && (t->p));
     
    733722                }
    734723        }
    735         page_table_unlock(AS, true);
    736724}
    737725
     
    752740         * Assume a write to a read-only page.
    753741         */
    754         page_table_lock(AS, true);
    755742        t = page_mapping_find(AS, va, true);
    756743        ASSERT((t) && (t->p));
     
    761748                panic_memtrap(istate, PF_ACCESS_WRITE, va, NULL);
    762749        }
    763         page_table_unlock(AS, true);
    764750}
    765751
     
    777763        va = istate->cr_ifa;  /* faulting address */
    778764       
    779         page_table_lock(AS, true);
    780765        t = page_mapping_find(AS, va, true);
    781766        ASSERT(t);
     
    790775                else
    791776                        dtc_pte_copy(t);
    792                 page_table_unlock(AS, true);
    793777        } else {
    794                 page_table_unlock(AS, true);
    795778                if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
    796779                        fault_if_from_uspace(istate, "Page fault at %p.",
  • kernel/arch/ia64/src/start.S

    r1761268 r7aaed09  
    3838#define KERNEL_TRANSLATION_I    0x0010000000000661
    3939#define KERNEL_TRANSLATION_D    0x0010000000000661
    40 #define KERNEL_TRANSLATION_VIO  0x0010000000000671
    41 #define KERNEL_TRANSLATION_IO   0x00100FFFFC000671
    42 #define KERNEL_TRANSLATION_FW   0x00100000F0000671
     40#define KERNEL_TRANSLATION_VIO  0x0010000000000671      // FIXME: [non-ident]
     41#define KERNEL_TRANSLATION_IO   0x00100FFFFC000671      // FIXME: [non-ident]
     42#define KERNEL_TRANSLATION_FW   0x00100000F0000671      // FIXME: [non-ident]
    4343
    4444.section K_TEXT_START, "ax"
  • kernel/arch/mips32/Makefile.inc

    r1761268 r7aaed09  
    6363        arch/$(KARCH)/src/debug/stacktrace.c \
    6464        arch/$(KARCH)/src/debug/stacktrace_asm.S \
     65        arch/$(KARCH)/src/mm/km.c \
    6566        arch/$(KARCH)/src/mm/frame.c \
    6667        arch/$(KARCH)/src/mm/page.c \
  • kernel/arch/mips32/include/mm/frame.h

    r1761268 r7aaed09  
    4141#ifndef __ASM__
    4242
    43 extern void frame_arch_init(void);
     43extern void frame_low_arch_init(void);
     44extern void frame_high_arch_init(void);
    4445extern void physmem_print(void);
    4546
  • kernel/arch/mips32/src/mm/frame.c

    r1761268 r7aaed09  
    131131}
    132132
    133 static void frame_add_region(pfn_t start_frame, pfn_t end_frame)
    134 {
    135         if (end_frame > start_frame) {
    136                 /* Convert 1M frames to 16K frames */
    137                 pfn_t first = ADDR2PFN(start_frame << ZERO_PAGE_WIDTH);
    138                 pfn_t count = ADDR2PFN((end_frame - start_frame) << ZERO_PAGE_WIDTH);
    139                
     133static void frame_add_region(pfn_t start_frame, pfn_t end_frame, bool low)
     134{
     135        if (end_frame <= start_frame)
     136                return;
     137
     138        uintptr_t base = start_frame << ZERO_PAGE_WIDTH;
     139        size_t size = (end_frame - start_frame) << ZERO_PAGE_WIDTH;
     140
     141        if (!frame_adjust_zone_bounds(low, &base, &size))
     142                return;
     143
     144        pfn_t first = ADDR2PFN(base);
     145        size_t count = SIZE2FRAMES(size);
     146        pfn_t conf_frame;
     147
     148        if (low) {
    140149                /* Interrupt vector frame is blacklisted */
    141                 pfn_t conf_frame;
    142150                if (first == 0)
    143151                        conf_frame = 1;
    144152                else
    145153                        conf_frame = first;
    146                
    147                 zone_create(first, count, conf_frame, 0);
    148                
    149                 if (phys_regions_count < MAX_REGIONS) {
    150                         phys_regions[phys_regions_count].start = first;
    151                         phys_regions[phys_regions_count].count = count;
    152                         phys_regions_count++;
    153                 }
     154                zone_create(first, count, conf_frame,
     155                    ZONE_AVAILABLE | ZONE_LOWMEM);
     156        } else {
     157                conf_frame = zone_external_conf_alloc(count);
     158                zone_create(first, count, conf_frame,
     159                    ZONE_AVAILABLE | ZONE_HIGHMEM);
     160        }
     161               
     162               
     163        if (phys_regions_count < MAX_REGIONS) {
     164                phys_regions[phys_regions_count].start = first;
     165                phys_regions[phys_regions_count].count = count;
     166                phys_regions_count++;
    154167        }
    155168}
     
    165178 *
    166179 */
    167 void frame_arch_init(void)
     180void frame_low_arch_init(void)
    168181{
    169182        ipl_t ipl = interrupts_disable();
     
    224237               
    225238                if (!avail) {
    226                         frame_add_region(start_frame, frame);
     239                        frame_add_region(start_frame, frame, true);
    227240                        start_frame = frame + 1;
    228241                        avail = true;
     
    230243        }
    231244       
    232         frame_add_region(start_frame, frame);
     245        frame_add_region(start_frame, frame, true);
    233246       
    234247        /* Blacklist interrupt vector frame */
     
    246259}
    247260
     261void frame_high_arch_init(void)
     262{
     263}
    248264
    249265void physmem_print(void)
  • kernel/arch/mips32/src/mm/page.c

    r1761268 r7aaed09  
    4141{
    4242        page_mapping_operations = &pt_mapping_operations;
    43 }
    44 
    45 /** Map device into kernel space
    46  * - on mips, all devices are already mapped into kernel space,
    47  *   translate the physical address to uncached area
    48  */
    49 uintptr_t hw_map(uintptr_t physaddr, size_t size)
    50 {
    51         return physaddr + 0xa0000000;
     43        as_switch(NULL, AS_KERNEL);
    5244}
    5345
  • kernel/arch/mips64/Makefile.inc

    r1761268 r7aaed09  
    5555        arch/$(KARCH)/src/debug/stacktrace.c \
    5656        arch/$(KARCH)/src/debug/stacktrace_asm.S \
     57        arch/$(KARCH)/src/mm/km.c \
    5758        arch/$(KARCH)/src/mm/frame.c \
    5859        arch/$(KARCH)/src/mm/page.c \
  • kernel/arch/mips64/include/mm/frame.h

    r1761268 r7aaed09  
    4141#ifndef __ASM__
    4242
    43 extern void frame_arch_init(void);
     43extern void frame_low_arch_init(void);
     44extern void frame_high_arch_init(void);
    4445extern void physmem_print(void);
    4546
  • kernel/arch/mips64/src/mm/frame.c

    r1761268 r7aaed09  
    123123}
    124124
    125 static void frame_add_region(pfn_t start_frame, pfn_t end_frame)
    126 {
    127         if (end_frame > start_frame) {
    128                 /* Convert 1M frames to 16K frames */
    129                 pfn_t first = ADDR2PFN(start_frame << ZERO_PAGE_WIDTH);
    130                 pfn_t count = ADDR2PFN((end_frame - start_frame) << ZERO_PAGE_WIDTH);
    131                
     125static void frame_add_region(pfn_t start_frame, pfn_t end_frame, bool low)
     126{
     127        if (end_frame <= start_frame)
     128                return;
     129
     130        uintptr_t base = start_frame << ZERO_PAGE_WIDTH;
     131        size_t size = (end_frame - start_frame) << ZERO_PAGE_WIDTH;
     132
     133        if (!frame_adjust_zone_bounds(low, &base, &size))
     134                return;
     135
     136        pfn_t first = ADDR2PFN(base);
     137        size_t count = SIZE2FRAMES(size);
     138        pfn_t conf_frame;
     139
     140        if (low) {
    132141                /* Interrupt vector frame is blacklisted */
    133                 pfn_t conf_frame;
    134142                if (first == 0)
    135143                        conf_frame = 1;
    136144                else
    137145                        conf_frame = first;
     146                zone_create(first, count, conf_frame,
     147                    ZONE_AVAILABLE | ZONE_LOWMEM);
     148        } else {
     149                conf_frame = zone_external_conf_alloc(count);
     150                zone_create(first, count, conf_frame,
     151                    ZONE_AVAILABLE | ZONE_HIGHMEM);
     152        }
    138153               
    139                 zone_create(first, count, conf_frame, 0);
    140154               
    141                 if (phys_regions_count < MAX_REGIONS) {
    142                         phys_regions[phys_regions_count].start = first;
    143                         phys_regions[phys_regions_count].count = count;
    144                         phys_regions_count++;
    145                 }
     155        if (phys_regions_count < MAX_REGIONS) {
     156                phys_regions[phys_regions_count].start = first;
     157                phys_regions[phys_regions_count].count = count;
     158                phys_regions_count++;
    146159        }
    147160}
     
    156169 *
    157170 */
    158 void frame_arch_init(void)
     171void frame_low_arch_init(void)
    159172{
    160173        ipl_t ipl = interrupts_disable();
     
    207220               
    208221                if (!avail) {
    209                         frame_add_region(start_frame, frame);
     222                        frame_add_region(start_frame, frame, true);
    210223                        start_frame = frame + 1;
    211224                        avail = true;
     
    213226        }
    214227       
    215         frame_add_region(start_frame, frame);
     228        frame_add_region(start_frame, frame, true);
    216229       
    217230        /* Blacklist interrupt vector frame */
     
    229242}
    230243
     244void frame_high_arch_init(void)
     245{
     246}
     247
    231248void physmem_print(void)
    232249{
  • kernel/arch/mips64/src/mm/page.c

    r1761268 r7aaed09  
    4343}
    4444
    45 /** Map device into kernel space
    46  * - on mips, all devices are already mapped into kernel space,
    47  *   translate the physical address to uncached area
    48  */
    49 uintptr_t hw_map(uintptr_t physaddr, size_t size)
    50 {
    51         return physaddr + 0xffffffffa0000000;
    52 }
    53 
    5445/** @}
    5546 */
  • kernel/arch/ppc32/Makefile.inc

    r1761268 r7aaed09  
    5252        arch/$(KARCH)/src/proc/scheduler.c \
    5353        arch/$(KARCH)/src/ddi/ddi.c \
     54        arch/$(KARCH)/src/mm/km.c \
    5455        arch/$(KARCH)/src/mm/as.c \
    5556        arch/$(KARCH)/src/mm/frame.c \
  • kernel/arch/ppc32/include/mm/frame.h

    r1761268 r7aaed09  
    4444#include <trace.h>
    4545
    46 extern uintptr_t last_frame;
    47 
    4846NO_TRACE static inline uint32_t physmem_top(void)
    4947{
     
    5856}
    5957
    60 extern void frame_arch_init(void);
     58extern void frame_low_arch_init(void);
     59extern void frame_high_arch_init(void);
    6160extern void physmem_print(void);
    6261
  • kernel/arch/ppc32/src/mm/frame.c

    r1761268 r7aaed09  
    4040#include <print.h>
    4141
    42 uintptr_t last_frame = 0;
    4342memmap_t memmap;
    4443
     
    5453}
    5554
    56 void frame_arch_init(void)
     55static void frame_common_arch_init(bool low)
    5756{
    5857        pfn_t minconf = 2;
     
    6160        for (i = 0; i < memmap.cnt; i++) {
    6261                /* To be safe, make the available zone possibly smaller */
    63                 uintptr_t new_start = ALIGN_UP((uintptr_t) memmap.zones[i].start,
     62                uintptr_t base = ALIGN_UP((uintptr_t) memmap.zones[i].start,
    6463                    FRAME_SIZE);
    65                 size_t new_size = ALIGN_DOWN(memmap.zones[i].size -
    66                     (new_start - ((uintptr_t) memmap.zones[i].start)), FRAME_SIZE);
     64                size_t size = ALIGN_DOWN(memmap.zones[i].size -
     65                    (base - ((uintptr_t) memmap.zones[i].start)), FRAME_SIZE);
    6766               
    68                 pfn_t pfn = ADDR2PFN(new_start);
    69                 size_t count = SIZE2FRAMES(new_size);
    70                
     67                if (!frame_adjust_zone_bounds(low, &base, &size))
     68                        return;
     69
     70                pfn_t pfn = ADDR2PFN(base);
     71                size_t count = SIZE2FRAMES(size);
    7172                pfn_t conf;
    72                 if ((minconf < pfn) || (minconf >= pfn + count))
    73                         conf = pfn;
    74                 else
    75                         conf = minconf;
    76                
    77                 zone_create(pfn, count, conf, 0);
    78                
    79                 if (last_frame < ALIGN_UP(new_start + new_size, FRAME_SIZE))
    80                         last_frame = ALIGN_UP(new_start + new_size, FRAME_SIZE);
     73
     74                if (low) {
     75                        if ((minconf < pfn) || (minconf >= pfn + count))
     76                                conf = pfn;
     77                        else
     78                                conf = minconf;
     79                        zone_create(pfn, count, conf,
     80                            ZONE_AVAILABLE | ZONE_LOWMEM);
     81                } else {
     82                        conf = zone_external_conf_alloc(count);
     83                        zone_create(pfn, count, conf,
     84                            ZONE_AVAILABLE | ZONE_HIGHMEM);
     85                }
    8186        }
     87       
     88}
     89
     90void frame_low_arch_init(void)
     91{
     92        frame_common_arch_init(true);
    8293       
    8394        /* First is exception vector, second is 'implementation specific',
     
    92103}
    93104
     105void frame_high_arch_init(void)
     106{
     107        frame_common_arch_init(false);
     108}
     109
    94110/** @}
    95111 */
  • kernel/arch/ppc32/src/mm/page.c

    r1761268 r7aaed09  
    4646}
    4747
    48 uintptr_t hw_map(uintptr_t physaddr, size_t size)
    49 {
    50         if (last_frame + ALIGN_UP(size, PAGE_SIZE) >
    51             KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH))
    52                 panic("Unable to map physical memory %p (%zu bytes).",
    53                     (void *) physaddr, size);
    54        
    55         uintptr_t virtaddr = PA2KA(last_frame);
    56         pfn_t i;
    57         page_table_lock(AS_KERNEL, true);
    58         for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++)
    59                 page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i),
    60                     physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE | PAGE_WRITE);
    61         page_table_unlock(AS_KERNEL, true);
    62        
    63         last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE);
    64        
    65         return virtaddr;
    66 }
    67 
    6848/** @}
    6949 */
  • kernel/arch/sparc64/Makefile.inc

    r1761268 r7aaed09  
    6868        arch/$(KARCH)/src/fpu_context.c \
    6969        arch/$(KARCH)/src/dummy.s \
     70        arch/$(KARCH)/src/mm/$(USARCH)/km.c \
    7071        arch/$(KARCH)/src/mm/$(USARCH)/as.c \
    7172        arch/$(KARCH)/src/mm/$(USARCH)/frame.c \
  • kernel/arch/sparc64/include/mm/sun4u/frame.h

    r1761268 r7aaed09  
    7272typedef union frame_address frame_address_t;
    7373
    74 extern uintptr_t last_frame;
    7574extern uintptr_t end_of_identity;
    7675
    77 extern void frame_arch_init(void);
     76extern void frame_low_arch_init(void);
     77extern void frame_high_arch_init(void);
    7878#define physmem_print()
    7979
  • kernel/arch/sparc64/include/mm/sun4v/frame.h

    r1761268 r7aaed09  
    4646#include <typedefs.h>
    4747
    48 extern uintptr_t last_frame;
    49 extern void frame_arch_init(void);
     48extern void frame_low_arch_init(void);
     49extern void frame_high_arch_init(void);
    5050#define physmem_print()
    5151
  • kernel/arch/sparc64/src/mm/page.c

    r1761268 r7aaed09  
    5151}
    5252
    53 /** Map memory-mapped device into virtual memory.
    54  *
    55  * We are currently using identity mapping for mapping device registers.
    56  *
    57  * @param physaddr Physical address of the page where the device is
    58  *                 located.
    59  * @param size     Size of the device's registers.
    60  *
    61  * @return Virtual address of the page where the device is mapped.
    62  *
    63  */
    64 uintptr_t hw_map(uintptr_t physaddr, size_t size)
    65 {
    66         return PA2KA(physaddr);
    67 }
    68 
    6953/** @}
    7054 */
  • kernel/arch/sparc64/src/mm/sun4u/frame.c

    r1761268 r7aaed09  
    4141#include <macros.h>
    4242
    43 uintptr_t last_frame = (uintptr_t) NULL;
    44 
    4543/** Create memory zones according to information stored in memmap.
    4644 *
    4745 * Walk the memory map and create frame zones according to it.
    4846 */
    49 void frame_arch_init(void)
     47static void frame_common_arch_init(bool low)
    5048{
    51         if (config.cpu_active == 1) {
    52                 unsigned int i;
     49        unsigned int i;
     50       
     51        for (i = 0; i < memmap.cnt; i++) {
     52                uintptr_t base;
     53                size_t size;
     54
     55                /*
     56                 * The memmap is created by HelenOS boot loader.
     57                 * It already contains no holes.
     58                 */
     59
     60                /* To be safe, make the available zone possibly smaller */
     61                base = ALIGN_UP((uintptr_t) memmap.zones[i].start, FRAME_SIZE);
     62                size = ALIGN_DOWN(memmap.zones[i].size -
     63                    (base - ((uintptr_t) memmap.zones[i].start)), FRAME_SIZE);
    5364               
    54                 for (i = 0; i < memmap.cnt; i++) {
    55                         /* To be safe, make the available zone possibly smaller */
    56                         uintptr_t new_start = ALIGN_UP((uintptr_t) memmap.zones[i].start,
    57                             FRAME_SIZE);
    58                         size_t new_size = ALIGN_DOWN(memmap.zones[i].size -
    59                             (new_start - ((uintptr_t) memmap.zones[i].start)), FRAME_SIZE);
    60                        
    61                         /*
    62                          * The memmap is created by HelenOS boot loader.
    63                          * It already contains no holes.
    64                          */
    65                        
    66                         pfn_t confdata = ADDR2PFN(new_start);
    67                        
     65                if (!frame_adjust_zone_bounds(low, &base, &size))
     66                        continue;
     67 
     68                pfn_t confdata;
     69                pfn_t pfn = ADDR2PFN(base);
     70                size_t count = SIZE2FRAMES(size);
     71
     72                if (low) {
     73                        confdata = pfn;
    6874                        if (confdata == ADDR2PFN(KA2PA(PFN2ADDR(0))))
    6975                                confdata = ADDR2PFN(KA2PA(PFN2ADDR(2)));
    7076                       
    71                         zone_create(ADDR2PFN(new_start), SIZE2FRAMES(new_size),
    72                             confdata, 0);
    73                        
    74                         last_frame = max(last_frame, new_start + new_size);
     77                        zone_create(pfn, count, confdata,
     78                            ZONE_AVAILABLE | ZONE_LOWMEM);
     79                } else {
     80                        confdata = zone_external_conf_alloc(count);
     81                        zone_create(pfn, count, confdata,
     82                            ZONE_AVAILABLE | ZONE_HIGHMEM);
    7583                }
     84        }
    7685               
    77                 /*
    78                  * On sparc64, physical memory can start on a non-zero address.
    79                  * The generic frame_init() only marks PFN 0 as not free, so we
    80                  * must mark the physically first frame not free explicitly
    81                  * here, no matter what is its address.
    82                  */
    83                 frame_mark_unavailable(ADDR2PFN(KA2PA(PFN2ADDR(0))), 1);
    84         }
     86}
     87
     88void frame_low_arch_init(void)
     89{
     90        if (config.cpu_active > 1)
     91                return;
    8592       
    86         end_of_identity = PA2KA(last_frame);
     93        frame_common_arch_init(true);
     94       
     95        /*
     96         * On sparc64, physical memory can start on a non-zero address.
     97         * The generic frame_init() only marks PFN 0 as not free, so we
     98         * must mark the physically first frame not free explicitly
     99         * here, no matter what is its address.
     100         */
     101        frame_mark_unavailable(ADDR2PFN(KA2PA(PFN2ADDR(0))), 1);
     102
     103        /* PA2KA will work only on low-memory. */
     104        end_of_identity = PA2KA(config.physmem_end - FRAME_SIZE) + PAGE_SIZE;
     105}
     106
     107void frame_high_arch_init(void)
     108{
     109        if (config.cpu_active > 1)
     110                return;
     111
     112        frame_common_arch_init(false);
    87113}
    88114
  • kernel/arch/sparc64/src/mm/sun4u/tlb.c

    r1761268 r7aaed09  
    206206        pte_t *t;
    207207
    208         page_table_lock(AS, true);
    209208        t = page_mapping_find(AS, page_16k, true);
    210209        if (t && PTE_EXECUTABLE(t)) {
     
    218217                itsb_pte_copy(t, index);
    219218#endif
    220                 page_table_unlock(AS, true);
    221219        } else {
    222220                /*
     
    224222                 * handler.
    225223                 */
    226                 page_table_unlock(AS, true);
    227224                if (as_page_fault(page_16k, PF_ACCESS_EXEC, istate) ==
    228225                    AS_PF_FAULT) {
     
    250247        size_t index;
    251248        pte_t *t;
     249        as_t *as = AS;
    252250
    253251        page_8k = (uint64_t) tag.vpn << MMU_PAGE_WIDTH;
     
    261259                            "Dereferencing NULL pointer.");
    262260                } else if (page_8k >= end_of_identity) {
    263                         /*
    264                          * The kernel is accessing the I/O space.
    265                          * We still do identity mapping for I/O,
    266                          * but without caching.
    267                          */
    268                         dtlb_insert_mapping(page_8k, KA2PA(page_8k),
    269                             PAGESIZE_8K, false, false);
    270                         return;
     261                        /* Kernel non-identity. */
     262                        as = AS_KERNEL;
     263                } else {
     264                        do_fast_data_access_mmu_miss_fault(istate, tag,
     265                    "Unexpected kernel page fault.");
    271266                }
    272                 do_fast_data_access_mmu_miss_fault(istate, tag, "Unexpected "
    273                     "kernel page fault.");
    274         }
    275 
    276         page_table_lock(AS, true);
    277         t = page_mapping_find(AS, page_16k, true);
     267        }
     268
     269        t = page_mapping_find(as, page_16k, true);
    278270        if (t) {
    279271                /*
     
    286278                dtsb_pte_copy(t, index, true);
    287279#endif
    288                 page_table_unlock(AS, true);
    289280        } else {
    290281                /*
    291282                 * Forward the page fault to the address space page fault
    292283                 * handler.
    293                  */             
    294                 page_table_unlock(AS, true);
     284                 */
    295285                if (as_page_fault(page_16k, PF_ACCESS_READ, istate) ==
    296286                    AS_PF_FAULT) {
     
    314304        size_t index;
    315305        pte_t *t;
     306        as_t *as = AS;
    316307
    317308        page_16k = ALIGN_DOWN((uint64_t) tag.vpn << MMU_PAGE_WIDTH, PAGE_SIZE);
    318309        index = tag.vpn % MMU_PAGES_PER_PAGE;   /* 16K-page emulation */
    319310
    320         page_table_lock(AS, true);
    321         t = page_mapping_find(AS, page_16k, true);
     311        if (tag.context == ASID_KERNEL)
     312                as = AS_KERNEL;
     313
     314        t = page_mapping_find(as, page_16k, true);
    322315        if (t && PTE_WRITABLE(t)) {
    323316                /*
     
    334327                dtsb_pte_copy(t, index, false);
    335328#endif
    336                 page_table_unlock(AS, true);
    337329        } else {
    338330                /*
     
    340332                 * handler.
    341333                 */             
    342                 page_table_unlock(AS, true);
    343334                if (as_page_fault(page_16k, PF_ACCESS_WRITE, istate) ==
    344335                    AS_PF_FAULT) {
  • kernel/arch/sparc64/src/mm/sun4v/frame.c

    r1761268 r7aaed09  
    4545 * Walk the memory map and create frame zones according to it.
    4646 */
    47 void frame_arch_init(void)
     47static void frame_common_arch_init(bool low)
    4848{
    49         if (config.cpu_active == 1) {
    50                 unsigned int i;
     49        unsigned int i;
    5150               
    52                 for (i = 0; i < memmap.cnt; i++) {
    53                         /* To be safe, make the available zone possibly smaller */
    54                         uintptr_t new_start = ALIGN_UP((uintptr_t) memmap.zones[i].start,
    55                             FRAME_SIZE);
    56                         size_t new_size = ALIGN_DOWN(memmap.zones[i].size -
    57                             (new_start - ((uintptr_t) memmap.zones[i].start)), FRAME_SIZE);
    58                        
    59                         /*
    60                          * The memmap is created by HelenOS boot loader.
    61                          * It already contains no holes.
    62                          */
    63                        
    64                         pfn_t confdata = ADDR2PFN(new_start);
    65                        
     51        for (i = 0; i < memmap.cnt; i++) {
     52                uintptr_t base;
     53                size_t size;
     54
     55                /*
     56                 * The memmap is created by HelenOS boot loader.
     57                 * It already contains no holes.
     58                 */
     59
     60                /* To be safe, make the available zone possibly smaller */
     61                base = ALIGN_UP((uintptr_t) memmap.zones[i].start, FRAME_SIZE);
     62                size = ALIGN_DOWN(memmap.zones[i].size -
     63                    (base - ((uintptr_t) memmap.zones[i].start)), FRAME_SIZE);
     64               
     65                if (!frame_adjust_zone_bounds(low, &base, &size))
     66                        continue;
     67
     68                pfn_t confdata;
     69                pfn_t pfn = ADDR2PFN(base);
     70                size_t count = SIZE2FRAMES(size);
     71
     72                if (low) {
     73                        confdata = pfn;
    6674                        if (confdata == ADDR2PFN(KA2PA(PFN2ADDR(0))))
    6775                                confdata = ADDR2PFN(KA2PA(PFN2ADDR(2)));
    6876                       
    69                         zone_create(ADDR2PFN(new_start), SIZE2FRAMES(new_size),
    70                             confdata, 0);
     77                        zone_create(pfn, count, confdata,
     78                            ZONE_AVAILABLE | ZONE_LOWMEM);
     79                } else {
     80                        confdata = zone_external_conf_alloc(count);
     81                        zone_create(pfn, count, confdata,
     82                            ZONE_AVAILABLE | ZONE_HIGHMEM);
    7183                }
     84        }
    7285               
    73                 /*
    74                  * On sparc64, physical memory can start on a non-zero address.
    75                  * The generic frame_init() only marks PFN 0 as not free, so we
    76                  * must mark the physically first frame not free explicitly
    77                  * here, no matter what is its address.
    78                  */
    79                 frame_mark_unavailable(ADDR2PFN(KA2PA(PFN2ADDR(0))), 1);
    80         }
     86}
     87
     88
     89void frame_low_arch_init(void)
     90{
     91        if (config.cpu_active > 1)
     92                return;
     93
     94        frame_common_arch_init(true);
     95
     96        /*
     97         * On sparc64, physical memory can start on a non-zero address.
     98         * The generic frame_init() only marks PFN 0 as not free, so we
     99         * must mark the physically first frame not free explicitly
     100         * here, no matter what is its address.
     101         */
     102        frame_mark_unavailable(ADDR2PFN(KA2PA(PFN2ADDR(0))), 1);
     103}
     104
     105void frame_high_arch_init(void)
     106{
     107        if (config.cpu_active > 1)
     108                return;
     109
     110        frame_common_arch_init(false);
    81111}
    82112
  • kernel/arch/sparc64/src/mm/sun4v/tlb.c

    r1761268 r7aaed09  
    218218        pte_t *t;
    219219
    220         page_table_lock(AS, true);
    221220        t = page_mapping_find(AS, va, true);
    222221
     
    231230                itsb_pte_copy(t);
    232231#endif
    233                 page_table_unlock(AS, true);
    234232        } else {
    235233                /*
     
    237235                 * handler.
    238236                 */
    239                 page_table_unlock(AS, true);
    240237                if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) {
    241238                        do_fast_instruction_access_mmu_miss_fault(istate,
     
    274271        }
    275272
    276         page_table_lock(AS, true);
    277273        t = page_mapping_find(AS, va, true);
    278274        if (t) {
     
    286282                dtsb_pte_copy(t, true);
    287283#endif
    288                 page_table_unlock(AS, true);
    289284        } else {
    290285                /*
     
    292287                 * handler.
    293288                 */             
    294                 page_table_unlock(AS, true);
    295289                if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
    296290                        do_fast_data_access_mmu_miss_fault(istate, page_and_ctx,
     
    316310        uint16_t ctx = DMISS_CONTEXT(page_and_ctx);
    317311
    318         page_table_lock(AS, true);
    319312        t = page_mapping_find(AS, va, true);
    320313        if (t && PTE_WRITABLE(t)) {
     
    331324                dtsb_pte_copy(t, false);
    332325#endif
    333                 page_table_unlock(AS, true);
    334326        } else {
    335327                /*
     
    337329                 * handler.
    338330                 */             
    339                 page_table_unlock(AS, true);
    340331                if (as_page_fault(va, PF_ACCESS_WRITE, istate) == AS_PF_FAULT) {
    341332                        do_fast_data_access_protection_fault(istate, page_and_ctx,
  • kernel/genarch/include/mm/page_ht.h

    r1761268 r7aaed09  
    4343#include <mm/as.h>
    4444#include <mm/page.h>
     45#include <mm/slab.h>
    4546#include <synch/mutex.h>
    4647#include <adt/hash_table.h>
     
    6465extern page_mapping_operations_t ht_mapping_operations;
    6566
     67extern slab_cache_t *pte_cache;
    6668extern mutex_t page_ht_lock;
    6769extern hash_table_t page_ht;
  • kernel/genarch/src/mm/as_ht.c

    r1761268 r7aaed09  
    4141#include <mm/as.h>
    4242#include <mm/frame.h>
     43#include <mm/slab.h>
    4344#include <typedefs.h>
    4445#include <memstr.h>
     
    7778                hash_table_create(&page_ht, PAGE_HT_ENTRIES, 2, &ht_operations);
    7879                mutex_initialize(&page_ht_lock, MUTEX_PASSIVE);
     80                pte_cache = slab_cache_create("pte_cache", sizeof(pte_t), 0, NULL, NULL,
     81                    SLAB_CACHE_MAGDEFERRED);
    7982        }
    8083       
  • kernel/genarch/src/mm/as_pt.c

    r1761268 r7aaed09  
    7373pte_t *ptl0_create(unsigned int flags)
    7474{
    75         pte_t *dst_ptl0 = (pte_t *) frame_alloc(PTL0_SIZE, FRAME_KA);
     75        pte_t *dst_ptl0 = (pte_t *) frame_alloc(PTL0_SIZE,
     76            FRAME_LOWMEM | FRAME_KA);
    7677        size_t table_size = FRAME_SIZE << PTL0_SIZE;
    7778       
     
    8990                    (pte_t *) PA2KA((uintptr_t) AS_KERNEL->genarch.page_table);
    9091               
    91                 uintptr_t src =
    92                     (uintptr_t) &src_ptl0[PTL0_INDEX(KERNEL_ADDRESS_SPACE_START)];
    93                 uintptr_t dst =
    94                     (uintptr_t) &dst_ptl0[PTL0_INDEX(KERNEL_ADDRESS_SPACE_START)];
     92                uintptr_t src = (uintptr_t)
     93                    &src_ptl0[PTL0_INDEX(KERNEL_ADDRESS_SPACE_START)];
     94                uintptr_t dst = (uintptr_t)
     95                    &dst_ptl0[PTL0_INDEX(KERNEL_ADDRESS_SPACE_START)];
    9596               
    9697                memsetb(dst_ptl0, table_size, 0);
  • kernel/genarch/src/mm/page_ht.c

    r1761268 r7aaed09  
    6060static pte_t *ht_mapping_find(as_t *, uintptr_t, bool);
    6161
     62slab_cache_t *pte_cache = NULL;
     63
    6264/**
    6365 * This lock protects the page hash table. It must be acquired
     
    163165        pte_t *pte = hash_table_get_instance(item, pte_t, link);
    164166       
    165         free(pte);
     167        slab_free(pte_cache, pte);
    166168}
    167169
     
    188190       
    189191        if (!hash_table_find(&page_ht, key)) {
    190                 pte_t *pte = (pte_t *) malloc(sizeof(pte_t), FRAME_ATOMIC);
     192                pte_t *pte = slab_alloc(pte_cache, FRAME_LOWMEM | FRAME_ATOMIC);
    191193                ASSERT(pte != NULL);
    192194               
  • kernel/genarch/src/mm/page_pt.c

    r1761268 r7aaed09  
    3939#include <mm/page.h>
    4040#include <mm/frame.h>
     41#include <mm/km.h>
    4142#include <mm/as.h>
    4243#include <arch/mm/page.h>
     
    7576       
    7677        if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) {
    77                 pte_t *newpt = (pte_t *) frame_alloc(PTL1_SIZE, FRAME_KA);
     78                pte_t *newpt = (pte_t *) frame_alloc(PTL1_SIZE,
     79                    FRAME_LOWMEM | FRAME_KA);
    7880                memsetb(newpt, FRAME_SIZE << PTL1_SIZE, 0);
    7981                SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page), KA2PA(newpt));
    80                 SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
     82                SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page),
     83                    PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
     84                    PAGE_WRITE);
    8185        }
    8286       
     
    8488       
    8589        if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) {
    86                 pte_t *newpt = (pte_t *) frame_alloc(PTL2_SIZE, FRAME_KA);
     90                pte_t *newpt = (pte_t *) frame_alloc(PTL2_SIZE,
     91                    FRAME_LOWMEM | FRAME_KA);
    8792                memsetb(newpt, FRAME_SIZE << PTL2_SIZE, 0);
    8893                SET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page), KA2PA(newpt));
    89                 SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
     94                SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page),
     95                    PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
     96                    PAGE_WRITE);
    9097        }
    9198       
     
    93100       
    94101        if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) {
    95                 pte_t *newpt = (pte_t *) frame_alloc(PTL3_SIZE, FRAME_KA);
     102                pte_t *newpt = (pte_t *) frame_alloc(PTL3_SIZE,
     103                    FRAME_LOWMEM | FRAME_KA);
    96104                memsetb(newpt, FRAME_SIZE << PTL3_SIZE, 0);
    97105                SET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page), KA2PA(newpt));
    98                 SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page), PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | PAGE_WRITE);
     106                SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page),
     107                    PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
     108                    PAGE_WRITE);
    99109        }
    100110       
     
    144154       
    145155        /*
    146          * Second, free all empty tables along the way from PTL3 down to PTL0.
    147          *
     156         * Second, free all empty tables along the way from PTL3 down to PTL0
     157         * except those needed for sharing the kernel non-identity mappings.
    148158         */
    149159       
     
    162172                /*
    163173                 * PTL3 is empty.
    164                  * Release the frame and remove PTL3 pointer from preceding table.
    165                  *
    166                  */
    167                 frame_free(KA2PA((uintptr_t) ptl3));
     174                 * Release the frame and remove PTL3 pointer from the parent
     175                 * table.
     176                 */
    168177#if (PTL2_ENTRIES != 0)
    169178                memsetb(&ptl2[PTL2_INDEX(page)], sizeof(pte_t), 0);
     
    171180                memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0);
    172181#else
     182                if (km_is_non_identity(page))
     183                        return;
     184
    173185                memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    174186#endif
     187                frame_free(KA2PA((uintptr_t) ptl3));
    175188        } else {
    176189                /*
     
    195208                /*
    196209                 * PTL2 is empty.
    197                  * Release the frame and remove PTL2 pointer from preceding table.
    198                  *
    199                  */
    200                 frame_free(KA2PA((uintptr_t) ptl2));
     210                 * Release the frame and remove PTL2 pointer from the parent
     211                 * table.
     212                 */
    201213#if (PTL1_ENTRIES != 0)
    202214                memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0);
    203215#else
     216                if (km_is_non_identity(page))
     217                        return;
     218
    204219                memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    205220#endif
     221                frame_free(KA2PA((uintptr_t) ptl2));
    206222        } else {
    207223                /*
     
    227243                /*
    228244                 * PTL1 is empty.
    229                  * Release the frame and remove PTL1 pointer from preceding table.
    230                  *
    231                  */
     245                 * Release the frame and remove PTL1 pointer from the parent
     246                 * table.
     247                 */
     248                if (km_is_non_identity(page))
     249                        return;
     250
     251                memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    232252                frame_free(KA2PA((uintptr_t) ptl1));
    233                 memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    234253        }
    235254#endif /* PTL1_ENTRIES != 0 */
  • kernel/generic/include/align.h

    r1761268 r7aaed09  
    4242 *
    4343 * @param s Address or size to be aligned.
    44  * @param a Size of alignment, must be power of 2.
     44 * @param a Size of alignment, must be a power of 2.
    4545 */
    4646#define ALIGN_DOWN(s, a)  ((s) & ~((a) - 1))
     
    5050 *
    5151 * @param s Address or size to be aligned.
    52  * @param a Size of alignment, must be power of 2.
     52 * @param a Size of alignment, must be a power of 2.
    5353 */
    5454#define ALIGN_UP(s, a)  (((s) + ((a) - 1)) & ~((a) - 1))
     55
     56/** Check alignment.
     57 *
     58 * @param s Address or size to be checked for alignment.
     59 * @param a Size of alignment, must be a power of 2.
     60 */
     61#define IS_ALIGNED(s, a)        (ALIGN_UP((s), (a)) == (s))
    5562
    5663#endif
  • kernel/generic/include/config.h

    r1761268 r7aaed09  
    7474
    7575typedef struct {
    76         unsigned int cpu_count;      /**< Number of processors detected. */
    77         volatile size_t cpu_active;  /**< Number of processors that are up and running. */
     76        /** Number of processors detected. */
     77        unsigned int cpu_count;
     78        /** Number of processors that are up and running. */
     79        volatile size_t cpu_active;
    7880       
    7981        uintptr_t base;
    80         size_t kernel_size;          /**< Size of memory in bytes taken by kernel and stack */
     82        /** Size of memory in bytes taken by kernel and stack. */
     83        size_t kernel_size;
    8184       
    82         uintptr_t stack_base;        /**< Base adddress of initial stack */
    83         size_t stack_size;           /**< Size of initial stack */
     85        /** Base adddress of initial stack. */
     86        uintptr_t stack_base;
     87        /** Size of initial stack. */
     88        size_t stack_size;
     89
     90        bool identity_configured;
     91        /** Base address of the kernel identity mapped memory. */
     92        uintptr_t identity_base;
     93        /** Size of the kernel identity mapped memory. */
     94        size_t identity_size;
     95
     96        bool non_identity_configured;   
     97
     98        /** End of physical memory. */
     99        uint64_t physmem_end;
    84100} config_t;
    85101
  • kernel/generic/include/macros.h

    r1761268 r7aaed09  
    7777#endif /* __ASM__ */
    7878
     79#define ispwr2(x)       (((x) & ((x) - 1)) == 0)
     80
    7981#define isdigit(d)     (((d) >= '0') && ((d) <= '9'))
    8082#define islower(c)     (((c) >= 'a') && ((c) <= 'z'))
  • kernel/generic/include/mm/frame.h

    r1761268 r7aaed09  
    5050typedef uint8_t frame_flags_t;
    5151
     52#define FRAME_NONE        0x0
    5253/** Convert the frame address to kernel VA. */
    5354#define FRAME_KA          0x1
     
    5859/** Do not reserve / unreserve memory. */
    5960#define FRAME_NO_RESERVE  0x8
     61/** Allocate a frame which can be identity-mapped. */
     62#define FRAME_LOWMEM      0x10
     63/** Allocate a frame which cannot be identity-mapped. */
     64#define FRAME_HIGHMEM     0x20
    6065
    6166typedef uint8_t zone_flags_t;
    6267
     68#define ZONE_NONE       0x0
    6369/** Available zone (free for allocation) */
    64 #define ZONE_AVAILABLE  0x0
     70#define ZONE_AVAILABLE  0x1
    6571/** Zone is reserved (not available for allocation) */
    66 #define ZONE_RESERVED   0x8
     72#define ZONE_RESERVED   0x2
    6773/** Zone is used by firmware (not available for allocation) */
    68 #define ZONE_FIRMWARE   0x10
     74#define ZONE_FIRMWARE   0x4
     75/** Zone contains memory that can be identity-mapped */
     76#define ZONE_LOWMEM     0x8
     77/** Zone contains memory that cannot be identity-mapped */
     78#define ZONE_HIGHMEM    0x10
    6979
    70 /** Currently there is no equivalent zone flags
    71     for frame flags */
    72 #define FRAME_TO_ZONE_FLAGS(frame_flags)  0
     80/** Mask of zone bits that must be matched exactly. */
     81#define ZONE_EF_MASK    0x7
     82
     83#define FRAME_TO_ZONE_FLAGS(ff) \
     84        ((((ff) & FRAME_LOWMEM) ? ZONE_LOWMEM : \
     85            (((ff) & FRAME_HIGHMEM) ? ZONE_HIGHMEM : ZONE_NONE)) | \
     86            (ZONE_AVAILABLE | ZONE_LOWMEM /* | ZONE_HIGHMEM */))
     87
     88#define ZONE_FLAGS_MATCH(zf, f) \
     89        (((((zf) & ZONE_EF_MASK)) == ((f) & ZONE_EF_MASK)) && \
     90            (((zf) & ~ZONE_EF_MASK) & (f)))
    7391
    7492typedef struct {
    7593        size_t refcount;      /**< Tracking of shared frames */
    76         uint8_t buddy_order;  /**< Buddy system block order */
    7794        link_t buddy_link;    /**< Link to the next free block inside
    7895                                   one order */
    7996        void *parent;         /**< If allocated by slab, this points there */
     97        uint8_t buddy_order;  /**< Buddy system block order */
    8098} frame_t;
    8199
     
    129147}
    130148
    131 NO_TRACE static inline bool zone_flags_available(zone_flags_t flags)
    132 {
    133         return ((flags & (ZONE_RESERVED | ZONE_FIRMWARE)) == 0);
    134 }
    135 
    136149#define IS_BUDDY_ORDER_OK(index, order) \
    137150    ((~(((sysarg_t) -1) << (order)) & (index)) == 0)
     
    146159
    147160extern void frame_init(void);
     161extern bool frame_adjust_zone_bounds(bool, uintptr_t *, size_t *);
    148162extern void *frame_alloc_generic(uint8_t, frame_flags_t, size_t *);
    149163extern void *frame_alloc(uint8_t, frame_flags_t);
     
    161175extern void frame_mark_unavailable(pfn_t, size_t);
    162176extern size_t zone_conf_size(size_t);
     177extern pfn_t zone_external_conf_alloc(size_t);
    163178extern bool zone_merge(size_t, size_t);
    164179extern void zone_merge_all(void);
  • kernel/generic/src/cpu/cpu.c

    r1761268 r7aaed09  
    7474                for (i = 0; i < config.cpu_count; i++) {
    7575                        cpus[i].stack = (uint8_t *) frame_alloc(STACK_FRAMES,
    76                             FRAME_KA | FRAME_ATOMIC);
     76                            FRAME_LOWMEM | FRAME_KA | FRAME_ATOMIC);
    7777                        cpus[i].id = i;
    7878                       
  • kernel/generic/src/main/main.c

    r1761268 r7aaed09  
    6868#include <mm/page.h>
    6969#include <genarch/mm/page_pt.h>
     70#include <mm/km.h>
    7071#include <mm/tlb.h>
    7172#include <mm/as.h>
     
    8889
    8990/** Global configuration structure. */
    90 config_t config;
     91config_t config = {
     92        .identity_configured = false,
     93        .non_identity_configured = false,
     94        .physmem_end = 0
     95};
    9196
    9297/** Initial user-space tasks */
     
    205210         */
    206211        arch_pre_mm_init();
     212        km_identity_init();
    207213        frame_init();
    208        
    209214        /* Initialize at least 1 memory segment big enough for slab to work. */
    210215        slab_cache_init();
     
    214219        page_init();
    215220        tlb_init();
     221        km_non_identity_init();
    216222        ddi_init();
    217223        arch_post_mm_init();
  • kernel/generic/src/mm/frame.c

    r1761268 r7aaed09  
    240240NO_TRACE static bool zone_can_alloc(zone_t *zone, uint8_t order)
    241241{
    242         return (zone_flags_available(zone->flags)
    243             && buddy_system_can_alloc(zone->buddy_system, order));
     242        return ((zone->flags & ZONE_AVAILABLE) &&
     243            buddy_system_can_alloc(zone->buddy_system, order));
    244244}
    245245
     
    265265                 * Check whether the zone meets the search criteria.
    266266                 */
    267                 if ((zones.info[i].flags & flags) == flags) {
     267                if (ZONE_FLAGS_MATCH(zones.info[i].flags, flags)) {
    268268                        /*
    269269                         * Check if the zone has 2^order frames area available.
     
    460460NO_TRACE static pfn_t zone_frame_alloc(zone_t *zone, uint8_t order)
    461461{
    462         ASSERT(zone_flags_available(zone->flags));
     462        ASSERT(zone->flags & ZONE_AVAILABLE);
    463463       
    464464        /* Allocate frames from zone buddy system */
     
    490490NO_TRACE static size_t zone_frame_free(zone_t *zone, size_t frame_idx)
    491491{
    492         ASSERT(zone_flags_available(zone->flags));
     492        ASSERT(zone->flags & ZONE_AVAILABLE);
    493493       
    494494        frame_t *frame = &zone->frames[frame_idx];
     
    518518NO_TRACE static void zone_mark_unavailable(zone_t *zone, size_t frame_idx)
    519519{
    520         ASSERT(zone_flags_available(zone->flags));
     520        ASSERT(zone->flags & ZONE_AVAILABLE);
    521521       
    522522        frame_t *frame = zone_get_frame(zone, frame_idx);
     
    549549    buddy_system_t *buddy)
    550550{
    551         ASSERT(zone_flags_available(zones.info[z1].flags));
    552         ASSERT(zone_flags_available(zones.info[z2].flags));
     551        ASSERT(zones.info[z1].flags & ZONE_AVAILABLE);
     552        ASSERT(zones.info[z2].flags & ZONE_AVAILABLE);
    553553        ASSERT(zones.info[z1].flags == zones.info[z2].flags);
    554554        ASSERT(zones.info[z1].base < zones.info[z2].base);
     
    645645NO_TRACE static void return_config_frames(size_t znum, pfn_t pfn, size_t count)
    646646{
    647         ASSERT(zone_flags_available(zones.info[znum].flags));
     647        ASSERT(zones.info[znum].flags & ZONE_AVAILABLE);
    648648       
    649649        size_t cframes = SIZE2FRAMES(zone_conf_size(count));
     
    681681    size_t count)
    682682{
    683         ASSERT(zone_flags_available(zones.info[znum].flags));
     683        ASSERT(zones.info[znum].flags & ZONE_AVAILABLE);
    684684        ASSERT(frame_idx + count < zones.info[znum].count);
    685685       
     
    723723         * set of flags
    724724         */
    725         if ((z1 >= zones.count) || (z2 >= zones.count)
    726             || (z2 - z1 != 1)
    727             || (!zone_flags_available(zones.info[z1].flags))
    728             || (!zone_flags_available(zones.info[z2].flags))
    729             || (zones.info[z1].flags != zones.info[z2].flags)) {
     725        if ((z1 >= zones.count) || (z2 >= zones.count) || (z2 - z1 != 1) ||
     726            (zones.info[z1].flags != zones.info[z2].flags)) {
    730727                ret = false;
    731728                goto errout;
     
    828825        zone->buddy_system = buddy;
    829826       
    830         if (zone_flags_available(flags)) {
     827        if (flags & ZONE_AVAILABLE) {
    831828                /*
    832829                 * Compute order for buddy system and initialize
     
    865862{
    866863        return (count * sizeof(frame_t) + buddy_conf_size(fnzb(count)));
     864}
     865
     866/** Allocate external configuration frames from low memory. */
     867pfn_t zone_external_conf_alloc(size_t count)
     868{
     869        size_t size = zone_conf_size(count);
     870        size_t order = ispwr2(size) ? fnzb(size) : (fnzb(size) + 1);
     871
     872        return ADDR2PFN((uintptr_t) frame_alloc(order - FRAME_WIDTH, FRAME_LOWMEM));
    867873}
    868874
     
    888894        irq_spinlock_lock(&zones.lock, true);
    889895       
    890         if (zone_flags_available(flags)) {  /* Create available zone */
     896        if (flags & ZONE_AVAILABLE) {  /* Create available zone */
    891897                /* Theoretically we could have NULL here, practically make sure
    892898                 * nobody tries to do that. If some platform requires, remove
     
    894900                 */
    895901                ASSERT(confframe != ADDR2PFN((uintptr_t ) NULL));
     902
     903                /* Update the known end of physical memory. */
     904                config.physmem_end = max(config.physmem_end, PFN2ADDR(start + count));
    896905               
    897906                /* If confframe is supposed to be inside our zone, then make sure
     
    12321241       
    12331242        /* Tell the architecture to create some memory */
    1234         frame_arch_init();
     1243        frame_low_arch_init();
    12351244        if (config.cpu_active == 1) {
    12361245                frame_mark_unavailable(ADDR2PFN(KA2PA(config.base)),
     
    12551264                frame_mark_unavailable(0, 1);
    12561265        }
     1266        frame_high_arch_init();
     1267}
     1268
     1269/** Adjust bounds of physical memory region according to low/high memory split.
     1270 *
     1271 * @param low[in]       If true, the adujstment is performed to make the region
     1272 *                      fit in the low memory. Otherwise the adjustment is
     1273 *                      performed to make the region fit in the high memory.
     1274 * @param basep[inout]  Pointer to a variable which contains the region's base
     1275 *                      address and which may receive the adjusted base address.
     1276 * @param sizep[inout]  Pointer to a variable which contains the region's size
     1277 *                      and which may receive the adjusted size.
     1278 * @retun               True if the region still exists even after the
     1279 *                      adjustment, false otherwise.
     1280 */
     1281bool frame_adjust_zone_bounds(bool low, uintptr_t *basep, size_t *sizep)
     1282{
     1283        uintptr_t limit = config.identity_size;
     1284
     1285        if (low) {
     1286                if (*basep > limit)
     1287                        return false;
     1288                if (*basep + *sizep > limit)
     1289                        *sizep = limit - *basep;
     1290        } else {
     1291                if (*basep + *sizep <= limit)
     1292                        return false;
     1293                if (*basep <= limit) {
     1294                        *sizep -= limit - *basep;
     1295                        *basep = limit;
     1296                }
     1297        }
     1298        return true;
    12571299}
    12581300
     
    12931335                *total += (uint64_t) FRAMES2SIZE(zones.info[i].count);
    12941336               
    1295                 if (zone_flags_available(zones.info[i].flags)) {
     1337                if (zones.info[i].flags & ZONE_AVAILABLE) {
    12961338                        *busy += (uint64_t) FRAMES2SIZE(zones.info[i].busy_count);
    12971339                        *free += (uint64_t) FRAMES2SIZE(zones.info[i].free_count);
     
    13441386                irq_spinlock_unlock(&zones.lock, true);
    13451387               
    1346                 bool available = zone_flags_available(flags);
     1388                bool available = ((flags & ZONE_AVAILABLE) != 0);
    13471389               
    13481390                printf("%-4zu", i);
     
    13561398#endif
    13571399               
    1358                 printf(" %12zu %c%c%c      ", count,
    1359                     available ? 'A' : ' ',
    1360                     (flags & ZONE_RESERVED) ? 'R' : ' ',
    1361                     (flags & ZONE_FIRMWARE) ? 'F' : ' ');
     1400                printf(" %12zu %c%c%c%c%c    ", count,
     1401                    available ? 'A' : '-',
     1402                    (flags & ZONE_RESERVED) ? 'R' : '-',
     1403                    (flags & ZONE_FIRMWARE) ? 'F' : '-',
     1404                    (flags & ZONE_LOWMEM) ? 'L' : '-',
     1405                    (flags & ZONE_HIGHMEM) ? 'H' : '-');
    13621406               
    13631407                if (available)
     
    14011445        irq_spinlock_unlock(&zones.lock, true);
    14021446       
    1403         bool available = zone_flags_available(flags);
     1447        bool available = ((flags & ZONE_AVAILABLE) != 0);
    14041448       
    14051449        uint64_t size;
     
    14111455        printf("Zone size:         %zu frames (%" PRIu64 " %s)\n", count,
    14121456            size, size_suffix);
    1413         printf("Zone flags:        %c%c%c\n",
    1414             available ? 'A' : ' ',
    1415             (flags & ZONE_RESERVED) ? 'R' : ' ',
    1416             (flags & ZONE_FIRMWARE) ? 'F' : ' ');
     1457        printf("Zone flags:        %c%c%c%c%c\n",
     1458            available ? 'A' : '-',
     1459            (flags & ZONE_RESERVED) ? 'R' : '-',
     1460            (flags & ZONE_FIRMWARE) ? 'F' : '-',
     1461            (flags & ZONE_LOWMEM) ? 'L' : '-',
     1462            (flags & ZONE_HIGHMEM) ? 'H' : '-');
    14171463       
    14181464        if (available) {
  • kernel/generic/src/mm/page.c

    r1761268 r7aaed09  
    6565#include <arch/mm/asid.h>
    6666#include <mm/as.h>
     67#include <mm/km.h>
    6768#include <mm/frame.h>
    6869#include <arch/barrier.h>
     
    177178}
    178179
     180uintptr_t hw_map(uintptr_t physaddr, size_t size)
     181{
     182        uintptr_t virtaddr;
     183        size_t asize;
     184        pfn_t i;
     185
     186        asize = ALIGN_UP(size, PAGE_SIZE);
     187        virtaddr = km_page_alloc(asize, PAGE_SIZE);
     188
     189        page_table_lock(AS_KERNEL, true);
     190        for (i = 0; i < ADDR2PFN(asize); i++) {
     191                uintptr_t addr = PFN2ADDR(i);
     192                page_mapping_insert(AS_KERNEL, virtaddr + addr, physaddr + addr,
     193                    PAGE_NOT_CACHEABLE | PAGE_WRITE);
     194        }
     195        page_table_unlock(AS_KERNEL, true);
     196       
     197        return virtaddr;
     198}
     199
    179200int page_find_mapping(uintptr_t virt, void **phys)
    180201{
  • kernel/generic/src/mm/reserve.c

    r1761268 r7aaed09  
    4242#include <typedefs.h>
    4343#include <arch/types.h>
     44#include <debug.h>
     45
     46static bool reserve_initialized = false;
    4447
    4548IRQ_SPINLOCK_STATIC_INITIALIZE_NAME(reserve_lock, "reserve_lock");
     
    5457{
    5558        reserve = frame_total_free_get();
     59        reserve_initialized = true;
    5660}
    5761
     
    6771{
    6872        bool reserved = false;
     73
     74        ASSERT(reserve_initialized);
    6975
    7076        irq_spinlock_lock(&reserve_lock, true);
     
    111117void reserve_force_alloc(size_t size)
    112118{
     119        if (!reserve_initialized)
     120                return;
     121
    113122        irq_spinlock_lock(&reserve_lock, true);
    114123        reserve -= size;
     
    122131void reserve_free(size_t size)
    123132{
     133        if (!reserve_initialized)
     134                return;
     135
    124136        irq_spinlock_lock(&reserve_lock, true);
    125137        reserve += size;
  • kernel/generic/src/proc/thread.c

    r1761268 r7aaed09  
    173173#endif /* CONFIG_FPU */
    174174       
     175        /*
     176         * Allocate the kernel stack from the low-memory to prevent an infinite
     177         * nesting of TLB-misses when accessing the stack from the part of the
     178         * TLB-miss handler written in C.
     179         *
     180         * Note that low-memory is safe to be used for the stack as it will be
     181         * covered by the kernel identity mapping, which guarantees not to
     182         * nest TLB-misses infinitely (either via some hardware mechanism or
     183         * by the construciton of the assembly-language part of the TLB-miss
     184         * handler).
     185         *
     186         * This restriction can be lifted once each architecture provides
     187         * a similar guarantee, for example by locking the kernel stack
     188         * in the TLB whenever it is allocated from the high-memory and the
     189         * thread is being scheduled to run.
     190         */
     191        kmflags |= FRAME_LOWMEM;
     192        kmflags &= ~FRAME_HIGHMEM;
     193
    175194        thread->kstack = (uint8_t *) frame_alloc(STACK_FRAMES, FRAME_KA | kmflags);
    176195        if (!thread->kstack) {
Note: See TracChangeset for help on using the changeset viewer.