Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Suchanek <msuchanek@suse.de>2019-10-03 10:22:15 +0200
committerMichal Suchanek <msuchanek@suse.de>2019-10-03 10:22:18 +0200
commit9ecbb0dadd66379c024170c046156199d8b4400c (patch)
treefdef4eebf58c4cb1b9166078820a95319287783b
parent9467589effc980f570d10313e1e899bc348d18e1 (diff)
powerpc/pseries: Read TLB Block Invalidate Characteristics
(bsc#1109158).
-rw-r--r--patches.suse/powerpc-pseries-Read-TLB-Block-Invalidate-Characteri.patch207
-rw-r--r--series.conf1
2 files changed, 208 insertions, 0 deletions
diff --git a/patches.suse/powerpc-pseries-Read-TLB-Block-Invalidate-Characteri.patch b/patches.suse/powerpc-pseries-Read-TLB-Block-Invalidate-Characteri.patch
new file mode 100644
index 0000000000..63c7152d18
--- /dev/null
+++ b/patches.suse/powerpc-pseries-Read-TLB-Block-Invalidate-Characteri.patch
@@ -0,0 +1,207 @@
+From 1211ee61b4a8e60d6dc77211cdcf01906915bfba Mon Sep 17 00:00:00 2001
+From: Laurent Dufour <ldufour@linux.ibm.com>
+Date: Fri, 20 Sep 2019 15:05:22 +0200
+Subject: [PATCH] powerpc/pseries: Read TLB Block Invalidate Characteristics
+
+References: bsc#1109158
+Patch-mainline: v5.4-rc1
+Git-commit: 1211ee61b4a8e60d6dc77211cdcf01906915bfba
+
+The PAPR document specifies the TLB Block Invalidate Characteristics
+which tells for each pair of segment base page size, actual page size,
+the size of the block the hcall H_BLOCK_REMOVE supports.
+
+These characteristics are loaded at boot time in a new table
+hblkr_size. The table is separate from the mmu_psize_def because this
+is specific to the pseries platform.
+
+A new init function, pseries_lpar_read_hblkrm_characteristics() is
+added to read the characteristics. It is called from
+pSeries_setup_arch().
+
+Fixes: ba2dd8a26baa ("powerpc/pseries/mm: call H_BLOCK_REMOVE")
+Signed-off-by: Laurent Dufour <ldufour@linux.ibm.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/20190920130523.20441-2-ldufour@linux.ibm.com
+Acked-by: Michal Suchanek <msuchanek@suse.de>
+---
+ arch/powerpc/platforms/pseries/lpar.c | 140 +++++++++++++++++++++++
+ arch/powerpc/platforms/pseries/pseries.h | 1 +
+ arch/powerpc/platforms/pseries/setup.c | 1 +
+ 3 files changed, 142 insertions(+)
+
+--- a/arch/powerpc/platforms/pseries/lpar.c
++++ b/arch/powerpc/platforms/pseries/lpar.c
+@@ -64,6 +64,15 @@ EXPORT_SYMBOL(plpar_hcall);
+ EXPORT_SYMBOL(plpar_hcall9);
+ EXPORT_SYMBOL(plpar_hcall_norets);
+
++/*
++ * H_BLOCK_REMOVE supported block size for this page size in segment who's base
++ * page size is that page size.
++ *
++ * The first index is the segment base page size, the second one is the actual
++ * page size.
++ */
++static int hblkrm_size[MMU_PAGE_COUNT][MMU_PAGE_COUNT] __ro_after_init;
++
+ void vpa_init(int cpu)
+ {
+ int hwcpu = get_hard_smp_processor_id(cpu);
+@@ -753,6 +762,137 @@ static void do_block_remove(unsigned lon
+ }
+
+ /*
++ * TLB Block Invalidate Characteristics
++ *
++ * These characteristics define the size of the block the hcall H_BLOCK_REMOVE
++ * is able to process for each couple segment base page size, actual page size.
++ *
++ * The ibm,get-system-parameter properties is returning a buffer with the
++ * following layout:
++ *
++ * [ 2 bytes size of the RTAS buffer (excluding these 2 bytes) ]
++ * -----------------
++ * TLB Block Invalidate Specifiers:
++ * [ 1 byte LOG base 2 of the TLB invalidate block size being specified ]
++ * [ 1 byte Number of page sizes (N) that are supported for the specified
++ * TLB invalidate block size ]
++ * [ 1 byte Encoded segment base page size and actual page size
++ * MSB=0 means 4k segment base page size and actual page size
++ * MSB=1 the penc value in mmu_psize_def ]
++ * ...
++ * -----------------
++ * Next TLB Block Invalidate Specifiers...
++ * -----------------
++ * [ 0 ]
++ */
++static inline void set_hblkrm_bloc_size(int bpsize, int psize,
++ unsigned int block_size)
++{
++ if (block_size > hblkrm_size[bpsize][psize])
++ hblkrm_size[bpsize][psize] = block_size;
++}
++
++/*
++ * Decode the Encoded segment base page size and actual page size.
++ * PAPR specifies:
++ * - bit 7 is the L bit
++ * - bits 0-5 are the penc value
++ * If the L bit is 0, this means 4K segment base page size and actual page size
++ * otherwise the penc value should be read.
++ */
++#define HBLKRM_L_MASK 0x80
++#define HBLKRM_PENC_MASK 0x3f
++static inline void __init check_lp_set_hblkrm(unsigned int lp,
++ unsigned int block_size)
++{
++ unsigned int bpsize, psize;
++
++ /* First, check the L bit, if not set, this means 4K */
++ if ((lp & HBLKRM_L_MASK) == 0) {
++ set_hblkrm_bloc_size(MMU_PAGE_4K, MMU_PAGE_4K, block_size);
++ return;
++ }
++
++ lp &= HBLKRM_PENC_MASK;
++ for (bpsize = 0; bpsize < MMU_PAGE_COUNT; bpsize++) {
++ struct mmu_psize_def *def = &mmu_psize_defs[bpsize];
++
++ for (psize = 0; psize < MMU_PAGE_COUNT; psize++) {
++ if (def->penc[psize] == lp) {
++ set_hblkrm_bloc_size(bpsize, psize, block_size);
++ return;
++ }
++ }
++ }
++}
++
++#define SPLPAR_TLB_BIC_TOKEN 50
++
++/*
++ * The size of the TLB Block Invalidate Characteristics is variable. But at the
++ * maximum it will be the number of possible page sizes *2 + 10 bytes.
++ * Currently MMU_PAGE_COUNT is 16, which means 42 bytes. Use a cache line size
++ * (128 bytes) for the buffer to get plenty of space.
++ */
++#define SPLPAR_TLB_BIC_MAXLENGTH 128
++
++void __init pseries_lpar_read_hblkrm_characteristics(void)
++{
++ unsigned char local_buffer[SPLPAR_TLB_BIC_MAXLENGTH];
++ int call_status, len, idx, bpsize;
++
++ spin_lock(&rtas_data_buf_lock);
++ memset(rtas_data_buf, 0, RTAS_DATA_BUF_SIZE);
++ call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1,
++ NULL,
++ SPLPAR_TLB_BIC_TOKEN,
++ __pa(rtas_data_buf),
++ RTAS_DATA_BUF_SIZE);
++ memcpy(local_buffer, rtas_data_buf, SPLPAR_TLB_BIC_MAXLENGTH);
++ local_buffer[SPLPAR_TLB_BIC_MAXLENGTH - 1] = '\0';
++ spin_unlock(&rtas_data_buf_lock);
++
++ if (call_status != 0) {
++ pr_warn("%s %s Error calling get-system-parameter (0x%x)\n",
++ __FILE__, __func__, call_status);
++ return;
++ }
++
++ /*
++ * The first two (2) bytes of the data in the buffer are the length of
++ * the returned data, not counting these first two (2) bytes.
++ */
++ len = be16_to_cpu(*((u16 *)local_buffer)) + 2;
++ if (len > SPLPAR_TLB_BIC_MAXLENGTH) {
++ pr_warn("%s too large returned buffer %d", __func__, len);
++ return;
++ }
++
++ idx = 2;
++ while (idx < len) {
++ u8 block_shift = local_buffer[idx++];
++ u32 block_size;
++ unsigned int npsize;
++
++ if (!block_shift)
++ break;
++
++ block_size = 1 << block_shift;
++
++ for (npsize = local_buffer[idx++];
++ npsize > 0 && idx < len; npsize--)
++ check_lp_set_hblkrm((unsigned int) local_buffer[idx++],
++ block_size);
++ }
++
++ for (bpsize = 0; bpsize < MMU_PAGE_COUNT; bpsize++)
++ for (idx = 0; idx < MMU_PAGE_COUNT; idx++)
++ if (hblkrm_size[bpsize][idx])
++ pr_info("H_BLOCK_REMOVE supports base psize:%d psize:%d block size:%d",
++ bpsize, idx, hblkrm_size[bpsize][idx]);
++}
++
++/*
+ * Take a spinlock around flushes to avoid bouncing the hypervisor tlbie
+ * lock.
+ */
+--- a/arch/powerpc/platforms/pseries/pseries.h
++++ b/arch/powerpc/platforms/pseries/pseries.h
+@@ -103,5 +103,6 @@ static inline unsigned long cmo_get_page
+ int dlpar_workqueue_init(void);
+
+ void pseries_setup_rfi_flush(void);
++void pseries_lpar_read_hblkrm_characteristics(void);
+
+ #endif /* _PSERIES_PSERIES_H */
+--- a/arch/powerpc/platforms/pseries/setup.c
++++ b/arch/powerpc/platforms/pseries/setup.c
+@@ -759,6 +759,7 @@ static void __init pSeries_setup_arch(vo
+
+ pseries_setup_rfi_flush();
+ setup_stf_barrier();
++ pseries_lpar_read_hblkrm_characteristics();
+
+ /* By default, only probe PCI (can be overridden by rtas_pci) */
+ pci_add_flags(PCI_PROBE_ONLY);
diff --git a/series.conf b/series.conf
index 310e80c18c..b779a224b5 100644
--- a/series.conf
+++ b/series.conf
@@ -24659,6 +24659,7 @@
patches.suse/power-reset-gpio-restart-Fix-typo-when-gpio-reset-is.patch
patches.suse/livepatch-nullify-obj-mod-in-klp_module_coming-s-error-path.patch
patches.suse/suse-hv-PCI-hv-Detect-and-fix-Hyper-V-PCI-domain-number-coll.patch
+ patches.suse/powerpc-pseries-Read-TLB-Block-Invalidate-Characteri.patch
patches.suse/powerpc-book3s64-mm-Don-t-do-tlbie-fixup-for-some-ha.patch
patches.suse/powerpc-book3s64-radix-Rename-CPU_FTR_P9_TLBIE_BUG-f.patch
patches.suse/powerpc-mm-Fixup-tlbie-vs-mtpidr-mtlpidr-ordering-is.patch