This means we generate the value at reset time. ACTLR already had a spot in the cp15 array (unused), but L2CTLR needs a new one. In particular, this means that qemu must create all the registers before calling KVM_SET_SREGS to set the target. Signed-off-by: Rusty Russell <rusty.russell@xxxxxxxxxx> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 91e40e7..045eb3a 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -90,6 +90,7 @@ enum cp15_regs { c5_AIFSR, /* Auxilary Instruction Fault Status Register */ c6_DFAR, /* Data Fault Address Register */ c6_IFAR, /* Instruction Fault Address Register */ + c9_L2CTLR, /* Cortex A15 L2 Control Register */ c10_PRRR, /* Primary Region Remap Register */ c10_NMRR, /* Normal Memory Remap Register */ c12_VBAR, /* Vector Base Address Register */ diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c index fd5b515..8724c3f 100644 --- a/arch/arm/kvm/coproc.c +++ b/arch/arm/kvm/coproc.c @@ -127,17 +127,23 @@ static bool access_l2ctlr(struct kvm_vcpu *vcpu, const struct coproc_params *p, const struct coproc_reg *r) { - u32 l2ctlr, ncores; - if (p->is_write) return ignore_write(vcpu, p, false); + *vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[c9_L2CTLR]; + return true; +} + +static void reset_l2ctlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r) +{ + u32 l2ctlr, ncores; + asm volatile("mrc p15, 1, %0, c9, c0, 2\n" : "=r" (l2ctlr)); l2ctlr &= ~(3 << 24); ncores = atomic_read(&vcpu->kvm->online_vcpus) - 1; l2ctlr |= (ncores & 3) << 24; - *vcpu_reg(vcpu, p->Rt1) = l2ctlr; - return true; + + vcpu->arch.cp15[c9_L2CTLR] = l2ctlr; } /* A15 TRM 4.3.49: R/O WI (even if NSACR.NS_L2ERR, a write of 1 is ignored). */ @@ -167,11 +173,18 @@ static bool access_actlr(struct kvm_vcpu *vcpu, const struct coproc_params *p, const struct coproc_reg *r) { - u32 actlr; - if (p->is_write) return ignore_write(vcpu, p, false); + *vcpu_reg(vcpu, p->Rt1) = vcpu->arch.cp15[c1_ACTLR]; + return true; +} + +static void reset_actlr(struct kvm_vcpu *vcpu, const struct coproc_reg *r) +{ + u32 actlr; + + /* ACTLR contains SMP bit: make sure you create all cpus first! */ asm volatile("mrc p15, 0, %0, c1, c0, 1\n" : "=r" (actlr)); /* Make the SMP bit consistent with the guest configuration */ if (atomic_read(&vcpu->kvm->online_vcpus) > 1) @@ -179,8 +192,7 @@ static bool access_actlr(struct kvm_vcpu *vcpu, else actlr &= ~(1U << 6); - *vcpu_reg(vcpu, p->Rt1) = actlr; - return true; + vcpu->arch.cp15[c1_ACTLR] = actlr; } /* See note at ARM ARM B1.14.4 */ @@ -375,15 +387,17 @@ static const struct coproc_reg cp15_cortex_a15_regs[] = { { CRn( 1), CRm( 0), Op1( 0), Op2( 0), is32, NULL, reset_val, c1_SCTLR, 0x00C50078 }, /* ACTLR: trapped by HCR.TAC bit. */ - { CRn( 1), CRm( 0), Op1( 0), Op2( 1), is32, access_actlr}, + { CRn( 1), CRm( 0), Op1( 0), Op2( 1), is32, + access_actlr, reset_actlr, c1_ACTLR }, /* CPACR: swapped by interrupt.S. */ { CRn( 1), CRm( 0), Op1( 0), Op2( 2), is32, NULL, reset_val, c1_CPACR, 0x00000000 }, /* * L2CTLR access (guest wants to know #CPUs). */ - { CRn( 9), CRm( 0), Op1( 1), Op2( 2), is32, access_l2ctlr}, + { CRn( 9), CRm( 0), Op1( 1), Op2( 2), is32, + access_l2ctlr, reset_l2ctlr, c9_L2CTLR }, { CRn( 9), CRm( 0), Op1( 1), Op2( 3), is32, access_l2ectlr}, /* The Configuration Base Address Register. */ _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm