diff options
| -rw-r--r-- | arch/s390/include/asm/kvm_host.h | 1 | ||||
| -rw-r--r-- | arch/s390/kvm/diag.c | 25 | ||||
| -rw-r--r-- | arch/s390/kvm/kvm-s390.c | 1 | ||||
| -rw-r--r-- | include/linux/kvm_host.h | 1 | ||||
| -rw-r--r-- | virt/kvm/kvm_main.c | 42 |
5 files changed, 54 insertions, 16 deletions
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index 7343872890a2..dd17537b9a9d 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h | |||
| @@ -148,6 +148,7 @@ struct kvm_vcpu_stat { | |||
| 148 | u32 instruction_sigp_restart; | 148 | u32 instruction_sigp_restart; |
| 149 | u32 diagnose_10; | 149 | u32 diagnose_10; |
| 150 | u32 diagnose_44; | 150 | u32 diagnose_44; |
| 151 | u32 diagnose_9c; | ||
| 151 | }; | 152 | }; |
| 152 | 153 | ||
| 153 | struct kvm_s390_io_info { | 154 | struct kvm_s390_io_info { |
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c index a353f0ea45c2..2d2ae327b747 100644 --- a/arch/s390/kvm/diag.c +++ b/arch/s390/kvm/diag.c | |||
| @@ -53,6 +53,29 @@ static int __diag_time_slice_end(struct kvm_vcpu *vcpu) | |||
| 53 | return 0; | 53 | return 0; |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | static int __diag_time_slice_end_directed(struct kvm_vcpu *vcpu) | ||
| 57 | { | ||
| 58 | struct kvm *kvm = vcpu->kvm; | ||
| 59 | struct kvm_vcpu *tcpu; | ||
| 60 | int tid; | ||
| 61 | int i; | ||
| 62 | |||
| 63 | tid = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4]; | ||
| 64 | vcpu->stat.diagnose_9c++; | ||
| 65 | VCPU_EVENT(vcpu, 5, "diag time slice end directed to %d", tid); | ||
| 66 | |||
| 67 | if (tid == vcpu->vcpu_id) | ||
| 68 | return 0; | ||
| 69 | |||
| 70 | kvm_for_each_vcpu(i, tcpu, kvm) | ||
| 71 | if (tcpu->vcpu_id == tid) { | ||
| 72 | kvm_vcpu_yield_to(tcpu); | ||
| 73 | break; | ||
| 74 | } | ||
| 75 | |||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 56 | static int __diag_ipl_functions(struct kvm_vcpu *vcpu) | 79 | static int __diag_ipl_functions(struct kvm_vcpu *vcpu) |
| 57 | { | 80 | { |
| 58 | unsigned int reg = vcpu->arch.sie_block->ipa & 0xf; | 81 | unsigned int reg = vcpu->arch.sie_block->ipa & 0xf; |
| @@ -89,6 +112,8 @@ int kvm_s390_handle_diag(struct kvm_vcpu *vcpu) | |||
| 89 | return diag_release_pages(vcpu); | 112 | return diag_release_pages(vcpu); |
| 90 | case 0x44: | 113 | case 0x44: |
| 91 | return __diag_time_slice_end(vcpu); | 114 | return __diag_time_slice_end(vcpu); |
| 115 | case 0x9c: | ||
| 116 | return __diag_time_slice_end_directed(vcpu); | ||
| 92 | case 0x308: | 117 | case 0x308: |
| 93 | return __diag_ipl_functions(vcpu); | 118 | return __diag_ipl_functions(vcpu); |
| 94 | default: | 119 | default: |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index d30c8350b949..fd98914a36f1 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
| @@ -74,6 +74,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { | |||
| 74 | { "instruction_sigp_restart", VCPU_STAT(instruction_sigp_restart) }, | 74 | { "instruction_sigp_restart", VCPU_STAT(instruction_sigp_restart) }, |
| 75 | { "diagnose_10", VCPU_STAT(diagnose_10) }, | 75 | { "diagnose_10", VCPU_STAT(diagnose_10) }, |
| 76 | { "diagnose_44", VCPU_STAT(diagnose_44) }, | 76 | { "diagnose_44", VCPU_STAT(diagnose_44) }, |
| 77 | { "diagnose_9c", VCPU_STAT(diagnose_9c) }, | ||
| 77 | { NULL } | 78 | { NULL } |
| 78 | }; | 79 | }; |
| 79 | 80 | ||
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 6f343307d72b..cae342d29d1b 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
| @@ -461,6 +461,7 @@ void mark_page_dirty_in_slot(struct kvm *kvm, struct kvm_memory_slot *memslot, | |||
| 461 | 461 | ||
| 462 | void kvm_vcpu_block(struct kvm_vcpu *vcpu); | 462 | void kvm_vcpu_block(struct kvm_vcpu *vcpu); |
| 463 | void kvm_vcpu_kick(struct kvm_vcpu *vcpu); | 463 | void kvm_vcpu_kick(struct kvm_vcpu *vcpu); |
| 464 | bool kvm_vcpu_yield_to(struct kvm_vcpu *target); | ||
| 464 | void kvm_vcpu_on_spin(struct kvm_vcpu *vcpu); | 465 | void kvm_vcpu_on_spin(struct kvm_vcpu *vcpu); |
| 465 | void kvm_resched(struct kvm_vcpu *vcpu); | 466 | void kvm_resched(struct kvm_vcpu *vcpu); |
| 466 | void kvm_load_guest_fpu(struct kvm_vcpu *vcpu); | 467 | void kvm_load_guest_fpu(struct kvm_vcpu *vcpu); |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 1847c762d8d9..7e140683ff14 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
| @@ -1543,6 +1543,31 @@ void kvm_resched(struct kvm_vcpu *vcpu) | |||
| 1543 | } | 1543 | } |
| 1544 | EXPORT_SYMBOL_GPL(kvm_resched); | 1544 | EXPORT_SYMBOL_GPL(kvm_resched); |
| 1545 | 1545 | ||
| 1546 | bool kvm_vcpu_yield_to(struct kvm_vcpu *target) | ||
| 1547 | { | ||
| 1548 | struct pid *pid; | ||
| 1549 | struct task_struct *task = NULL; | ||
| 1550 | |||
| 1551 | rcu_read_lock(); | ||
| 1552 | pid = rcu_dereference(target->pid); | ||
| 1553 | if (pid) | ||
| 1554 | task = get_pid_task(target->pid, PIDTYPE_PID); | ||
| 1555 | rcu_read_unlock(); | ||
| 1556 | if (!task) | ||
| 1557 | return false; | ||
| 1558 | if (task->flags & PF_VCPU) { | ||
| 1559 | put_task_struct(task); | ||
| 1560 | return false; | ||
| 1561 | } | ||
| 1562 | if (yield_to(task, 1)) { | ||
| 1563 | put_task_struct(task); | ||
| 1564 | return true; | ||
| 1565 | } | ||
| 1566 | put_task_struct(task); | ||
| 1567 | return false; | ||
| 1568 | } | ||
| 1569 | EXPORT_SYMBOL_GPL(kvm_vcpu_yield_to); | ||
| 1570 | |||
| 1546 | void kvm_vcpu_on_spin(struct kvm_vcpu *me) | 1571 | void kvm_vcpu_on_spin(struct kvm_vcpu *me) |
| 1547 | { | 1572 | { |
| 1548 | struct kvm *kvm = me->kvm; | 1573 | struct kvm *kvm = me->kvm; |
| @@ -1561,8 +1586,6 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me) | |||
| 1561 | */ | 1586 | */ |
| 1562 | for (pass = 0; pass < 2 && !yielded; pass++) { | 1587 | for (pass = 0; pass < 2 && !yielded; pass++) { |
| 1563 | kvm_for_each_vcpu(i, vcpu, kvm) { | 1588 | kvm_for_each_vcpu(i, vcpu, kvm) { |
| 1564 | struct task_struct *task = NULL; | ||
| 1565 | struct pid *pid; | ||
| 1566 | if (!pass && i < last_boosted_vcpu) { | 1589 | if (!pass && i < last_boosted_vcpu) { |
| 1567 | i = last_boosted_vcpu; | 1590 | i = last_boosted_vcpu; |
| 1568 | continue; | 1591 | continue; |
| @@ -1572,24 +1595,11 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me) | |||
| 1572 | continue; | 1595 | continue; |
| 1573 | if (waitqueue_active(&vcpu->wq)) | 1596 | if (waitqueue_active(&vcpu->wq)) |
| 1574 | continue; | 1597 | continue; |
| 1575 | rcu_read_lock(); | 1598 | if (kvm_vcpu_yield_to(vcpu)) { |
| 1576 | pid = rcu_dereference(vcpu->pid); | ||
| 1577 | if (pid) | ||
| 1578 | task = get_pid_task(vcpu->pid, PIDTYPE_PID); | ||
| 1579 | rcu_read_unlock(); | ||
| 1580 | if (!task) | ||
| 1581 | continue; | ||
| 1582 | if (task->flags & PF_VCPU) { | ||
| 1583 | put_task_struct(task); | ||
| 1584 | continue; | ||
| 1585 | } | ||
| 1586 | if (yield_to(task, 1)) { | ||
| 1587 | put_task_struct(task); | ||
| 1588 | kvm->last_boosted_vcpu = i; | 1599 | kvm->last_boosted_vcpu = i; |
| 1589 | yielded = 1; | 1600 | yielded = 1; |
| 1590 | break; | 1601 | break; |
| 1591 | } | 1602 | } |
| 1592 | put_task_struct(task); | ||
| 1593 | } | 1603 | } |
| 1594 | } | 1604 | } |
| 1595 | } | 1605 | } |
