Skip to contentSkip to conversation

powerpc: cmo fix page loaning and add info to lparcfg

PATCH Superseded Robert Jennings 2 participants 6 messages Aug 15, 2008 – Aug 18, 2008 PowerPC

lore
Share & tools
lore
#0 lore raw

cover powerpc: cmo fix page loaning and add info to lparcfg

We need to correct a problem found where the kernel is using 64k pages but the firmware pages size is 4k. In this case we were not properly marking pages as 'loaned' to firmware.

To fix this I exposed some data pulled from rtas during early setup. I also made these values available via /proc/ppc64/lparcfg in the second patch.

The first patch makes the data available and the other two patches (unrelated to each other) depend on the first.

Regards,
Robert Jennings

#1 lore raw

PATCH 1/3 powerpc: make CMO paging space pool ID and page size available

During platform setup, save off the primary/secondary paging space pool IDs and the page size. Added accessors in hvcall.h for these variables.

---
 arch/powerpc/include/asm/hvcall.h      |   21 +++++++++++++++++++++
 arch/powerpc/platforms/pseries/setup.c |   28 ++++++++++++++++++++--------
 2 files changed, 41 insertions(+), 8 deletions(-)
arch/powerpc/include/asm/hvcall.h +21 -0
Index: b/arch/powerpc/include/asm/hvcall.h
===================================================================
@@ -292,6 +292,27 @@ struct hvcall_mpp_data {
 
 int h_get_mpp(struct hvcall_mpp_data *);
 
+#ifdef CONFIG_PPC_PSERIES
+extern int CMO_PrPSP;
+extern int CMO_SecPSP;
+extern unsigned long CMO_PageSize;
+
+static inline int cmo_get_primary_psp(void)
+{
+	return CMO_PrPSP;
+}
+
+static inline int cmo_get_secondary_psp(void)
+{
+	return CMO_SecPSP;
+}
+
+static inline unsigned long cmo_get_page_size(void)
+{
+	return CMO_PageSize;
+}
+#endif /* CONFIG_PPC_PSERIES */
+
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_HVCALL_H */
arch/powerpc/platforms/pseries/setup.c +20 -8
Index: b/arch/powerpc/platforms/pseries/setup.c
===================================================================
@@ -68,6 +68,9 @@
 #include "plpar_wrappers.h"
 #include "pseries.h"
 
+int CMO_PrPSP = -1;
+int CMO_SecPSP = -1;
+unsigned long CMO_PageSize = (ASM_CONST(1) << IOMMU_PAGE_SHIFT);
 
 int fwnmi_active;  /* TRUE if an FWNMI handler is present */
 
@@ -325,8 +328,7 @@ void pSeries_cmo_feature_init(void)
 {
 	char *ptr, *key, *value, *end;
 	int call_status;
-	int PrPSP = -1;
-	int SecPSP = -1;
+	int page_order = IOMMU_PAGE_SHIFT;
 
 	pr_debug(" -> fw_cmo_feature_init()\n");
 	spin_lock(&rtas_data_buf_lock);
@@ -365,21 +367,31 @@ void pSeries_cmo_feature_init(void)
 				break;
 			}
 
-			if (0 == strcmp(key, "PrPSP"))
-				PrPSP = simple_strtol(value, NULL, 10);
+			if (0 == strcmp(key, "CMOPageSize"))
+				page_order = simple_strtol(value, NULL, 10);
+			else if (0 == strcmp(key, "PrPSP"))
+				CMO_PrPSP = simple_strtol(value, NULL, 10);
 			else if (0 == strcmp(key, "SecPSP"))
-				SecPSP = simple_strtol(value, NULL, 10);
+				CMO_SecPSP = simple_strtol(value, NULL, 10);
 			value = key = ptr + 1;
 		}
 		ptr++;
 	}
 
-	if (PrPSP != -1 || SecPSP != -1) {
+	/* Page size is returned as the power of 2 of the page size,
+	 * convert to the page size in bytes before returning
+	 */
+	CMO_PageSize = 1 << page_order;
+	pr_debug("CMO_PageSize = %lu\n", CMO_PageSize);
+
+	if (CMO_PrPSP != -1 || CMO_SecPSP != -1) {
 		pr_info("CMO enabled\n");
-		pr_debug("CMO enabled, PrPSP=%d, SecPSP=%d\n", PrPSP, SecPSP);
+		pr_debug("CMO enabled, PrPSP=%d, SecPSP=%d\n", CMO_PrPSP,
+		         CMO_SecPSP);
 		powerpc_firmware_features |= FW_FEATURE_CMO;
 	} else
-		pr_debug("CMO not enabled, PrPSP=%d, SecPSP=%d\n", PrPSP, SecPSP);
+		pr_debug("CMO not enabled, PrPSP=%d, SecPSP=%d\n", CMO_PrPSP,
+		         CMO_SecPSP);
 	spin_unlock(&rtas_data_buf_lock);
 	pr_debug(" <- fw_cmo_feature_init()\n");
 }
