Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/arch/x86/e820.c
Line
Count
Source (jump to first uncovered line)
1
#include <xen/init.h>
2
#include <xen/lib.h>
3
#include <xen/mm.h>
4
#include <xen/compat.h>
5
#include <xen/dmi.h>
6
#include <xen/pfn.h>
7
#include <asm/e820.h>
8
#include <asm/page.h>
9
#include <asm/processor.h>
10
#include <asm/mtrr.h>
11
#include <asm/msr.h>
12
13
/*
14
 * opt_mem: Limit maximum address of physical RAM.
15
 *          Any RAM beyond this address limit is ignored.
16
 */
17
static unsigned long long __initdata opt_mem;
18
size_param("mem", opt_mem);
19
20
/*
21
 * opt_availmem: Limit maximum usable amount of physical RAM.
22
 *               Any RAM beyond this limited amount is ignored.
23
 */
24
static unsigned long long __initdata opt_availmem;
25
size_param("availmem", opt_availmem);
26
27
/* opt_nomtrr_check: Don't clip ram to highest cacheable MTRR. */
28
static s8 __initdata e820_mtrr_clip = -1;
29
boolean_param("e820-mtrr-clip", e820_mtrr_clip);
30
31
/* opt_e820_verbose: Be verbose about clipping, the original e820, &c */
32
static bool __initdata e820_verbose;
33
boolean_param("e820-verbose", e820_verbose);
34
35
struct e820map e820;
36
struct e820map __initdata e820_raw;
37
38
/*
39
 * This function checks if the entire range <start,end> is mapped with type.
40
 *
41
 * Note: this function only works correct if the e820 table is sorted and
42
 * not-overlapping, which is the case
43
 */
44
int __init e820_all_mapped(u64 start, u64 end, unsigned type)
45
1
{
46
1
  int i;
47
1
48
16
  for (i = 0; i < e820.nr_map; i++) {
49
16
    struct e820entry *ei = &e820.map[i];
50
16
51
16
    if (type && ei->type != type)
52
10
      continue;
53
16
    /* is the region (part) in overlap with the current region ?*/
54
6
    if (ei->addr >= end || ei->addr + ei->size <= start)
55
5
      continue;
56
6
57
6
    /* if the region is at the beginning of <start,end> we move
58
6
     * start to the end of the region since it's ok until there
59
6
     */
60
1
    if (ei->addr <= start)
61
1
      start = ei->addr + ei->size;
62
1
    /*
63
1
     * if start is now at or beyond end, we're done, full
64
1
     * coverage
65
1
     */
66
1
    if (start >= end)
67
1
      return 1;
68
1
  }
69
0
  return 0;
70
1
}
71
72
static void __init add_memory_region(unsigned long long start,
73
                                     unsigned long long size, int type)
74
19
{
75
19
    int x;
76
19
77
19
    x = e820.nr_map;
78
19
79
19
    if (x == ARRAY_SIZE(e820.map)) {
80
0
        printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
81
0
        return;
82
0
    }
83
19
84
19
    e820.map[x].addr = start;
85
19
    e820.map[x].size = size;
86
19
    e820.map[x].type = type;
87
19
    e820.nr_map++;
88
19
}
89
90
static void __init print_e820_memory_map(struct e820entry *map, unsigned int entries)
91
1
{
92
1
    unsigned int i;
93
1
94
20
    for (i = 0; i < entries; i++) {
95
19
        printk(" %016Lx - %016Lx ",
96
19
               (unsigned long long)(map[i].addr),
97
19
               (unsigned long long)(map[i].addr + map[i].size));
98
19
        switch (map[i].type) {
99
8
        case E820_RAM:
100
8
            printk("(usable)\n");
101
8
            break;
102
8
        case E820_RESERVED:
103
8
            printk("(reserved)\n");
104
8
            break;
105
1
        case E820_ACPI:
106
1
            printk("(ACPI data)\n");
107
1
            break;
108
2
        case E820_NVS:
109
2
            printk("(ACPI NVS)\n");
110
2
            break;
111
0
        case E820_UNUSABLE:
112
0
            printk("(unusable)\n");
113
0
            break;
114
0
        default:
115
0
            printk("type %u\n", map[i].type);
116
0
            break;
117
19
        }
118
19
    }
119
1
}
120
121
/*
122
 * Sanitize the BIOS e820 map.
123
 *
124
 * Some e820 responses include overlapping entries.  The following 
125
 * replaces the original e820 map with a new one, removing overlaps.
126
 *
127
 */
