Merge branch 'topic/ppc-kvm' into next
authorMichael Ellerman <mpe@ellerman.id.au>
Tue, 14 Feb 2017 06:18:29 +0000 (17:18 +1100)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 14 Feb 2017 06:18:29 +0000 (17:18 +1100)
Merge the topic branch we're sharing with the kvm-ppc tree.

16 files changed:
1  2 
arch/powerpc/include/asm/head-64.h
arch/powerpc/include/asm/hvcall.h
arch/powerpc/include/asm/opal.h
arch/powerpc/include/asm/prom.h
arch/powerpc/include/asm/reg.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/idle_book3s.S
arch/powerpc/kernel/prom_init.c
arch/powerpc/mm/init-common.c
arch/powerpc/mm/pgtable-radix.c
arch/powerpc/mm/pgtable_64.c
arch/powerpc/platforms/powernv/opal-wrappers.S
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/platforms/pseries/firmware.c
arch/powerpc/platforms/pseries/lpar.c

index a475711cd9c3940e15a2eaae6617cf763a486526,9bd81619d0901fa13451a3fef809498ca48936b9..5067048daad4cc683f8465c54f9eb3b212e12ceb
@@@ -223,8 -217,8 +223,8 @@@ name
        FIXED_SECTION_ENTRY_BEGIN(virt_trampolines, name)
  
  #ifdef CONFIG_KVM_BOOK3S_64_HANDLER
 -#define TRAMP_KVM_BEGIN(name)                                         \
 +#define TRAMP_KVM_BEGIN(name)                                 \
-       TRAMP_REAL_BEGIN(name)
+       TRAMP_VIRT_BEGIN(name)
  #else
  #define TRAMP_KVM_BEGIN(name)
  #endif
index 490c4b9f4e3a767ba93151dfd94d1d34e5849f68,54d11b3a6bf706a31c069ba795a037c93a475a0f..3cc12a86ef5de4efb2ba88a0d380718d6866482c
  #define H_GET_MPP_X           0x314
  #define H_SET_MODE            0x31C
  #define H_CLEAR_HPT           0x358
 +#define H_RESIZE_HPT_PREPARE  0x36C
 +#define H_RESIZE_HPT_COMMIT   0x370
+ #define H_REGISTER_PROC_TBL   0x37C
  #define H_SIGNAL_SYS_RESET    0x380
  #define MAX_HCALL_OPCODE      H_SIGNAL_SYS_RESET
  
index 08ddea966601b1ad81737e7ce8d0458fd6a50f0a,16efe7406776a6ee29288596948cd61747d11dde..1ff03a6da76e2f1e2a03d1b9064758a6f044ee98
@@@ -228,11 -225,6 +225,7 @@@ int64_t opal_int_set_mfrr(uint32_t cpu
  int64_t opal_pci_tce_kill(uint64_t phb_id, uint32_t kill_type,
                          uint32_t pe_num, uint32_t tce_size,
                          uint64_t dma_addr, uint32_t npages);
- int64_t opal_rm_pci_tce_kill(uint64_t phb_id, uint32_t kill_type,
-                            uint32_t pe_num, uint32_t tce_size,
-                            uint64_t dma_addr, uint32_t npages);
 +int64_t opal_nmmu_set_ptcr(uint64_t chip_id, uint64_t ptcr);
  
  /* Internal functions */
  extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
index 00fcfcbdd053fbeece5d9c7f6f33b7e723d9c7f6,8af2546ea5932e8e1d00397795cbe00369c930e6..2c8001cc93b649e789b6415fb06c44ad9cea97db
@@@ -151,11 -153,17 +153,18 @@@ struct of_drconf_cell 
  #define OV5_XCMO              0x0440  /* Page Coalescing */
  #define OV5_TYPE1_AFFINITY    0x0580  /* Type 1 NUMA affinity */
  #define OV5_PRRN              0x0540  /* Platform Resource Reassignment */
- #define OV5_PFO_HW_RNG                0x0E80  /* PFO Random Number Generator */
- #define OV5_PFO_HW_842                0x0E40  /* PFO Compression Accelerator */
- #define OV5_PFO_HW_ENCR               0x0E20  /* PFO Encryption Accelerator */
- #define OV5_SUB_PROCESSORS    0x0F01  /* 1,2,or 4 Sub-Processors supported */
 +#define OV5_RESIZE_HPT                0x0601  /* Hash Page Table resizing */
+ #define OV5_PFO_HW_RNG                0x1180  /* PFO Random Number Generator */
+ #define OV5_PFO_HW_842                0x1140  /* PFO Compression Accelerator */
+ #define OV5_PFO_HW_ENCR               0x1120  /* PFO Encryption Accelerator */
+ #define OV5_SUB_PROCESSORS    0x1501  /* 1,2,or 4 Sub-Processors supported */
+ #define OV5_XIVE_EXPLOIT      0x1701  /* XIVE exploitation supported */
+ #define OV5_MMU_RADIX_300     0x1880  /* ISA v3.00 radix MMU supported */
+ #define OV5_MMU_HASH_300      0x1840  /* ISA v3.00 hash MMU supported */
+ #define OV5_MMU_SEGM_RADIX    0x1820  /* radix mode (no segmentation) */
+ #define OV5_MMU_PROC_TBL      0x1810  /* hcall selects SLB or proc table */
+ #define OV5_MMU_SLB           0x1800  /* always use SLB */
+ #define OV5_MMU_GTSE          0x1808  /* Guest translation shootdown */
  
  /* Option Vector 6: IBM PAPR hints */
  #define OV6_LINUX             0x02    /* Linux is our OS */
Simple merge
Simple merge
index a6205a4a3574034ad0d948a99b665f40e692e02b,76dd7738c122afa5dcf4791b57ebe76355b3e532..857bf7c5b9465aff743b3e62094cc47d808c8c92
@@@ -720,14 -720,10 +720,10 @@@ hardware_interrupt_hv
        FTR_SECTION_ELSE
                _MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt_common,
                                            EXC_STD, SOFTEN_TEST_PR)
