diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/include/asm/kvm_host.h | 21 | ||||
-rw-r--r-- | arch/powerpc/include/asm/time.h | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/asm-offsets.c | 13 | ||||
-rw-r--r-- | arch/powerpc/kernel/time.c | 6 | ||||
-rw-r--r-- | arch/powerpc/kvm/Kconfig | 14 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_hv.c | 150 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_hv_rmhandlers.S | 141 |
7 files changed, 346 insertions, 2 deletions
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index f1d0bbc0f079..d2068bba9059 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h | |||
@@ -369,6 +369,14 @@ struct kvmppc_slb { | |||
369 | u8 base_page_size; /* MMU_PAGE_xxx */ | 369 | u8 base_page_size; /* MMU_PAGE_xxx */ |
370 | }; | 370 | }; |
371 | 371 | ||
372 | /* Struct used to accumulate timing information in HV real mode code */ | ||
373 | struct kvmhv_tb_accumulator { | ||
374 | u64 seqcount; /* used to synchronize access, also count * 2 */ | ||
375 | u64 tb_total; /* total time in timebase ticks */ | ||
376 | u64 tb_min; /* min time */ | ||
377 | u64 tb_max; /* max time */ | ||
378 | }; | ||
379 | |||
372 | # ifdef CONFIG_PPC_FSL_BOOK3E | 380 | # ifdef CONFIG_PPC_FSL_BOOK3E |
373 | #define KVMPPC_BOOKE_IAC_NUM 2 | 381 | #define KVMPPC_BOOKE_IAC_NUM 2 |
374 | #define KVMPPC_BOOKE_DAC_NUM 2 | 382 | #define KVMPPC_BOOKE_DAC_NUM 2 |
@@ -657,6 +665,19 @@ struct kvm_vcpu_arch { | |||
657 | 665 | ||
658 | u32 emul_inst; | 666 | u32 emul_inst; |
659 | #endif | 667 | #endif |
668 | |||
669 | #ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING | ||
670 | struct kvmhv_tb_accumulator *cur_activity; /* What we're timing */ | ||
671 | u64 cur_tb_start; /* when it started */ | ||
672 | struct kvmhv_tb_accumulator rm_entry; /* real-mode entry code */ | ||
673 | struct kvmhv_tb_accumulator rm_intr; /* real-mode intr handling */ | ||
674 | struct kvmhv_tb_accumulator rm_exit; /* real-mode exit code */ | ||
675 | struct kvmhv_tb_accumulator guest_time; /* guest execution */ | ||
676 | struct kvmhv_tb_accumulator cede_time; /* time napping inside guest */ | ||
677 | |||
678 | struct dentry *debugfs_dir; | ||
679 | struct dentry *debugfs_timings; | ||
680 | #endif /* CONFIG_KVM_BOOK3S_HV_EXIT_TIMING */ | ||
660 | }; | 681 | }; |
661 | 682 | ||
662 | #define VCPU_FPR(vcpu, i) (vcpu)->arch.fp.fpr[i][TS_FPROFFSET] | 683 | #define VCPU_FPR(vcpu, i) (vcpu)->arch.fp.fpr[i][TS_FPROFFSET] |
diff --git a/arch/powerpc/include/asm/time.h b/arch/powerpc/include/asm/time.h index 03cbada59d3a..10fc784a2ad4 100644 --- a/arch/powerpc/include/asm/time.h +++ b/arch/powerpc/include/asm/time.h | |||
@@ -211,5 +211,8 @@ extern void secondary_cpu_time_init(void); | |||
211 | 211 | ||
212 | DECLARE_PER_CPU(u64, decrementers_next_tb); | 212 | DECLARE_PER_CPU(u64, decrementers_next_tb); |
213 | 213 | ||
214 | /* Convert timebase ticks to nanoseconds */ | ||
215 | unsigned long long tb_to_ns(unsigned long long tb_ticks); | ||
216 | |||
214 | #endif /* __KERNEL__ */ | 217 | #endif /* __KERNEL__ */ |
215 | #endif /* __POWERPC_TIME_H */ | 218 | #endif /* __POWERPC_TIME_H */ |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 4717859fdd04..3fea721f0da5 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -459,6 +459,19 @@ int main(void) | |||
459 | DEFINE(VCPU_SPRG2, offsetof(struct kvm_vcpu, arch.shregs.sprg2)); | 459 | DEFINE(VCPU_SPRG2, offsetof(struct kvm_vcpu, arch.shregs.sprg2)); |
460 | DEFINE(VCPU_SPRG3, offsetof(struct kvm_vcpu, arch.shregs.sprg3)); | 460 | DEFINE(VCPU_SPRG3, offsetof(struct kvm_vcpu, arch.shregs.sprg3)); |
461 | #endif | 461 | #endif |
462 | #ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING | ||
463 | DEFINE(VCPU_TB_RMENTRY, offsetof(struct kvm_vcpu, arch.rm_entry)); | ||
464 | DEFINE(VCPU_TB_RMINTR, offsetof(struct kvm_vcpu, arch.rm_intr)); | ||
465 | DEFINE(VCPU_TB_RMEXIT, offsetof(struct kvm_vcpu, arch.rm_exit)); | ||
466 | DEFINE(VCPU_TB_GUEST, offsetof(struct kvm_vcpu, arch.guest_time)); | ||
467 | DEFINE(VCPU_TB_CEDE, offsetof(struct kvm_vcpu, arch.cede_time)); | ||
468 | DEFINE(VCPU_CUR_ACTIVITY, offsetof(struct kvm_vcpu, arch.cur_activity)); | ||
469 | DEFINE(VCPU_ACTIVITY_START, offsetof(struct kvm_vcpu, arch.cur_tb_start)); | ||
470 | DEFINE(TAS_SEQCOUNT, offsetof(struct kvmhv_tb_accumulator, seqcount)); | ||
471 | DEFINE(TAS_TOTAL, offsetof(struct kvmhv_tb_accumulator, tb_total)); | ||
472 | DEFINE(TAS_MIN, offsetof(struct kvmhv_tb_accumulator, tb_min)); | ||
473 | DEFINE(TAS_MAX, offsetof(struct kvmhv_tb_accumulator, tb_max)); | ||
474 | #endif | ||
462 | DEFINE(VCPU_SHARED_SPRG3, offsetof(struct kvm_vcpu_arch_shared, sprg3)); | 475 | DEFINE(VCPU_SHARED_SPRG3, offsetof(struct kvm_vcpu_arch_shared, sprg3)); |
463 | DEFINE(VCPU_SHARED_SPRG4, offsetof(struct kvm_vcpu_arch_shared, sprg4)); | 476 | DEFINE(VCPU_SHARED_SPRG4, offsetof(struct kvm_vcpu_arch_shared, sprg4)); |
464 | DEFINE(VCPU_SHARED_SPRG5, offsetof(struct kvm_vcpu_arch_shared, sprg5)); | 477 | DEFINE(VCPU_SHARED_SPRG5, offsetof(struct kvm_vcpu_arch_shared, sprg5)); |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 2d7b33fab953..56f44848b044 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -608,6 +608,12 @@ void arch_suspend_enable_irqs(void) | |||
608 | } | 608 | } |
609 | #endif | 609 | #endif |
610 | 610 | ||
611 | unsigned long long tb_to_ns(unsigned long long ticks) | ||
612 | { | ||
613 | return mulhdu(ticks, tb_to_ns_scale) << tb_to_ns_shift; | ||
614 | } | ||
615 | EXPORT_SYMBOL_GPL(tb_to_ns); | ||
616 | |||
611 | /* | 617 | /* |
612 | * Scheduler clock - returns current time in nanosec units. | 618 | * Scheduler clock - returns current time in nanosec units. |
613 | * | 619 | * |
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig index 11850f310fb4..2963e4dd0b80 100644 --- a/arch/powerpc/kvm/Kconfig +++ b/arch/powerpc/kvm/Kconfig | |||
@@ -110,6 +110,20 @@ config KVM_BOOK3S_64_PR | |||
110 | processor, including emulating 32-bit processors on a 64-bit | 110 | processor, including emulating 32-bit processors on a 64-bit |
111 | host. | 111 | host. |
112 | 112 | ||
113 | config KVM_BOOK3S_HV_EXIT_TIMING | ||
114 | bool "Detailed timing for hypervisor real-mode code" | ||
115 | depends on KVM_BOOK3S_HV_POSSIBLE && DEBUG_FS | ||
116 | ---help--- | ||
117 | Calculate time taken for each vcpu in the real-mode guest entry, | ||
118 | exit, and interrupt handling code, plus time spent in the guest | ||
119 | and in nap mode due to idle (cede) while other threads are still | ||
120 | in the guest. The total, minimum and maximum times in nanoseconds | ||
121 | together with the number of executions are reported in debugfs in | ||
122 | kvm/vm#/vcpu#/timings. The overhead is of the order of 30 - 40 | ||
123 | ns per exit on POWER8. | ||
124 | |||
125 | If unsure, say N. | ||
126 | |||
113 | config KVM_BOOKE_HV | 127 | config KVM_BOOKE_HV |
114 | bool | 128 | bool |
115 | 129 | ||
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 08f8617f4046..64a02d4c737c 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c | |||
@@ -1423,6 +1423,154 @@ static struct kvmppc_vcore *kvmppc_vcore_create(struct kvm *kvm, int core) | |||
1423 | return vcore; | 1423 | return vcore; |
1424 | } | 1424 | } |
1425 | 1425 | ||
1426 | #ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING | ||
1427 | static struct debugfs_timings_element { | ||
1428 | const char *name; | ||
1429 | size_t offset; | ||
1430 | } timings[] = { | ||
1431 | {"rm_entry", offsetof(struct kvm_vcpu, arch.rm_entry)}, | ||
1432 | {"rm_intr", offsetof(struct kvm_vcpu, arch.rm_intr)}, | ||
1433 | {"rm_exit", offsetof(struct kvm_vcpu, arch.rm_exit)}, | ||
1434 | {"guest", offsetof(struct kvm_vcpu, arch.guest_time)}, | ||
1435 | {"cede", offsetof(struct kvm_vcpu, arch.cede_time)}, | ||
1436 | }; | ||
1437 | |||
1438 | #define N_TIMINGS (sizeof(timings) / sizeof(timings[0])) | ||
1439 | |||
1440 | struct debugfs_timings_state { | ||
1441 | struct kvm_vcpu *vcpu; | ||
1442 | unsigned int buflen; | ||
1443 | char buf[N_TIMINGS * 100]; | ||
1444 | }; | ||
1445 | |||
1446 | static int debugfs_timings_open(struct inode *inode, struct file *file) | ||
1447 | { | ||
1448 | struct kvm_vcpu *vcpu = inode->i_private; | ||
1449 | struct debugfs_timings_state *p; | ||
1450 | |||
1451 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
1452 | if (!p) | ||
1453 | return -ENOMEM; | ||
1454 | |||
1455 | kvm_get_kvm(vcpu->kvm); | ||
1456 | p->vcpu = vcpu; | ||
1457 | file->private_data = p; | ||
1458 | |||
1459 | return nonseekable_open(inode, file); | ||
1460 | } | ||
1461 | |||
1462 | static int debugfs_timings_release(struct inode *inode, struct file *file) | ||
1463 | { | ||
1464 | struct debugfs_timings_state *p = file->private_data; | ||
1465 | |||
1466 | kvm_put_kvm(p->vcpu->kvm); | ||
1467 | kfree(p); | ||
1468 | return 0; | ||
1469 | } | ||
1470 | |||
1471 | static ssize_t debugfs_timings_read(struct file *file, char __user *buf, | ||
1472 | size_t len, loff_t *ppos) | ||
1473 | { | ||
1474 | struct debugfs_timings_state *p = file->private_data; | ||
1475 | struct kvm_vcpu *vcpu = p->vcpu; | ||
1476 | char *s, *buf_end; | ||
1477 | struct kvmhv_tb_accumulator tb; | ||
1478 | u64 count; | ||
1479 | loff_t pos; | ||
1480 | ssize_t n; | ||
1481 | int i, loops; | ||
1482 | bool ok; | ||
1483 | |||
1484 | if (!p->buflen) { | ||
1485 | s = p->buf; | ||
1486 | buf_end = s + sizeof(p->buf); | ||
1487 | for (i = 0; i < N_TIMINGS; ++i) { | ||
1488 | struct kvmhv_tb_accumulator *acc; | ||
1489 | |||
1490 | acc = (struct kvmhv_tb_accumulator *) | ||
1491 | ((unsigned long)vcpu + timings[i].offset); | ||
1492 | ok = false; | ||
1493 | for (loops = 0; loops < 1000; ++loops) { | ||
1494 | count = acc->seqcount; | ||
1495 | if (!(count & 1)) { | ||
1496 | smp_rmb(); | ||
1497 | tb = *acc; | ||
1498 | smp_rmb(); | ||
1499 | if (count == acc->seqcount) { | ||
1500 | ok = true; | ||
1501 | break; | ||
1502 | } | ||
1503 | } | ||
1504 | udelay(1); | ||
1505 | } | ||
1506 | if (!ok) | ||
1507 | snprintf(s, buf_end - s, "%s: stuck\n", | ||
1508 | timings[i].name); | ||
1509 | else | ||
1510 | snprintf(s, buf_end - s, | ||
1511 | "%s: %llu %llu %llu %llu\n", | ||
1512 | timings[i].name, count / 2, | ||
1513 | tb_to_ns(tb.tb_total), | ||
1514 | tb_to_ns(tb.tb_min), | ||
1515 | tb_to_ns(tb.tb_max)); | ||
1516 | s += strlen(s); | ||
1517 | } | ||
1518 | p->buflen = s - p->buf; | ||
1519 | } | ||
1520 | |||
1521 | pos = *ppos; | ||
1522 | if (pos >= p->buflen) | ||
1523 | return 0; | ||
1524 | if (len > p->buflen - pos) | ||
1525 | len = p->buflen - pos; | ||
1526 | n = copy_to_user(buf, p->buf + pos, len); | ||
1527 | if (n) { | ||
1528 | if (n == len) | ||
1529 | return -EFAULT; | ||
1530 | len -= n; | ||
1531 | } | ||
1532 | *ppos = pos + len; | ||
1533 | return len; | ||
1534 | } | ||
1535 | |||
1536 | static ssize_t debugfs_timings_write(struct file *file, const char __user *buf, | ||
1537 | size_t len, loff_t *ppos) | ||
1538 | { | ||
1539 | return -EACCES; | ||
1540 | } | ||
1541 | |||
1542 | static const struct file_operations debugfs_timings_ops = { | ||
1543 | .owner = THIS_MODULE, | ||
1544 | .open = debugfs_timings_open, | ||
1545 | .release = debugfs_timings_release, | ||
1546 | .read = debugfs_timings_read, | ||
1547 | .write = debugfs_timings_write, | ||
1548 | .llseek = generic_file_llseek, | ||
1549 | }; | ||
1550 | |||
1551 | /* Create a debugfs directory for the vcpu */ | ||
1552 | static void debugfs_vcpu_init(struct kvm_vcpu *vcpu, unsigned int id) | ||
1553 | { | ||
1554 | char buf[16]; | ||
1555 | struct kvm *kvm = vcpu->kvm; | ||
1556 | |||
1557 | snprintf(buf, sizeof(buf), "vcpu%u", id); | ||
1558 | if (IS_ERR_OR_NULL(kvm->arch.debugfs_dir)) | ||
1559 | return; | ||
1560 | vcpu->arch.debugfs_dir = debugfs_create_dir(buf, kvm->arch.debugfs_dir); | ||
1561 | if (IS_ERR_OR_NULL(vcpu->arch.debugfs_dir)) | ||
1562 | return; | ||
1563 | vcpu->arch.debugfs_timings = | ||
1564 | debugfs_create_file("timings", 0444, vcpu->arch.debugfs_dir, | ||
1565 | vcpu, &debugfs_timings_ops); | ||
1566 | } | ||
1567 | |||
1568 | #else /* CONFIG_KVM_BOOK3S_HV_EXIT_TIMING */ | ||
1569 | static void debugfs_vcpu_init(struct kvm_vcpu *vcpu, unsigned int id) | ||
1570 | { | ||
1571 | } | ||
1572 | #endif /* CONFIG_KVM_BOOK3S_HV_EXIT_TIMING */ | ||
1573 | |||
1426 | static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm, | 1574 | static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm, |
1427 | unsigned int id) | 1575 | unsigned int id) |
1428 | { | 1576 | { |
@@ -1492,6 +1640,8 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm, | |||
1492 | vcpu->arch.cpu_type = KVM_CPU_3S_64; | 1640 | vcpu->arch.cpu_type = KVM_CPU_3S_64; |
1493 | kvmppc_sanity_check(vcpu); | 1641 | kvmppc_sanity_check(vcpu); |
1494 | 1642 | ||
1643 | debugfs_vcpu_init(vcpu, id); | ||
1644 | |||
1495 | return vcpu; | 1645 | return vcpu; |
1496 | 1646 | ||
1497 | free_vcpu: | 1647 | free_vcpu: |
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index 0814ca122fcd..b06fe53fd509 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S | |||
@@ -225,7 +225,13 @@ kvm_novcpu_wakeup: | |||
225 | /* Got an IPI but other vcpus aren't yet exiting, must be a latecomer */ | 225 | /* Got an IPI but other vcpus aren't yet exiting, must be a latecomer */ |
226 | ld r4, HSTATE_KVM_VCPU(r13) | 226 | ld r4, HSTATE_KVM_VCPU(r13) |
227 | cmpdi r4, 0 | 227 | cmpdi r4, 0 |
228 | bne kvmppc_got_guest | 228 | beq kvmppc_primary_no_guest |
229 | |||
230 | #ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING | ||
231 | addi r3, r4, VCPU_TB_RMENTRY | ||
232 | bl kvmhv_start_timing | ||
233 | #endif | ||
234 | b kvmppc_got_guest | ||
229 | 235 | ||
230 | kvm_novcpu_exit: | 236 | kvm_novcpu_exit: |
231 | b hdec_soon | 237 | b hdec_soon |
@@ -376,6 +382,14 @@ kvmppc_hv_entry: | |||
376 | li r6, KVM_GUEST_MODE_HOST_HV | 382 | li r6, KVM_GUEST_MODE_HOST_HV |
377 | stb r6, HSTATE_IN_GUEST(r13) | 383 | stb r6, HSTATE_IN_GUEST(r13) |
378 | 384 | ||
385 | #ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING | ||
386 | /* Store initial timestamp */ | ||
387 | cmpdi r4, 0 | ||
388 | beq 1f | ||
389 | addi r3, r4, VCPU_TB_RMENTRY | ||
390 | bl kvmhv_start_timing | ||
391 | 1: | ||
392 | #endif | ||
379 | /* Clear out SLB */ | 393 | /* Clear out SLB */ |
380 | li r6,0 | 394 | li r6,0 |
381 | slbmte r6,r6 | 395 | slbmte r6,r6 |
@@ -880,6 +894,12 @@ fast_guest_return: | |||
880 | li r9, KVM_GUEST_MODE_GUEST_HV | 894 | li r9, KVM_GUEST_MODE_GUEST_HV |
881 | stb r9, HSTATE_IN_GUEST(r13) | 895 | stb r9, HSTATE_IN_GUEST(r13) |
882 | 896 | ||
897 | #ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING | ||
898 | /* Accumulate timing */ | ||
899 | addi r3, r4, VCPU_TB_GUEST | ||
900 | bl kvmhv_accumulate_time | ||
901 | #endif | ||
902 | |||
883 | /* Enter guest */ | 903 | /* Enter guest */ |
884 | 904 | ||
885 | BEGIN_FTR_SECTION | 905 | BEGIN_FTR_SECTION |
@@ -917,6 +937,23 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) | |||
917 | hrfid | 937 | hrfid |
918 | b . | 938 | b . |
919 | 939 | ||
940 | #ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING | ||
941 | secondary_too_late: | ||
942 | cmpdi r4, 0 | ||
943 | beq 11f | ||
944 | addi r3, r4, VCPU_TB_RMEXIT | ||
945 | bl kvmhv_accumulate_time | ||
946 | 11: b kvmhv_switch_to_host | ||
947 | |||
948 | hdec_soon: | ||
949 | ld r4, HSTATE_KVM_VCPU(r13) | ||
950 | cmpdi r4, 0 | ||
951 | beq 12f | ||
952 | addi r3, r4, VCPU_TB_RMEXIT | ||
953 | bl kvmhv_accumulate_time | ||
954 | 12: b kvmhv_do_exit | ||
955 | #endif | ||
956 | |||
920 | /****************************************************************************** | 957 | /****************************************************************************** |
921 | * * | 958 | * * |
922 | * Exit code * | 959 | * Exit code * |
@@ -1002,6 +1039,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) | |||
1002 | 1039 | ||
1003 | stw r12,VCPU_TRAP(r9) | 1040 | stw r12,VCPU_TRAP(r9) |
1004 | 1041 | ||
1042 | #ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING | ||
1043 | addi r3, r9, VCPU_TB_RMINTR | ||
1044 | mr r4, r9 | ||
1045 | bl kvmhv_accumulate_time | ||
1046 | ld r5, VCPU_GPR(R5)(r9) | ||
1047 | ld r6, VCPU_GPR(R6)(r9) | ||
1048 | ld r7, VCPU_GPR(R7)(r9) | ||
1049 | ld r8, VCPU_GPR(R8)(r9) | ||
1050 | #endif | ||
1051 | |||
1005 | /* Save HEIR (HV emulation assist reg) in emul_inst | 1052 | /* Save HEIR (HV emulation assist reg) in emul_inst |
1006 | if this is an HEI (HV emulation interrupt, e40) */ | 1053 | if this is an HEI (HV emulation interrupt, e40) */ |
1007 | li r3,KVM_INST_FETCH_FAILED | 1054 | li r3,KVM_INST_FETCH_FAILED |
@@ -1073,6 +1120,11 @@ guest_exit_cont: /* r9 = vcpu, r12 = trap, r13 = paca */ | |||
1073 | cmpwi r12, BOOK3S_INTERRUPT_MACHINE_CHECK | 1120 | cmpwi r12, BOOK3S_INTERRUPT_MACHINE_CHECK |
1074 | beq machine_check_realmode | 1121 | beq machine_check_realmode |
1075 | mc_cont: | 1122 | mc_cont: |
1123 | #ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING | ||
1124 | addi r3, r9, VCPU_TB_RMEXIT | ||
1125 | mr r4, r9 | ||
1126 | bl kvmhv_accumulate_time | ||
1127 | #endif | ||
1076 | 1128 | ||
1077 | /* Save guest CTRL register, set runlatch to 1 */ | 1129 | /* Save guest CTRL register, set runlatch to 1 */ |
1078 | 6: mfspr r6,SPRN_CTRLF | 1130 | 6: mfspr r6,SPRN_CTRLF |
@@ -1417,7 +1469,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) | |||
1417 | slbia | 1469 | slbia |
1418 | ptesync | 1470 | ptesync |
1419 | 1471 | ||
1420 | hdec_soon: /* r12 = trap, r13 = paca */ | 1472 | #ifndef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING |
1473 | hdec_soon: | ||
1474 | #endif | ||
1475 | kvmhv_do_exit: /* r12 = trap, r13 = paca */ | ||
1421 | /* | 1476 | /* |
1422 | * POWER7/POWER8 guest -> host partition switch code. | 1477 | * POWER7/POWER8 guest -> host partition switch code. |
1423 | * We don't have to lock against tlbies but we do | 1478 | * We don't have to lock against tlbies but we do |
@@ -1476,7 +1531,10 @@ hdec_soon: /* r12 = trap, r13 = paca */ | |||
1476 | addi r6,r6,PACA_SIZE | 1531 | addi r6,r6,PACA_SIZE |
1477 | bne 42b | 1532 | bne 42b |
1478 | 1533 | ||
1534 | #ifndef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING | ||
1479 | secondary_too_late: | 1535 | secondary_too_late: |
1536 | #endif | ||
1537 | kvmhv_switch_to_host: | ||
1480 | /* Secondary threads wait for primary to do partition switch */ | 1538 | /* Secondary threads wait for primary to do partition switch */ |
1481 | 43: ld r5,HSTATE_KVM_VCORE(r13) | 1539 | 43: ld r5,HSTATE_KVM_VCORE(r13) |
1482 | ld r4,VCORE_KVM(r5) /* pointer to struct kvm */ | 1540 | ld r4,VCORE_KVM(r5) /* pointer to struct kvm */ |
@@ -1562,6 +1620,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) | |||
1562 | 1: addi r8,r8,16 | 1620 | 1: addi r8,r8,16 |
1563 | .endr | 1621 | .endr |
1564 | 1622 | ||
1623 | #ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING | ||
1624 | /* Finish timing, if we have a vcpu */ | ||
1625 | ld r4, HSTATE_KVM_VCPU(r13) | ||
1626 | cmpdi r4, 0 | ||
1627 | li r3, 0 | ||
1628 | beq 2f | ||
1629 | bl kvmhv_accumulate_time | ||
1630 | 2: | ||
1631 | #endif | ||
1565 | /* Unset guest mode */ | 1632 | /* Unset guest mode */ |
1566 | li r0, KVM_GUEST_MODE_NONE | 1633 | li r0, KVM_GUEST_MODE_NONE |
1567 | stb r0, HSTATE_IN_GUEST(r13) | 1634 | stb r0, HSTATE_IN_GUEST(r13) |
@@ -2069,6 +2136,12 @@ _GLOBAL(kvmppc_h_cede) | |||
2069 | /* save FP state */ | 2136 | /* save FP state */ |
2070 | bl kvmppc_save_fp | 2137 | bl kvmppc_save_fp |
2071 | 2138 | ||
2139 | #ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING | ||
2140 | ld r4, HSTATE_KVM_VCPU(r13) | ||
2141 | addi r3, r4, VCPU_TB_CEDE | ||
2142 | bl kvmhv_accumulate_time | ||
2143 | #endif | ||
2144 | |||
2072 | /* | 2145 | /* |
2073 | * Take a nap until a decrementer or external or doobell interrupt | 2146 | * Take a nap until a decrementer or external or doobell interrupt |
2074 | * occurs, with PECE1, PECE0 and PECEDP set in LPCR. Also clear the | 2147 | * occurs, with PECE1, PECE0 and PECEDP set in LPCR. Also clear the |
@@ -2109,6 +2182,11 @@ kvm_end_cede: | |||
2109 | /* Woken by external or decrementer interrupt */ | 2182 | /* Woken by external or decrementer interrupt */ |
2110 | ld r1, HSTATE_HOST_R1(r13) | 2183 | ld r1, HSTATE_HOST_R1(r13) |
2111 | 2184 | ||
2185 | #ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING | ||
2186 | addi r3, r4, VCPU_TB_RMINTR | ||
2187 | bl kvmhv_accumulate_time | ||
2188 | #endif | ||
2189 | |||
2112 | /* load up FP state */ | 2190 | /* load up FP state */ |
2113 | bl kvmppc_load_fp | 2191 | bl kvmppc_load_fp |
2114 | 2192 | ||
@@ -2429,3 +2507,62 @@ kvmppc_fix_pmao: | |||
2429 | mtspr SPRN_PMC6, r3 | 2507 | mtspr SPRN_PMC6, r3 |
2430 | isync | 2508 | isync |
2431 | blr | 2509 | blr |
2510 | |||
2511 | #ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING | ||
2512 | /* | ||
2513 | * Start timing an activity | ||
2514 | * r3 = pointer to time accumulation struct, r4 = vcpu | ||
2515 | */ | ||
2516 | kvmhv_start_timing: | ||
2517 | ld r5, HSTATE_KVM_VCORE(r13) | ||
2518 | lbz r6, VCORE_IN_GUEST(r5) | ||
2519 | cmpwi r6, 0 | ||
2520 | beq 5f /* if in guest, need to */ | ||
2521 | ld r6, VCORE_TB_OFFSET(r5) /* subtract timebase offset */ | ||
2522 | 5: mftb r5 | ||
2523 | subf r5, r6, r5 | ||
2524 | std r3, VCPU_CUR_ACTIVITY(r4) | ||
2525 | std r5, VCPU_ACTIVITY_START(r4) | ||
2526 | blr | ||
2527 | |||
2528 | /* | ||
2529 | * Accumulate time to one activity and start another. | ||
2530 | * r3 = pointer to new time accumulation struct, r4 = vcpu | ||
2531 | */ | ||
2532 | kvmhv_accumulate_time: | ||
2533 | ld r5, HSTATE_KVM_VCORE(r13) | ||
2534 | lbz r8, VCORE_IN_GUEST(r5) | ||
2535 | cmpwi r8, 0 | ||
2536 | beq 4f /* if in guest, need to */ | ||
2537 | ld r8, VCORE_TB_OFFSET(r5) /* subtract timebase offset */ | ||
2538 | 4: ld r5, VCPU_CUR_ACTIVITY(r4) | ||
2539 | ld r6, VCPU_ACTIVITY_START(r4) | ||
2540 | std r3, VCPU_CUR_ACTIVITY(r4) | ||
2541 | mftb r7 | ||
2542 | subf r7, r8, r7 | ||
2543 | std r7, VCPU_ACTIVITY_START(r4) | ||
2544 | cmpdi r5, 0 | ||
2545 | beqlr | ||
2546 | subf r3, r6, r7 | ||
2547 | ld r8, TAS_SEQCOUNT(r5) | ||
2548 | cmpdi r8, 0 | ||
2549 | addi r8, r8, 1 | ||
2550 | std r8, TAS_SEQCOUNT(r5) | ||
2551 | lwsync | ||
2552 | ld r7, TAS_TOTAL(r5) | ||
2553 | add r7, r7, r3 | ||
2554 | std r7, TAS_TOTAL(r5) | ||
2555 | ld r6, TAS_MIN(r5) | ||
2556 | ld r7, TAS_MAX(r5) | ||
2557 | beq 3f | ||
2558 | cmpd r3, r6 | ||
2559 | bge 1f | ||
2560 | 3: std r3, TAS_MIN(r5) | ||
2561 | 1: cmpd r3, r7 | ||
2562 | ble 2f | ||
2563 | std r3, TAS_MAX(r5) | ||
2564 | 2: lwsync | ||
2565 | addi r8, r8, 1 | ||
2566 | std r8, TAS_SEQCOUNT(r5) | ||
2567 | blr | ||
2568 | #endif | ||