aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorChristoffer Dall <c.dall@virtualopensystems.com>2013-01-20 18:28:10 -0500
committerChristoffer Dall <c.dall@virtualopensystems.com>2013-01-23 13:29:14 -0500
commitc27581ed32275897651a84043b04ea3ccdd644e0 (patch)
treedc541728d54d1c9114eafc3930634434c7912a69 /arch
parent1138245ccf9652429630c09fb068e9b12c56c3d3 (diff)
KVM: ARM: Demux CCSIDR in the userspace API
The Cache Size Selection Register (CSSELR) selects the current Cache Size ID Register (CCSIDR). You write which cache you are interested in to CSSELR, and read the information out of CCSIDR. Which cache numbers are valid is known by reading the Cache Level ID Register (CLIDR). To export this state to userspace, we add a KVM_REG_ARM_DEMUX numberspace (17), which uses 8 bits to represent which register is being demultiplexed (0 for CCSIDR), and the lower 8 bits to represent this demultiplexing (in our case, the CSSELR value, which is 4 bits). Reviewed-by: Will Deacon <will.deacon@arm.com> Reviewed-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/include/uapi/asm/kvm.h9
-rw-r--r--arch/arm/kvm/coproc.c164
2 files changed, 170 insertions, 3 deletions
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index 53f45f146875..71ae27ec0599 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -104,6 +104,15 @@ struct kvm_arch_memory_slot {
104#define KVM_REG_ARM_CORE (0x0010 << KVM_REG_ARM_COPROC_SHIFT) 104#define KVM_REG_ARM_CORE (0x0010 << KVM_REG_ARM_COPROC_SHIFT)
105#define KVM_REG_ARM_CORE_REG(name) (offsetof(struct kvm_regs, name) / 4) 105#define KVM_REG_ARM_CORE_REG(name) (offsetof(struct kvm_regs, name) / 4)
106 106
107/* Some registers need more space to represent values. */
108#define KVM_REG_ARM_DEMUX (0x0011 << KVM_REG_ARM_COPROC_SHIFT)
109#define KVM_REG_ARM_DEMUX_ID_MASK 0x000000000000FF00
110#define KVM_REG_ARM_DEMUX_ID_SHIFT 8
111#define KVM_REG_ARM_DEMUX_ID_CCSIDR (0x00 << KVM_REG_ARM_DEMUX_ID_SHIFT)
112#define KVM_REG_ARM_DEMUX_VAL_MASK 0x00000000000000FF
113#define KVM_REG_ARM_DEMUX_VAL_SHIFT 0
114
115
107/* KVM_IRQ_LINE irq field index values */ 116/* KVM_IRQ_LINE irq field index values */
108#define KVM_ARM_IRQ_TYPE_SHIFT 24 117#define KVM_ARM_IRQ_TYPE_SHIFT 24
109#define KVM_ARM_IRQ_TYPE_MASK 0xff 118#define KVM_ARM_IRQ_TYPE_MASK 0xff
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index 95a0f5e5c1fc..1827b643af15 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -35,6 +35,12 @@
35 * Co-processor emulation 35 * Co-processor emulation
36 *****************************************************************************/ 36 *****************************************************************************/
37 37
38/* 3 bits per cache level, as per CLIDR, but non-existent caches always 0 */
39static u32 cache_levels;
40
41/* CSSELR values; used to index KVM_REG_ARM_DEMUX_ID_CCSIDR */
42#define CSSELR_MAX 12
43
38int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run) 44int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run)
39{ 45{
40 kvm_inject_undefined(vcpu); 46 kvm_inject_undefined(vcpu);
@@ -548,11 +554,113 @@ static int set_invariant_cp15(u64 id, void __user *uaddr)
548 return 0; 554 return 0;
549} 555}
550 556
557static bool is_valid_cache(u32 val)
558{
559 u32 level, ctype;
560
561 if (val >= CSSELR_MAX)
562 return -ENOENT;
563
564 /* Bottom bit is Instruction or Data bit. Next 3 bits are level. */
565 level = (val >> 1);
566 ctype = (cache_levels >> (level * 3)) & 7;
567
568 switch (ctype) {
569 case 0: /* No cache */
570 return false;
571 case 1: /* Instruction cache only */
572 return (val & 1);
573 case 2: /* Data cache only */
574 case 4: /* Unified cache */
575 return !(val & 1);
576 case 3: /* Separate instruction and data caches */
577 return true;
578 default: /* Reserved: we can't know instruction or data. */
579 return false;
580 }
581}
582
583/* Which cache CCSIDR represents depends on CSSELR value. */
584static u32 get_ccsidr(u32 csselr)
585{
586 u32 ccsidr;
587
588 /* Make sure noone else changes CSSELR during this! */
589 local_irq_disable();
590 /* Put value into CSSELR */
591 asm volatile("mcr p15, 2, %0, c0, c0, 0" : : "r" (csselr));
592 isb();
593 /* Read result out of CCSIDR */
594 asm volatile("mrc p15, 1, %0, c0, c0, 0" : "=r" (ccsidr));
595 local_irq_enable();
596
597 return ccsidr;
598}
599
600static int demux_c15_get(u64 id, void __user *uaddr)
601{
602 u32 val;
603 u32 __user *uval = uaddr;
604
605 /* Fail if we have unknown bits set. */
606 if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
607 | ((1 << KVM_REG_ARM_COPROC_SHIFT)-1)))
608 return -ENOENT;
609
610 switch (id & KVM_REG_ARM_DEMUX_ID_MASK) {
611 case KVM_REG_ARM_DEMUX_ID_CCSIDR:
612 if (KVM_REG_SIZE(id) != 4)
613 return -ENOENT;
614 val = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
615 >> KVM_REG_ARM_DEMUX_VAL_SHIFT;
616 if (!is_valid_cache(val))
617 return -ENOENT;
618
619 return put_user(get_ccsidr(val), uval);
620 default:
621 return -ENOENT;
622 }
623}
624
625static int demux_c15_set(u64 id, void __user *uaddr)
626{
627 u32 val, newval;
628 u32 __user *uval = uaddr;
629
630 /* Fail if we have unknown bits set. */
631 if (id & ~(KVM_REG_ARCH_MASK|KVM_REG_SIZE_MASK|KVM_REG_ARM_COPROC_MASK
632 | ((1 << KVM_REG_ARM_COPROC_SHIFT)-1)))
633 return -ENOENT;
634
635 switch (id & KVM_REG_ARM_DEMUX_ID_MASK) {
636 case KVM_REG_ARM_DEMUX_ID_CCSIDR:
637 if (KVM_REG_SIZE(id) != 4)
638 return -ENOENT;
639 val = (id & KVM_REG_ARM_DEMUX_VAL_MASK)
640 >> KVM_REG_ARM_DEMUX_VAL_SHIFT;
641 if (!is_valid_cache(val))
642 return -ENOENT;
643
644 if (get_user(newval, uval))
645 return -EFAULT;
646
647 /* This is also invariant: you can't change it. */
648 if (newval != get_ccsidr(val))
649 return -EINVAL;
650 return 0;
651 default:
652 return -ENOENT;
653 }
654}
655
551int kvm_arm_coproc_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) 656int kvm_arm_coproc_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
552{ 657{
553 const struct coproc_reg *r; 658 const struct coproc_reg *r;
554 void __user *uaddr = (void __user *)(long)reg->addr; 659 void __user *uaddr = (void __user *)(long)reg->addr;
555 660
661 if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_DEMUX)
662 return demux_c15_get(reg->id, uaddr);
663
556 r = index_to_coproc_reg(vcpu, reg->id); 664 r = index_to_coproc_reg(vcpu, reg->id);
557 if (!r) 665 if (!r)
558 return get_invariant_cp15(reg->id, uaddr); 666 return get_invariant_cp15(reg->id, uaddr);
@@ -566,6 +674,9 @@ int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
566 const struct coproc_reg *r; 674 const struct coproc_reg *r;
567 void __user *uaddr = (void __user *)(long)reg->addr; 675 void __user *uaddr = (void __user *)(long)reg->addr;
568 676
677 if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_DEMUX)
678 return demux_c15_set(reg->id, uaddr);
679
569 r = index_to_coproc_reg(vcpu, reg->id); 680 r = index_to_coproc_reg(vcpu, reg->id);
570 if (!r) 681 if (!r)
571 return set_invariant_cp15(reg->id, uaddr); 682 return set_invariant_cp15(reg->id, uaddr);
@@ -574,6 +685,33 @@ int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
574 return reg_from_user(&vcpu->arch.cp15[r->reg], uaddr, reg->id); 685 return reg_from_user(&vcpu->arch.cp15[r->reg], uaddr, reg->id);
575} 686}
576 687
688static unsigned int num_demux_regs(void)
689{
690 unsigned int i, count = 0;
691
692 for (i = 0; i < CSSELR_MAX; i++)
693 if (is_valid_cache(i))
694 count++;
695
696 return count;
697}
698
699static int write_demux_regids(u64 __user *uindices)
700{
701 u64 val = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_DEMUX;
702 unsigned int i;
703
704 val |= KVM_REG_ARM_DEMUX_ID_CCSIDR;
705 for (i = 0; i < CSSELR_MAX; i++) {
706 if (!is_valid_cache(i))
707 continue;
708 if (put_user(val | i, uindices))
709 return -EFAULT;
710 uindices++;
711 }
712 return 0;
713}
714
577static u64 cp15_to_index(const struct coproc_reg *reg) 715static u64 cp15_to_index(const struct coproc_reg *reg)
578{ 716{
579 u64 val = KVM_REG_ARM | (15 << KVM_REG_ARM_COPROC_SHIFT); 717 u64 val = KVM_REG_ARM | (15 << KVM_REG_ARM_COPROC_SHIFT);
@@ -649,6 +787,7 @@ static int walk_cp15(struct kvm_vcpu *vcpu, u64 __user *uind)
649unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu) 787unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu)
650{ 788{
651 return ARRAY_SIZE(invariant_cp15) 789 return ARRAY_SIZE(invariant_cp15)
790 + num_demux_regs()
652 + walk_cp15(vcpu, (u64 __user *)NULL); 791 + walk_cp15(vcpu, (u64 __user *)NULL);
653} 792}
654 793
@@ -665,9 +804,11 @@ int kvm_arm_copy_coproc_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
665 } 804 }
666 805
667 err = walk_cp15(vcpu, uindices); 806 err = walk_cp15(vcpu, uindices);
668 if (err > 0) 807 if (err < 0)
669 err = 0; 808 return err;
670 return err; 809 uindices += err;
810
811 return write_demux_regids(uindices);
671} 812}
672 813
673void kvm_coproc_table_init(void) 814void kvm_coproc_table_init(void)
@@ -681,6 +822,23 @@ void kvm_coproc_table_init(void)
681 /* We abuse the reset function to overwrite the table itself. */ 822 /* We abuse the reset function to overwrite the table itself. */
682 for (i = 0; i < ARRAY_SIZE(invariant_cp15); i++) 823 for (i = 0; i < ARRAY_SIZE(invariant_cp15); i++)
683 invariant_cp15[i].reset(NULL, &invariant_cp15[i]); 824 invariant_cp15[i].reset(NULL, &invariant_cp15[i]);
825
826 /*
827 * CLIDR format is awkward, so clean it up. See ARM B4.1.20:
828 *
829 * If software reads the Cache Type fields from Ctype1
830 * upwards, once it has seen a value of 0b000, no caches
831 * exist at further-out levels of the hierarchy. So, for
832 * example, if Ctype3 is the first Cache Type field with a
833 * value of 0b000, the values of Ctype4 to Ctype7 must be
834 * ignored.
835 */
836 asm volatile("mrc p15, 1, %0, c0, c0, 1" : "=r" (cache_levels));
837 for (i = 0; i < 7; i++)
838 if (((cache_levels >> (i*3)) & 7) == 0)
839 break;
840 /* Clear all higher bits. */
841 cache_levels &= (1 << (i*3))-1;
684} 842}
685 843
686/** 844/**