128
struct change_member {
129
    struct e820entry *pbios; /* pointer to original bios entry */
130
    unsigned long long addr; /* address for this change point */
131
};
132
static struct change_member change_point_list[2*E820MAX] __initdata;
133
static struct change_member *change_point[2*E820MAX] __initdata;
134
static struct e820entry *overlap_list[E820MAX] __initdata;
135
static struct e820entry new_bios[E820MAX] __initdata;
136
137
static int __init sanitize_e820_map(struct e820entry *biosmap,
138
                                    unsigned int *pnr_map)
139
1
{
140
1
    struct change_member *change_tmp;
141
1
    unsigned long current_type, last_type;
142
1
    unsigned long long last_addr;
143
1
    int chgidx, still_changing;
144
1
    int overlap_entries;
145
1
    int new_bios_entry;
146
1
    int old_nr, new_nr, chg_nr;
147
1
    int i;
148
1
149
1
    /*
150
1
      Visually we're performing the following (1,2,3,4 = memory types)...
151
1
152
1
      Sample memory map (w/overlaps):
153
1
      ____22__________________
154
1
      ______________________4_
155
1
      ____1111________________
156
1
      _44_____________________
157
1
      11111111________________
158
1
      ____________________33__
159
1
      ___________44___________
160
1
      __________33333_________
161
1
      ______________22________
162
1
      ___________________2222_
163
1
      _________111111111______
164
1
      _____________________11_
165
1
      _________________4______
166
1
167
1
      Sanitized equivalent (no overlap):
168
1
      1_______________________
169
1
      _44_____________________
170
1
      ___1____________________
171
1
      ____22__________________
172
1
      ______11________________
173
1
      _________1______________
174
1
      __________3_____________
175
1
      ___________44___________
176
1
      _____________33_________
177
1
      _______________2________
178
1
      ________________1_______
179
1
      _________________4______
180
1
      ___________________2____
181
1
      ____________________33__
182
1
      ______________________4_
183
1
    */
184
1
185
1
    /* if there's only one memory region, don't bother */
186
1
    if (*pnr_map < 2)
187
0
        return -1;
188
1
189
1
    old_nr = *pnr_map;
190
1
191
1
    /* bail out if we find any unreasonable addresses in bios map */
192
20
    for (i=0; i<old_nr; i++)
193
19
        if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)
194
0
            return -1;
195
1
196
1
    /* create pointers for initial change-point information (for sorting) */
197
39
    for (i=0; i < 2*old_nr; i++)
198
38
        change_point[i] = &change_point_list[i];
199
1
200
1
    /* record all known change-points (starting and ending addresses),
201
1
       omitting those that are for empty memory regions */
202
1
    chgidx = 0;
203
20
    for (i=0; i < old_nr; i++) {
204
19
        if (biosmap[i].size != 0) {
205
19
            change_point[chgidx]->addr = biosmap[i].addr;
206
19
            change_point[chgidx++]->pbios = &biosmap[i];
207
19
            change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size;
208
19
            change_point[chgidx++]->pbios = &biosmap[i];
209
19
        }
210
19
    }
211
1
    chg_nr = chgidx;      /* true number of change-points */
212
1
213
1
    /* sort change-point list by memory addresses (low -> high) */
214
1
    still_changing = 1;
