]> Git Repo - linux.git/commitdiff
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
authorLinus Torvalds <[email protected]>
Thu, 10 Sep 2015 23:42:49 +0000 (16:42 -0700)
committerLinus Torvalds <[email protected]>
Thu, 10 Sep 2015 23:42:49 +0000 (16:42 -0700)
Pull more kvm updates from Paolo Bonzini:
 "ARM:
   - Full debug support for arm64
   - Active state switching for timer interrupts
   - Lazy FP/SIMD save/restore for arm64
   - Generic ARMv8 target

  PPC:
   - Book3S: A few bug fixes
   - Book3S: Allow micro-threading on POWER8

  x86:
   - Compiler warnings

  Generic:
   - Adaptive polling for guest halt"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (49 commits)
  kvm: irqchip: fix memory leak
  kvm: move new trace event outside #ifdef CONFIG_KVM_ASYNC_PF
  KVM: trace kvm_halt_poll_ns grow/shrink
  KVM: dynamic halt-polling
  KVM: make halt_poll_ns per-vCPU
  Silence compiler warning in arch/x86/kvm/emulate.c
  kvm: compile process_smi_save_seg_64() only for x86_64
  KVM: x86: avoid uninitialized variable warning
  KVM: PPC: Book3S: Fix typo in top comment about locking
  KVM: PPC: Book3S: Fix size of the PSPB register
  KVM: PPC: Book3S HV: Exit on H_DOORBELL if HOST_IPI is set
  KVM: PPC: Book3S HV: Fix race in starting secondary threads
  KVM: PPC: Book3S: correct width in XER handling
  KVM: PPC: Book3S HV: Fix preempted vcore stolen time calculation
  KVM: PPC: Book3S HV: Fix preempted vcore list locking
  KVM: PPC: Book3S HV: Implement H_CLEAR_REF and H_CLEAR_MOD
  KVM: PPC: Book3S HV: Fix bug in dirty page tracking
  KVM: PPC: Book3S HV: Fix race in reading change bit when removing HPTE
  KVM: PPC: Book3S HV: Implement dynamic micro-threading on POWER8
  KVM: PPC: Book3S HV: Make use of unused threads when running guests
  ...

1  2 
arch/arm64/kernel/hw_breakpoint.c
arch/arm64/kvm/hyp.S
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kvm/book3s.c
arch/powerpc/kvm/book3s_hv.c
arch/x86/kvm/x86.c
include/linux/irqchip/arm-gic-v3.h
include/linux/irqchip/arm-gic.h

