Changeset e49e234 in mainline


Ignore:
Timestamp:
2009-02-27T11:32:31Z (15 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c1f7f6ea
Parents:
5f0f29ce
Message:

kernel memory management revisited (phase 2): map physical memory according to zones

  • ia32: register reserved and ACPI zones
  • pareas are now used only for mapping of present physical memory (hw_area() is gone)
  • firmware zones and physical addresses outside any zones are allowed to be mapped generally
  • fix nasty antient bug in zones_insert_zone()
Location:
kernel
Files:
26 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/amd64/include/mm/frame.h

    r5f0f29ce re49e234  
    2727 */
    2828
    29 /** @addtogroup amd64mm 
     29/** @addtogroup amd64mm
    3030 * @{
    3131 */
     
    4040#endif /* __ASM__ */
    4141
    42 #define FRAME_WIDTH             12      /* 4K */
    43 #define FRAME_SIZE              (1 << FRAME_WIDTH)
     42#define FRAME_WIDTH  12  /* 4K */
     43#define FRAME_SIZE   (1 << FRAME_WIDTH)
    4444
    4545#ifndef __ASM__
    4646extern uintptr_t last_frame;
    47 extern uintptr_t end_frame;
    4847extern void frame_arch_init(void);
    4948extern void physmem_print(void);
  • kernel/arch/amd64/src/mm/page.c

    r5f0f29ce re49e234  
    3535#include <arch/mm/page.h>
    3636#include <genarch/mm/page_pt.h>
    37 #include <genarch/drivers/ega/ega.h>
    38 #include <genarch/drivers/legacy/ia32/io.h>
    3937#include <arch/mm/frame.h>
    4038#include <mm/page.h>
     
    4947#include <panic.h>
    5048#include <align.h>
    51 #include <ddi/ddi.h>
    52 
    53 /** Physical memory area for devices. */
    54 static parea_t dev_area;
    55 static parea_t ega_area;
    5649
    5750/* Definitions for identity page mapper */
     
    222215}
    223216
    224 void hw_area(void)
    225 {
    226         dev_area.pbase = end_frame;
    227         dev_area.frames = SIZE2FRAMES(0xfffffffffffff - end_frame);
    228         ddi_parea_register(&dev_area);
    229        
    230         ega_area.pbase = EGA_VIDEORAM;
    231         ega_area.frames = SIZE2FRAMES(EGA_VRAM_SIZE);
    232         ddi_parea_register(&ega_area);
    233 }
    234 
    235217/** @}
    236218 */
  • kernel/arch/arm32/include/mm/frame.h

    r5f0f29ce re49e234  
    2727 */
    2828
    29 /** @addtogroup arm32mm 
     29/** @addtogroup arm32mm
    3030 * @{
    3131 */
     
    3737#define KERN_arm32_FRAME_H_
    3838
    39 #define FRAME_WIDTH             12 /* 4KB frames */
    40 #define FRAME_SIZE              (1 << FRAME_WIDTH)
     39#define FRAME_WIDTH  12 /* 4KB frames */
     40#define FRAME_SIZE   (1 << FRAME_WIDTH)
    4141
    4242#ifdef KERNEL
     
    4545#include <arch/types.h>
    4646
    47 #define BOOT_PAGE_TABLE_SIZE    0x4000
    48 #define BOOT_PAGE_TABLE_ADDRESS 0x4000
     47#define BOOT_PAGE_TABLE_SIZE     0x4000
     48#define BOOT_PAGE_TABLE_ADDRESS  0x4000
    4949
    5050#define BOOT_PAGE_TABLE_START_FRAME     (BOOT_PAGE_TABLE_ADDRESS >> FRAME_WIDTH)
     
    5252
    5353extern uintptr_t last_frame;
    54 extern uintptr_t end_frame;
    5554
    5655extern void frame_arch_init(void);
  • kernel/arch/arm32/src/mm/frame.c

    r5f0f29ce re49e234  
    2727 */
    2828
    29 /** @addtogroup arm32mm 
     29/** @addtogroup arm32mm
    3030 * @{
    3131 */
     
    4242/** Address of the last frame in the memory. */
    4343uintptr_t last_frame = 0;
    44 uintptr_t end_frame = 0;
    4544
    4645/** Creates memory zones. */
     
    5150            BOOT_PAGE_TABLE_START_FRAME + BOOT_PAGE_TABLE_SIZE_IN_FRAMES, 0);
    5251        last_frame = machine_get_memory_size();
    53         end_frame = last_frame;
    5452       
    5553        /* blacklist boot page table */
  • kernel/arch/arm32/src/mm/page.c

    r5f0f29ce re49e234  
    4444#include <interrupt.h>
    4545#include <arch/mm/frame.h>
    46 #include <ddi/ddi.h>
    47 
    48 /** Physical memory area for devices. */
    49 static parea_t dev_area;
    5046
    5147/** Initializes page tables.
     
    111107}
    112108
    113 void hw_area(void)
    114 {
    115         dev_area.pbase = end_frame;
    116         dev_area.frames = SIZE2FRAMES(0xffffffff - end_frame);
    117         ddi_parea_register(&dev_area);
    118 }
    119 
    120109/** @}
    121110 */
  • kernel/arch/ia32/include/boot/memmap.h

    r5f0f29ce re49e234  
    2727 */
    2828
    29 /** @addtogroup ia32   
     29/** @addtogroup ia32
    3030 * @{
    3131 */
     
    3636#define KERN_ia32_MEMMAP_H_
    3737
    38 /* E820h memory range types - other values*/
    39         /* Free memory */
    40 #define MEMMAP_MEMORY_AVAILABLE 1
    41         /* Not available for OS */
    42 #define MEMMAP_MEMORY_RESERVED  2
    43         /* OS may use it after reading ACPI table */
    44 #define MEMMAP_MEMORY_ACPI      3
    45         /* Unusable, required to be saved and restored across an NVS sleep */
    46 #define MEMMAP_MEMORY_NVS       4
    47         /* Corrupted memory */
    48 #define MEMMAP_MEMORY_UNUSABLE  5
     38/* E820h memory range types */
    4939
    50          /* size of one entry */
    51 #define MEMMAP_E820_RECORD_SIZE 20
    52         /* maximum entries */
    53 #define MEMMAP_E820_MAX_RECORDS 32
     40/* Free memory */
     41#define MEMMAP_MEMORY_AVAILABLE  1
    5442
     43/* Not available for OS */
     44#define MEMMAP_MEMORY_RESERVED   2
     45
     46/* OS may use it after reading ACPI table */
     47#define MEMMAP_MEMORY_ACPI       3
     48
     49/* Unusable, required to be saved and restored across an NVS sleep */
     50#define MEMMAP_MEMORY_NVS        4
     51
     52/* Corrupted memory */
     53#define MEMMAP_MEMORY_UNUSABLE   5
     54
     55/* Size of one entry */
     56#define MEMMAP_E820_RECORD_SIZE  20
     57
     58/* Maximum entries */
     59#define MEMMAP_E820_MAX_RECORDS  32
    5560
    5661#ifndef __ASM__
  • kernel/arch/ia32/include/mm/frame.h

    r5f0f29ce re49e234  
    2727 */
    2828
    29 /** @addtogroup ia32mm 
     29/** @addtogroup ia32mm
    3030 * @{
    3131 */
     
    3636#define KERN_ia32_FRAME_H_
    3737
    38 #define FRAME_WIDTH     12      /* 4K */
    39 #define FRAME_SIZE      (1 << FRAME_WIDTH)
     38#define FRAME_WIDTH  12  /* 4K */
     39#define FRAME_SIZE   (1 << FRAME_WIDTH)
    4040
    4141#ifdef KERNEL
     
    4545
    4646extern uintptr_t last_frame;
    47 extern uintptr_t end_frame;
    4847
    4948extern void frame_arch_init(void);
  • kernel/arch/ia32/src/mm/frame.c

    r5f0f29ce re49e234  
    5151
    5252uintptr_t last_frame = 0;
    53 uintptr_t end_frame = 0;
    5453
    5554static void init_e820_memory(pfn_t minconf)
    5655{
    5756        unsigned int i;
    58         pfn_t start, conf;
    59         size_t size;
    60        
    6157        for (i = 0; i < e820counter; i++) {
     58                uint64_t base = e820table[i].base_address;
     59                uint64_t size = e820table[i].size;
     60               
     61#ifdef __32_BITS__
     62               
     63                /* Ignore physical memory above 4 GB */
     64                if ((base >> 32) != 0)
     65                        continue;
     66               
     67                /* Clip regions above 4 GB */
     68                if (((base + size) >> 32) != 0)
     69                        size = 0xffffffff - base;
     70               
     71#endif
     72                pfn_t pfn;
     73                count_t count;
     74               
    6275                if (e820table[i].type == MEMMAP_MEMORY_AVAILABLE) {
    63                         start = ADDR2PFN(ALIGN_UP(e820table[i].base_address, FRAME_SIZE));
    64                         size = SIZE2FRAMES(ALIGN_DOWN(e820table[i].size, FRAME_SIZE));
     76                        /* To be safe, make available zone possibly smaller */
     77                        pfn = ADDR2PFN(ALIGN_UP(base, FRAME_SIZE));
     78                        count = SIZE2FRAMES(ALIGN_DOWN(size, FRAME_SIZE));
    6579                       
    66                         if ((minconf < start) || (minconf >= start + size))
    67                                 conf = start;
     80                        pfn_t conf;
     81                        if ((minconf < pfn) || (minconf >= pfn + count))
     82                                conf = pfn;
    6883                        else
    6984                                conf = minconf;
    7085                       
    71                         zone_create(start, size, conf, 0);
     86                        zone_create(pfn, count, conf, ZONE_AVAILABLE);
    7287                       
    73                         if (last_frame < ALIGN_UP(e820table[i].base_address +
    74                             e820table[i].size, FRAME_SIZE))
    75                                 last_frame =
    76                                     ALIGN_UP(e820table[i].base_address + e820table[i].size, FRAME_SIZE);
     88                        // XXX this has to be removed
     89                        if (last_frame < ALIGN_UP(base + size, FRAME_SIZE))
     90                                last_frame = ALIGN_UP(base + size, FRAME_SIZE);
     91                }
     92               
     93                if (e820table[i].type == MEMMAP_MEMORY_RESERVED) {
     94                        /* To be safe, make reserved zone possibly larger */
     95                        pfn = ADDR2PFN(ALIGN_DOWN(base, FRAME_SIZE));
     96                        count = SIZE2FRAMES(ALIGN_UP(size, FRAME_SIZE));
     97                       
     98                        zone_create(pfn, count, 0, ZONE_RESERVED);
     99                }
     100               
     101                if (e820table[i].type == MEMMAP_MEMORY_ACPI) {
     102                        /* To be safe, make firmware zone possibly larger */
     103                        pfn = ADDR2PFN(ALIGN_DOWN(base, (uintptr_t) FRAME_SIZE));
     104                        count = SIZE2FRAMES(ALIGN_UP(size, (uintptr_t) FRAME_SIZE));
     105                       
     106                        zone_create(pfn, count, 0, ZONE_FIRMWARE);
    77107                }
    78108        }
    79        
    80         end_frame = last_frame;
    81109}
    82110
  • kernel/arch/ia32/src/mm/page.c

    r5f0f29ce re49e234  
    3535#include <arch/mm/page.h>
    3636#include <genarch/mm/page_pt.h>
    37 #include <genarch/drivers/ega/ega.h>
    38 #include <genarch/drivers/legacy/ia32/io.h>
    3937#include <arch/mm/frame.h>
    4038#include <mm/frame.h>
     
    5149#include <print.h>
    5250#include <interrupt.h>
    53 #include <ddi/ddi.h>
    54 
    55 /** Physical memory area for devices. */
    56 static parea_t dev_area;
    57 static parea_t ega_area;
    5851
    5952void page_arch_init(void)
     
    6154        uintptr_t cur;
    6255        int flags;
    63 
     56       
    6457        if (config.cpu_active == 1) {
    6558                page_mapping_operations = &pt_mapping_operations;
     
    7467                        page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
    7568                }
    76 
     69               
    7770                exc_register(14, "page_fault", (iroutine) page_fault);
    7871                write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
    7972        } else
    8073                write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
    81 
     74       
    8275        paging_on();
    8376}
     
    9992       
    10093        return virtaddr;
    101 }
    102 
    103 void hw_area(void)
    104 {
    105         dev_area.pbase = end_frame;
    106         dev_area.frames = SIZE2FRAMES(0xffffffff - end_frame);
    107         ddi_parea_register(&dev_area);
    108        
    109         ega_area.pbase = EGA_VIDEORAM;
    110         ega_area.frames = SIZE2FRAMES(EGA_VRAM_SIZE);
    111         ddi_parea_register(&ega_area);
    11294}
    11395
  • kernel/arch/ia64/include/mm/frame.h

    r5f0f29ce re49e234  
    2727 */
    2828
    29 /** @addtogroup ia64mm 
     29/** @addtogroup ia64mm
    3030 * @{
    3131 */
     
    3636#define KERN_ia64_FRAME_H_
    3737
    38 #define FRAME_WIDTH             14      /* 16K */
    39 #define FRAME_SIZE              (1 << FRAME_WIDTH)
     38#define FRAME_WIDTH  14  /* 16K */
     39#define FRAME_SIZE   (1 << FRAME_WIDTH)
    4040
    4141#ifdef KERNEL
     
    4545
    4646extern uintptr_t last_frame;
    47 extern uintptr_t end_frame;
    4847
    4948extern void frame_arch_init(void);
  • kernel/arch/ia64/src/mm/frame.c

    r5f0f29ce re49e234  
    2727 */
    2828
    29 /** @addtogroup ia64mm 
     29/** @addtogroup ia64mm
    3030 * @{
    3131 */
     
    5252
    5353uintptr_t last_frame = 0;
    54 uintptr_t end_frame = 0;
    5554
    5655void frame_arch_init(void)
  • kernel/arch/ia64/src/mm/page.c

    r5f0f29ce re49e234  
    4949#include <memstr.h>
    5050#include <align.h>
    51 #include <ddi/ddi.h>
    52 
    53 /** Physical memory area for devices. */
    54 static parea_t dev_area;
    5551
    5652static void set_environment(void);
     
    6864{
    6965        region_register rr;
    70         pta_register pta;       
     66        pta_register pta;
    7167        int i;
    72 #ifdef CONFIG_VHPT     
     68#ifdef CONFIG_VHPT
    7369        uintptr_t vhpt_base;
    7470#endif
     
    279275}
    280276
    281 void hw_area(void)
    282 {
    283         dev_area.pbase = end_frame;
    284         dev_area.frames = SIZE2FRAMES(0x7fffffffffffffffUL - end_frame);
    285         ddi_parea_register(&dev_area);
    286 }
    287 
    288277/** @}
    289278 */
  • kernel/arch/mips32/include/mm/frame.h

    r5f0f29ce re49e234  
    2727 */
    2828
    29 /** @addtogroup mips32mm       
     29/** @addtogroup mips32mm
    3030 * @{
    3131 */
     
    4747extern void physmem_print(void);
    4848
    49 extern uintptr_t end_frame;
    50 
    5149#endif /* __ASM__ */
    5250#endif /* KERNEL */
  • kernel/arch/mips32/src/mm/frame.c

    r5f0f29ce re49e234  
    6565static count_t phys_regions_count = 0;
    6666static phys_region_t phys_regions[MAX_REGIONS];
    67 
    68 uintptr_t end_frame = 0;
    6967
    7068
     
    239237        }
    240238       
    241         end_frame = frame;
    242        
    243         frame_add_region(start_frame, end_frame);
     239        frame_add_region(start_frame, frame);
    244240       
    245241        /* Blacklist interrupt vector frame */
  • kernel/arch/mips32/src/mm/page.c

    r5f0f29ce re49e234  
    3737#include <mm/page.h>
    3838#include <mm/frame.h>
    39 #include <ddi/ddi.h>
    40 
    41 /** Physical memory area for devices. */
    42 static parea_t dev_area;
    4339
    4440void page_arch_init(void)
     
    5652}
    5753
    58 void hw_area(void)
    59 {
    60         dev_area.pbase = end_frame;
    61         dev_area.frames = SIZE2FRAMES(0xffffffff - end_frame);
    62         ddi_parea_register(&dev_area);
    63 }
    64 
    6554/** @}
    6655 */
  • kernel/arch/ppc32/include/mm/frame.h

    r5f0f29ce re49e234  
    2727 */
    2828
    29 /** @addtogroup ppc32mm 
     29/** @addtogroup ppc32mm
    3030 * @{
    3131 */
     
    3636#define KERN_ppc32_FRAME_H_
    3737
    38 #define FRAME_WIDTH             12      /* 4K */
    39 #define FRAME_SIZE              (1 << FRAME_WIDTH)
     38#define FRAME_WIDTH  12  /* 4K */
     39#define FRAME_SIZE   (1 << FRAME_WIDTH)
    4040
    4141#ifdef KERNEL
     
    4545
    4646extern uintptr_t last_frame;
    47 extern uintptr_t end_frame;
    4847
    4948extern void frame_arch_init(void);
  • kernel/arch/ppc32/src/mm/frame.c

    r5f0f29ce re49e234  
    4141
    4242uintptr_t last_frame = 0;
    43 uintptr_t end_frame = 0;
    4443
    4544void physmem_print(void)
     
    7776        }
    7877       
    79         end_frame = last_frame;
    80        
    8178        /* First is exception vector, second is 'implementation specific',
    8279           third and fourth is reserved, other contain real mode code */
  • kernel/arch/ppc32/src/mm/page.c

    r5f0f29ce re49e234  
    2727 */
    2828
    29 /** @addtogroup ppc32mm 
     29/** @addtogroup ppc32mm
    3030 * @{
    3131 */
     
    3838#include <align.h>
    3939#include <config.h>
    40 #include <ddi/ddi.h>
    41 
    42 /** Physical memory area for devices. */
    43 static parea_t dev_area;
    4440
    4541void page_arch_init(void)
     
    6864}
    6965
    70 void hw_area(void)
    71 {
    72         dev_area.pbase = end_frame;
    73         dev_area.frames = SIZE2FRAMES(0xffffffff - end_frame);
    74         ddi_parea_register(&dev_area);
    75 }
    76 
    7766/** @}
    7867 */
  • kernel/arch/sparc64/include/mm/frame.h

    r5f0f29ce re49e234  
    7474
    7575extern uintptr_t last_frame;
    76 extern uintptr_t end_frame;
    7776extern void frame_arch_init(void);
    7877#define physmem_print()
  • kernel/arch/sparc64/src/mm/frame.c

    r5f0f29ce re49e234  
    2727 */
    2828
    29 /** @addtogroup sparc64mm       
     29/** @addtogroup sparc64mm
    3030 * @{
    3131 */
     
    4242
    4343uintptr_t last_frame = NULL;
    44 uintptr_t end_frame = NULL;
    4544
    4645/** Create memory zones according to information stored in bootinfo.
     
    8180                frame_mark_unavailable(ADDR2PFN(KA2PA(PFN2ADDR(0))), 1);
    8281        }
    83        
    84         end_frame = last_frame;
    8582}
    8683
  • kernel/arch/sparc64/src/mm/page.c

    r5f0f29ce re49e234  
    4242#include <align.h>
    4343#include <config.h>
    44 #include <ddi/ddi.h>
    45 
    46 /** Physical memory area for devices. */
    47 static parea_t dev_area;
    4844
    4945#ifdef CONFIG_SMP
     
    169165}
    170166
    171 void hw_area(void)
    172 {
    173         dev_area.pbase = end_frame;
    174         dev_area.frames = SIZE2FRAMES(0x7ffffffffff - end_frame);
    175         ddi_parea_register(&dev_area);
    176 }
    177 
    178167/** @}
    179168 */
  • kernel/generic/include/align.h

    r5f0f29ce re49e234  
    2727 */
    2828
    29 /** @addtogroup generic 
     29/** @addtogroup generic
    3030 * @ingroup others
    3131 * @{
     
    3333/**
    3434 * @file
    35  * @brief       Macros for making values and addresses aligned.
     35 * @brief Macros for making values and addresses aligned.
    3636 */
    3737
     
    4444 * @param a Size of alignment, must be power of 2.
    4545 */
    46 #define ALIGN_DOWN(s, a)        ((s) & ~((a) - 1))
     46#define ALIGN_DOWN(s, a)  ((s) & ~((a) - 1))
    4747
    4848
     
    5252 * @param a Size of alignment, must be power of 2.
    5353 */
    54 #define ALIGN_UP(s, a)          (((s) + ((a) - 1)) & ~((a) - 1))
     54#define ALIGN_UP(s, a)  (((s) + ((a) - 1)) & ~((a) - 1))
    5555
    5656#endif
  • kernel/generic/include/mm/frame.h

    r5f0f29ce re49e234  
    4040#include <adt/list.h>
    4141#include <mm/buddy.h>
     42#include <synch/spinlock.h>
    4243#include <arch/mm/page.h>
    4344#include <arch/mm/frame.h>
     
    6869typedef uint8_t zone_flags_t;
    6970
     71/** Available zone (free for allocation) */
     72#define ZONE_AVAILABLE  0x00
    7073/** Zone is reserved (not available for allocation) */
    71 #define ZONE_RESERVED  0x08
     74#define ZONE_RESERVED   0x08
    7275/** Zone is used by firmware (not available for allocation) */
    73 #define ZONE_FIRMWARE  0x10
     76#define ZONE_FIRMWARE   0x10
    7477
    7578/** Currently there is no equivalent zone flags
    7679    for frame flags */
    7780#define FRAME_TO_ZONE_FLAGS(frame_flags)  0
     81
     82typedef struct {
     83        count_t refcount;     /**< Tracking of shared frames */
     84        uint8_t buddy_order;  /**< Buddy system block order */
     85        link_t buddy_link;    /**< Link to the next free block inside
     86                               one order */
     87        void *parent;         /**< If allocated by slab, this points there */
     88} frame_t;
     89
     90typedef struct {
     91        pfn_t base;                    /**< Frame_no of the first frame
     92                                        in the frames array */
     93        count_t count;                 /**< Size of zone */
     94        count_t free_count;            /**< Number of free frame_t
     95                                        structures */
     96        count_t busy_count;            /**< Number of busy frame_t
     97                                        structures */
     98        zone_flags_t flags;            /**< Type of the zone */
     99       
     100        frame_t *frames;               /**< Array of frame_t structures
     101                                        in this zone */
     102        buddy_system_t *buddy_system;  /**< Buddy system for the zone */
     103} zone_t;
     104
     105/*
     106 * The zoneinfo.lock must be locked when accessing zoneinfo structure.
     107 * Some of the attributes in zone_t structures are 'read-only'
     108 */
     109typedef struct {
     110        SPINLOCK_DECLARE(lock);
     111        count_t count;
     112        zone_t info[ZONES_MAX];
     113} zones_t;
     114
     115extern zones_t zones;
    78116
    79117static inline uintptr_t PFN2ADDR(pfn_t frame)
     
    99137}
    100138
     139static inline bool zone_flags_available(zone_flags_t flags)
     140{
     141        return ((flags & (ZONE_RESERVED | ZONE_FIRMWARE)) == 0);
     142}
     143
    101144#define IS_BUDDY_ORDER_OK(index, order) \
    102145    ((~(((unative_t) -1) << (order)) & (index)) == 0)
     
    118161extern void frame_reference_add(pfn_t);
    119162
     163extern count_t find_zone(pfn_t frame, count_t count, count_t hint);
    120164extern count_t zone_create(pfn_t, count_t, pfn_t, zone_flags_t);
    121165extern void *frame_get_parent(pfn_t, count_t);
  • kernel/generic/include/mm/page.h

    r5f0f29ce re49e234  
    6262
    6363extern uintptr_t hw_map(uintptr_t physaddr, size_t size);
    64 extern void hw_area(void);
    6564
    6665#endif
  • kernel/generic/src/ddi/ddi.c

    r5f0f29ce re49e234  
    3030 * @{
    3131 */
    32  
     32
    3333/**
    3434 * @file
    35  * @brief       Device Driver Interface functions.
     35 * @brief Device Driver Interface functions.
    3636 *
    3737 * This file contains functions that comprise the Device Driver Interface.
     
    4848#include <synch/spinlock.h>
    4949#include <syscall/copy.h>
    50 #include <adt/list.h>
     50#include <adt/btree.h>
    5151#include <arch.h>
    5252#include <align.h>
     
    5656SPINLOCK_INITIALIZE(parea_lock);
    5757
    58 /** List with enabled physical memory areas. */
    59 static LIST_INITIALIZE(parea_head);
     58/** B+tree with enabled physical memory areas. */
     59static btree_t parea_btree;
    6060
    6161/** Initialize DDI. */
    6262void ddi_init(void)
    6363{
    64         hw_area();
     64        btree_create(&parea_btree);
    6565}
    6666
     
    6969 * @param parea Pointer to physical area structure.
    7070 *
    71  * @todo This function doesn't check for overlaps. It depends on the kernel to
    72  * create disjunct physical memory areas.
    7371 */
    7472void ddi_parea_register(parea_t *parea)
    7573{
    76         ipl_t ipl;
    77        
    78         ipl = interrupts_disable();
     74        ipl_t ipl = interrupts_disable();
    7975        spinlock_lock(&parea_lock);
    8076       
    8177        /*
    82          * TODO: we should really check for overlaps here.
    83          * However, we should be safe because the kernel is pretty sane.
    84          */
    85         link_initialize(&parea->link);
    86         list_append(&parea->link, &parea_head);
     78         * We don't check for overlaps here as the kernel is pretty sane.
     79         */
     80        btree_insert(&parea_btree, (btree_key_t) parea->pbase, parea, NULL);
    8781       
    8882        spinlock_unlock(&parea_lock);
     
    9286/** Map piece of physical memory into virtual address space of current task.
    9387 *
    94  * @param pf Physical address of the starting frame.
    95  * @param vp Virtual address of the starting page.
     88 * @param pf    Physical address of the starting frame.
     89 * @param vp    Virtual address of the starting page.
    9690 * @param pages Number of pages to map.
    9791 * @param flags Address space area flags for the mapping.
    9892 *
    9993 * @return 0 on success, EPERM if the caller lacks capabilities to use this
    100  *  syscall, ENOENT if there is no task matching the specified ID or the
    101  *  physical address space is not enabled for mapping and ENOMEM if there
    102  *  was a problem in creating address space area.
    103  */
    104 static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, pfn_t pages, int flags)
    105 {
    106         ipl_t ipl;
    107         cap_t caps;
     94 *         syscall, EBADMEM if pf or vf is not page aligned, ENOENT if there
     95 *         is no task matching the specified ID or the physical address space
     96 *         is not enabled for mapping and ENOMEM if there was a problem in
     97 *         creating address space area.
     98 *
     99 */
     100static int ddi_physmem_map(uintptr_t pf, uintptr_t vp, count_t pages, int flags)
     101{
     102        ASSERT(TASK);
     103        ASSERT((pf % FRAME_SIZE) == 0);
     104        ASSERT((vp % PAGE_SIZE) == 0);
     105       
     106        /*
     107         * Make sure the caller is authorised to make this syscall.
     108         */
     109        cap_t caps = cap_get(TASK);
     110        if (!(caps & CAP_MEM_MANAGER))
     111                return EPERM;
     112       
    108113        mem_backend_data_t backend_data;
    109        
    110114        backend_data.base = pf;
    111115        backend_data.frames = pages;
    112116       
    113         /*
    114          * Make sure the caller is authorised to make this syscall.
    115          */
    116         caps = cap_get(TASK);
    117         if (!(caps & CAP_MEM_MANAGER))
    118                 return EPERM;
    119        
    120         ipl = interrupts_disable();
    121        
    122         /*
    123          * Check if the physical memory area is enabled for mapping.
    124          */
    125         spinlock_lock(&parea_lock);
    126        
    127         bool fnd = false;
    128         link_t *cur;
    129        
    130         for (cur = parea_head.next; cur != &parea_head; cur = cur->next) {
    131                 parea_t *parea = list_get_instance(cur, parea_t, link);
    132                 if ((parea->pbase <= pf) && (ADDR2PFN(pf - parea->pbase) + pages <= parea->frames)) {
    133                         fnd = true;
    134                         break;
    135                 }
    136         }
    137        
    138         spinlock_unlock(&parea_lock);
    139        
    140         if (!fnd) {
    141                 /*
    142                  * Physical memory area cannot be mapped.
    143                  */
    144                 interrupts_restore(ipl);
    145                 return ENOENT;
    146         }
    147        
     117        ipl_t ipl = interrupts_disable();
     118       
     119        /* Find the zone of the physical memory */
     120        spinlock_lock(&zones.lock);
     121        count_t znum = find_zone(ADDR2PFN(pf), pages, 0);
     122       
     123        if (znum == (count_t) -1) {
     124                /* Frames not found in any zones
     125                 * -> assume it is hardware device and allow mapping
     126                 */
     127                spinlock_unlock(&zones.lock);
     128                goto map;
     129        }
     130       
     131        if (zones.info[znum].flags & ZONE_FIRMWARE) {
     132                /* Frames are part of firmware */
     133                spinlock_unlock(&zones.lock);
     134                goto map;
     135        }
     136       
     137        if (zone_flags_available(zones.info[znum].flags)) {
     138                /* Frames are part of physical memory, check if the memory
     139                 * region is enabled for mapping.
     140                 */
     141                spinlock_unlock(&zones.lock);
     142               
     143                spinlock_lock(&parea_lock);
     144                btree_node_t *nodep;
     145                parea_t *parea = (parea_t *) btree_search(&parea_btree,
     146                    (btree_key_t) pf, &nodep);
     147               
     148                if ((!parea) || (parea->frames < pages))
     149                        goto err;
     150               
     151                spinlock_unlock(&parea_lock);
     152                goto map;
     153        }
     154       
     155err:
     156        spinlock_unlock(&zones.lock);
     157        interrupts_restore(ipl);
     158        return ENOENT;
     159       
     160map:
    148161        spinlock_lock(&TASK->lock);
    149162       
    150         if (!as_area_create(TASK->as, flags, pages * PAGE_SIZE, vp, AS_AREA_ATTR_NONE,
    151                 &phys_backend, &backend_data)) {
     163        if (!as_area_create(TASK->as, flags, pages * PAGE_SIZE, vp,
     164            AS_AREA_ATTR_NONE, &phys_backend, &backend_data)) {
    152165                /*
    153166                 * The address space area could not have been created.
     
    175188 *
    176189 * @return 0 on success, EPERM if the caller lacks capabilities to use this
    177  *      syscall, ENOENT if there is no task matching the specified ID.
     190 *           syscall, ENOENT if there is no task matching the specified ID.
     191 *
    178192 */
    179193static int ddi_iospace_enable(task_id_t id, uintptr_t ioaddr, size_t size)
    180194{
    181         ipl_t ipl;
    182         cap_t caps;
    183         task_t *t;
    184         int rc;
    185        
    186195        /*
    187196         * Make sure the caller is authorised to make this syscall.
    188197         */
    189         caps = cap_get(TASK);
     198        cap_t caps = cap_get(TASK);
    190199        if (!(caps & CAP_IO_MANAGER))
    191200                return EPERM;
    192201       
    193         ipl = interrupts_disable();
     202        ipl_t ipl = interrupts_disable();
    194203        spinlock_lock(&tasks_lock);
    195204       
    196         t = task_find_by_id(id);
    197        
    198         if ((!t) || (!context_check(CONTEXT, t->context))) {
     205        task_t *task = task_find_by_id(id);
     206       
     207        if ((!task) || (!context_check(CONTEXT, task->context))) {
    199208                /*
    200209                 * There is no task with the specified ID
     
    206215                return ENOENT;
    207216        }
    208 
     217       
    209218        /* Lock the task and release the lock protecting tasks_btree. */
    210         spinlock_lock(&t->lock);
     219        spinlock_lock(&task->lock);
    211220        spinlock_unlock(&tasks_lock);
    212 
    213         rc = ddi_iospace_enable_arch(t, ioaddr, size);
    214        
    215         spinlock_unlock(&t->lock);
    216         interrupts_restore(ipl);
     221       
     222        int rc = ddi_iospace_enable_arch(task, ioaddr, size);
     223       
     224        spinlock_unlock(&task->lock);
     225        interrupts_restore(ipl);
     226       
    217227        return rc;
    218228}
     
    226236 *
    227237 * @return 0 on success, otherwise it returns error code found in errno.h
    228  */
     238 *
     239 */
    229240unative_t sys_physmem_map(unative_t phys_base, unative_t virt_base,
    230241    unative_t pages, unative_t flags)
     
    232243        return (unative_t) ddi_physmem_map(ALIGN_DOWN((uintptr_t) phys_base,
    233244            FRAME_SIZE), ALIGN_DOWN((uintptr_t) virt_base, PAGE_SIZE),
    234             (pfn_t) pages, (int) flags);
     245            (count_t) pages, (int) flags);
    235246}
    236247
     
    240251 *
    241252 * @return 0 on success, otherwise it returns error code found in errno.h
    242  */
     253 *
     254 */
    243255unative_t sys_iospace_enable(ddi_ioarg_t *uspace_io_arg)
    244256{
    245257        ddi_ioarg_t arg;
    246         int rc;
    247        
    248         rc = copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t));
     258        int rc = copy_from_uspace(&arg, uspace_io_arg, sizeof(ddi_ioarg_t));
    249259        if (rc != 0)
    250260                return (unative_t) rc;
    251                
     261       
    252262        return (unative_t) ddi_iospace_enable((task_id_t) arg.task_id,
    253263            (uintptr_t) arg.ioaddr, (size_t) arg.size);
     
    257267 *
    258268 * @param enable If non-zero, the preemption counter will be decremented,
    259  *      leading to potential enabling of preemption. Otherwise the preemption
    260  *      counter will be incremented, preventing preemption from occurring.
     269 *               leading to potential enabling of preemption. Otherwise
     270 *               the preemption counter will be incremented, preventing
     271 *               preemption from occurring.
    261272 *
    262273 * @return Zero on success or EPERM if callers capabilities are not sufficient.
    263  */
     274 *
     275 */
    264276unative_t sys_preempt_control(int enable)
    265277{
    266278        if (!cap_get(TASK) & CAP_PREEMPT_CONTROL)
    267279                return EPERM;
     280       
    268281        if (enable)
    269282                preemption_enable();
    270283        else
    271284                preemption_disable();
     285       
    272286        return 0;
    273287}
  • kernel/generic/src/mm/frame.c

    r5f0f29ce re49e234  
    4949#include <debug.h>
    5050#include <adt/list.h>
    51 #include <synch/spinlock.h>
    5251#include <synch/mutex.h>
    5352#include <synch/condvar.h>
     
    6160#include <config.h>
    6261
    63 typedef struct {
    64         count_t refcount;     /**< Tracking of shared frames */
    65         uint8_t buddy_order;  /**< Buddy system block order */
    66         link_t buddy_link;    /**< Link to the next free block inside
    67                                one order */
    68         void *parent;         /**< If allocated by slab, this points there */
    69 } frame_t;
    70 
    71 typedef struct {
    72         pfn_t base;                    /**< Frame_no of the first frame
    73                                         in the frames array */
    74         count_t count;                 /**< Size of zone */
    75         count_t free_count;            /**< Number of free frame_t
    76                                         structures */
    77         count_t busy_count;            /**< Number of busy frame_t
    78                                         structures */
    79         zone_flags_t flags;            /**< Type of the zone */
    80        
    81         frame_t *frames;               /**< Array of frame_t structures
    82                                         in this zone */
    83         buddy_system_t *buddy_system;  /**< Buddy system for the zone */
    84 } zone_t;
    85 
    86 /*
    87  * The zoneinfo.lock must be locked when accessing zoneinfo structure.
    88  * Some of the attributes in zone_t structures are 'read-only'
    89  */
    90 typedef struct {
    91         SPINLOCK_DECLARE(lock);
    92         count_t count;
    93         zone_t info[ZONES_MAX];
    94 } zones_t;
    95 
    96 static zones_t zones;
     62zones_t zones;
    9763
    9864/*
     
    12793{
    12894        return (frame - zone->frames);
    129 }
    130 
    131 static inline bool zone_flags_available(zone_flags_t flags)
    132 {
    133         return ((flags & (ZONE_RESERVED | ZONE_FIRMWARE)) == 0);
    13495}
    13596
     
    181142        /* Move other zones up */
    182143        count_t j;
    183         for (j = i; j < zones.count; j++)
    184                 zones.info[j + 1] = zones.info[j];
     144        for (j = zones.count; j > i; j--) {
     145                zones.info[j] = zones.info[j - 1];
     146                zones.info[j].buddy_system->data =
     147                    (void *) &zones.info[j - 1];
     148        }
    185149       
    186150        zones.count++;
     
    207171}
    208172
    209 /** Find a zone with a given frame.
     173/** Find a zone with a given frames.
    210174 *
    211175 * Assume interrupts are disabled and zones lock is
     
    213177 *
    214178 * @param frame Frame number contained in zone.
     179 * @param count Number of frames to look for.
    215180 * @param hint  Used as zone hint.
    216181 *
     
    218183 *
    219184 */
    220 static count_t find_zone(pfn_t frame, count_t hint)
     185count_t find_zone(pfn_t frame, count_t count, count_t hint)
    221186{
    222187        if (hint >= zones.count)
     
    226191        do {
    227192                if ((zones.info[i].base <= frame)
    228                     && (zones.info[i].base + zones.info[i].count > frame))
     193                    && (zones.info[i].base + zones.info[i].count >= frame + count))
    229194                        return i;
    230195               
     
    766731            zones.info[z2].count);
    767732       
    768         /* Shift existing zones */
     733        /* Move zones down */
    769734        count_t i;
    770         for (i = z2 + 1; i < zones.count; i++)
     735        for (i = z2 + 1; i < zones.count; i++) {
    771736                zones.info[i - 1] = zones.info[i];
     737                zones.info[i - 1].buddy_system->data =
     738                    (void *) &zones.info[i - 1];
     739        }
     740       
    772741        zones.count--;
    773742       
     
    965934        spinlock_lock(&zones.lock);
    966935       
    967         count_t znum = find_zone(pfn, hint);
     936        count_t znum = find_zone(pfn, 1, hint);
    968937       
    969938        ASSERT(znum != (count_t) -1);
     
    981950        spinlock_lock(&zones.lock);
    982951       
    983         count_t znum = find_zone(pfn, hint);
     952        count_t znum = find_zone(pfn, 1, hint);
    984953       
    985954        ASSERT(znum != (count_t) -1);
     
    11121081         */
    11131082        pfn_t pfn = ADDR2PFN(frame);
    1114         count_t znum = find_zone(pfn, NULL);
     1083        count_t znum = find_zone(pfn, 1, NULL);
    11151084       
    11161085        ASSERT(znum != (count_t) -1);
     
    11511120         * First, find host frame zone for addr.
    11521121         */
    1153         count_t znum = find_zone(pfn, NULL);
     1122        count_t znum = find_zone(pfn, 1, NULL);
    11541123       
    11551124        ASSERT(znum != (count_t) -1);
     
    11691138        count_t i;
    11701139        for (i = 0; i < count; i++) {
    1171                 count_t znum = find_zone(start + i, 0);
     1140                count_t znum = find_zone(start + i, 1, 0);
    11721141                if (znum == (count_t) -1)  /* PFN not found */
    11731142                        continue;
     
    12381207{
    12391208#ifdef __32_BITS__
    1240         printf("#  base address flags    free frames  busy frames\n");
    1241         printf("-- ------------ -------- ------------ ------------\n");
     1209        printf("#  base address frames       flags    free frames  busy frames\n");
     1210        printf("-- ------------ ------------ -------- ------------ ------------\n");
    12421211#endif
    12431212
    12441213#ifdef __64_BITS__
    1245         printf("#  base address         flags    free frames  busy frames\n");
    1246         printf("-- -------------------- -------- ------------ ------------\n");
     1214        printf("#  base address          frames      flags    free frames  busy frames\n");
     1215        printf("-- -------------------- ------------ -------- ------------ ------------\n");
    12471216#endif
    12481217       
     
    12701239               
    12711240                uintptr_t base = PFN2ADDR(zones.info[i].base);
     1241                count_t count = zones.info[i].count;
    12721242                zone_flags_t flags = zones.info[i].flags;
    12731243                count_t free_count = zones.info[i].free_count;
     
    12791249                bool available = zone_flags_available(flags);
    12801250               
     1251                printf("%-2" PRIc, i);
     1252               
    12811253#ifdef __32_BITS__
    1282                 printf("%-2" PRIc "   %10p %c%c%c      ", i, base,
     1254                printf("   %10p", base);
     1255#endif
     1256               
     1257#ifdef __64_BITS__
     1258                printf("   %18p", base);
     1259#endif
     1260               
     1261                printf(" %12" PRIc " %c%c%c      ", count,
    12831262                    available ? 'A' : ' ',
    12841263                    (flags & ZONE_RESERVED) ? 'R' : ' ',
    12851264                    (flags & ZONE_FIRMWARE) ? 'F' : ' ');
    1286 #endif
    1287                
    1288 #ifdef __64_BITS__
    1289                 printf("%-2" PRIc "   %18p %c%c%c      ", i, base,
    1290                     available ? 'A' : ' ',
    1291                     (flags & ZONE_RESERVED) ? 'R' : ' ',
    1292                     (flags & ZONE_FIRMWARE) ? 'F' : ' ');
    1293 #endif
    12941265               
    12951266                if (available)
    12961267                        printf("%12" PRIc " %12" PRIc,
    12971268                            free_count, busy_count);
     1269               
    12981270                printf("\n");
    12991271        }
Note: See TracChangeset for help on using the changeset viewer.