Changeset c520034 in mainline


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

Support for kernel non-identity mappings, phase I.

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

Breakage:

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

Not implemented yet (phase II):

  • allow high memory to be used for common kernel allocations
Location:
kernel
Files:
26 added
72 edited

Legend:

Unmodified
Added
Removed
  • kernel/Makefile

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

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

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

    r852052d rc520034  
    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/arch.h

    r852052d rc520034  
    3636#define KERN_ia64_ARCH_H_
    3737
    38 #include <arch/drivers/ski.h>
    39 
    4038extern void arch_pre_main(void);
    4139
  • kernel/arch/ia64/include/asm.h

    r852052d rc520034  
    3939#include <typedefs.h>
    4040#include <arch/register.h>
     41#include <arch/legacyio.h>
    4142#include <trace.h>
    4243
    43 #define IA64_IOSPACE_ADDRESS  0xE001000000000000ULL
    44 
    4544#define IO_SPACE_BOUNDARY       ((void *) (64 * 1024))
    4645
     46/** Map the I/O port address to a legacy I/O address. */
     47NO_TRACE static inline uintptr_t p2a(volatile void *p)
     48{
     49        uintptr_t prt = (uintptr_t) p;
     50
     51        return legacyio_virt_base + (((prt >> 2) << 12) | (prt & 0xfff));
     52}
     53       
    4754NO_TRACE static inline void pio_write_8(ioport8_t *port, uint8_t v)
    4855{
    49         if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
    50                 uintptr_t prt = (uintptr_t) port;
    51        
    52                 *((ioport8_t *) (IA64_IOSPACE_ADDRESS +
    53                     ((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
    54         } else {
     56        if (port < (ioport8_t *) IO_SPACE_BOUNDARY)
     57                *((ioport8_t *) p2a(port)) = v;
     58        else
    5559                *port = v;
    56         }
    5760       
    5861        asm volatile (
     
    6467NO_TRACE static inline void pio_write_16(ioport16_t *port, uint16_t v)
    6568{
    66         if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
    67                 uintptr_t prt = (uintptr_t) port;
    68        
    69                 *((ioport16_t *) (IA64_IOSPACE_ADDRESS +
    70                     ((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
    71         } else {
     69        if (port < (ioport16_t *) IO_SPACE_BOUNDARY)
     70                *((ioport16_t *) p2a(port)) = v;
     71        else
    7272                *port = v;
    73         }
    7473       
    7574        asm volatile (
     
    8180NO_TRACE static inline void pio_write_32(ioport32_t *port, uint32_t v)
    8281{
    83         if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
    84                 uintptr_t prt = (uintptr_t) port;
    85        
    86                 *((ioport32_t *) (IA64_IOSPACE_ADDRESS +
    87                     ((prt & 0xfff) | ((prt >> 2) << 12)))) = v;
    88         } else {
     82        if (port < (ioport32_t *) IO_SPACE_BOUNDARY)
     83                *((ioport32_t *) p2a(port)) = v;
     84        else
    8985                *port = v;
    90         }
    9186       
    9287        asm volatile (
     
    105100        );
    106101
    107         if (port < (ioport8_t *) IO_SPACE_BOUNDARY) {
    108                 uintptr_t prt = (uintptr_t) port;
    109 
    110                 v = *((ioport8_t *) (IA64_IOSPACE_ADDRESS +
    111                     ((prt & 0xfff) | ((prt >> 2) << 12))));
    112         } else {
     102        if (port < (ioport8_t *) IO_SPACE_BOUNDARY)
     103                v = *((ioport8_t *) p2a(port));
     104        else
    113105                v = *port;
    114         }
    115106       
    116107        return v;
     
    126117        );
    127118
    128         if (port < (ioport16_t *) IO_SPACE_BOUNDARY) {
    129                 uintptr_t prt = (uintptr_t) port;
    130 
    131                 v = *((ioport16_t *) (IA64_IOSPACE_ADDRESS +
    132                     ((prt & 0xfff) | ((prt >> 2) << 12))));
    133         } else {
     119        if (port < (ioport16_t *) IO_SPACE_BOUNDARY)
     120                v = *((ioport16_t *) p2a(port));
     121        else
    134122                v = *port;
    135         }
    136123       
    137124        return v;
     
    147134        );
    148135       
    149         if (port < (ioport32_t *) IO_SPACE_BOUNDARY) {
    150                 uintptr_t prt = (uintptr_t) port;
    151                
    152                 v = *((ioport32_t *) (IA64_IOSPACE_ADDRESS +
    153                     ((prt & 0xfff) | ((prt >> 2) << 12))));
    154         } else {
     136        if (port < (ioport32_t *) IO_SPACE_BOUNDARY)
     137                v = *((ioport32_t *) p2a(port));
     138        else
    155139                v = *port;
    156         }
    157140
    158141        return v;
  • kernel/arch/ia64/include/mm/frame.h

    r852052d rc520034  
    4343#include <typedefs.h>
    4444
    45 extern uintptr_t last_frame;
     45extern uintptr_t end_of_identity;
    4646
    47 extern void frame_arch_init(void);
     47extern void frame_low_arch_init(void);
     48extern void frame_high_arch_init(void);
    4849#define physmem_print()
    4950
  • kernel/arch/ia64/include/mm/page.h

    r852052d rc520034  
    4343
    4444/** Bit width of the TLB-locked portion of kernel address space. */
    45 #define KERNEL_PAGE_WIDTH  28  /* 256M */
    46 #define IO_PAGE_WIDTH      26  /* 64M */
    47 #define FW_PAGE_WIDTH      28  /* 256M */
    48 
    49 #define USPACE_IO_PAGE_WIDTH  12  /* 4K */
    50 
    51 
    52 /*
    53  * Statically mapped IO spaces - offsets to 0xe...00 of virtual addresses
    54  * because of "minimal virtual bits implemented is 51" it is possible to
    55  * have values up to 0x0007000000000000
    56  */
    57 
    58 /* Firmware area (bellow 4GB in phys mem) */
    59 #define FW_OFFSET   0x00000000F0000000
    60 /* Legacy IO space */
    61 #define IO_OFFSET   0x0001000000000000
    62 /* Videoram - now mapped to 0 as VGA text mode vram on 0xb8000 */
    63 #define VIO_OFFSET  0x0002000000000000
    64 
     45#define KERNEL_PAGE_WIDTH       28      /* 256M */
    6546
    6647#define PPN_SHIFT  12
  • kernel/arch/ia64/src/ia64.c

    r852052d rc520034  
    4545#include <arch/drivers/it.h>
    4646#include <arch/drivers/kbd.h>
     47#include <arch/legacyio.h>
    4748#include <genarch/drivers/ega/ega.h>
    4849#include <genarch/drivers/i8042/i8042.h>
     
    5152#include <genarch/kbrd/kbrd.h>
    5253#include <genarch/srln/srln.h>
     54#include <mm/page.h>
     55
     56#ifdef MACHINE_ski
     57#include <arch/drivers/ski.h>
     58#endif
    5359
    5460/* NS16550 as a COM 1 */
     
    5864
    5965static uint64_t iosapic_base = 0xfec00000;
     66uintptr_t legacyio_virt_base = 0;
    6067
    6168/** Performs ia64-specific initialization before main_bsp() is called. */
     
    8087static void iosapic_init(void)
    8188{
    82         uint64_t IOSAPIC = PA2KA((sysarg_t)(iosapic_base)) | FW_OFFSET;
     89        uintptr_t IOSAPIC = hw_map(iosapic_base, PAGE_SIZE);
    8390        int i;
    8491       
     
    107114{
    108115        if (config.cpu_active == 1) {
     116                /* Map the page with legacy I/O. */
     117                legacyio_virt_base = hw_map(LEGACYIO_PHYS_BASE, LEGACYIO_SIZE);
     118
    109119                iosapic_init();
    110120                irq_init(INR_COUNT, INR_COUNT);
     
    113123}
    114124
    115 void arch_post_cpu_init(void)
    116 {
     125void arch_post_cpu_init(void){
    117126}
    118127
     
    202211        sysinfo_set_item_val("ia64_iospace", NULL, true);
    203212        sysinfo_set_item_val("ia64_iospace.address", NULL, true);
    204         sysinfo_set_item_val("ia64_iospace.address.virtual", NULL, IO_OFFSET);
     213        sysinfo_set_item_val("ia64_iospace.address.virtual", NULL, LEGACYIO_USER_BASE);
    205214}
    206215
  • kernel/arch/ia64/src/mm/frame.c

    r852052d rc520034  
    5151#define MINCONF 1
    5252
    53 uintptr_t last_frame = 0;
     53uintptr_t end_of_identity = -1ULL;
    5454
    55 void frame_arch_init(void)
     55static void frame_common_arch_init(bool low)
    5656{
    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        unsigned int i;
    6458
    65                                 if (size > FRAME_SIZE)
    66                                         size -= abase - base;
     59        for (i = 0; i < bootinfo->memmap_items; i++) {
     60                if (bootinfo->memmap[i].type != MEMMAP_FREE_MEM)
     61                        continue;
    6762
    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;
     63                uintptr_t base = bootinfo->memmap[i].base;
     64                size_t size = bootinfo->memmap[i].size;
     65                uintptr_t abase = ALIGN_UP(base, FRAME_SIZE);
     66
     67                if (size > FRAME_SIZE)
     68                        size -= abase - base;
     69
     70                if (!frame_adjust_zone_bounds(low, &abase, &size))
     71                        continue;
     72
     73                if (size > MIN_ZONE_SIZE) {
     74                        pfn_t pfn = ADDR2PFN(abase);
     75                        size_t count = SIZE2FRAMES(size);
     76
     77                        if (low) {
     78                                zone_create(pfn, count, max(MINCONF, pfn),
     79                                    ZONE_AVAILABLE | ZONE_LOWMEM);
     80                        } else {
     81                                pfn_t conf;
     82
     83                                conf = zone_external_conf_alloc(count);
     84                                zone_create(pfn, count, conf,
     85                                    ZONE_AVAILABLE | ZONE_HIGHMEM);
    7686                        }
    7787                }
    78                
    79                 /*
    80                  * Blacklist ROM regions.
    81                  */
    82                 frame_mark_unavailable(ADDR2PFN(ROM_BASE),
    83                     SIZE2FRAMES(ROM_SIZE));
     88        }
     89}
    8490
    85                 frame_mark_unavailable(ADDR2PFN(KERNEL_RESERVED_AREA_BASE),
    86                     SIZE2FRAMES(KERNEL_RESERVED_AREA_SIZE));
    87         }       
     91void frame_low_arch_init(void)
     92{
     93        if (config.cpu_active > 1)
     94                return;
     95       
     96        frame_common_arch_init(true);
     97       
     98        /*
     99         * Blacklist ROM regions.
     100         */
     101        frame_mark_unavailable(ADDR2PFN(ROM_BASE),
     102            SIZE2FRAMES(ROM_SIZE));
     103
     104        frame_mark_unavailable(ADDR2PFN(KERNEL_RESERVED_AREA_BASE),
     105            SIZE2FRAMES(KERNEL_RESERVED_AREA_SIZE));
     106
     107        /* PA2KA will work only on low-memory. */
     108        end_of_identity = PA2KA(config.physmem_end - FRAME_SIZE) + PAGE_SIZE;
     109}
     110
     111void frame_high_arch_init(void)
     112{
     113        if (config.cpu_active > 1)
     114                return;
     115       
     116        frame_common_arch_init(false);
    88117}
    89118
  • kernel/arch/ia64/src/mm/page.c

    r852052d rc520034  
    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

    r852052d rc520034  
    5252#include <arch.h>
    5353#include <interrupt.h>
    54 
    55 #define IO_FRAME_BASE 0xFFFFC000000
     54#include <arch/legacyio.h>
    5655
    5756/** Invalidate all TLB entries. */
     
    467466}
    468467
     468static bool is_kernel_fault(uintptr_t va)
     469{
     470        region_register_t rr;
     471
     472        rr.word = rr_read(VA2VRN(va));
     473        rid_t rid = rr.map.rid;
     474        return (RID2ASID(rid) == ASID_KERNEL) && (VA2VRN(va) == VRN_KERNEL);
     475}
     476
    469477/** Instruction TLB fault handler for faults with VHPT turned off.
    470478 *
     
    480488        va = istate->cr_ifa; /* faulting address */
    481489       
    482         page_table_lock(AS, true);
     490        ASSERT(!is_kernel_fault(va));
     491
    483492        t = page_mapping_find(AS, va, true);
    484493        if (t) {
     
    488497                 */
    489498                itc_pte_copy(t);
    490                 page_table_unlock(AS, true);
    491499        } else {
    492500                /*
    493501                 * Forward the page fault to address space page fault handler.
    494502                 */
    495                 page_table_unlock(AS, true);
    496503                if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) {
    497504                        fault_if_from_uspace(istate, "Page fault at %p.",
     
    522529static int try_memmap_io_insertion(uintptr_t va, istate_t *istate)
    523530{
    524         if ((va >= IO_OFFSET ) && (va < IO_OFFSET + (1 << IO_PAGE_WIDTH))) {
     531        if ((va >= LEGACYIO_USER_BASE) && (va < LEGACYIO_USER_BASE + (1 << LEGACYIO_PAGE_WIDTH))) {
    525532                if (TASK) {
    526                         uint64_t io_page = (va & ((1 << IO_PAGE_WIDTH) - 1)) >>
    527                             USPACE_IO_PAGE_WIDTH;
     533                        uint64_t io_page = (va & ((1 << LEGACYIO_PAGE_WIDTH) - 1)) >>
     534                            LEGACYIO_SINGLE_PAGE_WIDTH;
    528535                       
    529536                        if (is_io_page_accessible(io_page)) {
    530537                                uint64_t page, frame;
    531538                               
    532                                 page = IO_OFFSET +
    533                                     (1 << USPACE_IO_PAGE_WIDTH) * io_page;
    534                                 frame = IO_FRAME_BASE +
    535                                     (1 << USPACE_IO_PAGE_WIDTH) * io_page;
     539                                page = LEGACYIO_USER_BASE +
     540                                    (1 << LEGACYIO_SINGLE_PAGE_WIDTH) * io_page;
     541                                frame = LEGACYIO_PHYS_BASE +
     542                                    (1 << LEGACYIO_SINGLE_PAGE_WIDTH) * io_page;
    536543                               
    537544                                tlb_entry_t entry;
     
    547554                                entry.ar = AR_READ | AR_WRITE;
    548555                                entry.ppn = frame >> PPN_SHIFT;
    549                                 entry.ps = USPACE_IO_PAGE_WIDTH;
     556                                entry.ps = LEGACYIO_SINGLE_PAGE_WIDTH;
    550557                               
    551558                                dtc_mapping_insert(page, TASK->as->asid, entry);
     
    570577{
    571578        if (istate->cr_isr.sp) {
    572                 /* Speculative load. Deffer the exception
    573                    until a more clever approach can be used.
    574                   
    575                    Currently if we try to find the mapping
    576                    for the speculative load while in the kernel,
    577                    we might introduce a livelock because of
    578                    the possibly invalid values of the address. */
     579                /*
     580                 * Speculative load. Deffer the exception until a more clever
     581                 * approach can be used. Currently if we try to find the
     582                 * mapping for the speculative load while in the kernel, we
     583                 * might introduce a livelock because of the possibly invalid
     584                 * values of the address.
     585                 */
    579586                istate->cr_ipsr.ed = true;
    580587                return;
     
    582589       
    583590        uintptr_t va = istate->cr_ifa;  /* faulting address */
    584        
    585         region_register_t rr;
    586         rr.word = rr_read(VA2VRN(va));
    587         rid_t rid = rr.map.rid;
    588         if (RID2ASID(rid) == ASID_KERNEL) {
    589                 if (VA2VRN(va) == VRN_KERNEL) {
     591        as_t *as = AS;
     592       
     593        if (is_kernel_fault(va)) {
     594                if (va < end_of_identity) {
    590595                        /*
    591                          * Provide KA2PA(identity) mapping for faulting piece of
    592                          * kernel address space.
     596                         * Create kernel identity mapping for low memory.
    593597                         */
    594598                        dtlb_kernel_mapping_insert(va, KA2PA(va), false, 0);
    595599                        return;
     600                } else {
     601                        as = AS_KERNEL;
    596602                }
    597603        }
    598604       
    599605       
    600         page_table_lock(AS, true);
    601         pte_t *entry = page_mapping_find(AS, va, true);
     606        pte_t *entry = page_mapping_find(as, va, true);
    602607        if (entry) {
    603608                /*
     
    606611                 */
    607612                dtc_pte_copy(entry);
    608                 page_table_unlock(AS, true);
    609613        } else {
    610                 page_table_unlock(AS, true);
    611614                if (try_memmap_io_insertion(va, istate))
    612615                        return;
     
    647650        uintptr_t va;
    648651        pte_t *t;
     652        as_t *as = AS;
    649653       
    650654        va = istate->cr_ifa;  /* faulting address */
    651655       
    652         page_table_lock(AS, true);
    653         t = page_mapping_find(AS, va, true);
     656        if (is_kernel_fault(va))
     657                as = AS_KERNEL;
     658
     659        t = page_mapping_find(as, va, true);
    654660        ASSERT((t) && (t->p));
    655661        if ((t) && (t->p) && (t->w)) {
     
    667673                }
    668674        }
    669         page_table_unlock(AS, true);
    670675}
    671676
     
    682687       
    683688        va = istate->cr_ifa;  /* faulting address */
    684        
    685         page_table_lock(AS, true);
     689
     690        ASSERT(!is_kernel_fault(va));
     691       
    686692        t = page_mapping_find(AS, va, true);
    687693        ASSERT((t) && (t->p));
     
    700706                }
    701707        }
    702         page_table_unlock(AS, true);
    703708}
    704709
     
    713718        uintptr_t va;
    714719        pte_t *t;
     720        as_t *as = AS;
    715721       
    716722        va = istate->cr_ifa;  /* faulting address */
    717723       
    718         page_table_lock(AS, true);
    719         t = page_mapping_find(AS, va, true);
     724        if (is_kernel_fault(va))
     725                as = AS_KERNEL;
     726
     727        t = page_mapping_find(as, va, true);
    720728        ASSERT((t) && (t->p));
    721729        if ((t) && (t->p)) {
     
    733741                }
    734742        }
    735         page_table_unlock(AS, true);
    736743}
    737744
     
    748755       
    749756        va = istate->cr_ifa;  /* faulting address */
     757
     758        ASSERT(!is_kernel_fault(va));
    750759       
    751760        /*
    752761         * Assume a write to a read-only page.
    753762         */
    754         page_table_lock(AS, true);
    755763        t = page_mapping_find(AS, va, true);
    756764        ASSERT((t) && (t->p));
     
    761769                panic_memtrap(istate, PF_ACCESS_WRITE, va, NULL);
    762770        }
    763         page_table_unlock(AS, true);
    764771}
    765772
     
    777784        va = istate->cr_ifa;  /* faulting address */
    778785       
    779         page_table_lock(AS, true);
     786        ASSERT(!is_kernel_fault(va));
     787
    780788        t = page_mapping_find(AS, va, true);
    781789        ASSERT(t);
     
    790798                else
    791799                        dtc_pte_copy(t);
    792                 page_table_unlock(AS, true);
    793800        } else {
    794                 page_table_unlock(AS, true);
    795801                if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
    796802                        fault_if_from_uspace(istate, "Page fault at %p.",
  • kernel/arch/ia64/src/start.S

    r852052d rc520034  
    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
    4340
    4441.section K_TEXT_START, "ax"
     
    8885        itr.d dtr[r0] = r10
    8986       
    90         movl r7 = 1
    91         movl r8 = (VRN_KERNEL << VRN_SHIFT) | VIO_OFFSET
    92         mov cr.ifa = r8
    93         movl r10 = (KERNEL_TRANSLATION_VIO)
    94         itr.d dtr[r7] = r10
    95        
    96         mov r11 = cr.itir
    97         movl r10 = ~0xfc
    98         and r10 = r10, r11
    99         movl r11 = (IO_PAGE_WIDTH << PS_SHIFT)
    100         or r10 = r10, r11
    101         mov cr.itir = r10
    102        
    103         movl r7 = 2
    104         movl r8 = (VRN_KERNEL << VRN_SHIFT) | IO_OFFSET
    105         mov cr.ifa = r8
    106         movl r10 = (KERNEL_TRANSLATION_IO)
    107         itr.d dtr[r7] = r10
    108        
    109         # Setup mapping for firmware area (also SAPIC)
    110        
    111         mov r11 = cr.itir
    112         movl r10 = ~0xfc
    113         and r10 = r10, r11
    114         movl r11 = (FW_PAGE_WIDTH << PS_SHIFT)
    115         or r10 = r10, r11
    116         mov cr.itir = r10
    117        
    118         movl r7 = 3
    119         movl r8 = (VRN_KERNEL << VRN_SHIFT) | FW_OFFSET
    120         mov cr.ifa = r8
    121         movl r10 = (KERNEL_TRANSLATION_FW)
    122         itr.d dtr[r7] = r10
    123        
    124         # Initialize DSR
     87        # Initialize DCR
    12588       
    12689        movl r10 = (DCR_DP_MASK | DCR_DK_MASK | DCR_DX_MASK | DCR_DR_MASK | DCR_DA_MASK | DCR_DD_MASK | DCR_LC_MASK)
  • kernel/arch/mips32/Makefile.inc

    r852052d rc520034  
    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/as.h

    r852052d rc520034  
    3939
    4040#define KERNEL_ADDRESS_SPACE_START_ARCH  UINT32_C(0x80000000)
    41 #define KERNEL_ADDRESS_SPACE_END_ARCH    UINT32_C(0x9fffffff)
     41#define KERNEL_ADDRESS_SPACE_END_ARCH    UINT32_C(0xffffffff)
    4242#define USER_ADDRESS_SPACE_START_ARCH    UINT32_C(0x00000000)
    4343#define USER_ADDRESS_SPACE_END_ARCH      UINT32_C(0x7fffffff)
  • kernel/arch/mips32/include/mm/frame.h

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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/mips32/src/mm/tlb.c

    r852052d rc520034  
    9595       
    9696        badvaddr = cp0_badvaddr_read();
    97        
    98         mutex_lock(&AS->lock);
    9997        asid = AS->asid;
    100         mutex_unlock(&AS->lock);
    10198       
    10299        pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate, &pfrc);
  • kernel/arch/mips64/Makefile.inc

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    5959static void ht_mapping_remove(as_t *, uintptr_t);
    6060static pte_t *ht_mapping_find(as_t *, uintptr_t, bool);
     61static void ht_mapping_make_global(uintptr_t, size_t);
     62
     63slab_cache_t *pte_cache = NULL;
    6164
    6265/**
     
    8689        .mapping_insert = ht_mapping_insert,
    8790        .mapping_remove = ht_mapping_remove,
    88         .mapping_find = ht_mapping_find
     91        .mapping_find = ht_mapping_find,
     92        .mapping_make_global = ht_mapping_make_global
    8993};
    9094
     
    163167        pte_t *pte = hash_table_get_instance(item, pte_t, link);
    164168       
    165         free(pte);
     169        slab_free(pte_cache, pte);
    166170}
    167171
     
    188192       
    189193        if (!hash_table_find(&page_ht, key)) {
    190                 pte_t *pte = (pte_t *) malloc(sizeof(pte_t), FRAME_ATOMIC);
     194                pte_t *pte = slab_alloc(pte_cache, FRAME_LOWMEM | FRAME_ATOMIC);
    191195                ASSERT(pte != NULL);
    192196               
     
    260264}
    261265
     266void ht_mapping_make_global(uintptr_t base, size_t size)
     267{
     268        /* nothing to do */
     269}
     270
    262271/** @}
    263272 */
  • kernel/genarch/src/mm/page_pt.c

    r852052d rc520034  
    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>
     
    4546#include <arch/asm.h>
    4647#include <memstr.h>
     48#include <align.h>
     49#include <macros.h>
    4750
    4851static void pt_mapping_insert(as_t *, uintptr_t, uintptr_t, unsigned int);
    4952static void pt_mapping_remove(as_t *, uintptr_t);
    5053static pte_t *pt_mapping_find(as_t *, uintptr_t, bool);
     54static void pt_mapping_make_global(uintptr_t, size_t);
    5155
    5256page_mapping_operations_t pt_mapping_operations = {
    5357        .mapping_insert = pt_mapping_insert,
    5458        .mapping_remove = pt_mapping_remove,
    55         .mapping_find = pt_mapping_find
     59        .mapping_find = pt_mapping_find,
     60        .mapping_make_global = pt_mapping_make_global
    5661};
    5762
     
    7580       
    7681        if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT) {
    77                 pte_t *newpt = (pte_t *) frame_alloc(PTL1_SIZE, FRAME_KA);
     82                pte_t *newpt = (pte_t *) frame_alloc(PTL1_SIZE,
     83                    FRAME_LOWMEM | FRAME_KA);
    7884                memsetb(newpt, FRAME_SIZE << PTL1_SIZE, 0);
    7985                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);
     86                SET_PTL1_FLAGS(ptl0, PTL0_INDEX(page),
     87                    PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
     88                    PAGE_WRITE);
    8189        }
    8290       
     
    8492       
    8593        if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT) {
    86                 pte_t *newpt = (pte_t *) frame_alloc(PTL2_SIZE, FRAME_KA);
     94                pte_t *newpt = (pte_t *) frame_alloc(PTL2_SIZE,
     95                    FRAME_LOWMEM | FRAME_KA);
    8796                memsetb(newpt, FRAME_SIZE << PTL2_SIZE, 0);
    8897                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);
     98                SET_PTL2_FLAGS(ptl1, PTL1_INDEX(page),
     99                    PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
     100                    PAGE_WRITE);
    90101        }
    91102       
     
    93104       
    94105        if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT) {
    95                 pte_t *newpt = (pte_t *) frame_alloc(PTL3_SIZE, FRAME_KA);
     106                pte_t *newpt = (pte_t *) frame_alloc(PTL3_SIZE,
     107                    FRAME_LOWMEM | FRAME_KA);
    96108                memsetb(newpt, FRAME_SIZE << PTL3_SIZE, 0);
    97109                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);
     110                SET_PTL3_FLAGS(ptl2, PTL2_INDEX(page),
     111                    PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
     112                    PAGE_WRITE);
    99113        }
    100114       
     
    123137        /*
    124138         * First, remove the mapping, if it exists.
    125          *
    126139         */
    127140       
     
    140153        pte_t *ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
    141154       
    142         /* Destroy the mapping. Setting to PAGE_NOT_PRESENT is not sufficient. */
     155        /*
     156         * Destroy the mapping.
     157         * Setting to PAGE_NOT_PRESENT is not sufficient.
     158         */
    143159        memsetb(&ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0);
    144160       
    145161        /*
    146          * Second, free all empty tables along the way from PTL3 down to PTL0.
    147          *
     162         * Second, free all empty tables along the way from PTL3 down to PTL0
     163         * except those needed for sharing the kernel non-identity mappings.
    148164         */
    149165       
     
    162178                /*
    163179                 * PTL3 is empty.
    164                  * Release the frame and remove PTL3 pointer from preceding table.
    165                  *
    166                  */
    167                 frame_free(KA2PA((uintptr_t) ptl3));
     180                 * Release the frame and remove PTL3 pointer from the parent
     181                 * table.
     182                 */
    168183#if (PTL2_ENTRIES != 0)
    169184                memsetb(&ptl2[PTL2_INDEX(page)], sizeof(pte_t), 0);
     
    171186                memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0);
    172187#else
     188                if (km_is_non_identity(page))
     189                        return;
     190
    173191                memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    174192#endif
     193                frame_free(KA2PA((uintptr_t) ptl3));
    175194        } else {
    176195                /*
     
    195214                /*
    196215                 * PTL2 is empty.
    197                  * Release the frame and remove PTL2 pointer from preceding table.
    198                  *
    199                  */
    200                 frame_free(KA2PA((uintptr_t) ptl2));
     216                 * Release the frame and remove PTL2 pointer from the parent
     217                 * table.
     218                 */
    201219#if (PTL1_ENTRIES != 0)
    202220                memsetb(&ptl1[PTL1_INDEX(page)], sizeof(pte_t), 0);
    203221#else
     222                if (km_is_non_identity(page))
     223                        return;
     224
    204225                memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    205226#endif
     227                frame_free(KA2PA((uintptr_t) ptl2));
    206228        } else {
    207229                /*
     
    227249                /*
    228250                 * PTL1 is empty.
    229                  * Release the frame and remove PTL1 pointer from preceding table.
    230                  *
    231                  */
     251                 * Release the frame and remove PTL1 pointer from the parent
     252                 * table.
     253                 */
     254                if (km_is_non_identity(page))
     255                        return;
     256
     257                memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    232258                frame_free(KA2PA((uintptr_t) ptl1));
    233                 memsetb(&ptl0[PTL0_INDEX(page)], sizeof(pte_t), 0);
    234259        }
    235260#endif /* PTL1_ENTRIES != 0 */
     
    267292}
    268293
     294/** Make the mappings in the given range global accross all address spaces.
     295 *
     296 * All PTL0 entries in the given range will be mapped to a next level page
     297 * table. The next level page table will be allocated and cleared.
     298 *
     299 * pt_mapping_remove() will never deallocate these page tables even when there
     300 * are no PTEs in them.
     301 *
     302 * @param as   Address space.
     303 * @param base Base address corresponding to the first PTL0 entry that will be
     304 *             altered by this function.
     305 * @param size Size in bytes defining the range of PTL0 entries that will be
     306 *             altered by this function.
     307 */
     308void pt_mapping_make_global(uintptr_t base, size_t size)
     309{
     310        uintptr_t ptl0 = PA2KA((uintptr_t) AS_KERNEL->genarch.page_table);
     311        uintptr_t ptl0step = (((uintptr_t) -1) / PTL0_ENTRIES) + 1;
     312        size_t order;
     313        uintptr_t addr;
     314
     315#if (PTL1_ENTRIES != 0)
     316        order = PTL1_SIZE;
     317#elif (PTL2_ENTRIES != 0)
     318        order = PTL2_SIZE;
     319#else
     320        order = PTL3_SIZE;
     321#endif
     322
     323        ASSERT(ispwr2(ptl0step));
     324
     325        for (addr = ALIGN_DOWN(base, ptl0step); addr < base + size;
     326            addr += ptl0step) {
     327                uintptr_t l1;
     328
     329                l1 = (uintptr_t) frame_alloc(order, FRAME_KA | FRAME_LOWMEM);
     330                memsetb((void *) l1, FRAME_SIZE << order, 0);
     331                SET_PTL1_ADDRESS(ptl0, PTL0_INDEX(addr), KA2PA(l1));
     332                SET_PTL1_FLAGS(ptl0, PTL0_INDEX(addr),
     333                    PAGE_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE |
     334                    PAGE_WRITE);
     335        }
     336}
     337
    269338/** @}
    270339 */
  • kernel/generic/include/align.h

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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

    r852052d rc520034  
    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/include/mm/page.h

    r852052d rc520034  
    4949        void (* mapping_remove)(as_t *, uintptr_t);
    5050        pte_t *(* mapping_find)(as_t *, uintptr_t, bool);
     51        void (* mapping_make_global)(uintptr_t, size_t);
    5152} page_mapping_operations_t;
    5253
     
    6061extern void page_mapping_remove(as_t *, uintptr_t);
    6162extern pte_t *page_mapping_find(as_t *, uintptr_t, bool);
     63extern void page_mapping_make_global(uintptr_t, size_t);
    6264extern pte_t *page_table_create(unsigned int);
    6365extern void page_table_destroy(pte_t *);
  • kernel/generic/src/cpu/cpu.c

    r852052d rc520034  
    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

    r852052d rc520034  
    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>
     
    8687#include <sysinfo/sysinfo.h>
    8788#include <sysinfo/stats.h>
     89#include <lib/ra.h>
    8890
    8991/** Global configuration structure. */
    90 config_t config;
     92config_t config = {
     93        .identity_configured = false,
     94        .non_identity_configured = false,
     95        .physmem_end = 0
     96};
    9197
    9298/** Initial user-space tasks */
     
    205211         */
    206212        arch_pre_mm_init();
     213        km_identity_init();
    207214        frame_init();
    208        
    209         /* Initialize at least 1 memory segment big enough for slab to work. */
    210215        slab_cache_init();
     216        ra_init();     
    211217        sysinfo_init();
    212218        btree_init();
     
    214220        page_init();
    215221        tlb_init();
     222        km_non_identity_init();
    216223        ddi_init();
    217224        arch_post_mm_init();
  • kernel/generic/src/mm/frame.c

    r852052d rc520034  
    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

    r852052d rc520034  
    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>
     
    7576#include <errno.h>
    7677#include <align.h>
     78#include <macros.h>
     79#include <bitops.h>
    7780
    7881/** Virtual operations for page subsystem. */
     
    177180}
    178181
     182/** Make the mapping shared by all page tables (not address spaces).
     183 *
     184 * @param base Starting virtual address of the range that is made global.
     185 * @param size Size of the address range that is made global.
     186 */
     187void page_mapping_make_global(uintptr_t base, size_t size)
     188{
     189        ASSERT(page_mapping_operations);
     190        ASSERT(page_mapping_operations->mapping_make_global);
     191       
     192        return page_mapping_operations->mapping_make_global(base, size);
     193}
     194
     195uintptr_t hw_map(uintptr_t physaddr, size_t size)
     196{
     197        uintptr_t virtaddr;
     198        size_t asize;
     199        size_t align;
     200        pfn_t i;
     201
     202        asize = ALIGN_UP(size, PAGE_SIZE);
     203        align = ispwr2(size) ? size : (1U << (fnzb(size) + 1));
     204        virtaddr = km_page_alloc(asize, align);
     205
     206        page_table_lock(AS_KERNEL, true);
     207        for (i = 0; i < ADDR2PFN(asize); i++) {
     208                uintptr_t addr = PFN2ADDR(i);
     209                page_mapping_insert(AS_KERNEL, virtaddr + addr, physaddr + addr,
     210                    PAGE_NOT_CACHEABLE | PAGE_WRITE);
     211        }
     212        page_table_unlock(AS_KERNEL, true);
     213       
     214        return virtaddr;
     215}
     216
    179217int page_find_mapping(uintptr_t virt, void **phys)
    180218{
  • kernel/generic/src/mm/reserve.c

    r852052d rc520034  
    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

    r852052d rc520034  
    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.