index 003bc3d50636f585e3777661ad270baedaf1fe15,77bee00bd7ea04e7de6dd6a51edae3721cf743a7..c97040ecf838096069e1ebd0fdd50f2d0050b5ad
@@@ -48,18 -48,6 +48,6 @@@ static DEFINE_PER_CPU(int, stepping_ker
  static int core_num_brps;
  static int core_num_wrps;
  
- /* Determine number of BRP registers available. */
- static int get_num_brps(void)
- {
-       return ((read_cpuid(ID_AA64DFR0_EL1) >> 12) & 0xf) + 1;
- }
- /* Determine number of WRP registers available. */
- static int get_num_wrps(void)
- {
-       return ((read_cpuid(ID_AA64DFR0_EL1) >> 20) & 0xf) + 1;
- }
  int hw_breakpoint_slots(int type)
  {
        /*
@@@ -156,7 -144,7 +144,7 @@@ static void write_wb_reg(int reg, int n
   * Convert a breakpoint privilege level to the corresponding exception
   * level.
   */
 -static enum debug_el debug_exception_level(int privilege)
 +static enum dbg_active_el debug_exception_level(int privilege)
  {
        switch (privilege) {
        case AARCH64_BREAKPOINT_EL0:
@@@ -230,7 -218,7 +218,7 @@@ static int hw_breakpoint_control(struc
        struct perf_event **slots;
        struct debug_info *debug_info = &current->thread.debug;
        int i, max_slots, ctrl_reg, val_reg, reg_enable;
 -      enum debug_el dbg_el = debug_exception_level(info->ctrl.privilege);
 +      enum dbg_active_el dbg_el = debug_exception_level(info->ctrl.privilege);
        u32 ctrl;
  
        if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
@@@ -537,7 -525,7 +525,7 @@@ int arch_validate_hwbkpt_settings(struc
   * exception level at the register level.
   * This is used when single-stepping after a breakpoint exception.
   */
 -static void toggle_bp_registers(int reg, enum debug_el el, int enable)
 +static void toggle_bp_registers(int reg, enum dbg_active_el el, int enable)
  {
        int i, max_slots, privilege;
        u32 ctrl;
diff --combined arch/arm64/kvm/hyp.S
index 10915aaf0b015b7281efa832e3ea50a90e42394c,8188f6ae8fc40fbd0e7518c99a97c59b73e91220..37c89ea2c572ed858c0425344b45e0897a89b74f
        stp     x24, x25, [x3, #160]
  .endm
  
- .macro save_debug
-       // x2: base address for cpu context
-       // x3: tmp register
-       mrs     x26, id_aa64dfr0_el1
-       ubfx    x24, x26, #12, #4       // Extract BRPs
-       ubfx    x25, x26, #20, #4       // Extract WRPs
-       mov     w26, #15
-       sub     w24, w26, w24           // How many BPs to skip
-       sub     w25, w26, w25           // How many WPs to skip
-       add     x3, x2, #CPU_SYSREG_OFFSET(DBGBCR0_EL1)
-       adr     x26, 1f
-       add     x26, x26, x24, lsl #2
-       br      x26
- 1:
-       mrs     x20, dbgbcr15_el1
-       mrs     x19, dbgbcr14_el1
-       mrs     x18, dbgbcr13_el1
-       mrs     x17, dbgbcr12_el1
-       mrs     x16, dbgbcr11_el1
-       mrs     x15, dbgbcr10_el1
-       mrs     x14, dbgbcr9_el1
-       mrs     x13, dbgbcr8_el1
-       mrs     x12, dbgbcr7_el1
-       mrs     x11, dbgbcr6_el1
-       mrs     x10, dbgbcr5_el1
-       mrs     x9, dbgbcr4_el1
-       mrs     x8, dbgbcr3_el1
-       mrs     x7, dbgbcr2_el1
-       mrs     x6, dbgbcr1_el1
-       mrs     x5, dbgbcr0_el1
-       adr     x26, 1f
-       add     x26, x26, x24, lsl #2
-       br      x26
- 1:
-       str     x20, [x3, #(15 * 8)]
-       str     x19, [x3, #(14 * 8)]
-       str     x18, [x3, #(13 * 8)]
-       str     x17, [x3, #(12 * 8)]
-       str     x16, [x3, #(11 * 8)]
-       str     x15, [x3, #(10 * 8)]
-       str     x14, [x3, #(9 * 8)]
-       str     x13, [x3, #(8 * 8)]
-       str     x12, [x3, #(7 * 8)]
-       str     x11, [x3, #(6 * 8)]
-       str     x10, [x3, #(5 * 8)]
-       str     x9, [x3, #(4 * 8)]
-       str     x8, [x3, #(3 * 8)]
-       str     x7, [x3, #(2 * 8)]
-       str     x6, [x3, #(1 * 8)]
-       str     x5, [x3, #(0 * 8)]
-       add     x3, x2, #CPU_SYSREG_OFFSET(DBGBVR0_EL1)
-       adr     x26, 1f
-       add     x26, x26, x24, lsl #2
-       br      x26
+ .macro save_debug type
+       // x4: pointer to register set
+       // x5: number of registers to skip
+       // x6..x22 trashed
+       adr     x22, 1f
+       add     x22, x22, x5, lsl #2
+       br      x22
  1:
-       mrs     x20, dbgbvr15_el1
-       mrs     x19, dbgbvr14_el1
-       mrs     x18, dbgbvr13_el1
-       mrs     x17, dbgbvr12_el1
-       mrs     x16, dbgbvr11_el1
-       mrs     x15, dbgbvr10_el1
-       mrs     x14, dbgbvr9_el1
-       mrs     x13, dbgbvr8_el1
-       mrs     x12, dbgbvr7_el1
-       mrs     x11, dbgbvr6_el1
-       mrs     x10, dbgbvr5_el1
-       mrs     x9, dbgbvr4_el1
-       mrs     x8, dbgbvr3_el1
-       mrs     x7, dbgbvr2_el1
-       mrs     x6, dbgbvr1_el1
-       mrs     x5, dbgbvr0_el1
-       adr     x26, 1f
-       add     x26, x26, x24, lsl #2
-       br      x26
- 1:
-       str     x20, [x3, #(15 * 8)]
-       str     x19, [x3, #(14 * 8)]
-       str     x18, [x3, #(13 * 8)]
-       str     x17, [x3, #(12 * 8)]
-       str     x16, [x3, #(11 * 8)]
-       str     x15, [x3, #(10 * 8)]
-       str     x14, [x3, #(9 * 8)]
-       str     x13, [x3, #(8 * 8)]
-       str     x12, [x3, #(7 * 8)]
-       str     x11, [x3, #(6 * 8)]
-       str     x10, [x3, #(5 * 8)]
-       str     x9, [x3, #(4 * 8)]
-       str     x8, [x3, #(3 * 8)]
-       str     x7, [x3, #(2 * 8)]
-       str     x6, [x3, #(1 * 8)]
-       str     x5, [x3, #(0 * 8)]
-       add     x3, x2, #CPU_SYSREG_OFFSET(DBGWCR0_EL1)
-       adr     x26, 1f
-       add     x26, x26, x25, lsl #2
-       br      x26
- 1:
-       mrs     x20, dbgwcr15_el1
-       mrs     x19, dbgwcr14_el1
-       mrs     x18, dbgwcr13_el1
-       mrs     x17, dbgwcr12_el1
-       mrs     x16, dbgwcr11_el1
-       mrs     x15, dbgwcr10_el1
-       mrs     x14, dbgwcr9_el1
-       mrs     x13, dbgwcr8_el1
-       mrs     x12, dbgwcr7_el1
-       mrs     x11, dbgwcr6_el1
-       mrs     x10, dbgwcr5_el1
-       mrs     x9, dbgwcr4_el1
-       mrs     x8, dbgwcr3_el1
-       mrs     x7, dbgwcr2_el1
-       mrs     x6, dbgwcr1_el1
-       mrs     x5, dbgwcr0_el1
-       adr     x26, 1f
-       add     x26, x26, x25, lsl #2
-       br      x26
- 1:
-       str     x20, [x3, #(15 * 8)]
-       str     x19, [x3, #(14 * 8)]
-       str     x18, [x3, #(13 * 8)]
-       str     x17, [x3, #(12 * 8)]
-       str     x16, [x3, #(11 * 8)]
-       str     x15, [x3, #(10 * 8)]
-       str     x14, [x3, #(9 * 8)]
-       str     x13, [x3, #(8 * 8)]
-       str     x12, [x3, #(7 * 8)]
-       str     x11, [x3, #(6 * 8)]
-       str     x10, [x3, #(5 * 8)]
-       str     x9, [x3, #(4 * 8)]
-       str     x8, [x3, #(3 * 8)]
-       str     x7, [x3, #(2 * 8)]
-       str     x6, [x3, #(1 * 8)]
-       str     x5, [x3, #(0 * 8)]
-       add     x3, x2, #CPU_SYSREG_OFFSET(DBGWVR0_EL1)
-       adr     x26, 1f
-       add     x26, x26, x25, lsl #2
-       br      x26
- 1:
-       mrs     x20, dbgwvr15_el1
-       mrs     x19, dbgwvr14_el1
-       mrs     x18, dbgwvr13_el1
-       mrs     x17, dbgwvr12_el1
-       mrs     x16, dbgwvr11_el1
-       mrs     x15, dbgwvr10_el1
-       mrs     x14, dbgwvr9_el1
-       mrs     x13, dbgwvr8_el1
-       mrs     x12, dbgwvr7_el1
-       mrs     x11, dbgwvr6_el1
-       mrs     x10, dbgwvr5_el1
-       mrs     x9, dbgwvr4_el1
-       mrs     x8, dbgwvr3_el1
-       mrs     x7, dbgwvr2_el1
-       mrs     x6, dbgwvr1_el1
-       mrs     x5, dbgwvr0_el1
-       adr     x26, 1f
-       add     x26, x26, x25, lsl #2
-       br      x26
+       mrs     x21, \type\()15_el1
+       mrs     x20, \type\()14_el1
+       mrs     x19, \type\()13_el1
+       mrs     x18, \type\()12_el1
+       mrs     x17, \type\()11_el1
+       mrs     x16, \type\()10_el1
+       mrs     x15, \type\()9_el1
+       mrs     x14, \type\()8_el1
+       mrs     x13, \type\()7_el1
+       mrs     x12, \type\()6_el1
+       mrs     x11, \type\()5_el1
+       mrs     x10, \type\()4_el1
+       mrs     x9, \type\()3_el1
+       mrs     x8, \type\()2_el1
+       mrs     x7, \type\()1_el1
+       mrs     x6, \type\()0_el1
+       adr     x22, 1f
+       add     x22, x22, x5, lsl #2
+       br      x22
  1:
-       str     x20, [x3, #(15 * 8)]
-       str     x19, [x3, #(14 * 8)]
-       str     x18, [x3, #(13 * 8)]
-       str     x17, [x3, #(12 * 8)]
-       str     x16, [x3, #(11 * 8)]
-       str     x15, [x3, #(10 * 8)]
-       str     x14, [x3, #(9 * 8)]
-       str     x13, [x3, #(8 * 8)]
-       str     x12, [x3, #(7 * 8)]
-       str     x11, [x3, #(6 * 8)]
-       str     x10, [x3, #(5 * 8)]
-       str     x9, [x3, #(4 * 8)]
-       str     x8, [x3, #(3 * 8)]
-       str     x7, [x3, #(2 * 8)]
-       str     x6, [x3, #(1 * 8)]
-       str     x5, [x3, #(0 * 8)]
-       mrs     x21, mdccint_el1
-       str     x21, [x2, #CPU_SYSREG_OFFSET(MDCCINT_EL1)]
+       str     x21, [x4, #(15 * 8)]
+       str     x20, [x4, #(14 * 8)]
+       str     x19, [x4, #(13 * 8)]
+       str     x18, [x4, #(12 * 8)]
+       str     x17, [x4, #(11 * 8)]
+       str     x16, [x4, #(10 * 8)]
+       str     x15, [x4, #(9 * 8)]
+       str     x14, [x4, #(8 * 8)]
+       str     x13, [x4, #(7 * 8)]
+       str     x12, [x4, #(6 * 8)]
+       str     x11, [x4, #(5 * 8)]
+       str     x10, [x4, #(4 * 8)]
+       str     x9, [x4, #(3 * 8)]
+       str     x8, [x4, #(2 * 8)]
+       str     x7, [x4, #(1 * 8)]
+       str     x6, [x4, #(0 * 8)]
  .endm
  
  .macro restore_sysregs
        msr     mdscr_el1,      x25
  .endm
  
- .macro restore_debug
-       // x2: base address for cpu context
-       // x3: tmp register
-       mrs     x26, id_aa64dfr0_el1
-       ubfx    x24, x26, #12, #4       // Extract BRPs
-       ubfx    x25, x26, #20, #4       // Extract WRPs
-       mov     w26, #15
-       sub     w24, w26, w24           // How many BPs to skip
-       sub     w25, w26, w25           // How many WPs to skip
-       add     x3, x2, #CPU_SYSREG_OFFSET(DBGBCR0_EL1)
+ .macro restore_debug type
+       // x4: pointer to register set
+       // x5: number of registers to skip
+       // x6..x22 trashed
  
-       adr     x26, 1f
-       add     x26, x26, x24, lsl #2
-       br      x26
- 1:
-       ldr     x20, [x3, #(15 * 8)]
-       ldr     x19, [x3, #(14 * 8)]
-       ldr     x18, [x3, #(13 * 8)]
-       ldr     x17, [x3, #(12 * 8)]
-       ldr     x16, [x3, #(11 * 8)]
-       ldr     x15, [x3, #(10 * 8)]
-       ldr     x14, [x3, #(9 * 8)]
-       ldr     x13, [x3, #(8 * 8)]
-       ldr     x12, [x3, #(7 * 8)]
-       ldr     x11, [x3, #(6 * 8)]
-       ldr     x10, [x3, #(5 * 8)]
-       ldr     x9, [x3, #(4 * 8)]
-       ldr     x8, [x3, #(3 * 8)]
-       ldr     x7, [x3, #(2 * 8)]
-       ldr     x6, [x3, #(1 * 8)]
-       ldr     x5, [x3, #(0 * 8)]
-       adr     x26, 1f
-       add     x26, x26, x24, lsl #2
-       br      x26
+       adr     x22, 1f
+       add     x22, x22, x5, lsl #2
+       br      x22
  1:
-       msr     dbgbcr15_el1, x20
-       msr     dbgbcr14_el1, x19
-       msr     dbgbcr13_el1, x18
-       msr     dbgbcr12_el1, x17
-       msr     dbgbcr11_el1, x16
-       msr     dbgbcr10_el1, x15
-       msr     dbgbcr9_el1, x14
-       msr     dbgbcr8_el1, x13
-       msr     dbgbcr7_el1, x12
-       msr     dbgbcr6_el1, x11
-       msr     dbgbcr5_el1, x10
-       msr     dbgbcr4_el1, x9
-       msr     dbgbcr3_el1, x8
-       msr     dbgbcr2_el1, x7
-       msr     dbgbcr1_el1, x6
-       msr     dbgbcr0_el1, x5
-       add     x3, x2, #CPU_SYSREG_OFFSET(DBGBVR0_EL1)
-       adr     x26, 1f
-       add     x26, x26, x24, lsl #2
-       br      x26
+       ldr     x21, [x4, #(15 * 8)]
+       ldr     x20, [x4, #(14 * 8)]
+       ldr     x19, [x4, #(13 * 8)]
+       ldr     x18, [x4, #(12 * 8)]
+       ldr     x17, [x4, #(11 * 8)]
+       ldr     x16, [x4, #(10 * 8)]
+       ldr     x15, [x4, #(9 * 8)]
+       ldr     x14, [x4, #(8 * 8)]
+       ldr     x13, [x4, #(7 * 8)]
+       ldr     x12, [x4, #(6 * 8)]
+       ldr     x11, [x4, #(5 * 8)]
+       ldr     x10, [x4, #(4 * 8)]
+       ldr     x9, [x4, #(3 * 8)]
+       ldr     x8, [x4, #(2 * 8)]
+       ldr     x7, [x4, #(1 * 8)]
+       ldr     x6, [x4, #(0 * 8)]
+       adr     x22, 1f
+       add     x22, x22, x5, lsl #2
+       br      x22
  1:
-       ldr     x20, [x3, #(15 * 8)]
-       ldr     x19, [x3, #(14 * 8)]
-       ldr     x18, [x3, #(13 * 8)]
-       ldr     x17, [x3, #(12 * 8)]
-       ldr     x16, [x3, #(11 * 8)]
-       ldr     x15, [x3, #(10 * 8)]
-       ldr     x14, [x3, #(9 * 8)]
-       ldr     x13, [x3, #(8 * 8)]
-       ldr     x12, [x3, #(7 * 8)]
-       ldr     x11, [x3, #(6 * 8)]
-       ldr     x10, [x3, #(5 * 8)]
-       ldr     x9, [x3, #(4 * 8)]
-       ldr     x8, [x3, #(3 * 8)]
-       ldr     x7, [x3, #(2 * 8)]
-       ldr     x6, [x3, #(1 * 8)]
-       ldr     x5, [x3, #(0 * 8)]
-       adr     x26, 1f
-       add     x26, x26, x24, lsl #2
-       br      x26
- 1:
-       msr     dbgbvr15_el1, x20
-       msr     dbgbvr14_el1, x19
-       msr     dbgbvr13_el1, x18
-       msr     dbgbvr12_el1, x17
-       msr     dbgbvr11_el1, x16
-       msr     dbgbvr10_el1, x15
-       msr     dbgbvr9_el1, x14
-       msr     dbgbvr8_el1, x13
-       msr     dbgbvr7_el1, x12
-       msr     dbgbvr6_el1, x11
-       msr     dbgbvr5_el1, x10
-       msr     dbgbvr4_el1, x9
-       msr     dbgbvr3_el1, x8
-       msr     dbgbvr2_el1, x7
-       msr     dbgbvr1_el1, x6
-       msr     dbgbvr0_el1, x5
-       add     x3, x2, #CPU_SYSREG_OFFSET(DBGWCR0_EL1)
-       adr     x26, 1f
-       add     x26, x26, x25, lsl #2
-       br      x26
- 1:
-       ldr     x20, [x3, #(15 * 8)]
-       ldr     x19, [x3, #(14 * 8)]
-       ldr     x18, [x3, #(13 * 8)]
-       ldr     x17, [x3, #(12 * 8)]
-       ldr     x16, [x3, #(11 * 8)]
-       ldr     x15, [x3, #(10 * 8)]
-       ldr     x14, [x3, #(9 * 8)]
-       ldr     x13, [x3, #(8 * 8)]
-       ldr     x12, [x3, #(7 * 8)]
-       ldr     x11, [x3, #(6 * 8)]
-       ldr     x10, [x3, #(5 * 8)]
-       ldr     x9, [x3, #(4 * 8)]
-       ldr     x8, [x3, #(3 * 8)]
-       ldr     x7, [x3, #(2 * 8)]
-       ldr     x6, [x3, #(1 * 8)]
-       ldr     x5, [x3, #(0 * 8)]
-       adr     x26, 1f
-       add     x26, x26, x25, lsl #2
-       br      x26
- 1:
-       msr     dbgwcr15_el1, x20
-       msr     dbgwcr14_el1, x19
-       msr     dbgwcr13_el1, x18
-       msr     dbgwcr12_el1, x17
-       msr     dbgwcr11_el1, x16
-       msr     dbgwcr10_el1, x15
-       msr     dbgwcr9_el1, x14
-       msr     dbgwcr8_el1, x13
-       msr     dbgwcr7_el1, x12
-       msr     dbgwcr6_el1, x11
-       msr     dbgwcr5_el1, x10
-       msr     dbgwcr4_el1, x9
-       msr     dbgwcr3_el1, x8
-       msr     dbgwcr2_el1, x7
-       msr     dbgwcr1_el1, x6
-       msr     dbgwcr0_el1, x5
-       add     x3, x2, #CPU_SYSREG_OFFSET(DBGWVR0_EL1)
-       adr     x26, 1f
-       add     x26, x26, x25, lsl #2
-       br      x26
- 1:
-       ldr     x20, [x3, #(15 * 8)]
-       ldr     x19, [x3, #(14 * 8)]
-       ldr     x18, [x3, #(13 * 8)]
-       ldr     x17, [x3, #(12 * 8)]
-       ldr     x16, [x3, #(11 * 8)]
-       ldr     x15, [x3, #(10 * 8)]
-       ldr     x14, [x3, #(9 * 8)]
-       ldr     x13, [x3, #(8 * 8)]
-       ldr     x12, [x3, #(7 * 8)]
-       ldr     x11, [x3, #(6 * 8)]
-       ldr     x10, [x3, #(5 * 8)]
-       ldr     x9, [x3, #(4 * 8)]
-       ldr     x8, [x3, #(3 * 8)]
-       ldr     x7, [x3, #(2 * 8)]
-       ldr     x6, [x3, #(1 * 8)]
-       ldr     x5, [x3, #(0 * 8)]
-       adr     x26, 1f
-       add     x26, x26, x25, lsl #2
-       br      x26
- 1:
-       msr     dbgwvr15_el1, x20
-       msr     dbgwvr14_el1, x19
-       msr     dbgwvr13_el1, x18
-       msr     dbgwvr12_el1, x17
-       msr     dbgwvr11_el1, x16
-       msr     dbgwvr10_el1, x15
-       msr     dbgwvr9_el1, x14
-       msr     dbgwvr8_el1, x13
-       msr     dbgwvr7_el1, x12
-       msr     dbgwvr6_el1, x11
-       msr     dbgwvr5_el1, x10
-       msr     dbgwvr4_el1, x9
-       msr     dbgwvr3_el1, x8
-       msr     dbgwvr2_el1, x7
-       msr     dbgwvr1_el1, x6
-       msr     dbgwvr0_el1, x5
-       ldr     x21, [x2, #CPU_SYSREG_OFFSET(MDCCINT_EL1)]
-       msr     mdccint_el1, x21
+       msr     \type\()15_el1, x21
+       msr     \type\()14_el1, x20
+       msr     \type\()13_el1, x19
+       msr     \type\()12_el1, x18
+       msr     \type\()11_el1, x17
+       msr     \type\()10_el1, x16
+       msr     \type\()9_el1, x15
+       msr     \type\()8_el1, x14
+       msr     \type\()7_el1, x13
+       msr     \type\()6_el1, x12
+       msr     \type\()5_el1, x11
+       msr     \type\()4_el1, x10
+       msr     \type\()3_el1, x9
+       msr     \type\()2_el1, x8
+       msr     \type\()1_el1, x7
+       msr     \type\()0_el1, x6
  .endm
  
  .macro skip_32bit_state tmp, target
        tbz     \tmp, #KVM_ARM64_DEBUG_DIRTY_SHIFT, \target
  .endm
  
+ /*
+  * Branch to target if CPTR_EL2.TFP bit is set (VFP/SIMD trapping enabled)
+  */
+ .macro skip_fpsimd_state tmp, target
+       mrs     \tmp, cptr_el2
+       tbnz    \tmp, #CPTR_EL2_TFP_SHIFT, \target
+ .endm
  .macro compute_debug_state target
        // Compute debug state: If any of KDE, MDE or KVM_ARM64_DEBUG_DIRTY
        // is set, we do a full save/restore cycle and disable trapping.
        add     x3, x2, #CPU_SYSREG_OFFSET(DACR32_EL2)
        mrs     x4, dacr32_el2
        mrs     x5, ifsr32_el2
-       mrs     x6, fpexc32_el2
        stp     x4, x5, [x3]
-       str     x6, [x3, #16]
  
+       skip_fpsimd_state x8, 3f
+       mrs     x6, fpexc32_el2
+       str     x6, [x3, #16]
+ 3:
        skip_debug_state x8, 2f
        mrs     x7, dbgvcr32_el2
        str     x7, [x3, #24]
  
        add     x3, x2, #CPU_SYSREG_OFFSET(DACR32_EL2)
        ldp     x4, x5, [x3]
-       ldr     x6, [x3, #16]
        msr     dacr32_el2, x4
        msr     ifsr32_el2, x5
-       msr     fpexc32_el2, x6
  
        skip_debug_state x8, 2f
        ldr     x7, [x3, #24]
  
  .macro activate_traps
        ldr     x2, [x0, #VCPU_HCR_EL2]
+       /*
+        * We are about to set CPTR_EL2.TFP to trap all floating point
+        * register accesses to EL2, however, the ARM ARM clearly states that
+        * traps are only taken to EL2 if the operation would not otherwise
+        * trap to EL1.  Therefore, always make sure that for 32-bit guests,
+        * we set FPEXC.EN to prevent traps to EL1, when setting the TFP bit.
+        */
+       tbnz    x2, #HCR_RW_SHIFT, 99f // open code skip_32bit_state
+       mov     x3, #(1 << 30)
+       msr     fpexc32_el2, x3
+       isb
+ 99:
        msr     hcr_el2, x2
        mov     x2, #CPTR_EL2_TTA
+       orr     x2, x2, #CPTR_EL2_TFP
        msr     cptr_el2, x2
  
        mov     x2, #(1 << 15)  // Trap CP15 Cr=15
        msr     hstr_el2, x2
  
-       mrs     x2, mdcr_el2
-       and     x2, x2, #MDCR_EL2_HPMN_MASK
-       orr     x2, x2, #(MDCR_EL2_TPM | MDCR_EL2_TPMCR)
-       orr     x2, x2, #(MDCR_EL2_TDRA | MDCR_EL2_TDOSA)
-       // Check for KVM_ARM64_DEBUG_DIRTY, and set debug to trap
-       // if not dirty.
-       ldr     x3, [x0, #VCPU_DEBUG_FLAGS]
-       tbnz    x3, #KVM_ARM64_DEBUG_DIRTY_SHIFT, 1f
-       orr     x2, x2,  #MDCR_EL2_TDA
- 1:
+       // Monitor Debug Config - see kvm_arm_setup_debug()
+       ldr     x2, [x0, #VCPU_MDCR_EL2]
        msr     mdcr_el2, x2
  .endm
  
  .macro deactivate_traps
        mov     x2, #HCR_RW
        msr     hcr_el2, x2
-       msr     cptr_el2, xzr
        msr     hstr_el2, xzr
  
        mrs     x2, mdcr_el2
   * Call into the vgic backend for state saving
   */
  .macro save_vgic_state
 -      alternative_insn "bl __save_vgic_v2_state", "bl __save_vgic_v3_state", ARM64_HAS_SYSREG_GIC_CPUIF
 +alternative_if_not ARM64_HAS_SYSREG_GIC_CPUIF
 +      bl      __save_vgic_v2_state
 +alternative_else
 +      bl      __save_vgic_v3_state
 +alternative_endif
        mrs     x24, hcr_el2
        mov     x25, #HCR_INT_OVERRIDE
        neg     x25, x25
        orr     x24, x24, #HCR_INT_OVERRIDE
        orr     x24, x24, x25
        msr     hcr_el2, x24
 -      alternative_insn "bl __restore_vgic_v2_state", "bl __restore_vgic_v3_state", ARM64_HAS_SYSREG_GIC_CPUIF
 +alternative_if_not ARM64_HAS_SYSREG_GIC_CPUIF
 +      bl      __restore_vgic_v2_state
 +alternative_else
 +      bl      __restore_vgic_v3_state
 +alternative_endif
  .endm
  
  .macro save_timer_state
@@@ -900,21 -614,101 +622,101 @@@ __restore_sysregs
        restore_sysregs
        ret
  
+ /* Save debug state */
  __save_debug:
-       save_debug
+       // x2: ptr to CPU context
+       // x3: ptr to debug reg struct
+       // x4/x5/x6-22/x24-26: trashed
+       mrs     x26, id_aa64dfr0_el1
+       ubfx    x24, x26, #12, #4       // Extract BRPs
+       ubfx    x25, x26, #20, #4       // Extract WRPs
+       mov     w26, #15
+       sub     w24, w26, w24           // How many BPs to skip
+       sub     w25, w26, w25           // How many WPs to skip
+       mov     x5, x24
+       add     x4, x3, #DEBUG_BCR
+       save_debug dbgbcr
+       add     x4, x3, #DEBUG_BVR
+       save_debug dbgbvr
+       mov     x5, x25
+       add     x4, x3, #DEBUG_WCR
+       save_debug dbgwcr
+       add     x4, x3, #DEBUG_WVR
+       save_debug dbgwvr
+       mrs     x21, mdccint_el1
+       str     x21, [x2, #CPU_SYSREG_OFFSET(MDCCINT_EL1)]
        ret
  
+ /* Restore debug state */
  __restore_debug:
-       restore_debug
+       // x2: ptr to CPU context
+       // x3: ptr to debug reg struct
+       // x4/x5/x6-22/x24-26: trashed
+       mrs     x26, id_aa64dfr0_el1
+       ubfx    x24, x26, #12, #4       // Extract BRPs
+       ubfx    x25, x26, #20, #4       // Extract WRPs
+       mov     w26, #15
+       sub     w24, w26, w24           // How many BPs to skip
+       sub     w25, w26, w25           // How many WPs to skip
+       mov     x5, x24
+       add     x4, x3, #DEBUG_BCR
+       restore_debug dbgbcr
+       add     x4, x3, #DEBUG_BVR
+       restore_debug dbgbvr
+       mov     x5, x25
+       add     x4, x3, #DEBUG_WCR
+       restore_debug dbgwcr
+       add     x4, x3, #DEBUG_WVR
+       restore_debug dbgwvr
+       ldr     x21, [x2, #CPU_SYSREG_OFFSET(MDCCINT_EL1)]
+       msr     mdccint_el1, x21
        ret
  
  __save_fpsimd:
+       skip_fpsimd_state x3, 1f
        save_fpsimd
      ret
1:    ret
  
  __restore_fpsimd:
+       skip_fpsimd_state x3, 1f
        restore_fpsimd
-       ret
+ 1:    ret
+ switch_to_guest_fpsimd:
+       push    x4, lr
+       mrs     x2, cptr_el2
+       bic     x2, x2, #CPTR_EL2_TFP
+       msr     cptr_el2, x2
+       isb
+       mrs     x0, tpidr_el2
+       ldr     x2, [x0, #VCPU_HOST_CONTEXT]
+       kern_hyp_va x2
+       bl __save_fpsimd
+       add     x2, x0, #VCPU_CONTEXT
+       bl __restore_fpsimd
+       skip_32bit_state x3, 1f
+       ldr     x4, [x2, #CPU_SYSREG_OFFSET(FPEXC32_EL2)]
+       msr     fpexc32_el2, x4
+ 1:
+       pop     x4, lr
+       pop     x2, x3
+       pop     x0, x1
+       eret
  
  /*
   * u64 __kvm_vcpu_run(struct kvm_vcpu *vcpu);
@@@ -936,10 -730,10 +738,10 @@@ ENTRY(__kvm_vcpu_run
        kern_hyp_va x2
  
        save_host_regs
-       bl __save_fpsimd
        bl __save_sysregs
  
        compute_debug_state 1f
+       add     x3, x0, #VCPU_HOST_DEBUG_STATE
        bl      __save_debug
  1:
        activate_traps
        add     x2, x0, #VCPU_CONTEXT
  
        bl __restore_sysregs
-       bl __restore_fpsimd
  
        skip_debug_state x3, 1f
+       ldr     x3, [x0, #VCPU_DEBUG_PTR]
+       kern_hyp_va x3
        bl      __restore_debug
  1:
        restore_guest_32bit_state
@@@ -975,6 -770,8 +778,8 @@@ __kvm_vcpu_return
        bl __save_sysregs
  
        skip_debug_state x3, 1f
+       ldr     x3, [x0, #VCPU_DEBUG_PTR]
+       kern_hyp_va x3
        bl      __save_debug
  1:
        save_guest_32bit_state
  
        bl __restore_sysregs
        bl __restore_fpsimd
+       /* Clear FPSIMD and Trace trapping */
+       msr     cptr_el2, xzr
  
        skip_debug_state x3, 1f
        // Clear the dirty flag for the next run, as all the state has
        // already been saved. Note that we nuke the whole 64bit word.
        // If we ever add more flags, we'll have to be more careful...
        str     xzr, [x0, #VCPU_DEBUG_FLAGS]
+       add     x3, x0, #VCPU_HOST_DEBUG_STATE
        bl      __restore_debug
  1:
        restore_host_regs
@@@ -1199,6 -999,11 +1007,11 @@@ el1_trap
         * x1: ESR
         * x2: ESR_EC
         */
+       /* Guest accessed VFP/SIMD registers, save host, restore Guest */
+       cmp     x2, #ESR_ELx_EC_FP_ASIMD
+       b.eq    switch_to_guest_fpsimd
        cmp     x2, #ESR_ELx_EC_DABT_LOW
        mov     x0, #ESR_ELx_EC_IABT_LOW
        ccmp    x2, x0, #4, ne
@@@ -1293,4 -1098,10 +1106,10 @@@ ENTRY(__kvm_hyp_vector
        ventry  el1_error_invalid               // Error 32-bit EL1
  ENDPROC(__kvm_hyp_vector)
  
+ ENTRY(__kvm_get_mdcr_el2)
+       mrs     x0, mdcr_el2
+       ret
+ ENDPROC(__kvm_get_mdcr_el2)
        .popsection
index 810f433731dcac24809dea42f1973c5a967bcae9,de62392f093c1cb9ca4448ff60b609b07678a661..221d584d089f9418abfa1087cffd9d0b0117c090
@@@ -213,6 -213,7 +213,6 @@@ int main(void
                offsetof(struct tlb_core_data, esel_max));
        DEFINE(TCD_ESEL_FIRST,
                offsetof(struct tlb_core_data, esel_first));
 -      DEFINE(TCD_LOCK, offsetof(struct tlb_core_data, lock));
  #endif /* CONFIG_PPC_BOOK3E */
  
  #ifdef CONFIG_PPC_STD_MMU_64
        DEFINE(VCPU_VPA, offsetof(struct kvm_vcpu, arch.vpa.pinned_addr));
        DEFINE(VCPU_VPA_DIRTY, offsetof(struct kvm_vcpu, arch.vpa.dirty));
        DEFINE(VCPU_HEIR, offsetof(struct kvm_vcpu, arch.emul_inst));
+       DEFINE(VCPU_CPU, offsetof(struct kvm_vcpu, cpu));
+       DEFINE(VCPU_THREAD_CPU, offsetof(struct kvm_vcpu, arch.thread_cpu));
  #endif
  #ifdef CONFIG_PPC_BOOK3S
        DEFINE(VCPU_VCPUID, offsetof(struct kvm_vcpu, vcpu_id));
        HSTATE_FIELD(HSTATE_DSCR, host_dscr);
        HSTATE_FIELD(HSTATE_DABR, dabr);
        HSTATE_FIELD(HSTATE_DECEXP, dec_expires);
+       HSTATE_FIELD(HSTATE_SPLIT_MODE, kvm_split_mode);
        DEFINE(IPI_PRIORITY, IPI_PRIORITY);
+       DEFINE(KVM_SPLIT_RPR, offsetof(struct kvm_split_mode, rpr));
+       DEFINE(KVM_SPLIT_PMMAR, offsetof(struct kvm_split_mode, pmmar));
+       DEFINE(KVM_SPLIT_LDBAR, offsetof(struct kvm_split_mode, ldbar));
+       DEFINE(KVM_SPLIT_SIZE, offsetof(struct kvm_split_mode, subcore_size));
+       DEFINE(KVM_SPLIT_DO_NAP, offsetof(struct kvm_split_mode, do_nap));
+       DEFINE(KVM_SPLIT_NAPPED, offsetof(struct kvm_split_mode, napped));
  #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
  
  #ifdef CONFIG_PPC_BOOK3S_64
index 6d6398f4d632d0c4e5e9d2439ce7e8df4f46767f,53285d52e38127aa8b03ae1cecedaae5b7e4a4e4..d75bf325f54a17ebf4e19dda7a85eed271e4f3ed
@@@ -240,7 -240,8 +240,8 @@@ void kvmppc_core_queue_inst_storage(str
        kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE);
  }
  
- int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
+ static int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu,
+                                        unsigned int priority)
  {
        int deliver = 1;
        int vec = 0;
@@@ -902,7 -903,7 +903,7 @@@ int kvmppc_core_check_processor_compat(
  {
        /*
         * We always return 0 for book3s. We check
 -       * for compatability while loading the HV
 +       * for compatibility while loading the HV
         * or PR module
         */
        return 0;
index a9f753fb73a816143ec4a013d9424b2acf6dbee4,c5edf1719314fbfdeb118e8666b3722d7a892076..9754e6815e521c80d6b8cadfe9123ab24b97c014
@@@ -81,6 -81,12 +81,12 @@@ static DECLARE_BITMAP(default_enabled_h
  #define MPP_BUFFER_ORDER      3
  #endif
  
+ static int dynamic_mt_modes = 6;
+ module_param(dynamic_mt_modes, int, S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(dynamic_mt_modes, "Set of allowed dynamic micro-threading modes: 0 (= none), 2, 4, or 6 (= 2 or 4)");
+ static int target_smt_mode;
+ module_param(target_smt_mode, int, S_IRUGO | S_IWUSR);
+ MODULE_PARM_DESC(target_smt_mode, "Target threads per core (0 = max)");
  
  static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
  static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu);
@@@ -114,7 -120,7 +120,7 @@@ static bool kvmppc_ipi_thread(int cpu
  
  static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu)
  {
-       int cpu = vcpu->cpu;
+       int cpu;
        wait_queue_head_t *wqp;
  
        wqp = kvm_arch_vcpu_wq(vcpu);
                ++vcpu->stat.halt_wakeup;
        }
  
-       if (kvmppc_ipi_thread(cpu + vcpu->arch.ptid))
+       if (kvmppc_ipi_thread(vcpu->arch.thread_cpu))
                return;
  
        /* CPU points to the first thread of the core */
+       cpu = vcpu->cpu;
        if (cpu >= 0 && cpu < nr_cpu_ids && cpu_online(cpu))
                smp_send_reschedule(cpu);
  }
   * they should never fail.)
   */
  
+ static void kvmppc_core_start_stolen(struct kvmppc_vcore *vc)
+ {
+       unsigned long flags;
+       spin_lock_irqsave(&vc->stoltb_lock, flags);
+       vc->preempt_tb = mftb();
+       spin_unlock_irqrestore(&vc->stoltb_lock, flags);
+ }
+ static void kvmppc_core_end_stolen(struct kvmppc_vcore *vc)
+ {
+       unsigned long flags;
+       spin_lock_irqsave(&vc->stoltb_lock, flags);
+       if (vc->preempt_tb != TB_NIL) {
+               vc->stolen_tb += mftb() - vc->preempt_tb;
+               vc->preempt_tb = TB_NIL;
+       }
+       spin_unlock_irqrestore(&vc->stoltb_lock, flags);
+ }
  static void kvmppc_core_vcpu_load_hv(struct kvm_vcpu *vcpu, int cpu)
  {
        struct kvmppc_vcore *vc = vcpu->arch.vcore;
         * vcpu, and once it is set to this vcpu, only this task
         * ever sets it to NULL.
         */
-       if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE) {
-               spin_lock_irqsave(&vc->stoltb_lock, flags);
-               if (vc->preempt_tb != TB_NIL) {
-                       vc->stolen_tb += mftb() - vc->preempt_tb;
-                       vc->preempt_tb = TB_NIL;
-               }
-               spin_unlock_irqrestore(&vc->stoltb_lock, flags);
-       }
+       if (vc->runner == vcpu && vc->vcore_state >= VCORE_SLEEPING)
+               kvmppc_core_end_stolen(vc);
        spin_lock_irqsave(&vcpu->arch.tbacct_lock, flags);
        if (vcpu->arch.state == KVMPPC_VCPU_BUSY_IN_HOST &&
            vcpu->arch.busy_preempt != TB_NIL) {
@@@ -197,11 -220,9 +220,9 @@@ static void kvmppc_core_vcpu_put_hv(str
        struct kvmppc_vcore *vc = vcpu->arch.vcore;
        unsigned long flags;
  
-       if (vc->runner == vcpu && vc->vcore_state != VCORE_INACTIVE) {
-               spin_lock_irqsave(&vc->stoltb_lock, flags);
-               vc->preempt_tb = mftb();
-               spin_unlock_irqrestore(&vc->stoltb_lock, flags);
-       }
+       if (vc->runner == vcpu && vc->vcore_state >= VCORE_SLEEPING)
+               kvmppc_core_start_stolen(vc);
        spin_lock_irqsave(&vcpu->arch.tbacct_lock, flags);
        if (vcpu->arch.state == KVMPPC_VCPU_BUSY_IN_HOST)
                vcpu->arch.busy_preempt = mftb();
@@@ -214,12 -235,12 +235,12 @@@ static void kvmppc_set_msr_hv(struct kv
        kvmppc_end_cede(vcpu);
  }
  
- void kvmppc_set_pvr_hv(struct kvm_vcpu *vcpu, u32 pvr)
static void kvmppc_set_pvr_hv(struct kvm_vcpu *vcpu, u32 pvr)
  {
        vcpu->arch.pvr = pvr;
  }
  
- int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
  {
        unsigned long pcr = 0;
        struct kvmppc_vcore *vc = vcpu->arch.vcore;
        return 0;
  }
  
- void kvmppc_dump_regs(struct kvm_vcpu *vcpu)
static void kvmppc_dump_regs(struct kvm_vcpu *vcpu)
  {
        int r;
  
               vcpu->arch.last_inst);
  }
  
- struct kvm_vcpu *kvmppc_find_vcpu(struct kvm *kvm, int id)
+ static struct kvm_vcpu *kvmppc_find_vcpu(struct kvm *kvm, int id)
  {
        int r;
        struct kvm_vcpu *v, *ret = NULL;
@@@ -641,7 -662,8 +662,8 @@@ static int kvm_arch_vcpu_yield_to(struc
  
        spin_lock(&vcore->lock);
        if (target->arch.state == KVMPPC_VCPU_RUNNABLE &&
-           vcore->vcore_state != VCORE_INACTIVE)
+           vcore->vcore_state != VCORE_INACTIVE &&
+           vcore->runner)
                target = vcore->runner;
        spin_unlock(&vcore->lock);
  
@@@ -1431,6 -1453,7 +1453,7 @@@ static struct kvmppc_vcore *kvmppc_vcor
        vcore->lpcr = kvm->arch.lpcr;
        vcore->first_vcpuid = core * threads_per_subcore;
        vcore->kvm = kvm;
+       INIT_LIST_HEAD(&vcore->preempt_list);
  
        vcore->mpp_buffer_is_valid = false;
  
@@@ -1655,6 -1678,7 +1678,7 @@@ static struct kvm_vcpu *kvmppc_core_vcp
        spin_unlock(&vcore->lock);
        vcpu->arch.vcore = vcore;
        vcpu->arch.ptid = vcpu->vcpu_id - vcore->first_vcpuid;
+       vcpu->arch.thread_cpu = -1;
  
        vcpu->arch.cpu_type = KVM_CPU_3S_64;
        kvmppc_sanity_check(vcpu);
@@@ -1749,6 -1773,7 +1773,7 @@@ static int kvmppc_grab_hwthread(int cpu
  
        /* Ensure the thread won't go into the kernel if it wakes */
        tpaca->kvm_hstate.kvm_vcpu = NULL;
+       tpaca->kvm_hstate.kvm_vcore = NULL;
        tpaca->kvm_hstate.napping = 0;
        smp_wmb();
        tpaca->kvm_hstate.hwthread_req = 1;
@@@ -1780,26 -1805,32 +1805,32 @@@ static void kvmppc_release_hwthread(in
        tpaca = &paca[cpu];
        tpaca->kvm_hstate.hwthread_req = 0;
        tpaca->kvm_hstate.kvm_vcpu = NULL;
+       tpaca->kvm_hstate.kvm_vcore = NULL;
+       tpaca->kvm_hstate.kvm_split_mode = NULL;
  }
  
- static void kvmppc_start_thread(struct kvm_vcpu *vcpu)
+ static void kvmppc_start_thread(struct kvm_vcpu *vcpu, struct kvmppc_vcore *vc)
  {
        int cpu;
        struct paca_struct *tpaca;
-       struct kvmppc_vcore *vc = vcpu->arch.vcore;
+       struct kvmppc_vcore *mvc = vc->master_vcore;
  
-       if (vcpu->arch.timer_running) {
-               hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
-               vcpu->arch.timer_running = 0;
+       cpu = vc->pcpu;
+       if (vcpu) {
+               if (vcpu->arch.timer_running) {
+                       hrtimer_try_to_cancel(&vcpu->arch.dec_timer);
+                       vcpu->arch.timer_running = 0;
+               }
+               cpu += vcpu->arch.ptid;
+               vcpu->cpu = mvc->pcpu;
+               vcpu->arch.thread_cpu = cpu;
        }
-       cpu = vc->pcpu + vcpu->arch.ptid;
        tpaca = &paca[cpu];
-       tpaca->kvm_hstate.kvm_vcore = vc;
-       tpaca->kvm_hstate.ptid = vcpu->arch.ptid;
-       vcpu->cpu = vc->pcpu;
-       /* Order stores to hstate.kvm_vcore etc. before store to kvm_vcpu */
-       smp_wmb();
        tpaca->kvm_hstate.kvm_vcpu = vcpu;
+       tpaca->kvm_hstate.ptid = cpu - mvc->pcpu;
+       /* Order stores to hstate.kvm_vcpu etc. before store to kvm_vcore */
+       smp_wmb();
+       tpaca->kvm_hstate.kvm_vcore = mvc;
        if (cpu != smp_processor_id())
                kvmppc_ipi_thread(cpu);
  }
@@@ -1812,12 -1843,12 +1843,12 @@@ static void kvmppc_wait_for_nap(void
        for (loops = 0; loops < 1000000; ++loops) {
                /*
                 * Check if all threads are finished.
-                * We set the vcpu pointer when starting a thread
+                * We set the vcore pointer when starting a thread
                 * and the thread clears it when finished, so we look
-                * for any threads that still have a non-NULL vcpu ptr.
+                * for any threads that still have a non-NULL vcore ptr.
                 */
                for (i = 1; i < threads_per_subcore; ++i)
-                       if (paca[cpu + i].kvm_hstate.kvm_vcpu)
+                       if (paca[cpu + i].kvm_hstate.kvm_vcore)
                                break;
                if (i == threads_per_subcore) {
                        HMT_medium();
        }
        HMT_medium();
        for (i = 1; i < threads_per_subcore; ++i)
-               if (paca[cpu + i].kvm_hstate.kvm_vcpu)
+               if (paca[cpu + i].kvm_hstate.kvm_vcore)
                        pr_err("KVM: CPU %d seems to be stuck\n", cpu + i);
  }
  
@@@ -1890,6 -1921,278 +1921,278 @@@ static void kvmppc_start_restoring_l2_c
        mtspr(SPRN_MPPR, mpp_addr | PPC_MPPR_FETCH_WHOLE_TABLE);
  }
  
+ /*
+  * A list of virtual cores for each physical CPU.
+  * These are vcores that could run but their runner VCPU tasks are
+  * (or may be) preempted.
+  */
+ struct preempted_vcore_list {
+       struct list_head        list;
+       spinlock_t              lock;
+ };
+ static DEFINE_PER_CPU(struct preempted_vcore_list, preempted_vcores);
+ static void init_vcore_lists(void)
+ {
+       int cpu;
+       for_each_possible_cpu(cpu) {
+               struct preempted_vcore_list *lp = &per_cpu(preempted_vcores, cpu);
+               spin_lock_init(&lp->lock);
+               INIT_LIST_HEAD(&lp->list);
+       }
+ }
+ static void kvmppc_vcore_preempt(struct kvmppc_vcore *vc)
+ {
+       struct preempted_vcore_list *lp = this_cpu_ptr(&preempted_vcores);
+       vc->vcore_state = VCORE_PREEMPT;
+       vc->pcpu = smp_processor_id();
+       if (vc->num_threads < threads_per_subcore) {
+               spin_lock(&lp->lock);
+               list_add_tail(&vc->preempt_list, &lp->list);
+               spin_unlock(&lp->lock);
+       }
+       /* Start accumulating stolen time */
+       kvmppc_core_start_stolen(vc);
+ }
+ static void kvmppc_vcore_end_preempt(struct kvmppc_vcore *vc)
+ {
+       struct preempted_vcore_list *lp;
+       kvmppc_core_end_stolen(vc);
+       if (!list_empty(&vc->preempt_list)) {
+               lp = &per_cpu(preempted_vcores, vc->pcpu);
+               spin_lock(&lp->lock);
+               list_del_init(&vc->preempt_list);
+               spin_unlock(&lp->lock);
+       }
+       vc->vcore_state = VCORE_INACTIVE;
+ }
+ /*
+  * This stores information about the virtual cores currently
+  * assigned to a physical core.
+  */
+ struct core_info {
+       int             n_subcores;
+       int             max_subcore_threads;
+       int             total_threads;
+       int             subcore_threads[MAX_SUBCORES];
+       struct kvm      *subcore_vm[MAX_SUBCORES];
+       struct list_head vcs[MAX_SUBCORES];
+ };
+ /*
+  * This mapping means subcores 0 and 1 can use threads 0-3 and 4-7
+  * respectively in 2-way micro-threading (split-core) mode.
+  */
+ static int subcore_thread_map[MAX_SUBCORES] = { 0, 4, 2, 6 };
+ static void init_core_info(struct core_info *cip, struct kvmppc_vcore *vc)
+ {
+       int sub;
+       memset(cip, 0, sizeof(*cip));
+       cip->n_subcores = 1;
+       cip->max_subcore_threads = vc->num_threads;
+       cip->total_threads = vc->num_threads;
+       cip->subcore_threads[0] = vc->num_threads;
+       cip->subcore_vm[0] = vc->kvm;
+       for (sub = 0; sub < MAX_SUBCORES; ++sub)
+               INIT_LIST_HEAD(&cip->vcs[sub]);
+       list_add_tail(&vc->preempt_list, &cip->vcs[0]);
+ }
+ static bool subcore_config_ok(int n_subcores, int n_threads)
+ {
+       /* Can only dynamically split if unsplit to begin with */
+       if (n_subcores > 1 && threads_per_subcore < MAX_SMT_THREADS)
+               return false;
+       if (n_subcores > MAX_SUBCORES)
+               return false;
+       if (n_subcores > 1) {
+               if (!(dynamic_mt_modes & 2))
+                       n_subcores = 4;
+               if (n_subcores > 2 && !(dynamic_mt_modes & 4))
+                       return false;
+       }
+       return n_subcores * roundup_pow_of_two(n_threads) <= MAX_SMT_THREADS;
+ }
+ static void init_master_vcore(struct kvmppc_vcore *vc)
+ {
+       vc->master_vcore = vc;
+       vc->entry_exit_map = 0;
+       vc->in_guest = 0;
+       vc->napping_threads = 0;
+       vc->conferring_threads = 0;
+ }
+ /*
+  * See if the existing subcores can be split into 3 (or fewer) subcores
+  * of at most two threads each, so we can fit in another vcore.  This
+  * assumes there are at most two subcores and at most 6 threads in total.
+  */
+ static bool can_split_piggybacked_subcores(struct core_info *cip)
+ {
+       int sub, new_sub;
+       int large_sub = -1;
+       int thr;
+       int n_subcores = cip->n_subcores;
+       struct kvmppc_vcore *vc, *vcnext;
+       struct kvmppc_vcore *master_vc = NULL;
+       for (sub = 0; sub < cip->n_subcores; ++sub) {
+               if (cip->subcore_threads[sub] <= 2)
+                       continue;
+               if (large_sub >= 0)
+                       return false;
+               large_sub = sub;
+               vc = list_first_entry(&cip->vcs[sub], struct kvmppc_vcore,
+                                     preempt_list);
+               if (vc->num_threads > 2)
+                       return false;
+               n_subcores += (cip->subcore_threads[sub] - 1) >> 1;
+       }
+       if (n_subcores > 3 || large_sub < 0)
+               return false;
+       /*
+        * Seems feasible, so go through and move vcores to new subcores.
+        * Note that when we have two or more vcores in one subcore,
+        * all those vcores must have only one thread each.
+        */
+       new_sub = cip->n_subcores;
+       thr = 0;
+       sub = large_sub;
+       list_for_each_entry_safe(vc, vcnext, &cip->vcs[sub], preempt_list) {
+               if (thr >= 2) {
+                       list_del(&vc->preempt_list);
+                       list_add_tail(&vc->preempt_list, &cip->vcs[new_sub]);
+                       /* vc->num_threads must be 1 */
+                       if (++cip->subcore_threads[new_sub] == 1) {
+                               cip->subcore_vm[new_sub] = vc->kvm;
+                               init_master_vcore(vc);
+                               master_vc = vc;
+                               ++cip->n_subcores;
+                       } else {
+                               vc->master_vcore = master_vc;
+                               ++new_sub;
+                       }
+               }
+               thr += vc->num_threads;
+       }
+       cip->subcore_threads[large_sub] = 2;
+       cip->max_subcore_threads = 2;
+       return true;
+ }
+ static bool can_dynamic_split(struct kvmppc_vcore *vc, struct core_info *cip)
+ {
+       int n_threads = vc->num_threads;
+       int sub;
+       if (!cpu_has_feature(CPU_FTR_ARCH_207S))
+               return false;
+       if (n_threads < cip->max_subcore_threads)
+               n_threads = cip->max_subcore_threads;
+       if (subcore_config_ok(cip->n_subcores + 1, n_threads)) {
+               cip->max_subcore_threads = n_threads;
+       } else if (cip->n_subcores <= 2 && cip->total_threads <= 6 &&
+                  vc->num_threads <= 2) {
+               /*
+                * We may be able to fit another subcore in by
+                * splitting an existing subcore with 3 or 4
+                * threads into two 2-thread subcores, or one
+                * with 5 or 6 threads into three subcores.
+                * We can only do this if those subcores have
+                * piggybacked virtual cores.
+                */
+               if (!can_split_piggybacked_subcores(cip))
+                       return false;
+       } else {
+               return false;
+       }
+       sub = cip->n_subcores;
+       ++cip->n_subcores;
+       cip->total_threads += vc->num_threads;
+       cip->subcore_threads[sub] = vc->num_threads;
+       cip->subcore_vm[sub] = vc->kvm;
+       init_master_vcore(vc);
+       list_del(&vc->preempt_list);
+       list_add_tail(&vc->preempt_list, &cip->vcs[sub]);
+       return true;
+ }
+ static bool can_piggyback_subcore(struct kvmppc_vcore *pvc,
+                                 struct core_info *cip, int sub)
+ {
+       struct kvmppc_vcore *vc;
+       int n_thr;
+       vc = list_first_entry(&cip->vcs[sub], struct kvmppc_vcore,
+                             preempt_list);
+       /* require same VM and same per-core reg values */
+       if (pvc->kvm != vc->kvm ||
+           pvc->tb_offset != vc->tb_offset ||
+           pvc->pcr != vc->pcr ||
+           pvc->lpcr != vc->lpcr)
+               return false;
+       /* P8 guest with > 1 thread per core would see wrong TIR value */
+       if (cpu_has_feature(CPU_FTR_ARCH_207S) &&
+           (vc->num_threads > 1 || pvc->num_threads > 1))
+               return false;
+       n_thr = cip->subcore_threads[sub] + pvc->num_threads;
+       if (n_thr > cip->max_subcore_threads) {
+               if (!subcore_config_ok(cip->n_subcores, n_thr))
+                       return false;
+               cip->max_subcore_threads = n_thr;
+       }
+       cip->total_threads += pvc->num_threads;
+       cip->subcore_threads[sub] = n_thr;
+       pvc->master_vcore = vc;
+       list_del(&pvc->preempt_list);
+       list_add_tail(&pvc->preempt_list, &cip->vcs[sub]);
+       return true;
+ }
+ /*
+  * Work out whether it is possible to piggyback the execution of
+  * vcore *pvc onto the execution of the other vcores described in *cip.
+  */
+ static bool can_piggyback(struct kvmppc_vcore *pvc, struct core_info *cip,
+                         int target_threads)
+ {
+       int sub;
+       if (cip->total_threads + pvc->num_threads > target_threads)
+               return false;
+       for (sub = 0; sub < cip->n_subcores; ++sub)
+               if (cip->subcore_threads[sub] &&
+                   can_piggyback_subcore(pvc, cip, sub))
+                       return true;
+       if (can_dynamic_split(pvc, cip))
+               return true;
+       return false;
+ }
  static void prepare_threads(struct kvmppc_vcore *vc)
  {
        struct kvm_vcpu *vcpu, *vnext;
        }
  }
  
- static void post_guest_process(struct kvmppc_vcore *vc)
+ static void collect_piggybacks(struct core_info *cip, int target_threads)
+ {
+       struct preempted_vcore_list *lp = this_cpu_ptr(&preempted_vcores);
+       struct kvmppc_vcore *pvc, *vcnext;
+       spin_lock(&lp->lock);
+       list_for_each_entry_safe(pvc, vcnext, &lp->list, preempt_list) {
+               if (!spin_trylock(&pvc->lock))
+                       continue;
+               prepare_threads(pvc);
+               if (!pvc->n_runnable) {
+                       list_del_init(&pvc->preempt_list);
+                       if (pvc->runner == NULL) {
+                               pvc->vcore_state = VCORE_INACTIVE;
+                               kvmppc_core_end_stolen(pvc);
+                       }
+                       spin_unlock(&pvc->lock);
+                       continue;
+               }
+               if (!can_piggyback(pvc, cip, target_threads)) {
+                       spin_unlock(&pvc->lock);
+                       continue;
+               }
+               kvmppc_core_end_stolen(pvc);
+               pvc->vcore_state = VCORE_PIGGYBACK;
+               if (cip->total_threads >= target_threads)
+                       break;
+       }
+       spin_unlock(&lp->lock);
+ }
+ static void post_guest_process(struct kvmppc_vcore *vc, bool is_master)
  {
+       int still_running = 0;
        u64 now;
        long ret;
        struct kvm_vcpu *vcpu, *vnext;
  
+       spin_lock(&vc->lock);
        now = get_tb();
        list_for_each_entry_safe(vcpu, vnext, &vc->runnable_threads,
                                 arch.run_list) {
                vcpu->arch.ret = ret;
                vcpu->arch.trap = 0;
  
-               if (vcpu->arch.ceded) {
-                       if (!is_kvmppc_resume_guest(ret))
-                               kvmppc_end_cede(vcpu);
-                       else
+               if (is_kvmppc_resume_guest(vcpu->arch.ret)) {
+                       if (vcpu->arch.pending_exceptions)
+                               kvmppc_core_prepare_to_enter(vcpu);
+                       if (vcpu->arch.ceded)
                                kvmppc_set_timer(vcpu);
-               }
-               if (!is_kvmppc_resume_guest(vcpu->arch.ret)) {
+                       else
+                               ++still_running;
+               } else {
                        kvmppc_remove_runnable(vc, vcpu);
                        wake_up(&vcpu->arch.cpu_run);
                }
        }
+       list_del_init(&vc->preempt_list);
+       if (!is_master) {
+               if (still_running > 0) {
+                       kvmppc_vcore_preempt(vc);
+               } else if (vc->runner) {
+                       vc->vcore_state = VCORE_PREEMPT;
+                       kvmppc_core_start_stolen(vc);
+               } else {
+                       vc->vcore_state = VCORE_INACTIVE;
+               }
+               if (vc->n_runnable > 0 && vc->runner == NULL) {
+                       /* make sure there's a candidate runner awake */
+                       vcpu = list_first_entry(&vc->runnable_threads,
+                                               struct kvm_vcpu, arch.run_list);
+                       wake_up(&vcpu->arch.cpu_run);
+               }
+       }
+       spin_unlock(&vc->lock);
  }
  
  /*
@@@ -1955,6 -2310,15 +2310,15 @@@ static noinline void kvmppc_run_core(st
        struct kvm_vcpu *vcpu, *vnext;
        int i;
        int srcu_idx;
+       struct core_info core_info;
+       struct kvmppc_vcore *pvc, *vcnext;
+       struct kvm_split_mode split_info, *sip;
+       int split, subcore_size, active;
+       int sub;
+       bool thr0_done;
+       unsigned long cmd_bit, stat_bit;
+       int pcpu, thr;
+       int target_threads;
  
        /*
         * Remove from the list any threads that have a signal pending
        /*
         * Initialize *vc.
         */
-       vc->entry_exit_map = 0;
+       init_master_vcore(vc);
        vc->preempt_tb = TB_NIL;
-       vc->in_guest = 0;
-       vc->napping_threads = 0;
-       vc->conferring_threads = 0;
  
        /*
         * Make sure we are running on primary threads, and that secondary
                goto out;
        }
  
+       /*
+        * See if we could run any other vcores on the physical core
+        * along with this one.
+        */
+       init_core_info(&core_info, vc);
+       pcpu = smp_processor_id();
+       target_threads = threads_per_subcore;
+       if (target_smt_mode && target_smt_mode < target_threads)
+               target_threads = target_smt_mode;
+       if (vc->num_threads < target_threads)
+               collect_piggybacks(&core_info, target_threads);
+       /* Decide on micro-threading (split-core) mode */
+       subcore_size = threads_per_subcore;
+       cmd_bit = stat_bit = 0;
+       split = core_info.n_subcores;
+       sip = NULL;
+       if (split > 1) {
+               /* threads_per_subcore must be MAX_SMT_THREADS (8) here */
+               if (split == 2 && (dynamic_mt_modes & 2)) {
+                       cmd_bit = HID0_POWER8_1TO2LPAR;
+                       stat_bit = HID0_POWER8_2LPARMODE;
+               } else {
+                       split = 4;
+                       cmd_bit = HID0_POWER8_1TO4LPAR;
+                       stat_bit = HID0_POWER8_4LPARMODE;
+               }
+               subcore_size = MAX_SMT_THREADS / split;
+               sip = &split_info;
+               memset(&split_info, 0, sizeof(split_info));
+               split_info.rpr = mfspr(SPRN_RPR);
+               split_info.pmmar = mfspr(SPRN_PMMAR);
+               split_info.ldbar = mfspr(SPRN_LDBAR);
+               split_info.subcore_size = subcore_size;
+               for (sub = 0; sub < core_info.n_subcores; ++sub)
+                       split_info.master_vcs[sub] =
+                               list_first_entry(&core_info.vcs[sub],
+                                       struct kvmppc_vcore, preempt_list);
+               /* order writes to split_info before kvm_split_mode pointer */
+               smp_wmb();
+       }
+       pcpu = smp_processor_id();
+       for (thr = 0; thr < threads_per_subcore; ++thr)
+               paca[pcpu + thr].kvm_hstate.kvm_split_mode = sip;
+       /* Initiate micro-threading (split-core) if required */
+       if (cmd_bit) {
+               unsigned long hid0 = mfspr(SPRN_HID0);
+               hid0 |= cmd_bit | HID0_POWER8_DYNLPARDIS;
+               mb();
+               mtspr(SPRN_HID0, hid0);
+               isync();
+               for (;;) {
+                       hid0 = mfspr(SPRN_HID0);
+                       if (hid0 & stat_bit)
+                               break;
+                       cpu_relax();
+               }
+       }
  
-       vc->pcpu = smp_processor_id();
-       list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) {
-               kvmppc_start_thread(vcpu);
-               kvmppc_create_dtl_entry(vcpu, vc);
-               trace_kvm_guest_enter(vcpu);
+       /* Start all the threads */
+       active = 0;
+       for (sub = 0; sub < core_info.n_subcores; ++sub) {
+               thr = subcore_thread_map[sub];
+               thr0_done = false;
+               active |= 1 << thr;
+               list_for_each_entry(pvc, &core_info.vcs[sub], preempt_list) {
+                       pvc->pcpu = pcpu + thr;
+                       list_for_each_entry(vcpu, &pvc->runnable_threads,
+                                           arch.run_list) {
+                               kvmppc_start_thread(vcpu, pvc);
+                               kvmppc_create_dtl_entry(vcpu, pvc);
+                               trace_kvm_guest_enter(vcpu);
+                               if (!vcpu->arch.ptid)
+                                       thr0_done = true;
+                               active |= 1 << (thr + vcpu->arch.ptid);
+                       }
+                       /*
+                        * We need to start the first thread of each subcore
+                        * even if it doesn't have a vcpu.
+                        */
+                       if (pvc->master_vcore == pvc && !thr0_done)
+                               kvmppc_start_thread(NULL, pvc);
+                       thr += pvc->num_threads;
+               }
        }
  
-       /* Set this explicitly in case thread 0 doesn't have a vcpu */
-       get_paca()->kvm_hstate.kvm_vcore = vc;
-       get_paca()->kvm_hstate.ptid = 0;
+       /*
+        * Ensure that split_info.do_nap is set after setting
+        * the vcore pointer in the PACA of the secondaries.
+        */
+       smp_mb();
+       if (cmd_bit)
+               split_info.do_nap = 1;  /* ask secondaries to nap when done */
+       /*
+        * When doing micro-threading, poke the inactive threads as well.
+        * This gets them to the nap instruction after kvm_do_nap,
+        * which reduces the time taken to unsplit later.
+        */
+       if (split > 1)
+               for (thr = 1; thr < threads_per_subcore; ++thr)
+                       if (!(active & (1 << thr)))
+                               kvmppc_ipi_thread(pcpu + thr);
  
        vc->vcore_state = VCORE_RUNNING;
        preempt_disable();
  
        trace_kvmppc_run_core(vc, 0);
  
-       spin_unlock(&vc->lock);
+       for (sub = 0; sub < core_info.n_subcores; ++sub)
+               list_for_each_entry(pvc, &core_info.vcs[sub], preempt_list)
+                       spin_unlock(&pvc->lock);
  
        kvm_guest_enter();
  
  
        __kvmppc_vcore_entry();
  
-       spin_lock(&vc->lock);
        if (vc->mpp_buffer)
                kvmppc_start_saving_l2_cache(vc);
  
-       /* disable sending of IPIs on virtual external irqs */
-       list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list)
-               vcpu->cpu = -1;
-       /* wait for secondary threads to finish writing their state to memory */
-       kvmppc_wait_for_nap();
-       for (i = 0; i < threads_per_subcore; ++i)
-               kvmppc_release_hwthread(vc->pcpu + i);
+       srcu_read_unlock(&vc->kvm->srcu, srcu_idx);
+       spin_lock(&vc->lock);
        /* prevent other vcpu threads from doing kvmppc_start_thread() now */
        vc->vcore_state = VCORE_EXITING;
-       spin_unlock(&vc->lock);
  
-       srcu_read_unlock(&vc->kvm->srcu, srcu_idx);
+       /* wait for secondary threads to finish writing their state to memory */
+       kvmppc_wait_for_nap();
+       /* Return to whole-core mode if we split the core earlier */
+       if (split > 1) {
+               unsigned long hid0 = mfspr(SPRN_HID0);
+               unsigned long loops = 0;
+               hid0 &= ~HID0_POWER8_DYNLPARDIS;
+               stat_bit = HID0_POWER8_2LPARMODE | HID0_POWER8_4LPARMODE;
+               mb();
+               mtspr(SPRN_HID0, hid0);
+               isync();
+               for (;;) {
+                       hid0 = mfspr(SPRN_HID0);
+                       if (!(hid0 & stat_bit))
+                               break;
+                       cpu_relax();
+                       ++loops;
+               }
+               split_info.do_nap = 0;
+       }
+       /* Let secondaries go back to the offline loop */
+       for (i = 0; i < threads_per_subcore; ++i) {
+               kvmppc_release_hwthread(pcpu + i);
+               if (sip && sip->napped[i])
+                       kvmppc_ipi_thread(pcpu + i);
+       }
+       spin_unlock(&vc->lock);
  
        /* make sure updates to secondary vcpu structs are visible now */
        smp_mb();
        kvm_guest_exit();
  
-       preempt_enable();
+       for (sub = 0; sub < core_info.n_subcores; ++sub)
+               list_for_each_entry_safe(pvc, vcnext, &core_info.vcs[sub],
+                                        preempt_list)
+                       post_guest_process(pvc, pvc == vc);
  
        spin_lock(&vc->lock);
-       post_guest_process(vc);
+       preempt_enable();
  
   out:
        vc->vcore_state = VCORE_INACTIVE;
   * Wait for some other vcpu thread to execute us, and
   * wake us up when we need to handle something in the host.
   */
- static void kvmppc_wait_for_exec(struct kvm_vcpu *vcpu, int wait_state)
+ static void kvmppc_wait_for_exec(struct kvmppc_vcore *vc,
+                                struct kvm_vcpu *vcpu, int wait_state)
  {
        DEFINE_WAIT(wait);
  
        prepare_to_wait(&vcpu->arch.cpu_run, &wait, wait_state);
-       if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE)
+       if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE) {
+               spin_unlock(&vc->lock);
                schedule();
+               spin_lock(&vc->lock);
+       }
        finish_wait(&vcpu->arch.cpu_run, &wait);
  }
  
@@@ -2137,9 -2624,21 +2624,21 @@@ static int kvmppc_run_vcpu(struct kvm_r
         * this thread straight away and have it join in.
         */
        if (!signal_pending(current)) {
-               if (vc->vcore_state == VCORE_RUNNING && !VCORE_IS_EXITING(vc)) {
+               if (vc->vcore_state == VCORE_PIGGYBACK) {
+                       struct kvmppc_vcore *mvc = vc->master_vcore;
+                       if (spin_trylock(&mvc->lock)) {
+                               if (mvc->vcore_state == VCORE_RUNNING &&
+                                   !VCORE_IS_EXITING(mvc)) {
+                                       kvmppc_create_dtl_entry(vcpu, vc);
+                                       kvmppc_start_thread(vcpu, vc);
+                                       trace_kvm_guest_enter(vcpu);
+                               }
+                               spin_unlock(&mvc->lock);
+                       }
+               } else if (vc->vcore_state == VCORE_RUNNING &&
+                          !VCORE_IS_EXITING(vc)) {
                        kvmppc_create_dtl_entry(vcpu, vc);
-                       kvmppc_start_thread(vcpu);
+                       kvmppc_start_thread(vcpu, vc);
                        trace_kvm_guest_enter(vcpu);
                } else if (vc->vcore_state == VCORE_SLEEPING) {
                        wake_up(&vc->wq);
  
        while (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE &&
               !signal_pending(current)) {
+               if (vc->vcore_state == VCORE_PREEMPT && vc->runner == NULL)
+                       kvmppc_vcore_end_preempt(vc);
                if (vc->vcore_state != VCORE_INACTIVE) {
-                       spin_unlock(&vc->lock);
-                       kvmppc_wait_for_exec(vcpu, TASK_INTERRUPTIBLE);
-                       spin_lock(&vc->lock);
+                       kvmppc_wait_for_exec(vc, vcpu, TASK_INTERRUPTIBLE);
                        continue;
                }
                list_for_each_entry_safe(v, vn, &vc->runnable_threads,
                vc->runner = vcpu;
                if (n_ceded == vc->n_runnable) {
                        kvmppc_vcore_blocked(vc);
 -              } else if (should_resched()) {
 +              } else if (need_resched()) {
-                       vc->vcore_state = VCORE_PREEMPT;
+                       kvmppc_vcore_preempt(vc);
                        /* Let something else run */
                        cond_resched_lock(&vc->lock);
-                       vc->vcore_state = VCORE_INACTIVE;
+                       if (vc->vcore_state == VCORE_PREEMPT)
+                               kvmppc_vcore_end_preempt(vc);
                } else {
                        kvmppc_run_core(vc);
                }
  
        while (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE &&
               (vc->vcore_state == VCORE_RUNNING ||
-               vc->vcore_state == VCORE_EXITING)) {
-               spin_unlock(&vc->lock);
-               kvmppc_wait_for_exec(vcpu, TASK_UNINTERRUPTIBLE);
-               spin_lock(&vc->lock);
-       }
+               vc->vcore_state == VCORE_EXITING))
+               kvmppc_wait_for_exec(vc, vcpu, TASK_UNINTERRUPTIBLE);
  
        if (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE) {
                kvmppc_remove_runnable(vc, vcpu);
@@@ -2755,6 -3253,8 +3253,8 @@@ static int kvmppc_book3s_init_hv(void
  
        init_default_hcalls();
  
+       init_vcore_lists();
        r = kvmppc_mmu_hv_init();
        return r;
  }
diff --combined arch/x86/kvm/x86.c
index 1e7e76e14e8927ea3c909e4d83e879d63b90a815,13728dbdbb5604ef5ce942e680ac1ac51c73d0c6..a60bdbccff5189b5a98b9a7fcc6a3b9f7ff5eeec
@@@ -1441,8 -1441,20 +1441,8 @@@ EXPORT_SYMBOL_GPL(kvm_write_tsc)
  
  static cycle_t read_tsc(void)
  {
 -      cycle_t ret;
 -      u64 last;
 -
 -      /*
 -       * Empirically, a fence (of type that depends on the CPU)
 -       * before rdtsc is enough to ensure that rdtsc is ordered
 -       * with respect to loads.  The various CPU manuals are unclear
 -       * as to whether rdtsc can be reordered with later loads,
 -       * but no one has ever seen it happen.
 -       */
 -      rdtsc_barrier();
 -      ret = (cycle_t)vget_cycles();
 -
 -      last = pvclock_gtod_data.clock.cycle_last;
 +      cycle_t ret = (cycle_t)rdtsc_ordered();
 +      u64 last = pvclock_gtod_data.clock.cycle_last;
  
        if (likely(ret >= last))
                return ret;
@@@ -1631,7 -1643,7 +1631,7 @@@ static int kvm_guest_time_update(struc
                return 1;
        }
        if (!use_master_clock) {
 -              host_tsc = native_read_tsc();
 +              host_tsc = rdtsc();
                kernel_ns = get_kernel_ns();
        }
  
@@@ -1973,7 -1985,7 +1973,7 @@@ int kvm_set_msr_common(struct kvm_vcpu 
                if (guest_cpuid_has_tsc_adjust(vcpu)) {
                        if (!msr_info->host_initiated) {
                                s64 adj = data - vcpu->arch.ia32_tsc_adjust_msr;
 -                              kvm_x86_ops->adjust_tsc_offset(vcpu, adj, true);
 +                              adjust_tsc_offset_guest(vcpu, adj);
                        }
                        vcpu->arch.ia32_tsc_adjust_msr = data;
                }
@@@ -2608,7 -2620,7 +2608,7 @@@ void kvm_arch_vcpu_load(struct kvm_vcp
  
        if (unlikely(vcpu->cpu != cpu) || check_tsc_unstable()) {
                s64 tsc_delta = !vcpu->arch.last_host_tsc ? 0 :
 -                              native_read_tsc() - vcpu->arch.last_host_tsc;
 +                              rdtsc() - vcpu->arch.last_host_tsc;
                if (tsc_delta < 0)
                        mark_tsc_unstable("KVM discovered backwards TSC");
                if (check_tsc_unstable()) {
@@@ -2636,7 -2648,7 +2636,7 @@@ void kvm_arch_vcpu_put(struct kvm_vcpu 
  {
        kvm_x86_ops->vcpu_put(vcpu);
        kvm_put_guest_fpu(vcpu);
 -      vcpu->arch.last_host_tsc = native_read_tsc();
 +      vcpu->arch.last_host_tsc = rdtsc();
  }
  
  static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
@@@ -5943,6 -5955,7 +5943,7 @@@ static void process_smi_save_seg_32(str
        put_smstate(u32, buf, offset, process_smi_get_segment_flags(&seg));
  }
  
+ #ifdef CONFIG_X86_64
  static void process_smi_save_seg_64(struct kvm_vcpu *vcpu, char *buf, int n)
  {
        struct kvm_segment seg;
        put_smstate(u32, buf, offset + 4, seg.limit);
        put_smstate(u64, buf, offset + 8, seg.base);
  }
+ #endif
  
  static void process_smi_save_state_32(struct kvm_vcpu *vcpu, char *buf)
  {
@@@ -6069,7 -6083,6 +6071,7 @@@ static void process_smi_save_state_64(s
  static void process_smi(struct kvm_vcpu *vcpu)
  {
        struct kvm_segment cs, ds;
 +      struct desc_ptr dt;
        char buf[512];
        u32 cr0;
  
  
        kvm_x86_ops->set_cr4(vcpu, 0);
  
 +      /* Undocumented: IDT limit is set to zero on entry to SMM.  */
 +      dt.address = dt.size = 0;
 +      kvm_x86_ops->set_idt(vcpu, &dt);
 +
        __kvm_set_dr(vcpu, 7, DR7_FIXED_1);
  
        cs.selector = (vcpu->arch.smbase >> 4) & 0xffff;
@@@ -6375,7 -6384,7 +6377,7 @@@ static int vcpu_enter_guest(struct kvm_
                hw_breakpoint_restore();
  
        vcpu->arch.last_guest_tsc = kvm_x86_ops->read_l1_tsc(vcpu,
 -                                                         native_read_tsc());
 +                                                         rdtsc());
  
        vcpu->mode = OUTSIDE_GUEST_MODE;
        smp_wmb();
@@@ -7184,7 -7193,7 +7186,7 @@@ int kvm_arch_hardware_enable(void
        if (ret != 0)
                return ret;
  
 -      local_tsc = native_read_tsc();
 +      local_tsc = rdtsc();
        stable = !check_tsc_unstable();
        list_for_each_entry(kvm, &vm_list, vm_list) {
                kvm_for_each_vcpu(i, vcpu, kvm) {
index 71e4faf33091a114ba666054bc020adaed4a08d5,cf637d65b589b264e482536dfb3d0fc8070c4256..9eeeb9589acfc35baed79a89d7d3f0c1be134cf3
  #define GICR_SYNCR                    0x00C0
  #define GICR_MOVLPIR                  0x0100
  #define GICR_MOVALLR                  0x0110
 +#define GICR_ISACTIVER                        GICD_ISACTIVER
 +#define GICR_ICACTIVER                        GICD_ICACTIVER
  #define GICR_IDREGS                   GICD_IDREGS
  #define GICR_PIDR2                    GICD_PIDR2
  
  
  #define ICH_LR_EOI                    (1UL << 41)
  #define ICH_LR_GROUP                  (1UL << 60)
+ #define ICH_LR_HW                     (1UL << 61)
  #define ICH_LR_STATE                  (3UL << 62)
  #define ICH_LR_PENDING_BIT            (1UL << 62)
  #define ICH_LR_ACTIVE_BIT             (1UL << 63)
+ #define ICH_LR_PHYS_ID_SHIFT          32
+ #define ICH_LR_PHYS_ID_MASK           (0x3ffUL << ICH_LR_PHYS_ID_SHIFT)
  
  #define ICH_MISR_EOI                  (1 << 0)
  #define ICH_MISR_U                    (1 << 1)
  #define ICH_VMCR_PMR_MASK             (0xffUL << ICH_VMCR_PMR_SHIFT)
  
  #define ICC_EOIR1_EL1                 sys_reg(3, 0, 12, 12, 1)
 +#define ICC_DIR_EL1                   sys_reg(3, 0, 12, 11, 1)
  #define ICC_IAR1_EL1                  sys_reg(3, 0, 12, 12, 0)
  #define ICC_SGI1R_EL1                 sys_reg(3, 0, 12, 11, 5)
  #define ICC_PMR_EL1                   sys_reg(3, 0, 4, 6, 0)
  #ifndef __ASSEMBLY__
  
  #include <linux/stringify.h>
 +#include <asm/msi.h>
  
  /*
   * We need a value to serve as a irq-type for LPIs. Choose one that will
@@@ -388,12 -387,6 +391,12 @@@ static inline void gic_write_eoir(u64 i
        isb();
  }
  
 +static inline void gic_write_dir(u64 irq)
 +{
 +      asm volatile("msr_s " __stringify(ICC_DIR_EL1) ", %0" : : "r" (irq));
 +      isb();
 +}
 +
  struct irq_domain;
  int its_cpu_init(void);
  int its_init(struct device_node *node, struct rdists *rdists,
index af3d29f7078117f0b3f260804e419e6e7610d3e5,ca88dad65260233271df3c5a973516d8372f749b..b8901dfd9e9584ba06de5f585f14c6edc9da8fb5
  #define GIC_CPU_ALIAS_BINPOINT                0x1c
  #define GIC_CPU_ACTIVEPRIO            0xd0
  #define GIC_CPU_IDENT                 0xfc
 +#define GIC_CPU_DEACTIVATE            0x1000
  
  #define GICC_ENABLE                   0x1
  #define GICC_INT_PRI_THRESHOLD                0xf0
 +
 +#define GIC_CPU_CTRL_EOImodeNS                (1 << 9)
 +
  #define GICC_IAR_INT_ID_MASK          0x3ff
  #define GICC_INT_SPURIOUS             1023
  #define GICC_DIS_BYPASS_MASK          0x1e0
  
  #define GICH_LR_VIRTUALID             (0x3ff << 0)
  #define GICH_LR_PHYSID_CPUID_SHIFT    (10)
- #define GICH_LR_PHYSID_CPUID          (7 << GICH_LR_PHYSID_CPUID_SHIFT)
+ #define GICH_LR_PHYSID_CPUID          (0x3ff << GICH_LR_PHYSID_CPUID_SHIFT)
  #define GICH_LR_STATE                 (3 << 28)
  #define GICH_LR_PENDING_BIT           (1 << 28)
  #define GICH_LR_ACTIVE_BIT            (1 << 29)
  #define GICH_LR_EOI                   (1 << 19)
+ #define GICH_LR_HW                    (1 << 31)
  
  #define GICH_VMCR_CTRL_SHIFT          0
  #define GICH_VMCR_CTRL_MASK           (0x21f << GICH_VMCR_CTRL_SHIFT)
  
  struct device_node;
  
 -void gic_set_irqchip_flags(unsigned long flags);
  void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
                    u32 offset, struct device_node *);
  void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 -void gic_cpu_if_down(void);
 +int gic_cpu_if_down(unsigned int gic_nr);
  
  static inline void gic_init(unsigned int nr, int start,
                            void __iomem *dist , void __iomem *cpu)
This page took 0.158118 seconds and 4 git commands to generate.