Re: [PATCH 4/6] pseries: Add support for hash table resizing

2016-12-08 Thread kbuild test robot
Hi David,

[auto build test ERROR on v4.9-rc8]
[cannot apply to powerpc/next kvm/linux-next kvm-ppc/kvm-ppc-next next-20161208]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/David-Gibson/powerpc-Hash-Page-Table-resizing-for-PAPR-guests/20161208-145142
config: powerpc-ps3_defconfig (attached as .config)
compiler: powerpc64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget 
https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross
 -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=powerpc 

All errors (new ones prefixed by >>):

   arch/powerpc/mm/hash_utils_64.c: In function 'hash64_debugfs':
>> arch/powerpc/mm/hash_utils_64.c:1838:45: error: 'powerpc_debugfs_root' 
>> undeclared (first use in this function)
 if (!debugfs_create_file("pft-size", 0600, powerpc_debugfs_root,
^~~~
   arch/powerpc/mm/hash_utils_64.c:1838:45: note: each undeclared identifier is 
reported only once for each function it appears in

vim +/powerpc_debugfs_root +1838 arch/powerpc/mm/hash_utils_64.c

  1832  
  1833  DEFINE_SIMPLE_ATTRIBUTE(fops_ppc64_pft_size,
  1834  ppc64_pft_size_get, ppc64_pft_size_set, 
"%llu\n");
  1835  
  1836  static int __init hash64_debugfs(void)
  1837  {
> 1838  if (!debugfs_create_file("pft-size", 0600, powerpc_debugfs_root,
  1839   NULL, _ppc64_pft_size)) {
  1840  pr_err("lpar: unable to create ppc64_pft_size debugsfs 
file\n");
  1841  }

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: application/gzip


[PATCH 4/6] pseries: Add support for hash table resizing

2016-12-07 Thread David Gibson
This adds support for using experimental hypercalls to change the size
of the main hash page table while running as a PAPR guest.  For now these
hypercalls are only in experimental qemu versions.

The interface is two part: first H_RESIZE_HPT_PREPARE is used to allocate
and prepare the new hash table.  This may be slow, but can be done
asynchronously.  Then, H_RESIZE_HPT_COMMIT is used to switch to the new
hash table.  This requires that no CPUs be concurrently updating the HPT,
and so must be run under stop_machine().

This also adds a debugfs file which can be used to manually control
HPT resizing or testing purposes.

Signed-off-by: David Gibson 
Reviewed-by: Paul Mackerras 
---
 arch/powerpc/include/asm/book3s/64/mmu-hash.h |   1 +
 arch/powerpc/mm/hash_utils_64.c   |  28 +++
 arch/powerpc/platforms/pseries/lpar.c | 110 ++
 3 files changed, 139 insertions(+)

diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h 
b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
index e407af2..efba649 100644
--- a/arch/powerpc/include/asm/book3s/64/mmu-hash.h
+++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
@@ -153,6 +153,7 @@ struct mmu_hash_ops {
   unsigned long addr,
   unsigned char *hpte_slot_array,
   int psize, int ssize, int local);
+   int (*resize_hpt)(unsigned long shift);
/*
 * Special for kexec.
 * To be called in real mode with interrupts disabled. No locks are
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 78dabf06..474da2e 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -35,6 +35,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -1815,3 +1816,30 @@ void hash__setup_initial_memory_limit(phys_addr_t 
first_memblock_base,
/* Finally limit subsequent allocations */
memblock_set_current_limit(ppc64_rma_size);
 }
+
+static int ppc64_pft_size_get(void *data, u64 *val)
+{
+   *val = ppc64_pft_size;
+   return 0;
+}
+
+static int ppc64_pft_size_set(void *data, u64 val)
+{
+   if (!mmu_hash_ops.resize_hpt)
+   return -ENODEV;
+   return mmu_hash_ops.resize_hpt(val);
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_ppc64_pft_size,
+   ppc64_pft_size_get, ppc64_pft_size_set, "%llu\n");
+
+static int __init hash64_debugfs(void)
+{
+   if (!debugfs_create_file("pft-size", 0600, powerpc_debugfs_root,
+NULL, _ppc64_pft_size)) {
+   pr_err("lpar: unable to create ppc64_pft_size debugsfs file\n");
+   }
+
+   return 0;
+}
+machine_device_initcall(pseries, hash64_debugfs);
diff --git a/arch/powerpc/platforms/pseries/lpar.c 
b/arch/powerpc/platforms/pseries/lpar.c
index aa35245..5f0cee3 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -27,6 +27,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -589,6 +591,113 @@ static int __init disable_bulk_remove(char *str)
 
 __setup("bulk_remove=", disable_bulk_remove);
 
+#define HPT_RESIZE_TIMEOUT 1 /* ms */
+
+struct hpt_resize_state {
+   unsigned long shift;
+   int commit_rc;
+};
+
+static int pseries_lpar_resize_hpt_commit(void *data)
+{
+   struct hpt_resize_state *state = data;
+
+   state->commit_rc = plpar_resize_hpt_commit(0, state->shift);
+   if (state->commit_rc != H_SUCCESS)
+   return -EIO;
+
+   /* Hypervisor has transitioned the HTAB, update our globals */
+   ppc64_pft_size = state->shift;
+   htab_size_bytes = 1UL << ppc64_pft_size;
+   htab_hash_mask = (htab_size_bytes >> 7) - 1;
+
+   return 0;
+}
+
+/* Must be called in user context */
+static int pseries_lpar_resize_hpt(unsigned long shift)
+{
+   struct hpt_resize_state state = {
+   .shift = shift,
+   .commit_rc = H_FUNCTION,
+   };
+   unsigned int delay, total_delay = 0;
+   int rc;
+   ktime_t t0, t1, t2;
+
+   might_sleep();
+
+   if (!firmware_has_feature(FW_FEATURE_HPT_RESIZE))
+   return -ENODEV;
+
+   printk(KERN_INFO "lpar: Attempting to resize HPT to shift %lu\n",
+  shift);
+
+   t0 = ktime_get();
+
+   rc = plpar_resize_hpt_prepare(0, shift);
+   while (H_IS_LONG_BUSY(rc)) {
+   delay = get_longbusy_msecs(rc);
+   total_delay += delay;
+   if (total_delay > HPT_RESIZE_TIMEOUT) {
+   /* prepare call with shift==0 cancels an
+* in-progress resize */
+   rc = plpar_resize_hpt_prepare(0, 0);
+   if (rc != H_SUCCESS)
+