- do_kvm_0x500:
-               KVM_HANDLER(PACA_EXGEN, EXC_STD, 0x500)
        ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
 -EXC_REAL_END(hardware_interrupt, 0x500, 0x600)
 +EXC_REAL_END(hardware_interrupt, 0x500, 0x100)
  
 -EXC_VIRT_BEGIN(hardware_interrupt, 0x4500, 0x4600)
 +EXC_VIRT_BEGIN(hardware_interrupt, 0x4500, 0x100)
        .globl hardware_interrupt_relon_hv;
  hardware_interrupt_relon_hv:
        BEGIN_FTR_SECTION
        FTR_SECTION_ELSE
                _MASKABLE_RELON_EXCEPTION_PSERIES(0x500, hardware_interrupt_common, EXC_STD, SOFTEN_TEST_PR)
        ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)
 -EXC_VIRT_END(hardware_interrupt, 0x4500, 0x4600)
 +EXC_VIRT_END(hardware_interrupt, 0x4500, 0x100)
  
+ TRAMP_KVM(PACA_EXGEN, 0x500)
+ TRAMP_KVM_HV(PACA_EXGEN, 0x500)
  EXC_COMMON_ASYNC(hardware_interrupt_common, 0x500, do_IRQ)
  
  
@@@ -884,35 -907,15 +907,15 @@@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE
        b       system_call_common ;
  #endif
  
 -EXC_REAL_BEGIN(system_call, 0xc00, 0xd00)
 +EXC_REAL_BEGIN(system_call, 0xc00, 0x100)
-        /*
-         * If CONFIG_KVM_BOOK3S_64_HANDLER is set, save the PPR (on systems
-         * that support it) before changing to HMT_MEDIUM. That allows the KVM
-         * code to save that value into the guest state (it is the guest's PPR
-         * value). Otherwise just change to HMT_MEDIUM as userspace has
-         * already saved the PPR.
-         */
- #ifdef CONFIG_KVM_BOOK3S_64_HANDLER
-       SET_SCRATCH0(r13)
-       GET_PACA(r13)
-       std     r9,PACA_EXGEN+EX_R9(r13)
-       OPT_GET_SPR(r9, SPRN_PPR, CPU_FTR_HAS_PPR);
-       HMT_MEDIUM;
-       std     r10,PACA_EXGEN+EX_R10(r13)
-       OPT_SAVE_REG_TO_PACA(PACA_EXGEN+EX_PPR, r9, CPU_FTR_HAS_PPR);
-       mfcr    r9
-       KVMTEST_PR(0xc00)
-       GET_SCRATCH0(r13)
- #else
-       HMT_MEDIUM;
- #endif
+       SYSCALL_KVMTEST
        SYSCALL_PSERIES_1
        SYSCALL_PSERIES_2_RFID
        SYSCALL_PSERIES_3
 -EXC_REAL_END(system_call, 0xc00, 0xd00)
 +EXC_REAL_END(system_call, 0xc00, 0x100)
  
 -EXC_VIRT_BEGIN(system_call, 0x4c00, 0x4d00)
 +EXC_VIRT_BEGIN(system_call, 0x4c00, 0x100)
