]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/bootstrap/server/src/platform_common.cc
Update
[l4.git] / l4 / pkg / bootstrap / server / src / platform_common.cc
1 #include "support.h"
2 #include <l4/cxx/minmax>
3 #include <cassert>
4
5 #ifdef RAM_SIZE_MB
6
7 static unsigned long
8 scan_ram_size(unsigned long base_addr, unsigned long max_scan_size_mb)
9 {
10   // scan the RAM to find out the RAM size, note that at this point we have
11   // two regions in RAM that we cannot touch, &_start - &_end and the
12   // modules
13
14   // assume that the image is loaded correctly and we need to start
15   // probing for memory wraparounds beyond the end of our image
16   extern char _end[];
17 #ifdef IMAGE_MODE
18   extern char _module_data_end[];
19   l4_addr_t lower_bound
20     = l4_round_size((l4_addr_t)cxx::max(_end, _module_data_end), 20);
21 #else
22   l4_addr_t lower_bound = l4_round_size((l4_addr_t)_end, 20);
23 #endif
24
25   assert(base_addr <= lower_bound);
26   lower_bound -= base_addr;
27
28   // must be a power of 2 and >= (1 << 20)
29   unsigned long increment;
30   unsigned long max_scan_size = max_scan_size_mb << 20;
31
32   // push the initial probe point beyond lower_bound
33   for (increment = 1 << 20;
34        increment < lower_bound && increment < max_scan_size;
35        increment *= 2)
36     {}
37
38   printf("  Scanning up to %ld MB RAM, starting at offset %ldMB\n",
39          max_scan_size_mb, increment >> 20);
40
41   // initialize memory probe points
42   for (unsigned long offset = increment;
43        offset < max_scan_size;
44        offset *= 2)
45     *(unsigned long *)(base_addr + offset) = 0;
46
47   // avoid gcc/clang optimization figuring out that base_addr might
48   // always be 0 and generating a trap here
49   asm("" : "+r" (base_addr));
50   // write something at offset 0, does it appear elsewhere?
51   *(unsigned long *)base_addr = 0x12345678;
52   asm volatile("" : : : "memory");
53   for (unsigned long offset = increment;
54        offset < max_scan_size;
55        offset *= 2)
56     if (*(unsigned long *)(base_addr + offset) == 0x12345678)
57       return offset >> 20;  // detected a wrap around at offset
58
59   return max_scan_size_mb;
60 }
61
62 void
63 Platform_single_region_ram::setup_memory_map()
64 {
65   unsigned long ram_size_mb = scan_ram_size(RAM_BASE, RAM_SIZE_MB);
66   printf("  Memory size is %ldMB%s (%08lx - %08lx)\n",
67          ram_size_mb, ram_size_mb != RAM_SIZE_MB ? " (Limited by Scan)" : "",
68          (unsigned long)RAM_BASE, RAM_BASE + (ram_size_mb << 20) - 1);
69   mem_manager->ram->add(
70       Region::n(RAM_BASE,
71                 (unsigned long long)RAM_BASE + (ram_size_mb << 20),
72                 ".ram", Region::Ram));
73 }
74 #endif