in kernel/pdt.c [147:237]
void __init pdc_pdt_init(void)
{
int ret, i;
unsigned long entries;
struct pdc_mem_read_pdt pdt_read_ret;
pdt_type = PDT_PAT_NEW;
ret = get_info_pat_new();
if (ret != PDC_OK) {
pdt_type = PDT_PAT_CELL;
ret = get_info_pat_cell();
}
if (ret != PDC_OK) {
pdt_type = PDT_PDC;
/* non-PAT machines provide the standard PDC call */
ret = pdc_mem_pdt_info(&pdt_status);
}
if (ret != PDC_OK) {
pdt_type = PDT_NONE;
pr_info("PDT: Firmware does not provide any page deallocation"
" information.\n");
return;
}
entries = pdt_status.pdt_entries;
if (WARN_ON(entries > MAX_PDT_ENTRIES))
entries = pdt_status.pdt_entries = MAX_PDT_ENTRIES;
pr_info("PDT: type %s, size %lu, entries %lu, status %lu, dbe_loc 0x%lx,"
" good_mem %lu MB\n",
pdt_type == PDT_PDC ? __stringify(PDT_PDC) :
pdt_type == PDT_PAT_CELL ? __stringify(PDT_PAT_CELL)
: __stringify(PDT_PAT_NEW),
pdt_status.pdt_size, pdt_status.pdt_entries,
pdt_status.pdt_status, pdt_status.first_dbe_loc,
pdt_status.good_mem / 1024 / 1024);
if (entries == 0) {
pr_info("PDT: Firmware reports all memory OK.\n");
return;
}
if (pdt_status.first_dbe_loc &&
pdt_status.first_dbe_loc <= __pa((unsigned long)&_end))
pr_crit("CRITICAL: Bad memory inside kernel image memory area!\n");
pr_warn("PDT: Firmware reports %lu entries of faulty memory:\n",
entries);
if (pdt_type == PDT_PDC)
ret = pdc_mem_pdt_read_entries(&pdt_read_ret, pdt_entry);
else {
#ifdef CONFIG_64BIT
struct pdc_pat_mem_read_pd_retinfo pat_pret;
if (pdt_type == PDT_PAT_CELL)
ret = pdc_pat_mem_read_cell_pdt(&pat_pret, pdt_entry,
MAX_PDT_ENTRIES);
else
ret = pdc_pat_mem_read_pd_pdt(&pat_pret, pdt_entry,
MAX_PDT_TABLE_SIZE, 0);
#else
ret = PDC_BAD_PROC;
#endif
}
if (ret != PDC_OK) {
pdt_type = PDT_NONE;
pr_warn("PDT: Get PDT entries failed with %d\n", ret);
return;
}
for (i = 0; i < pdt_status.pdt_entries; i++) {
unsigned long addr;
report_mem_err(pdt_entry[i]);
addr = pdt_entry[i] & PDT_ADDR_PHYS_MASK;
if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) &&
addr >= initrd_start && addr < initrd_end)
pr_crit("CRITICAL: initrd possibly broken "
"due to bad memory!\n");
/* mark memory page bad */
memblock_reserve(pdt_entry[i] & PAGE_MASK, PAGE_SIZE);
num_poisoned_pages_inc();
}
}