215
3
    while (still_changing) {
216
2
        still_changing = 0;
217
76
        for (i=1; i < chg_nr; i++)  {
218
74
            /* if <current_addr> > <last_addr>, swap */
219
74
            /* or, if current=<start_addr> & last=<end_addr>, swap */
220
74
            if ((change_point[i]->addr < change_point[i-1]->addr) ||
221
74
                ((change_point[i]->addr == change_point[i-1]->addr) &&
222
28
                 (change_point[i]->addr == change_point[i]->pbios->addr) &&
223
14
                 (change_point[i-1]->addr != change_point[i-1]->pbios->addr))
224
74
                )
225
14
            {
226
14
                change_tmp = change_point[i];
227
14
                change_point[i] = change_point[i-1];
228
14
                change_point[i-1] = change_tmp;
229
14
                still_changing=1;
230
14
            }
231
74
        }
232
2
    }
233
1
234
1
    /* create a new bios memory map, removing overlaps */
235
1
    overlap_entries=0;   /* number of entries in the overlap table */
236
1
    new_bios_entry=0;  /* index for creating new bios map entries */
237
1
    last_type = 0;     /* start with undefined memory type */
238
1
    last_addr = 0;     /* start with 0 as last starting address */
239
1
    /* loop through change-points, determining affect on the new bios map */
240
39
    for (chgidx=0; chgidx < chg_nr; chgidx++)
241
38
    {
242
38
        /* keep track of all overlapping bios entries */
243
38
        if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr)
244
19
        {
245
19
            /* add map entry to overlap list (> 1 entry implies an overlap) */
246
19
            overlap_list[overlap_entries++]=change_point[chgidx]->pbios;
247
19
        }
248
38
        else
249
19
        {
250
19
            /* remove entry from list (order independent, so swap with last) */
251
52
            for (i=0; i<overlap_entries; i++)
252
33
            {
253
33
                if (overlap_list[i] == change_point[chgidx]->pbios)
254
19
                    overlap_list[i] = overlap_list[overlap_entries-1];
255
33
            }
256
19
            overlap_entries--;
257
19
        }
258
38
        /* if there are overlapping entries, decide which "type" to use */
259
38
        /* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */
260
38
        current_type = 0;
261
85
        for (i=0; i<overlap_entries; i++)
262
47
            if (overlap_list[i]->type > current_type)
263
40
                current_type = overlap_list[i]->type;
264
38
        /* continue building up new bios map based on this information */
265
38
        if (current_type != last_type) {
266
24
            if (last_type != 0)  {
267
19
                new_bios[new_bios_entry].size =
268
19
                    change_point[chgidx]->addr - last_addr;
269
19
        /* move forward only if the new size was non-zero */
270
19
                if (new_bios[new_bios_entry].size != 0)
271
19
                    if (++new_bios_entry >= ARRAY_SIZE(new_bios))
272
0
                        break;   /* no more space left for new bios entries */
273
19
            }
274
24
            if (current_type != 0) {
275
19
                new_bios[new_bios_entry].addr = change_point[chgidx]->addr;
276
19
                new_bios[new_bios_entry].type = current_type;
277
19
                last_addr=change_point[chgidx]->addr;
278
19
            }
279
24
            last_type = current_type;
280
24
        }
281
38
    }
282
1
    new_nr = new_bios_entry;   /* retain count for new bios entries */
283
1
284
1
    /* copy new bios mapping into original location */
285
1
    memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry));
286
1
    *pnr_map = new_nr;
287
1
288
1
    return 0;
289
1
}
290
291
/*
292
 * Copy the BIOS e820 map into a safe place.
293
 *
294
 * Sanity-check it while we're at it..
295
 *
296
 * If we're lucky and live on a modern system, the setup code
297
 * will have given us a memory map that we can use to properly
298
 * set up memory.  If we aren't, we'll fake a memory map.
299
 *
300
 * We check to see that the memory map contains at least 2 elements
301
 * before we'll use it, because the detection code in setup.S may
302
 * not be perfect and most every PC known to man has two memory
303
 * regions: one from 0 to 640k, and one from 1mb up.  (The IBM
304
 * thinkpad 560x, for example, does not cooperate with the memory
305
 * detection code.)
306
 */
