The bitmap an earlier kernel filled in gets in this one through EFI, but nothing reads it back yet. Introduce range_contains_poisoned_memory(), which the page allocator will use to ask about a block before handing it out. Signed-off-by: Breno Leitao --- drivers/firmware/efi/poison.c | 26 ++++++++++++++++++++++++++ include/linux/mm.h | 14 ++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/drivers/firmware/efi/poison.c b/drivers/firmware/efi/poison.c index c18edf111c710..e16d43f4438ee 100644 --- a/drivers/firmware/efi/poison.c +++ b/drivers/firmware/efi/poison.c @@ -96,6 +96,32 @@ static struct linux_efi_poisoned_memory *efi_poisoned_memory(void) return phys_to_virt(efi.poisoned_memory); } +/* Does the range cover a unit an earlier kernel recorded as bad? */ +bool range_contains_poisoned_memory(phys_addr_t start, unsigned long size) +{ + struct linux_efi_poisoned_memory *pm = efi_poisoned_memory(); + u64 first, last, nbits; + + if (!pm) + return false; + + nbits = pm->size * BITS_PER_BYTE; + + if (start + size <= pm->phys_base) + return false; + if (start < pm->phys_base) + start = pm->phys_base; + + first = (start - pm->phys_base) / pm->unit_size; + if (first >= nbits) + return false; + + last = (start + size - 1 - pm->phys_base) / pm->unit_size; + last = min(last, nbits - 1); + + return find_next_bit(pm->bitmap, last + 1, first) <= last; +} + /* * A bit is never cleared: it stands for a whole EFI_POISON_UNIT_SIZE, so an * unpoison cannot tell whether the unit as a whole is good again. diff --git a/include/linux/mm.h b/include/linux/mm.h index 274fa880077c5..b68824fcfbef1 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -5387,6 +5387,20 @@ static inline bool pfn_is_unaccepted_memory(unsigned long pfn) return range_contains_unaccepted_memory(pfn << PAGE_SHIFT, PAGE_SIZE); } +#ifdef CONFIG_EFI_POISONED_MEMORY + +bool range_contains_poisoned_memory(phys_addr_t start, unsigned long size); + +#else + +static inline bool range_contains_poisoned_memory(phys_addr_t start, + unsigned long size) +{ + return false; +} + +#endif + void vma_pgtable_walk_begin(struct vm_area_struct *vma); void vma_pgtable_walk_end(struct vm_area_struct *vma); -- 2.53.0-Meta