Skip to contentSkip to conversation

parisc: use Page Deallocation Table from firmware to exclude broken memory (v1)

RFC PATCH New Helge Deller 1 participant 1 message May 8, 2013 PA-RISC architecture

lore
Share & tools
lore

Helge Deller

author maintainer
#0 lore raw

RFC 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!

arch/parisc/include/asm/pdc.h +15 -0
index 7eb616e..8b8ad6f 100644
@@ -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
index 702498f..b067b86 100644
@@ -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
index f65fa48..87ad71c 100644
@@ -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