307
static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
308
1
{
309
1
    /* Only one memory region (or negative)? Ignore it */
310
1
    if (nr_map < 2)
311
0
        return -1;
312
1
313
19
    do {
314
19
        unsigned long long start = biosmap->addr;
315
19
        unsigned long long size = biosmap->size;
316
19
        unsigned long long end = start + size;
317
19
        unsigned long type = biosmap->type;
318
19
319
19
        /* Overflow in 64 bits? Ignore the memory map. */
320
19
        if (start > end)
321
0
            return -1;
322
19
323
19
        /*
324
19
         * Some BIOSes claim RAM in the 640k - 1M region.
325
19
         * Not right. Fix it up.
326
19
         */
327
19
        if (type == E820_RAM) {
328
8
            if (start < 0x100000ULL && end > 0xA0000ULL) {
329
0
                if (start < 0xA0000ULL)
330
0
                    add_memory_region(start, 0xA0000ULL-start, type);
331
0
                if (end <= 0x100000ULL)
332
0
                    continue;
333
0
                start = 0x100000ULL;
334
0
                size = end - start;
335
0
            }
336
8
        }
337
19
        add_memory_region(start, size, type);
338
19
    } while (biosmap++,--nr_map);
339
1
    return 0;
340
1
}
341
342
343
/*
344
 * Find the highest page frame number we have available
345
 */