-       HMT_MEDIUM
+       SYSCALL_KVMTEST
        SYSCALL_PSERIES_1
        SYSCALL_PSERIES_2_DIRECT
        SYSCALL_PSERIES_3
@@@ -926,8 -929,8 +929,8 @@@ EXC_VIRT(single_step, 0x4d00, 0x100, 0x
  TRAMP_KVM(PACA_EXGEN, 0xd00)
  EXC_COMMON(single_step_common, 0xd00, single_step_exception)
  
 -EXC_REAL_OOL_HV(h_data_storage, 0xe00, 0xe20)
 -EXC_VIRT_OOL_HV(h_data_storage, 0x4e00, 0x4e20, 0xe00)
 +EXC_REAL_OOL_HV(h_data_storage, 0xe00, 0x20)
- EXC_VIRT_NONE(0x4e00, 0x20)
++EXC_VIRT_OOL_HV(h_data_storage, 0x4e00, 0x20, 0xe00)
  TRAMP_KVM_HV_SKIP(PACA_EXGEN, 0xe00)
  EXC_COMMON_BEGIN(h_data_storage_common)
        mfspr   r10,SPRN_HDAR
        b       ret_from_except
  
  
 -EXC_REAL_OOL_HV(h_instr_storage, 0xe20, 0xe40)
 -EXC_VIRT_OOL_HV(h_instr_storage, 0x4e20, 0x4e40, 0xe20)
 +EXC_REAL_OOL_HV(h_instr_storage, 0xe20, 0x20)
- EXC_VIRT_NONE(0x4e20, 0x20)
++EXC_VIRT_OOL_HV(h_instr_storage, 0x4e20, 0x20, 0xe20)
  TRAMP_KVM_HV(PACA_EXGEN, 0xe20)
  EXC_COMMON(h_instr_storage_common, 0xe20, unknown_exception)
  
Simple merge
Simple merge
index f2108c40e697dfa5128dc7b8f742e8a2db8063fd,2be5dc24283289a9bd1222d4a5b4f63f9ac33037..eb8c6c8c4851a9a7e25a555dd3e61c7b0613fb4e
@@@ -78,15 -79,11 +79,15 @@@ void pgtable_cache_add(unsigned shift, 
        align = max_t(unsigned long, align, minalign);
        name = kasprintf(GFP_KERNEL, "pgtable-2^%d", shift);
        new = kmem_cache_create(name, table_size, align, 0, ctor);
 +      if (!new)
 +              panic("Could not allocate pgtable cache for order %d", shift);
 +
        kfree(name);
        pgtable_cache[shift - 1] = new;
 +
        pr_debug("Allocated pgtable cache for order %d\n", shift);
  }
+ EXPORT_SYMBOL_GPL(pgtable_cache_add); /* used by kvm_hv module */
  
  void pgtable_cache_init(void)
  {
Simple merge
Simple merge
index 63fe1b2b11755f7c942ece5eeeba90c15e45563c,28799e557348c16c500ec7df7f65ca38f66863ce..6693f75e93d1629b51cd3104f24b84528a00969f
@@@ -304,12 -296,7 +296,8 @@@ OPAL_CALL(opal_pci_get_presence_state
  OPAL_CALL(opal_pci_get_power_state,           OPAL_PCI_GET_POWER_STATE);
  OPAL_CALL(opal_pci_set_power_state,           OPAL_PCI_SET_POWER_STATE);
  OPAL_CALL(opal_int_get_xirr,                  OPAL_INT_GET_XIRR);
- OPAL_CALL_REAL(opal_rm_int_get_xirr,          OPAL_INT_GET_XIRR);
  OPAL_CALL(opal_int_set_cppr,                  OPAL_INT_SET_CPPR);
  OPAL_CALL(opal_int_eoi,                               OPAL_INT_EOI);
- OPAL_CALL_REAL(opal_rm_int_eoi,                       OPAL_INT_EOI);
  OPAL_CALL(opal_int_set_mfrr,                  OPAL_INT_SET_MFRR);
- OPAL_CALL_REAL(opal_rm_int_set_mfrr,          OPAL_INT_SET_MFRR);
  OPAL_CALL(opal_pci_tce_kill,                  OPAL_PCI_TCE_KILL);
- OPAL_CALL_REAL(opal_rm_pci_tce_kill,          OPAL_PCI_TCE_KILL);
 +OPAL_CALL(opal_nmmu_set_ptcr,                 OPAL_NMMU_SET_PTCR);
index c2e13a51f369d5f5aa7bebd85332d166fce7bac0,0587655aea6996816e2d7d44779f69cc35946c7e..251060cf171364f1dd4dd08452189133dd713265
@@@ -611,112 -609,29 +611,135 @@@ static int __init disable_bulk_remove(c
  
  __setup("bulk_remove=", disable_bulk_remove);
  
 +#define HPT_RESIZE_TIMEOUT    10000 /* 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 with shift==0 cancels an in-progress resize */
 +                      rc = plpar_resize_hpt_prepare(0, 0);
 +                      if (rc != H_SUCCESS)
 +                              printk(KERN_WARNING
 +                                     "lpar: Unexpected error %d cancelling timed out HPT resize\n",
 +                                     rc);
 +                      return -ETIMEDOUT;
 +              }
 +              msleep(delay);
 +              rc = plpar_resize_hpt_prepare(0, shift);
 +      };
 +
 +      switch (rc) {
 +      case H_SUCCESS:
 +              /* Continue on */
 +              break;
 +
 +      case H_PARAMETER:
 +              return -EINVAL;
 +      case H_RESOURCE:
 +              return -EPERM;
 +      default:
 +              printk(KERN_WARNING
 +                     "lpar: Unexpected error %d from H_RESIZE_HPT_PREPARE\n",
 +                     rc);
 +              return -EIO;
 +      }
 +
 +      t1 = ktime_get();
 +
 +      rc = stop_machine(pseries_lpar_resize_hpt_commit, &state, NULL);
 +
 +      t2 = ktime_get();
 +
 +      if (rc != 0) {
 +              switch (state.commit_rc) {
 +              case H_PTEG_FULL:
 +                      printk(KERN_WARNING
 +                             "lpar: Hash collision while resizing HPT\n");
 +                      return -ENOSPC;
 +
 +              default:
 +                      printk(KERN_WARNING
 +                             "lpar: Unexpected error %d from H_RESIZE_HPT_COMMIT\n",
 +                             state.commit_rc);
 +                      return -EIO;
 +              };
 +      }
 +
 +      printk(KERN_INFO
 +             "lpar: HPT resize to shift %lu complete (%lld ms / %lld ms)\n",
 +             shift, (long long) ktime_ms_delta(t1, t0),
 +             (long long) ktime_ms_delta(t2, t1));
 +
 +      return 0;
 +}
 +
+ /* Actually only used for radix, so far */
+ static int pseries_lpar_register_process_table(unsigned long base,
+                       unsigned long page_size, unsigned long table_size)
+ {
+       long rc;
+       unsigned long flags = PROC_TABLE_NEW;
+       if (radix_enabled())
+               flags |= PROC_TABLE_RADIX | PROC_TABLE_GTSE;
+       for (;;) {
+               rc = plpar_hcall_norets(H_REGISTER_PROC_TBL, flags, base,
+                                       page_size, table_size);
+               if (!H_IS_LONG_BUSY(rc))
+                       break;
+               mdelay(get_longbusy_msecs(rc));
+       }
+       if (rc != H_SUCCESS) {
+               pr_err("Failed to register process table (rc=%ld)\n", rc);
+               BUG();
+       }
+       return rc;
+ }
  void __init hpte_init_pseries(void)
  {
        mmu_hash_ops.hpte_invalidate     = pSeries_lpar_hpte_invalidate;
        mmu_hash_ops.flush_hash_range    = pSeries_lpar_flush_hash_range;
        mmu_hash_ops.hpte_clear_all      = pseries_hpte_clear_all;
        mmu_hash_ops.hugepage_invalidate = pSeries_lpar_hugepage_invalidate;
 +      mmu_hash_ops.resize_hpt          = pseries_lpar_resize_hpt;
  }
  
+ void radix_init_pseries(void)
+ {
+       pr_info("Using radix MMU under hypervisor\n");
+       register_process_table = pseries_lpar_register_process_table;
+ }
  #ifdef CONFIG_PPC_SMLPAR
  #define CMO_FREE_HINT_DEFAULT 1
  static int cmo_free_hint_flag = CMO_FREE_HINT_DEFAULT;