static void __hyp_text __sysreg_save_state(struct kvm_cpu_context *ctxt) { ctxt->sys_regs[MPIDR_EL1] = read_sysreg(vmpidr_el2); ctxt->sys_regs[CSSELR_EL1] = read_sysreg(csselr_el1); ctxt->sys_regs[SCTLR_EL1] = read_sysreg_el1(sctlr); ctxt->sys_regs[CPACR_EL1] = read_sysreg_el1(cpacr); ctxt->sys_regs[TTBR0_EL1] = read_sysreg_el1(ttbr0); ctxt->sys_regs[TTBR1_EL1] = read_sysreg_el1(ttbr1); ctxt->sys_regs[TCR_EL1] = read_sysreg_el1(tcr); ctxt->sys_regs[ESR_EL1] = read_sysreg_el1(esr); ctxt->sys_regs[AFSR0_EL1] = read_sysreg_el1(afsr0); ctxt->sys_regs[AFSR1_EL1] = read_sysreg_el1(afsr1); ctxt->sys_regs[FAR_EL1] = read_sysreg_el1(far); ctxt->sys_regs[MAIR_EL1] = read_sysreg_el1(mair); ctxt->sys_regs[VBAR_EL1] = read_sysreg_el1(vbar); ctxt->sys_regs[CONTEXTIDR_EL1] = read_sysreg_el1(contextidr); ctxt->sys_regs[AMAIR_EL1] = read_sysreg_el1(amair); ctxt->sys_regs[CNTKCTL_EL1] = read_sysreg_el1(cntkctl); ctxt->sys_regs[PAR_EL1] = read_sysreg(par_el1); ctxt->sys_regs[TPIDR_EL1] = read_sysreg(tpidr_el1); ctxt->gp_regs.sp_el1 = read_sysreg(sp_el1); ctxt->gp_regs.elr_el1 = read_sysreg_el1(elr); ctxt->gp_regs.spsr[KVM_SPSR_EL1]= read_sysreg_el1(spsr); ctxt->gp_regs.regs.pc = read_sysreg_el2(elr); ctxt->gp_regs.regs.pstate = read_sysreg_el2(spsr); if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN)) ctxt->sys_regs[DISR_EL1] = read_sysreg_s(SYS_VDISR_EL2); }
static void __hyp_text __sysreg_save_common_state(struct kvm_cpu_context *ctxt) { ctxt->sys_regs[ACTLR_EL1] = read_sysreg(actlr_el1); ctxt->sys_regs[TPIDR_EL0] = read_sysreg(tpidr_el0); ctxt->sys_regs[TPIDRRO_EL0] = read_sysreg(tpidrro_el0); ctxt->sys_regs[MDSCR_EL1] = read_sysreg(mdscr_el1); ctxt->gp_regs.regs.sp = read_sysreg(sp_el0); }
static bool __hyp_text __is_be(struct kvm_vcpu *vcpu) { if (vcpu_mode_is_32bit(vcpu)) return !!(read_sysreg_el2(spsr) & PSR_AA32_E_BIT); return !!(read_sysreg(SCTLR_EL1) & SCTLR_ELx_EE); }
static void cntfrq_read_handler(unsigned int esr, struct pt_regs *regs) { int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; pt_regs_write_reg(regs, rt, read_sysreg(cntfrq_el0)); regs->pc += 4; }
static inline u32 armv8pmu_read_counter(struct perf_event *event) { struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu); struct hw_perf_event *hwc = &event->hw; int idx = hwc->idx; u32 value = 0; if (!armv8pmu_counter_valid(cpu_pmu, idx)) pr_err("CPU%u reading wrong counter %d\n", smp_processor_id(), idx); else if (idx == ARMV8_IDX_CYCLE_COUNTER) value = read_sysreg(pmccntr_el0); else if (armv8pmu_select_counter(idx) == idx) value = read_sysreg(pmxevcntr_el0); return value; }
static void cntfrq_read_handler(unsigned int esr, struct pt_regs *regs) { int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT; if (rt != 31) regs->regs[rt] = read_sysreg(cntfrq_el0); regs->pc += 4; }
void __hyp_text enable_el1_phys_timer_access(void) { u64 val; /* Allow physical timer/counter access for the host */ val = read_sysreg(cnthctl_el2); val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN; write_sysreg(val, cnthctl_el2); }
static inline enum cache_type get_cache_type(int level) { u64 clidr; if (level > MAX_CACHE_LEVEL) return CACHE_TYPE_NOCACHE; clidr = read_sysreg(clidr_el1); return CLIDR_CTYPE(clidr, level); }
static void __armv8pmu_probe_pmu(void *info) { struct arm_pmu *cpu_pmu = info; u32 pmceid[2]; /* Read the nb of CNTx counters supported from PMNC */ cpu_pmu->num_events = (armv8pmu_pmcr_read() >> ARMV8_PMU_PMCR_N_SHIFT) & ARMV8_PMU_PMCR_N_MASK; /* Add the CPU cycles counter */ cpu_pmu->num_events += 1; pmceid[0] = read_sysreg(pmceid0_el0); pmceid[1] = read_sysreg(pmceid1_el0); bitmap_from_u32array(cpu_pmu->pmceid_bitmap, ARMV8_PMUV3_MAX_COMMON_EVENTS, pmceid, ARRAY_SIZE(pmceid)); }
/* * Cache Size Selection Register(CSSELR) selects which Cache Size ID * Register(CCSIDR) is accessible by specifying the required cache * level and the cache type. We need to ensure that no one else changes * CSSELR by calling this in non-preemtible context */ u64 __attribute_const__ cache_get_ccsidr(u64 csselr) { u64 ccsidr; WARN_ON(preemptible()); write_sysreg(csselr, csselr_el1); isb(); ccsidr = read_sysreg(ccsidr_el1); return ccsidr; }
unsigned long vcpu_read_spsr32(const struct kvm_vcpu *vcpu) { int spsr_idx = vcpu_spsr32_mode(vcpu); if (!vcpu->arch.sysregs_loaded_on_cpu) return vcpu_gp_regs(vcpu)->spsr[spsr_idx]; switch (spsr_idx) { case KVM_SPSR_SVC: return read_sysreg_el1(spsr); case KVM_SPSR_ABT: return read_sysreg(spsr_abt); case KVM_SPSR_UND: return read_sysreg(spsr_und); case KVM_SPSR_IRQ: return read_sysreg(spsr_irq); case KVM_SPSR_FIQ: return read_sysreg(spsr_fiq); default: BUG(); } }
static inline u32 armv8pmu_getreset_flags(void) { u32 value; /* Read */ value = read_sysreg(pmovsclr_el0); /* Write to clear flags */ value &= ARMV8_PMU_OVSR_MASK; write_sysreg(value, pmovsclr_el0); return value; }
/* vcpu is already in the HYP VA space */ void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu) { struct kvm *kvm = kern_hyp_va(vcpu->kvm); struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; u64 val; if (kvm->arch.timer.enabled) { timer->cntv_ctl = read_sysreg(cntv_ctl_el0); timer->cntv_cval = read_sysreg(cntv_cval_el0); } /* Disable the virtual timer */ write_sysreg(0, cntv_ctl_el0); /* Allow physical timer/counter access for the host */ val = read_sysreg(cnthctl_el2); val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN; write_sysreg(val, cnthctl_el2); /* Clear cntvoff for the host */ write_sysreg(0, cntvoff_el2); }
void __hyp_text disable_el1_phys_timer_access(void) { u64 val; /* * Disallow physical timer access for the guest * Physical counter access is allowed */ val = read_sysreg(cnthctl_el2); val &= ~CNTHCTL_EL1PCEN; val |= CNTHCTL_EL1PCTEN; write_sysreg(val, cnthctl_el2); }
static void tls_thread_switch(struct task_struct *next) { unsigned long tpidr, tpidrro; tpidr = read_sysreg(tpidr_el0); *task_user_tls(current) = tpidr; tpidr = *task_user_tls(next); tpidrro = is_compat_thread(task_thread_info(next)) ? next->thread.tp_value : 0; write_sysreg(tpidr, tpidr_el0); write_sysreg(tpidrro, tpidrro_el0); }
/* * Prepare vcpu for saving the host's FPSIMD state and loading the guest's. * The actual loading is done by the FPSIMD access trap taken to hyp. * * Here, we just set the correct metadata to indicate that the FPSIMD * state in the cpu regs (if any) belongs to current on the host. * * TIF_SVE is backed up here, since it may get clobbered with guest state. * This flag is restored by kvm_arch_vcpu_put_fp(vcpu). */ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu) { BUG_ON(!current->mm); vcpu->arch.flags &= ~(KVM_ARM64_FP_ENABLED | KVM_ARM64_HOST_SVE_IN_USE | KVM_ARM64_HOST_SVE_ENABLED); vcpu->arch.flags |= KVM_ARM64_FP_HOST; if (test_thread_flag(TIF_SVE)) vcpu->arch.flags |= KVM_ARM64_HOST_SVE_IN_USE; if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN) vcpu->arch.flags |= KVM_ARM64_HOST_SVE_ENABLED; }
int copy_thread(unsigned long clone_flags, unsigned long stack_start, unsigned long stk_sz, struct task_struct *p) { struct pt_regs *childregs = task_pt_regs(p); memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context)); if (likely(!(p->flags & PF_KTHREAD))) { *childregs = *current_pt_regs(); childregs->regs[0] = 0; /* * Read the current TLS pointer from tpidr_el0 as it may be * out-of-sync with the saved value. */ *task_user_tls(p) = read_sysreg(tpidr_el0); if (stack_start) { if (is_compat_thread(task_thread_info(p))) childregs->compat_sp = stack_start; else childregs->sp = stack_start; } /* * If a TLS pointer was passed to clone (4th argument), use it * for the new thread. */ if (clone_flags & CLONE_SETTLS) p->thread.tp_value = childregs->regs[3]; } else { memset(childregs, 0, sizeof(struct pt_regs)); childregs->pstate = PSR_MODE_EL1h; if (IS_ENABLED(CONFIG_ARM64_UAO) && cpus_have_const_cap(ARM64_HAS_UAO)) childregs->pstate |= PSR_UAO_BIT; p->thread.cpu_context.x19 = stack_start; p->thread.cpu_context.x20 = stk_sz; } p->thread.cpu_context.pc = (unsigned long)ret_from_fork; p->thread.cpu_context.sp = (unsigned long)childregs; ptrace_hw_copy_thread(p); return 0; }
void __hyp_text __sysreg32_save_state(struct kvm_vcpu *vcpu) { u64 *spsr, *sysreg; if (read_sysreg(hcr_el2) & HCR_RW) return; spsr = vcpu->arch.ctxt.gp_regs.spsr; sysreg = vcpu->arch.ctxt.sys_regs; spsr[KVM_SPSR_ABT] = read_sysreg(spsr_abt); spsr[KVM_SPSR_UND] = read_sysreg(spsr_und); spsr[KVM_SPSR_IRQ] = read_sysreg(spsr_irq); spsr[KVM_SPSR_FIQ] = read_sysreg(spsr_fiq); sysreg[DACR32_EL2] = read_sysreg(dacr32_el2); sysreg[IFSR32_EL2] = read_sysreg(ifsr32_el2); if (__fpsimd_enabled()) sysreg[FPEXC32_EL2] = read_sysreg(fpexc32_el2); if (vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY) sysreg[DBGVCR32_EL2] = read_sysreg(dbgvcr32_el2); }
static void __cpu_do_idle_irqprio(void) { unsigned long pmr; unsigned long daif_bits; daif_bits = read_sysreg(daif); write_sysreg(daif_bits | PSR_I_BIT, daif); /* * Unmask PMR before going idle to make sure interrupts can * be raised. */ pmr = gic_read_pmr(); gic_write_pmr(GIC_PRIO_IRQON); __cpu_do_idle(); gic_write_pmr(pmr); write_sysreg(daif_bits, daif); }
static void __hyp_text __tlb_switch_to_guest_vhe(struct kvm *kvm, unsigned long *flags) { u64 val; local_irq_save(*flags); /* * With VHE enabled, we have HCR_EL2.{E2H,TGE} = {1,1}, and * most TLB operations target EL2/EL0. In order to affect the * guest TLBs (EL1/EL0), we need to change one of these two * bits. Changing E2H is impossible (goodbye TTBR1_EL2), so * let's flip TGE before executing the TLB operation. */ write_sysreg(kvm->arch.vttbr, vttbr_el2); val = read_sysreg(hcr_el2); val &= ~HCR_TGE; write_sysreg(val, hcr_el2); isb(); }
void __hyp_text __sysreg32_restore_state(struct kvm_vcpu *vcpu) { u64 *spsr, *sysreg; if (read_sysreg(hcr_el2) & HCR_RW) return; spsr = vcpu->arch.ctxt.gp_regs.spsr; sysreg = vcpu->arch.ctxt.sys_regs; write_sysreg(spsr[KVM_SPSR_ABT], spsr_abt); write_sysreg(spsr[KVM_SPSR_UND], spsr_und); write_sysreg(spsr[KVM_SPSR_IRQ], spsr_irq); write_sysreg(spsr[KVM_SPSR_FIQ], spsr_fiq); write_sysreg(sysreg[DACR32_EL2], dacr32_el2); write_sysreg(sysreg[IFSR32_EL2], ifsr32_el2); if (vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY) write_sysreg(sysreg[DBGVCR32_EL2], dbgvcr32_el2); }
void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu) { struct kvm *kvm = kern_hyp_va(vcpu->kvm); struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; u64 val; /* * Disallow physical timer access for the guest * Physical counter access is allowed */ val = read_sysreg(cnthctl_el2); val &= ~CNTHCTL_EL1PCEN; val |= CNTHCTL_EL1PCTEN; write_sysreg(val, cnthctl_el2); if (kvm->arch.timer.enabled) { write_sysreg(kvm->arch.timer.cntvoff, cntvoff_el2); write_sysreg(timer->cntv_cval, cntv_cval_el0); isb(); write_sysreg(timer->cntv_ctl, cntv_ctl_el0); } }
if (!efi_sve_state) goto fail; return; fail: panic("Cannot allocate percpu memory for EFI SVE save/restore"); } /* * Enable SVE for EL1. * Intended for use by the cpufeatures code during CPU boot. */ void sve_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p) { write_sysreg(read_sysreg(CPACR_EL1) | CPACR_EL1_ZEN_EL1EN, CPACR_EL1); isb(); } /* * Read the pseudo-ZCR used by cpufeatures to identify the supported SVE * vector length. * * Use only if SVE is present. * This function clobbers the SVE vector length. */ u64 read_zcr_features(void) { u64 zcr; unsigned int vq_max;
}, { .oem_id = "HISI ", .oem_table_id = "HIP07 ", .oem_revision = 0, }, { /* Sentinel indicating the end of the OEM array */ }, }; #endif #ifdef CONFIG_ARM64_ERRATUM_858921 static u64 notrace arm64_858921_read_cntvct_el0(void) { u64 old, new; old = read_sysreg(cntvct_el0); new = read_sysreg(cntvct_el0); return (((old ^ new) >> 32) & 1) ? old : new; } #endif #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *, timer_unstable_counter_workaround); EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround); DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled); EXPORT_SYMBOL_GPL(arch_timer_read_ool_enabled); static void erratum_set_next_event_tval_generic(const int access, unsigned long evt, struct clock_event_device *clk)
static inline u32 prbar_read(void) { return read_sysreg(PRBAR); }
void tls_preserve_current_state(void) { *task_user_tls(current) = read_sysreg(tpidr_el0); }
static inline u32 armv8pmu_read_evcntr(int idx) { armv8pmu_select_counter(idx); return read_sysreg(pmxevcntr_el0); }
static void reset_actlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { vcpu_sys_reg(vcpu, ACTLR_EL1) = read_sysreg(actlr_el1); }
int copy_thread(unsigned long clone_flags, unsigned long stack_start, unsigned long stk_sz, struct task_struct *p) { struct pt_regs *childregs = task_pt_regs(p); memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context)); /* * Unalias p->thread.sve_state (if any) from the parent task * and disable discard SVE state for p: */ clear_tsk_thread_flag(p, TIF_SVE); p->thread.sve_state = NULL; /* * In case p was allocated the same task_struct pointer as some * other recently-exited task, make sure p is disassociated from * any cpu that may have run that now-exited task recently. * Otherwise we could erroneously skip reloading the FPSIMD * registers for p. */ fpsimd_flush_task_state(p); if (likely(!(p->flags & PF_KTHREAD))) { *childregs = *current_pt_regs(); childregs->regs[0] = 0; /* * Read the current TLS pointer from tpidr_el0 as it may be * out-of-sync with the saved value. */ *task_user_tls(p) = read_sysreg(tpidr_el0); if (stack_start) { if (is_compat_thread(task_thread_info(p))) childregs->compat_sp = stack_start; else childregs->sp = stack_start; } /* * If a TLS pointer was passed to clone (4th argument), use it * for the new thread. */ if (clone_flags & CLONE_SETTLS) p->thread.uw.tp_value = childregs->regs[3]; } else { memset(childregs, 0, sizeof(struct pt_regs)); childregs->pstate = PSR_MODE_EL1h; if (IS_ENABLED(CONFIG_ARM64_UAO) && cpus_have_const_cap(ARM64_HAS_UAO)) childregs->pstate |= PSR_UAO_BIT; if (arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE) childregs->pstate |= PSR_SSBS_BIT; if (system_uses_irq_prio_masking()) childregs->pmr_save = GIC_PRIO_IRQON; p->thread.cpu_context.x19 = stack_start; p->thread.cpu_context.x20 = stk_sz; } p->thread.cpu_context.pc = (unsigned long)ret_from_fork; p->thread.cpu_context.sp = (unsigned long)childregs; ptrace_hw_copy_thread(p); return 0; }
static inline u32 armv8pmu_pmcr_read(void) { return read_sysreg(pmcr_el0); }