346
static unsigned long __init find_max_pfn(void)
347
1
{
348
1
    int i;
349
1
    unsigned long max_pfn = 0;
350
1
351
20
    for (i = 0; i < e820.nr_map; i++) {
352
19
        unsigned long start, end;
353
19
        /* RAM? */
354
19
        if (e820.map[i].type != E820_RAM)
355
11
            continue;
356
8
        start = PFN_UP(e820.map[i].addr);
357
8
        end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
358
8
        if (start >= end)
359
0
            continue;
360
8
        if (end > max_pfn)
361
8
            max_pfn = end;
362
8
    }
363
1
364
1
    return max_pfn;
365
1
}
366
367
static void __init clip_to_limit(uint64_t limit, char *warnmsg)
368
2
{
369
2
    int i;
370
2
    char _warnmsg[160];
371
2
    uint64_t old_limit = 0;
372
2
373
2
    for ( ; ; )
374
2
    {
375
2
        /* Find a RAM region needing clipping. */
376
40
        for ( i = 0; i < e820.nr_map; i++ )
377
38
            if ( (e820.map[i].type == E820_RAM) &&
378
16
                 ((e820.map[i].addr + e820.map[i].size) > limit) )
379
0
                break;
380
2
381
2
        /* If none found, we are done. */
382
2
        if ( i == e820.nr_map )
383
2
            break;        
384
2
385
0
        old_limit = max_t(
386
0
            uint64_t, old_limit, e820.map[i].addr + e820.map[i].size);
387
0
388
0
        /* We try to convert clipped RAM areas to E820_UNUSABLE. */
389
0
        if ( e820_change_range_type(&e820, max(e820.map[i].addr, limit),
390
0
                                    e820.map[i].addr + e820.map[i].size,
391
0
                                    E820_RAM, E820_UNUSABLE) )
392
0
            continue;
393
0
394
0
        /*
395
0
         * If the type change fails (e.g., not space in table) then we clip or 
396
0
         * delete the region as appropriate.
397
0
         */
398
0
        if ( e820.map[i].addr < limit )
399
0
        {
400
0
            e820.map[i].size = limit - e820.map[i].addr;
401
0
        }
402
0
        else
403
0
        {
404
0
            memmove(&e820.map[i], &e820.map[i+1],
405
0
                    (e820.nr_map - i - 1) * sizeof(struct e820entry));
406
0
            e820.nr_map--;
407
0
        }
408
0
    }
409
2
410
2
    if ( old_limit )
411
0
    {
412
0
        if ( warnmsg )
413
0
        {
414
0
            snprintf(_warnmsg, sizeof(_warnmsg), warnmsg, (long)(limit>>30));
415
0
            printk("WARNING: %s\n", _warnmsg);
416
0
        }
417
0
        printk("Truncating RAM from %lukB to %lukB\n",
418
0
               (unsigned long)(old_limit >> 10), (unsigned long)(limit >> 10));
419
0
    }
420
2
}
421
422
/* Conservative estimate of top-of-RAM by looking for MTRR WB regions. */
423
static uint64_t __init mtrr_top_of_ram(void)
424
1
{
425
1
    uint32_t eax, ebx, ecx, edx;
426
1
    uint64_t mtrr_cap, mtrr_def, addr_mask, base, mask, top;
427
1
    unsigned int i, phys_bits = 36;
428
1
429
1
    /* By default we check only Intel systems. */
430
1
    if ( e820_mtrr_clip == -1 )
431
1
    {
432
1
        char vendor[13];
433
1
        cpuid(0x00000000, &eax,
434
1
              (uint32_t *)&vendor[0],
435
1
              (uint32_t *)&vendor[8],
436
1
              (uint32_t *)&vendor[4]);
437
1
        vendor[12] = '\0';
438
1
        e820_mtrr_clip = !strcmp(vendor, "GenuineIntel");
439
1
    }
440
1
441
1
    if ( !e820_mtrr_clip )
442
0
        return 0;
443
1
444
1
    if ( e820_verbose )
445
0
        printk("Checking MTRR ranges...\n");
446
1
447
1
    /* Does the CPU support architectural MTRRs? */
448
1
    cpuid(0x00000001, &eax, &ebx, &ecx, &edx);
449
1
    if ( !test_bit(X86_FEATURE_MTRR & 31, &edx) )
450
0
         return 0;
451
1
452
1
    /* Find the physical address size for this CPU. */
453
1
    eax = cpuid_eax(0x80000000);
454
1
    if ( (eax >> 16) == 0x8000 && eax >= 0x80000008 )
455
1
    {
456
1
        phys_bits = (uint8_t)cpuid_eax(0x80000008);
457
1
        if ( phys_bits > PADDR_BITS )
458
0
            phys_bits = PADDR_BITS;
459
1
    }
460
1
    addr_mask = ((1ull << phys_bits) - 1) & ~((1ull << 12) - 1);
461
1
462
1
    rdmsrl(MSR_MTRRcap, mtrr_cap);
463
1
    rdmsrl(MSR_MTRRdefType, mtrr_def);
464
1
465
1
    if ( e820_verbose )
466
0
        printk(" MTRR cap: %"PRIx64" type: %"PRIx64"\n", mtrr_cap, mtrr_def);
467
1
468
1
    /* MTRRs enabled, and default memory type is not writeback? */
469
1
    if ( !test_bit(11, &mtrr_def) || ((uint8_t)mtrr_def == MTRR_TYPE_WRBACK) )
470
0
        return 0;
471
1
472
1
    /*
473
1
     * Find end of highest WB-type range. This is a conservative estimate
474
1
     * of the highest WB address since overlapping UC/WT ranges dominate.
475
1
     */
476
1
    top = 0;
477
11
    for ( i = 0; i < (uint8_t)mtrr_cap; i++ )
478
10
    {
479
10
        rdmsrl(MSR_IA32_MTRR_PHYSBASE(i), base);
480
10
        rdmsrl(MSR_IA32_MTRR_PHYSMASK(i), mask);
481
10
482
10
        if ( e820_verbose )
483
0
            printk(" MTRR[%d]: base %"PRIx64" mask %"PRIx64"\n",
484
0
                   i, base, mask);
485
10
486
10
        if ( !test_bit(11, &mask) || ((uint8_t)base != MTRR_TYPE_WRBACK) )
487
8
            continue;
488
2
        base &= addr_mask;
489
2
        mask &= addr_mask;
490
2
        top = max_t(uint64_t, top, ((base | ~mask) & addr_mask) + PAGE_SIZE);
491
2
    }
492
1
493
1
    return top;
494
1
}
495
496
static void __init reserve_dmi_region(void)
497
1
{
498
1
    for ( ; ; )
499
2
    {
500
2
        paddr_t base;
501
2
        u32 len;
502
2
        const char *what = dmi_get_table(&base, &len);
503
2
504
2
        if ( !what )
505
1
            break;
506
1
        if ( ((base + len) > base) &&
507
1
             reserve_e820_ram(&e820, base, base + len) )
508
0
            printk("WARNING: %s table located in E820 RAM %"PRIpaddr"-%"PRIpaddr". Fixed.\n",
509
0
                   what, base, base + len);
510
1
    }
511
1
}
512
513
static void __init machine_specific_memory_setup(struct e820map *raw)
514
1
{
515
1
    unsigned long mpt_limit, ro_mpt_limit;
516
1
    uint64_t top_of_ram, size;
517
1
    int i;
518
1
519
1
    sanitize_e820_map(raw->map, &raw->nr_map);
520
1
    copy_e820_map(raw->map, raw->nr_map);
521
1
522
1
    if ( opt_mem )
523
0
        clip_to_limit(opt_mem, NULL);
524
1
525
1
    if ( opt_availmem )
526
0
    {
527
0
        for ( i = size = 0; (i < e820.nr_map) && (size <= opt_availmem); i++ )
528
0
            if ( e820.map[i].type == E820_RAM )
529
0
                size += e820.map[i].size;
530
0
        if ( size > opt_availmem )
531
0
            clip_to_limit(
532
0
                e820.map[i-1].addr + e820.map[i-1].size - (size-opt_availmem),
533
0
                NULL);
534
0
    }
535
1
536
1
    mpt_limit = ((RDWR_MPT_VIRT_END - RDWR_MPT_VIRT_START)
537
1
                 / sizeof(unsigned long)) << PAGE_SHIFT;
538
1
    ro_mpt_limit = ((RO_MPT_VIRT_END - RO_MPT_VIRT_START)
539
1
                    / sizeof(unsigned long)) << PAGE_SHIFT;
540
1
    if ( mpt_limit > ro_mpt_limit )
541
0
        mpt_limit = ro_mpt_limit;
542
1
    clip_to_limit(mpt_limit,
543
1
                  "Only the first %lu GB of the physical "
544
1
                  "memory map can be accessed by Xen.");
545
1
546
1
    reserve_dmi_region();
547
1
548
1
    top_of_ram = mtrr_top_of_ram();
549
1
    if ( top_of_ram )
550
1
        clip_to_limit(top_of_ram, "MTRRs do not cover all of memory.");
551
1
}
552
553
/* This function relies on the passed in e820->map[] being sorted. */
554
int __init e820_add_range(
555
    struct e820map *e820, uint64_t s, uint64_t e, uint32_t type)
