void __init pdc_pdt_init()

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();
	}
}