#2 lore raw

Re: [PATCH 1/3] powerpc: make CMO paging space pool ID and page size available

Quoted 4 lines · Robert Jennings

During platform setup, save off the primary/secondary paging space pool IDs and the page size. Added accessors in hvcall.h for these variables.

What's this "Submitted-by"? Did you mean to type "Signed-off-by"?

Paul.

#3 lore raw

PATCH v2 1/3 powerpc: make CMO paging space pool ID and page size available

In reply to Robert Jennings

During platform setup, save off the primary/secondary paging space pool IDs and the page size. Added accessors in hvcall.h for these variables.

---
I wrote "Submitted-by" on the last patch for some strange reason, that't the only thing changed here.

---
 arch/powerpc/include/asm/hvcall.h      |   21 +++++++++++++++++++++
 arch/powerpc/platforms/pseries/setup.c |   28 ++++++++++++++++++++--------
 2 files changed, 41 insertions(+), 8 deletions(-)
arch/powerpc/include/asm/hvcall.h +21 -0
Index: b/arch/powerpc/include/asm/hvcall.h
===================================================================
@@ -292,6 +292,27 @@ struct hvcall_mpp_data {
 
 int h_get_mpp(struct hvcall_mpp_data *);
 
+#ifdef CONFIG_PPC_PSERIES
+extern int CMO_PrPSP;
+extern int CMO_SecPSP;
+extern unsigned long CMO_PageSize;
+
+static inline int cmo_get_primary_psp(void)
+{
+	return CMO_PrPSP;
+}
+
+static inline int cmo_get_secondary_psp(void)
+{
+	return CMO_SecPSP;
+}
+
+static inline unsigned long cmo_get_page_size(void)
+{
+	return CMO_PageSize;
+}
+#endif /* CONFIG_PPC_PSERIES */
+
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_HVCALL_H */
arch/powerpc/platforms/pseries/setup.c +20 -8
Index: b/arch/powerpc/platforms/pseries/setup.c
===================================================================
@@ -68,6 +68,9 @@
 #include "plpar_wrappers.h"
 #include "pseries.h"
 
+int CMO_PrPSP = -1;
+int CMO_SecPSP = -1;
+unsigned long CMO_PageSize = (ASM_CONST(1) << IOMMU_PAGE_SHIFT);
 
 int fwnmi_active;  /* TRUE if an FWNMI handler is present */
 
@@ -325,8 +328,7 @@ void pSeries_cmo_feature_init(void)
 {
 	char *ptr, *key, *value, *end;
 	int call_status;
-	int PrPSP = -1;
-	int SecPSP = -1;
+	int page_order = IOMMU_PAGE_SHIFT;
 
 	pr_debug(" -> fw_cmo_feature_init()\n");
 	spin_lock(&rtas_data_buf_lock);
@@ -365,21 +367,31 @@ void pSeries_cmo_feature_init(void)
 				break;
 			}
 
-			if (0 == strcmp(key, "PrPSP"))
-				PrPSP = simple_strtol(value, NULL, 10);
+			if (0 == strcmp(key, "CMOPageSize"))
+				page_order = simple_strtol(value, NULL, 10);
+			else if (0 == strcmp(key, "PrPSP"))
+				CMO_PrPSP = simple_strtol(value, NULL, 10);
 			else if (0 == strcmp(key, "SecPSP"))
-				SecPSP = simple_strtol(value, NULL, 10);
+				CMO_SecPSP = simple_strtol(value, NULL, 10);
 			value = key = ptr + 1;
 		}
 		ptr++;
 	}
 
-	if (PrPSP != -1 || SecPSP != -1) {
+	/* Page size is returned as the power of 2 of the page size,
+	 * convert to the page size in bytes before returning
+	 */
+	CMO_PageSize = 1 << page_order;
+	pr_debug("CMO_PageSize = %lu\n", CMO_PageSize);
+
+	if (CMO_PrPSP != -1 || CMO_SecPSP != -1) {
 		pr_info("CMO enabled\n");
-		pr_debug("CMO enabled, PrPSP=%d, SecPSP=%d\n", PrPSP, SecPSP);
+		pr_debug("CMO enabled, PrPSP=%d, SecPSP=%d\n", CMO_PrPSP,
+		         CMO_SecPSP);
 		powerpc_firmware_features |= FW_FEATURE_CMO;
 	} else
-		pr_debug("CMO not enabled, PrPSP=%d, SecPSP=%d\n", PrPSP, SecPSP);
+		pr_debug("CMO not enabled, PrPSP=%d, SecPSP=%d\n", CMO_PrPSP,
+		         CMO_SecPSP);
 	spin_unlock(&rtas_data_buf_lock);
 	pr_debug(" <- fw_cmo_feature_init()\n");
 }