556
0
{
557
0
    unsigned int i;
558
0
559
0
    for ( i = 0; i < e820->nr_map; ++i )
560
0
    {
561
0
        uint64_t rs = e820->map[i].addr;
562
0
        uint64_t re = rs + e820->map[i].size;
563
0
564
0
        if ( rs == e && e820->map[i].type == type )
565
0
        {
566
0
            e820->map[i].addr = s;
567
0
            return 1;
568
0
        }
569
0
570
0
        if ( re == s && e820->map[i].type == type &&
571
0
             (i + 1 == e820->nr_map || e820->map[i + 1].addr >= e) )
572
0
        {
573
0
            e820->map[i].size += e - s;
574
0
            return 1;
575
0
        }
576
0
577
0
        if ( rs >= e )
578
0
            break;
579
0
580
0
        if ( re > s )
581
0
            return 0;
582
0
    }
583
0
584
0
    if ( e820->nr_map >= ARRAY_SIZE(e820->map) )
585
0
    {
586
0
        printk(XENLOG_WARNING "E820: overflow while adding region"
587
0
               " %"PRIx64"-%"PRIx64"\n", s, e);
588
0
        return 0;
589
0
    }
590
0
591
0
    memmove(e820->map + i + 1, e820->map + i,
592
0
            (e820->nr_map - i) * sizeof(*e820->map));
593
0
594
0
    e820->nr_map++;
595
0
    e820->map[i].addr = s;
596
0
    e820->map[i].size = e - s;
597
0
    e820->map[i].type = type;
598
0
599
0
    return 1;
600
0
}
601
602
int __init e820_change_range_type(
603
    struct e820map *e820, uint64_t s, uint64_t e,
604
    uint32_t orig_type, uint32_t new_type)
