diff options
author | Mike Rapoport <rppt@linux.ibm.com> | 2022-02-15 09:03:15 +0200 |
---|---|---|
committer | Mike Rapoport <rppt@linux.ibm.com> | 2022-02-15 09:04:46 +0200 |
commit | b7a4baac6a2866224710f92d96fdf2ed5227e392 (patch) | |
tree | df0784424871b1d39d36a89cb4845a2cfd23b85d | |
parent | 0688376261c29bf8452c5c77f8bc6fa9a4252bf5 (diff) | |
download | linux-x86/e820-update-range.tar.gz |
x86/e820: implement e820__range_remove() using __e820__ranage_update()x86/e820-update-range
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
-rw-r--r-- | arch/x86/include/asm/e820/types.h | 6 | ||||
-rw-r--r-- | arch/x86/kernel/e820.c | 73 |
2 files changed, 21 insertions, 58 deletions
diff --git a/arch/x86/include/asm/e820/types.h b/arch/x86/include/asm/e820/types.h index 314f75d886d08a..85c4b3276c90e3 100644 --- a/arch/x86/include/asm/e820/types.h +++ b/arch/x86/include/asm/e820/types.h @@ -8,6 +8,12 @@ * These are the E820 types known to the kernel: */ enum e820_type { + /* + * Special value that indicates that a range must be removed during + * updates of e820 table + */ + E820_TYPE_NONE = 0, + E820_TYPE_RAM = 1, E820_TYPE_RESERVED = 2, E820_TYPE_ACPI = 3, diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index e3594690466b59..f431d7bbd737ac 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -187,6 +187,7 @@ void __init e820__range_add(u64 start, u64 size, enum e820_type type) static void __init e820_print_type(enum e820_type type) { switch (type) { + case E820_TYPE_NONE: pr_cont("none"); break; case E820_TYPE_RAM: /* Fall through: */ case E820_TYPE_RESERVED_KERN: pr_cont("usable"); break; case E820_TYPE_RESERVED: pr_cont("reserved"); break; @@ -462,6 +463,7 @@ static int __init append_e820_table(struct boot_e820_entry *entries, u32 nr_entr struct e820_update_params { enum e820_type old_type; enum e820_type new_type; + int check_type; }; static u64 __init @@ -469,6 +471,7 @@ __e820__range_update(struct e820_table *table, u64 start, u64 size, struct e820_ { enum e820_type old_type = params->old_type; enum e820_type new_type = params->new_type; + int check_type = params->check_type; u64 end; unsigned int i; @@ -481,6 +484,7 @@ __e820__range_update(struct e820_table *table, u64 start, u64 size, struct e820_ end = start + size; printk(KERN_DEBUG "e820: update [mem %#010Lx-%#010Lx] ", start, end - 1); + e820_print_type(old_type); pr_cont(" ==> "); e820_print_type(new_type); @@ -491,7 +495,7 @@ __e820__range_update(struct e820_table *table, u64 start, u64 size, struct e820_ u64 final_start, final_end; u64 entry_end; - if (entry->type != old_type) + if (check_type && entry->type != old_type) continue; entry_end = entry->addr + entry->size; @@ -500,12 +504,15 @@ __e820__range_update(struct e820_table *table, u64 start, u64 size, struct e820_ if (entry->addr >= start && entry_end <= end) { entry->type = new_type; real_updated_size += entry->size; + if (new_type == E820_TYPE_NONE) + memset(entry, 0, sizeof(*entry)); continue; } /* New range is completely covered? */ if (entry->addr < start && entry_end > end) { - __e820__range_add(table, start, size, new_type); + if (new_type != E820_TYPE_NONE) + __e820__range_add(table, start, size, new_type); __e820__range_add(table, end, entry_end - end, entry->type); entry->size = start - entry->addr; real_updated_size += size; @@ -558,63 +565,13 @@ static u64 __init e820__range_update_kexec(u64 start, u64 size, enum e820_type o /* Remove a range of memory from the E820 table: */ u64 __init e820__range_remove(u64 start, u64 size, enum e820_type old_type, bool check_type) { - int i; - u64 end; - u64 real_removed_size = 0; - - if (size > (ULLONG_MAX - start)) - size = ULLONG_MAX - start; - - end = start + size; - printk(KERN_DEBUG "e820: remove [mem %#010Lx-%#010Lx] ", start, end - 1); - if (check_type) - e820_print_type(old_type); - pr_cont("\n"); - - for (i = 0; i < e820_table->nr_entries; i++) { - struct e820_entry *entry = &e820_table->entries[i]; - u64 final_start, final_end; - u64 entry_end; - - if (check_type && entry->type != old_type) - continue; - - entry_end = entry->addr + entry->size; - - /* Completely covered? */ - if (entry->addr >= start && entry_end <= end) { - real_removed_size += entry->size; - memset(entry, 0, sizeof(*entry)); - continue; - } - - /* Is the new range completely covered? */ - if (entry->addr < start && entry_end > end) { - e820__range_add(end, entry_end - end, entry->type); - entry->size = start - entry->addr; - real_removed_size += size; - continue; - } - - /* Partially covered: */ - final_start = max(start, entry->addr); - final_end = min(end, entry_end); - if (final_start >= final_end) - continue; - - real_removed_size += final_end - final_start; - - /* - * Left range could be head or tail, so need to update - * the size first: - */ - entry->size -= final_end - final_start; - if (entry->addr < final_start) - continue; + struct e820_update_params params = { + .old_type = old_type, + .new_type = E820_TYPE_NONE, + .check_type = check_type, + }; - entry->addr = final_end; - } - return real_removed_size; + return __e820__range_update(e820_table, start, size, ¶ms); } void __init e820__update_table_print(void) |