parisc: use Page Deallocation Table from firmware to exclude broken memory (v1)
Helge Deller
maintainerRFC PATCH 1/1 parisc: use Page Deallocation Table from firmware to exclude broken memory (v1)
This is an initial patch which uses the Page Deallocation Table (PDT) from firmware to exclude known-to-be-broken memory regions.
Currently only reporting is implemented.
TODOs:
- really exclude broken memory regions from being used by Linux
- check if PDT works as expected on a 32bit kernel as well.
- check if currently implemented reporting is correct.
Feedback/Testers (with broken hardware :-)) wanted!
Signed-off-by Helge Deller <[email protected]>
arch/parisc/include/asm/pdc.h +15 -0
@@ -143,6 +143,18 @@ struct pdc_btlb_info { /* PDC_BLOCK_TLB, return of PDC_BTLB_INFO */#endif /* !CONFIG_PA20 */ +struct pdc_memory_retinfo {/* PDC_MEM/PDC_MEM_MEMINFO (return info) */ +unsigned long pdt_size; +unsigned long page_entries; +unsigned long pdt_status; +unsigned long dbe_loc; +unsigned long good_mem; +}; + +struct pdc_memory_read_pdt {/* PDC_MEM/PDC_MEM_READ_PDT (return info) */ +unsigned long page_entries; +}; + #ifdef CONFIG_64BIT struct pdc_memory_table_raddr { /* PDC_MEM/PDC_MEM_TABLE (return info) */ unsigned long entries_returned;
@@ -301,6 +313,9 @@ int pdc_get_initiator(struct hardware_path *, struct pdc_initiator *);int pdc_tod_read (struct pdc_tod *tod);int pdc_tod_set (unsigned long sec,unsigned long usec); +int pdc_mem_pdt_info (struct pdc_memory_retinfo *rinfo); +int pdc_mem_pdt_read_entries (struct pdc_memory_read_pdt *rpdt_read, +unsigned long *pdt_entries_ptr);#ifdef CONFIG_64BIT int pdc_mem_mem_table (struct pdc_memory_table_raddr *r_addr,struct pdc_memory_table *tbl,unsigned long entries);
arch/parisc/include/uapi/asm/pdc.h +6 -6
@@ -131,12 +131,12 @@#define PDC_TLB_SETUP 1/* set up miss handling */ #define PDC_MEM 20/* Manage memory */ -#define PDC_MEM_MEMINFO 0 -#define PDC_MEM_ADD_PAGE 1 -#define PDC_MEM_CLEAR_PDT 2 -#define PDC_MEM_READ_PDT 3 -#define PDC_MEM_RESET_CLEAR 4 -#define PDC_MEM_GOODMEM 5 +#define PDC_MEM_MEMINFO 0/* Return Page Deallocation Table (PDT) info */ +#define PDC_MEM_ADD_PAGE 1/* Add page to PDT */ +#define PDC_MEM_CLEAR_PDT 2/* Clear PDT */ +#define PDC_MEM_READ_PDT 3/* Read PDT entry */ +#define PDC_MEM_RESET_CLEAR 4/* Reset PDT clear flag */ +#define PDC_MEM_GOODMEM 5/* Set good_mem value */ #define PDC_MEM_TABLE 128/* Non contig mem map (sprockets) */ #define PDC_MEM_RETURN_ADDRESS_TABLE PDC_MEM_TABLE#define PDC_MEM_GET_MEMORY_SYSTEM_TABLES_SIZE 131
arch/parisc/kernel/firmware.c +35 -0
@@ -955,6 +955,41 @@ int pdc_tod_read(struct pdc_tod *tod) }EXPORT_SYMBOL (pdc_tod_read); +int __init pdc_mem_pdt_info (struct pdc_memory_retinfo *rinfo) +{ +int retval; +unsigned long flags; + +spin_lock_irqsave (&pdc_lock, flags); + retval =mem_pdc_call (PDC_MEM ,PDC_MEM_MEMINFO ,__pa (pdc_result),0 ); +convert_to_wide (pdc_result); +memcpy (rinfo, pdc_result,sizeof (*rinfo)); +spin_unlock_irqrestore (&pdc_lock, flags); + +return retval; +} + +int __init pdc_mem_pdt_read_entries (struct pdc_memory_read_pdt *rpdt_read, +unsigned long *pdt_entries_ptr) +{ +int retval; +unsigned long flags; + +spin_lock_irqsave (&pdc_lock, flags); + retval =mem_pdc_call (PDC_MEM ,PDC_MEM_READ_PDT ,__pa (pdc_result), +__pa (pdc_result2)); +if (retval ==PDC_OK ) { +convert_to_wide (pdc_result); +memcpy (rpdt_read, pdc_result,sizeof (*rpdt_read)); +convert_to_wide (pdc_result2); +memcpy (pdt_entries_ptr, pdc_result2, + rpdt_read->page_entries *sizeof (*pdt_entries_ptr)); + } +spin_unlock_irqrestore (&pdc_lock, flags); + +return retval; +} +/** * pdc_tod_set - Set the Time-Of-Day clock. * @sec: The number of seconds since epoch.
arch/parisc/mm/init.c +46 -0
58 lines not on this page · raw message