605
4
{
606
4
    uint64_t rs = 0, re = 0;
607
4
    int i;
608
4
609
55
    for ( i = 0; i < e820->nr_map; i++ )
610
55
    {
611
55
        /* Have we found the e820 region that includes the specified range? */
612
55
        rs = e820->map[i].addr;
613
55
        re = rs + e820->map[i].size;
614
55
        if ( (s >= rs) && (e <= re) )
615
4
            break;
616
55
    }
617
4
618
4
    if ( (i == e820->nr_map) || (e820->map[i].type != orig_type) )
619
1
        return 0;
620
4
621
3
    if ( (s == rs) && (e == re) )
622
1
    {
623
1
        e820->map[i].type = new_type;
624
1
    }
625
2
    else if ( (s == rs) || (e == re) )
626
0
    {
627
0
        if ( (e820->nr_map + 1) > ARRAY_SIZE(e820->map) )
628
0
            goto overflow;
629
0
630
0
        memmove(&e820->map[i+1], &e820->map[i],
631
0
                (e820->nr_map-i) * sizeof(e820->map[0]));
632
0
        e820->nr_map++;
633
0
634
0
        if ( s == rs )
635
0
        {
636
0
            e820->map[i].size = e - s;
637
0
            e820->map[i].type = new_type;
638
0
            e820->map[i+1].addr = e;
639
0
            e820->map[i+1].size = re - e;
640
0
        }
641
0
        else
642
0
        {
643
0
            e820->map[i].size = s - rs;
644
0
            e820->map[i+1].addr = s;
645
0
            e820->map[i+1].size = e - s;
646
0
            e820->map[i+1].type = new_type;
647
0
        }
648
0
    }
649
2
    else
650
2
    {
651
2
        if ( (e820->nr_map + 2) > ARRAY_SIZE(e820->map) )
652
0
            goto overflow;
653
2
654
2
        memmove(&e820->map[i+2], &e820->map[i],
655
2
                (e820->nr_map-i) * sizeof(e820->map[0]));
656
2
        e820->nr_map += 2;
657
2
658
2
        e820->map[i].size = s - rs;
659
2
        e820->map[i+1].addr = s;
660
2
        e820->map[i+1].size = e - s;
661
2
        e820->map[i+1].type = new_type;
662
2
        e820->map[i+2].addr = e;
663
2
        e820->map[i+2].size = re - e;
664
2
    }
665
3
666
3
    /* Finally, look for any opportunities to merge adjacent e820 entries. */
667
64
    for ( i = 0; i < (e820->nr_map - 1); i++ )
668
61
    {
669
61
        if ( (e820->map[i].type != e820->map[i+1].type) ||
670
10
             ((e820->map[i].addr + e820->map[i].size) != e820->map[i+1].addr) )
671
60
            continue;
672
1
        e820->map[i].size += e820->map[i+1].size;
673
1
        memmove(&e820->map[i+1], &e820->map[i+2],
674
1
                (e820->nr_map-i-2) * sizeof(e820->map[0]));
675
1
        e820->nr_map--;
676
1
        i--;
677
1
    }
678
3
679
3
    return 1;
680
3
681
0
 overflow:
682
0
    printk("Overflow in e820 while reserving region %"PRIx64"-%"PRIx64"\n",
683
0
           s, e);
684
0
    return 0;
685
3
}
686
687
/* Set E820_RAM area (@s,@e) as RESERVED in specified e820 map. */
688
int __init reserve_e820_ram(struct e820map *e820, uint64_t s, uint64_t e)
689
4
{
690
4
    return e820_change_range_type(e820, s, e, E820_RAM, E820_RESERVED);
691
4
}
692
693
unsigned long __init init_e820(const char *str, struct e820map *raw)
694
1
{
695
1
    if ( e820_verbose )
696
0
    {
697
0
        printk("Initial %s RAM map:\n", str);
698
0
        print_e820_memory_map(raw->map, raw->nr_map);
699
0
    }
700
1
701
1
    machine_specific_memory_setup(raw);
702
1
703
1
    printk("%s RAM map:\n", str);
704
1
    print_e820_memory_map(e820.map, e820.nr_map);
705
1
706
1
    return find_max_pfn();
707
1
}