diff options
Diffstat (limited to 'arch/arm/kvm/coproc.c')
-rw-r--r-- | arch/arm/kvm/coproc.c | 106 |
1 files changed, 74 insertions, 32 deletions
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c index 2c14b69511e9..6d1d2e26dfe5 100644 --- a/arch/arm/kvm/coproc.c +++ b/arch/arm/kvm/coproc.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <asm/vfp.h> | 32 | #include <asm/vfp.h> |
33 | #include "../vfp/vfpinstr.h" | 33 | #include "../vfp/vfpinstr.h" |
34 | 34 | ||
35 | #define CREATE_TRACE_POINTS | ||
35 | #include "trace.h" | 36 | #include "trace.h" |
36 | #include "coproc.h" | 37 | #include "coproc.h" |
37 | 38 | ||
@@ -111,12 +112,6 @@ int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
111 | return 1; | 112 | return 1; |
112 | } | 113 | } |
113 | 114 | ||
114 | int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run) | ||
115 | { | ||
116 | kvm_inject_undefined(vcpu); | ||
117 | return 1; | ||
118 | } | ||
119 | |||
120 | static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r) | 115 | static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r) |
121 | { | 116 | { |
122 | /* | 117 | /* |
@@ -284,7 +279,7 @@ static bool access_gic_sre(struct kvm_vcpu *vcpu, | |||
284 | * must always support PMCCNTR (the cycle counter): we just RAZ/WI for | 279 | * must always support PMCCNTR (the cycle counter): we just RAZ/WI for |
285 | * all PM registers, which doesn't crash the guest kernel at least. | 280 | * all PM registers, which doesn't crash the guest kernel at least. |
286 | */ | 281 | */ |
287 | static bool pm_fake(struct kvm_vcpu *vcpu, | 282 | static bool trap_raz_wi(struct kvm_vcpu *vcpu, |
288 | const struct coproc_params *p, | 283 | const struct coproc_params *p, |
289 | const struct coproc_reg *r) | 284 | const struct coproc_reg *r) |
290 | { | 285 | { |
@@ -294,19 +289,19 @@ static bool pm_fake(struct kvm_vcpu *vcpu, | |||
294 | return read_zero(vcpu, p); | 289 | return read_zero(vcpu, p); |
295 | } | 290 | } |
296 | 291 | ||
297 | #define access_pmcr pm_fake | 292 | #define access_pmcr trap_raz_wi |
298 | #define access_pmcntenset pm_fake | 293 | #define access_pmcntenset trap_raz_wi |
299 | #define access_pmcntenclr pm_fake | 294 | #define access_pmcntenclr trap_raz_wi |
300 | #define access_pmovsr pm_fake | 295 | #define access_pmovsr trap_raz_wi |
301 | #define access_pmselr pm_fake | 296 | #define access_pmselr trap_raz_wi |
302 | #define access_pmceid0 pm_fake | 297 | #define access_pmceid0 trap_raz_wi |
303 | #define access_pmceid1 pm_fake | 298 | #define access_pmceid1 trap_raz_wi |
304 | #define access_pmccntr pm_fake | 299 | #define access_pmccntr trap_raz_wi |
305 | #define access_pmxevtyper pm_fake | 300 | #define access_pmxevtyper trap_raz_wi |
306 | #define access_pmxevcntr pm_fake | 301 | #define access_pmxevcntr trap_raz_wi |
307 | #define access_pmuserenr pm_fake | 302 | #define access_pmuserenr trap_raz_wi |
308 | #define access_pmintenset pm_fake | 303 | #define access_pmintenset trap_raz_wi |
309 | #define access_pmintenclr pm_fake | 304 | #define access_pmintenclr trap_raz_wi |
310 | 305 | ||
311 | /* Architected CP15 registers. | 306 | /* Architected CP15 registers. |
312 | * CRn denotes the primary register number, but is copied to the CRm in the | 307 | * CRn denotes the primary register number, but is copied to the CRm in the |
@@ -532,12 +527,7 @@ static int emulate_cp15(struct kvm_vcpu *vcpu, | |||
532 | return 1; | 527 | return 1; |
533 | } | 528 | } |
534 | 529 | ||
535 | /** | 530 | static struct coproc_params decode_64bit_hsr(struct kvm_vcpu *vcpu) |
536 | * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access | ||
537 | * @vcpu: The VCPU pointer | ||
538 | * @run: The kvm_run struct | ||
539 | */ | ||
540 | int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) | ||
541 | { | 531 | { |
542 | struct coproc_params params; | 532 | struct coproc_params params; |
543 | 533 | ||
@@ -551,9 +541,38 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
551 | params.Rt2 = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf; | 541 | params.Rt2 = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf; |
552 | params.CRm = 0; | 542 | params.CRm = 0; |
553 | 543 | ||
544 | return params; | ||
545 | } | ||
546 | |||
547 | /** | ||
548 | * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access | ||
549 | * @vcpu: The VCPU pointer | ||
550 | * @run: The kvm_run struct | ||
551 | */ | ||
552 | int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) | ||
553 | { | ||
554 | struct coproc_params params = decode_64bit_hsr(vcpu); | ||
555 | |||
554 | return emulate_cp15(vcpu, ¶ms); | 556 | return emulate_cp15(vcpu, ¶ms); |
555 | } | 557 | } |
556 | 558 | ||
559 | /** | ||
560 | * kvm_handle_cp14_64 -- handles a mrrc/mcrr trap on a guest CP14 access | ||
561 | * @vcpu: The VCPU pointer | ||
562 | * @run: The kvm_run struct | ||
563 | */ | ||
564 | int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run) | ||
565 | { | ||
566 | struct coproc_params params = decode_64bit_hsr(vcpu); | ||
567 | |||
568 | /* raz_wi cp14 */ | ||
569 | trap_raz_wi(vcpu, ¶ms, NULL); | ||
570 | |||
571 | /* handled */ | ||
572 | kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); | ||
573 | return 1; | ||
574 | } | ||
575 | |||
557 | static void reset_coproc_regs(struct kvm_vcpu *vcpu, | 576 | static void reset_coproc_regs(struct kvm_vcpu *vcpu, |
558 | const struct coproc_reg *table, size_t num) | 577 | const struct coproc_reg *table, size_t num) |
559 | { | 578 | { |
@@ -564,12 +583,7 @@ static void reset_coproc_regs(struct kvm_vcpu *vcpu, | |||
564 | table[i].reset(vcpu, &table[i]); | 583 | table[i].reset(vcpu, &table[i]); |
565 | } | 584 | } |
566 | 585 | ||
567 | /** | 586 | static struct coproc_params decode_32bit_hsr(struct kvm_vcpu *vcpu) |
568 | * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access | ||
569 | * @vcpu: The VCPU pointer | ||
570 | * @run: The kvm_run struct | ||
571 | */ | ||
572 | int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) | ||
573 | { | 587 | { |
574 | struct coproc_params params; | 588 | struct coproc_params params; |
575 | 589 | ||
@@ -583,9 +597,37 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
583 | params.Op2 = (kvm_vcpu_get_hsr(vcpu) >> 17) & 0x7; | 597 | params.Op2 = (kvm_vcpu_get_hsr(vcpu) >> 17) & 0x7; |
584 | params.Rt2 = 0; | 598 | params.Rt2 = 0; |
585 | 599 | ||
600 | return params; | ||
601 | } | ||
602 | |||
603 | /** | ||
604 | * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access | ||
605 | * @vcpu: The VCPU pointer | ||
606 | * @run: The kvm_run struct | ||
607 | */ | ||
608 | int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) | ||
609 | { | ||
610 | struct coproc_params params = decode_32bit_hsr(vcpu); | ||
586 | return emulate_cp15(vcpu, ¶ms); | 611 | return emulate_cp15(vcpu, ¶ms); |
587 | } | 612 | } |
588 | 613 | ||
614 | /** | ||
615 | * kvm_handle_cp14_32 -- handles a mrc/mcr trap on a guest CP14 access | ||
616 | * @vcpu: The VCPU pointer | ||
617 | * @run: The kvm_run struct | ||
618 | */ | ||
619 | int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run) | ||
620 | { | ||
621 | struct coproc_params params = decode_32bit_hsr(vcpu); | ||
622 | |||
623 | /* raz_wi cp14 */ | ||
624 | trap_raz_wi(vcpu, ¶ms, NULL); | ||
625 | |||
626 | /* handled */ | ||
627 | kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); | ||
628 | return 1; | ||
629 | } | ||
630 | |||
589 | /****************************************************************************** | 631 | /****************************************************************************** |
590 | * Userspace API | 632 | * Userspace API |
591 | *****************************************************************************/ | 633 | *****************************************************************************/ |