----- End forwarded message -----

#4 lore raw

PATCH 2/3 powerpc: Fix CMM page loaning on 64k page kernel with 4k hardware pages

In reply to Robert Jennings

=46rom: Brian King <[email protected]>

If the firmware page size used for collaborative memory overcommit is 4k, but the kernel is using 64k pages, the page loaning is currently broken as it only marks the first 4k page of each 64k page as loaned. This fixes this to iterate through each 4k page and mark them all as loaned/active.

---

arch/powerpc/platforms/pseries/plpar_wrappers.h | 27 +++++++++++++++++++=
+++--

 1 file changed, 25 insertions(+), 2 deletions(-)

Index: b/arch/powerpc/platforms/pseries/plpar_wrappers.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

arch/powerpc/platforms/pseries/plpar_wrappers.h +0 -0
@@ -2,6 +2,7 @@
 #define _PSERIES_PLPAR_WRAPPERS_H

=20
#include <asm/hvcall.h>
+#include <asm/page.h>
=20
static inline long poll_pending(void)
{
@@ -44,12 +45,34 @@ static inline long register_slb_shadow(u =20
static inline long plpar_page_set_loaned(unsigned long vpa) {
- return plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED, vpa, 0);
+ unsigned long cmo_page_sz =3D cmo_get_page_size();
+ long rc =3D 0;
+ int i;
+
+ for (i =3D 0; !rc && i < PAGE_SIZE; i +=3D cmo_page_sz)
+ rc =3D plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED, vpa + i, 0);
+
+ for (i -=3D cmo_page_sz; rc && i !=3D 0; i -=3D cmo_page_sz)
+ plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE,
+ vpa + i - cmo_page_sz, 0);
+
+ return rc;
}
=20
static inline long plpar_page_set_active(unsigned long vpa) {
- return plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE, vpa, 0);
+ unsigned long cmo_page_sz =3D cmo_get_page_size();
+ long rc =3D 0;
+ int i;
+
+ for (i =3D 0; !rc && i < PAGE_SIZE; i +=3D cmo_page_sz)
+ rc =3D plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_ACTIVE, vpa + i, 0);
+
+ for (i -=3D cmo_page_sz; rc && i !=3D 0; i -=3D cmo_page_sz)
+ plpar_hcall_norets(H_PAGE_INIT, H_PAGE_SET_LOANED,
+ vpa + i - cmo_page_sz, 0);
+
+ return rc;
}
=20
extern void vpa_init(int cpu);

#5 lore raw

PATCH 3/3 powerpc: add CMO enabled flag and paging space data to lparcfg

In reply to Robert Jennings

Add a field in lparcfg output to indicate whether the kernel is running on a dedicated or shared memory lpar. Added fields to show the paging space pool IDs and the CMO page size.

---
 arch/powerpc/kernel/lparcfg.c |    5 +++++
 1 file changed, 5 insertions(+)
arch/powerpc/kernel/lparcfg.c +5 -0
Index: b/arch/powerpc/kernel/lparcfg.c
===================================================================
@@ -416,6 +416,8 @@ static void pseries_cmo_data(struct seq_
 	unsigned long cmo_faults = 0;
 	unsigned long cmo_fault_time = 0;
 
+	seq_printf(m, "cmo_enabled=%d\n", firmware_has_feature(FW_FEATURE_CMO));
+
 	if (!firmware_has_feature(FW_FEATURE_CMO))
 		return;
 
@@ -427,6 +429,9 @@ static void pseries_cmo_data(struct seq_
 	seq_printf(m, "cmo_faults=%lu\n", cmo_faults);
 	seq_printf(m, "cmo_fault_time_usec=%lu\n",
 		   cmo_fault_time / tb_ticks_per_usec);
+	seq_printf(m, "cmo_primary_psp=%d\n", cmo_get_primary_psp());
+	seq_printf(m, "cmo_secondary_psp=%d\n", cmo_get_secondary_psp());
+	seq_printf(m, "cmo_page_size=%lu\n", cmo_get_page_size());
 }
 
 static int pseries_lparcfg_data(struct seq_file *m, void *v)