]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - arch/arm64/kvm/sys_regs.c
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[karo-tx-linux.git] / arch / arm64 / kvm / sys_regs.c
index b96afdf6cee4de3d2abcd0ae75eeebaa6ca89681..c370b4014799697c292a99cf24721a425fcb3790 100644 (file)
@@ -113,6 +113,27 @@ static bool access_vm_reg(struct kvm_vcpu *vcpu,
        return true;
 }
 
+/*
+ * Trap handler for the GICv3 SGI generation system register.
+ * Forward the request to the VGIC emulation.
+ * The cp15_64 code makes sure this automatically works
+ * for both AArch64 and AArch32 accesses.
+ */
+static bool access_gic_sgi(struct kvm_vcpu *vcpu,
+                          const struct sys_reg_params *p,
+                          const struct sys_reg_desc *r)
+{
+       u64 val;
+
+       if (!p->is_write)
+               return read_from_write_only(vcpu, p);
+
+       val = *vcpu_reg(vcpu, p->Rt);
+       vgic_v3_dispatch_sgi(vcpu, val);
+
+       return true;
+}
+
 static bool trap_raz_wi(struct kvm_vcpu *vcpu,
                        const struct sys_reg_params *p,
                        const struct sys_reg_desc *r)
@@ -200,10 +221,19 @@ static void reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
 
 static void reset_mpidr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
 {
+       u64 mpidr;
+
        /*
-        * Simply map the vcpu_id into the Aff0 field of the MPIDR.
+        * Map the vcpu_id into the first three affinity level fields of
+        * the MPIDR. We limit the number of VCPUs in level 0 due to a
+        * limitation to 16 CPUs in that level in the ICC_SGIxR registers
+        * of the GICv3 to be able to address each CPU directly when
+        * sending IPIs.
         */
-       vcpu_sys_reg(vcpu, MPIDR_EL1) = (1UL << 31) | (vcpu->vcpu_id & 0xff);
+       mpidr = (vcpu->vcpu_id & 0x0f) << MPIDR_LEVEL_SHIFT(0);
+       mpidr |= ((vcpu->vcpu_id >> 4) & 0xff) << MPIDR_LEVEL_SHIFT(1);
+       mpidr |= ((vcpu->vcpu_id >> 12) & 0xff) << MPIDR_LEVEL_SHIFT(2);
+       vcpu_sys_reg(vcpu, MPIDR_EL1) = (1ULL << 31) | mpidr;
 }
 
 /* Silly macro to expand the DBG{BCR,BVR,WVR,WCR}n_EL1 registers in one go */
@@ -373,6 +403,9 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b0000), Op2(0b000),
          NULL, reset_val, VBAR_EL1, 0 },
 
+       /* ICC_SGI1R_EL1 */
+       { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1011), Op2(0b101),
+         access_gic_sgi },
        /* ICC_SRE_EL1 */
        { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1100), Op2(0b101),
          trap_raz_wi },
@@ -605,6 +638,8 @@ static const struct sys_reg_desc cp14_64_regs[] = {
  * register).
  */
 static const struct sys_reg_desc cp15_regs[] = {
+       { Op1( 0), CRn( 0), CRm(12), Op2( 0), access_gic_sgi },
+
        { Op1( 0), CRn( 1), CRm( 0), Op2( 0), access_vm_reg, NULL, c1_SCTLR },
        { Op1( 0), CRn( 2), CRm( 0), Op2( 0), access_vm_reg, NULL, c2_TTBR0 },
        { Op1( 0), CRn( 2), CRm( 0), Op2( 1), access_vm_reg, NULL, c2_TTBR1 },
@@ -652,6 +687,7 @@ static const struct sys_reg_desc cp15_regs[] = {
 
 static const struct sys_reg_desc cp15_64_regs[] = {
        { Op1( 0), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR0 },
+       { Op1( 0), CRn( 0), CRm(12), Op2( 0), access_gic_sgi },
        { Op1( 1), CRn( 0), CRm( 2), Op2( 0), access_vm_reg, NULL, c2_TTBR1 },
 };