Main Page | Directories | File List | Globals

memory.c

Go to the documentation of this file.
00001 /*
00002  * kernel_arch/i386/kernel/memory/memory.c
00003  *
00004  * Copyright (c) 2003-2004 Lukasz Dembinski <dembol@nasa.com.pl>
00005  * All Rights Reserved
00006  * 
00007  * Date:        2004/01
00008  * Author:      Lukasz Dembinski
00009  * Info:        memory.c core file
00010  * Contact:     mailto: <dembol@nasa.com.pl>
00011  *
00012  */
00013 
00014 #include <agnix/agnix.h>
00015 #include <agnix/init.h>
00016 #include <asm/bios_parametrs.h>
00017 #include <agnix/memory.h>
00018 #include <asm/memtests.h>
00019 #include <agnix/console.h>
00020 
00021 #define MOD_NAME        "BOOTM: "
00022 
00023 struct main_memory_s  main_memory;
00024 struct memory_block_s main_block;
00025 extern struct bin_allocator_s bin_alloc;
00026 extern u32 swapper_pg_dir[1024];
00027 extern int page_tables_init(struct main_memory_s *mem);
00028 
00029 extern char __init_begin, __init_end;
00030 
00031 void __init modify_memory_entry(struct memory_block_s *mem_block, unsigned long long start, unsigned long long size,
00032                          unsigned long type, int block_nr)
00033 {
00034     mem_block->entries[block_nr].start = start;
00035     mem_block->entries[block_nr].size  = size;
00036     mem_block->entries[block_nr].type  = type;
00037 }
00038 
00039 void __init add_memory_entry(struct memory_block_s *mem_block, struct e820_entry_s *entry)
00040 {
00041     int block_nr = mem_block->mem_nr;
00042 
00043     memcpy(&mem_block->entries[block_nr], entry, sizeof(struct e820_entry_s));
00044     mem_block->mem_nr++;
00045 }
00046 
00047 #define mem_block_size(mem_block, i) \
00048         mem_block->entries[i].size
00049 
00050 #define mem_block_start(mem_block, i) \
00051         mem_block->entries[i].start
00052 
00053 #define mem_block_end(mem_block, i) \
00054         mem_block->entries[i].start + mem_block->entries[i].size
00055 
00056 #define mem_block_type(mem_block, i) \
00057         mem_block->entries[i].type
00058 
00059 unsigned long __init parse_biosmap(struct e820_entry_s *biosentry, char map_nr)
00060 {
00061     struct e820_entry_s *bios_entry  = biosentry;
00062     struct e820_entry_s bios_entry_tmp;
00063     struct memory_block_s *mem_block = &main_block;
00064     unsigned long max_ram_addr  = 0;
00065     int           max_entry;
00066     unsigned long max_addr;
00067     unsigned long prev_max_addr = -1;
00068     int           i;
00069     int           map_count = (int)map_nr;
00070 
00071     do {
00072         max_entry = -1;
00073         max_addr  = -1;
00074         for (i = 0; i < map_nr; i++) {
00075             if (((prev_max_addr == -1) || (bios_entry[i].start > prev_max_addr)) && (bios_entry[i].start < max_addr)) {
00076                 max_entry = i;
00077                 max_addr = bios_entry[i].start;
00078             }   
00079         }
00080         if (max_entry == -1) break;
00081     
00082         prev_max_addr = max_addr;
00083         
00084         memcpy(&bios_entry_tmp, &bios_entry[max_entry], sizeof(bios_entry_tmp));
00085 
00086         for (i = 0; i < mem_block->mem_nr; i++) {
00087             if (bios_entry_tmp.start < mem_block_end(mem_block, i)) {
00088                 if (bios_entry_tmp.type > mem_block_type(mem_block, i)) {
00089                     mem_block_size(mem_block, i) = mem_block_start(mem_block, i) - 
00090                                                bios_entry_tmp.start;
00091                 } else {
00092                     bios_entry_tmp.start = mem_block_end(mem_block, i);
00093                 }
00094             }
00095         }
00096 
00097         add_memory_entry(mem_block, &bios_entry_tmp);
00098         if (bios_entry_tmp.type == E820_RAM) { 
00099             if (max_ram_addr < bios_entry_tmp.start + bios_entry_tmp.size)
00100                 max_ram_addr = bios_entry_tmp.start + bios_entry_tmp.size;
00101         }
00102                 
00103         map_count--;
00104     } while(map_count);
00105 
00106     return max_ram_addr;
00107 }
00108 
00109 void print_memory_map(struct main_memory_s *memory, int broadcast)
00110 {
00111     int i;
00112     char *e820_name;
00113     
00114     if (broadcast) {
00115         printk("\n");
00116         printk(MOD_NAME "Memory size = %dKB\n", (unsigned long)(memory->mem_size));
00117         printk(MOD_NAME "Memory map (BIOS):\n");
00118     } else {
00119         printf("\n");
00120         printf(MOD_NAME "Memory size = %dKB\n", (unsigned long)(memory->mem_size));
00121         printf(MOD_NAME "Memory map (BIOS):\n");
00122     }
00123     
00124     for (i = 0; i < main_block.mem_nr; i++) {
00125     
00126         if (main_block.entries[i].size == 0)
00127             continue;
00128     
00129         switch (main_block.entries[i].type) {
00130         
00131             case E820_RAM:
00132                 e820_name = "(RAM)     ";
00133                 break;
00134             case E820_RESERVED:
00135                 e820_name = "(RESERVED)";
00136                 break;
00137             case E820_ACPI:
00138                 e820_name = "(ACPI)    ";
00139                 break;
00140             case E820_NVS:
00141                 e820_name = "(NVS)     ";
00142                 break;
00143             default:
00144                 e820_name = "(UNKNOWN) ";
00145         }
00146         
00147         if (broadcast) {
00148             printk("\t%s %08x-%08x\n", e820_name, (unsigned long)main_block.entries[i].start, 
00149                    (unsigned long)(main_block.entries[i].start + main_block.entries[i].size));
00150         } else {
00151             printf("\t%s %08x-%08x\n", e820_name, (unsigned long)main_block.entries[i].start, 
00152                    (unsigned long)(main_block.entries[i].start + main_block.entries[i].size));
00153         }
00154     }
00155 
00156     if (broadcast)
00157         printk("\n");    
00158     else
00159         printf("\n");    
00160 }
00161 
00162 void bootmem_free_ram(void)
00163 {
00164     int i;
00165 
00166     for (i = 0; i < main_block.mem_nr; i++) {
00167     
00168         if (main_block.entries[i].size == 0)
00169             continue;
00170     
00171         if (main_block.entries[i].type == E820_RAM) {
00172             bin_free_pages(&bin_alloc, (unsigned long)(main_block.entries[i].start) >> PAGE_SHIFT, (unsigned long)(main_block.entries[i].size) >> PAGE_SHIFT);
00173         }
00174     }
00175 }
00176 
00177 int __init bootmem_init_bh(void)
00178 {
00179     memset(&main_memory, 0, sizeof(main_memory));
00180     memset(&main_block, 0, sizeof(main_block));
00181     INIT_LIST_HEAD(&main_memory.list);
00182     INIT_LIST_HEAD(&main_block.list);
00183     list_add(&main_block.list, &main_memory.list);
00184 
00185     main_memory.mem_size = parse_biosmap(E820_MAP, E820_MAP_NR) >> 10;
00186     main_memory.pdbr     = (u32)swapper_pg_dir;
00187 
00188     return 0;
00189 }
00190 
00191 int __init bootmem_init_dh(void) 
00192 {
00193     bootmem_free_ram();
00194     bin_reserve_system_pages();
00195     print_memory_map(&main_memory, 1);
00196 
00197     page_tables_init(&main_memory);
00198 
00199 #if CONFIG_MEMTESTS
00200     if (do_memtests() < 0) {
00201         return -1;
00202     }
00203 #endif
00204 
00205     return 0;
00206 }
00207 
00208 int bootmem_free_init(void)
00209 {
00210     u32 init_start = (u32)&__init_begin;
00211     u32 init_end = (u32)&__init_end;
00212 
00213     printk("Freeing __init segment (%d kb)\n", (init_end - init_start) >> 10);
00214         
00215     return 0;
00216 }
00217 
00218 void bootmem_print_memory(void)
00219 {
00220     print_memory_map(&main_memory, 0);
00221 }
Dokumentacje wygenerowano programem Doxygen 1.4.2 dla projektu Agnix