162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * VGIC system registers handling functions for AArch64 mode 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/irqchip/arm-gic-v3.h> 762306a36Sopenharmony_ci#include <linux/kvm.h> 862306a36Sopenharmony_ci#include <linux/kvm_host.h> 962306a36Sopenharmony_ci#include <asm/kvm_emulate.h> 1062306a36Sopenharmony_ci#include "vgic/vgic.h" 1162306a36Sopenharmony_ci#include "sys_regs.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic int set_gic_ctlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, 1462306a36Sopenharmony_ci u64 val) 1562306a36Sopenharmony_ci{ 1662306a36Sopenharmony_ci u32 host_pri_bits, host_id_bits, host_seis, host_a3v, seis, a3v; 1762306a36Sopenharmony_ci struct vgic_cpu *vgic_v3_cpu = &vcpu->arch.vgic_cpu; 1862306a36Sopenharmony_ci struct vgic_vmcr vmcr; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci vgic_get_vmcr(vcpu, &vmcr); 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci /* 2362306a36Sopenharmony_ci * Disallow restoring VM state if not supported by this 2462306a36Sopenharmony_ci * hardware. 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_ci host_pri_bits = FIELD_GET(ICC_CTLR_EL1_PRI_BITS_MASK, val) + 1; 2762306a36Sopenharmony_ci if (host_pri_bits > vgic_v3_cpu->num_pri_bits) 2862306a36Sopenharmony_ci return -EINVAL; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci vgic_v3_cpu->num_pri_bits = host_pri_bits; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci host_id_bits = FIELD_GET(ICC_CTLR_EL1_ID_BITS_MASK, val); 3362306a36Sopenharmony_ci if (host_id_bits > vgic_v3_cpu->num_id_bits) 3462306a36Sopenharmony_ci return -EINVAL; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci vgic_v3_cpu->num_id_bits = host_id_bits; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci host_seis = FIELD_GET(ICH_VTR_SEIS_MASK, kvm_vgic_global_state.ich_vtr_el2); 3962306a36Sopenharmony_ci seis = FIELD_GET(ICC_CTLR_EL1_SEIS_MASK, val); 4062306a36Sopenharmony_ci if (host_seis != seis) 4162306a36Sopenharmony_ci return -EINVAL; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci host_a3v = FIELD_GET(ICH_VTR_A3V_MASK, kvm_vgic_global_state.ich_vtr_el2); 4462306a36Sopenharmony_ci a3v = FIELD_GET(ICC_CTLR_EL1_A3V_MASK, val); 4562306a36Sopenharmony_ci if (host_a3v != a3v) 4662306a36Sopenharmony_ci return -EINVAL; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci /* 4962306a36Sopenharmony_ci * Here set VMCR.CTLR in ICC_CTLR_EL1 layout. 5062306a36Sopenharmony_ci * The vgic_set_vmcr() will convert to ICH_VMCR layout. 5162306a36Sopenharmony_ci */ 5262306a36Sopenharmony_ci vmcr.cbpr = FIELD_GET(ICC_CTLR_EL1_CBPR_MASK, val); 5362306a36Sopenharmony_ci vmcr.eoim = FIELD_GET(ICC_CTLR_EL1_EOImode_MASK, val); 5462306a36Sopenharmony_ci vgic_set_vmcr(vcpu, &vmcr); 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci return 0; 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistatic int get_gic_ctlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, 6062306a36Sopenharmony_ci u64 *valp) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci struct vgic_cpu *vgic_v3_cpu = &vcpu->arch.vgic_cpu; 6362306a36Sopenharmony_ci struct vgic_vmcr vmcr; 6462306a36Sopenharmony_ci u64 val; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci vgic_get_vmcr(vcpu, &vmcr); 6762306a36Sopenharmony_ci val = 0; 6862306a36Sopenharmony_ci val |= FIELD_PREP(ICC_CTLR_EL1_PRI_BITS_MASK, vgic_v3_cpu->num_pri_bits - 1); 6962306a36Sopenharmony_ci val |= FIELD_PREP(ICC_CTLR_EL1_ID_BITS_MASK, vgic_v3_cpu->num_id_bits); 7062306a36Sopenharmony_ci val |= FIELD_PREP(ICC_CTLR_EL1_SEIS_MASK, 7162306a36Sopenharmony_ci FIELD_GET(ICH_VTR_SEIS_MASK, 7262306a36Sopenharmony_ci kvm_vgic_global_state.ich_vtr_el2)); 7362306a36Sopenharmony_ci val |= FIELD_PREP(ICC_CTLR_EL1_A3V_MASK, 7462306a36Sopenharmony_ci FIELD_GET(ICH_VTR_A3V_MASK, kvm_vgic_global_state.ich_vtr_el2)); 7562306a36Sopenharmony_ci /* 7662306a36Sopenharmony_ci * The VMCR.CTLR value is in ICC_CTLR_EL1 layout. 7762306a36Sopenharmony_ci * Extract it directly using ICC_CTLR_EL1 reg definitions. 7862306a36Sopenharmony_ci */ 7962306a36Sopenharmony_ci val |= FIELD_PREP(ICC_CTLR_EL1_CBPR_MASK, vmcr.cbpr); 8062306a36Sopenharmony_ci val |= FIELD_PREP(ICC_CTLR_EL1_EOImode_MASK, vmcr.eoim); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci *valp = val; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci return 0; 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic int set_gic_pmr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, 8862306a36Sopenharmony_ci u64 val) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci struct vgic_vmcr vmcr; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci vgic_get_vmcr(vcpu, &vmcr); 9362306a36Sopenharmony_ci vmcr.pmr = FIELD_GET(ICC_PMR_EL1_MASK, val); 9462306a36Sopenharmony_ci vgic_set_vmcr(vcpu, &vmcr); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci return 0; 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic int get_gic_pmr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, 10062306a36Sopenharmony_ci u64 *val) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci struct vgic_vmcr vmcr; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci vgic_get_vmcr(vcpu, &vmcr); 10562306a36Sopenharmony_ci *val = FIELD_PREP(ICC_PMR_EL1_MASK, vmcr.pmr); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci return 0; 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic int set_gic_bpr0(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, 11162306a36Sopenharmony_ci u64 val) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci struct vgic_vmcr vmcr; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci vgic_get_vmcr(vcpu, &vmcr); 11662306a36Sopenharmony_ci vmcr.bpr = FIELD_GET(ICC_BPR0_EL1_MASK, val); 11762306a36Sopenharmony_ci vgic_set_vmcr(vcpu, &vmcr); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci return 0; 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic int get_gic_bpr0(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, 12362306a36Sopenharmony_ci u64 *val) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci struct vgic_vmcr vmcr; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci vgic_get_vmcr(vcpu, &vmcr); 12862306a36Sopenharmony_ci *val = FIELD_PREP(ICC_BPR0_EL1_MASK, vmcr.bpr); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci return 0; 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic int set_gic_bpr1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, 13462306a36Sopenharmony_ci u64 val) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci struct vgic_vmcr vmcr; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci vgic_get_vmcr(vcpu, &vmcr); 13962306a36Sopenharmony_ci if (!vmcr.cbpr) { 14062306a36Sopenharmony_ci vmcr.abpr = FIELD_GET(ICC_BPR1_EL1_MASK, val); 14162306a36Sopenharmony_ci vgic_set_vmcr(vcpu, &vmcr); 14262306a36Sopenharmony_ci } 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci return 0; 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic int get_gic_bpr1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, 14862306a36Sopenharmony_ci u64 *val) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci struct vgic_vmcr vmcr; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci vgic_get_vmcr(vcpu, &vmcr); 15362306a36Sopenharmony_ci if (!vmcr.cbpr) 15462306a36Sopenharmony_ci *val = FIELD_PREP(ICC_BPR1_EL1_MASK, vmcr.abpr); 15562306a36Sopenharmony_ci else 15662306a36Sopenharmony_ci *val = min((vmcr.bpr + 1), 7U); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci return 0; 16062306a36Sopenharmony_ci} 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistatic int set_gic_grpen0(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, 16362306a36Sopenharmony_ci u64 val) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci struct vgic_vmcr vmcr; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci vgic_get_vmcr(vcpu, &vmcr); 16862306a36Sopenharmony_ci vmcr.grpen0 = FIELD_GET(ICC_IGRPEN0_EL1_MASK, val); 16962306a36Sopenharmony_ci vgic_set_vmcr(vcpu, &vmcr); 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci return 0; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic int get_gic_grpen0(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, 17562306a36Sopenharmony_ci u64 *val) 17662306a36Sopenharmony_ci{ 17762306a36Sopenharmony_ci struct vgic_vmcr vmcr; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci vgic_get_vmcr(vcpu, &vmcr); 18062306a36Sopenharmony_ci *val = FIELD_PREP(ICC_IGRPEN0_EL1_MASK, vmcr.grpen0); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci return 0; 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_cistatic int set_gic_grpen1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, 18662306a36Sopenharmony_ci u64 val) 18762306a36Sopenharmony_ci{ 18862306a36Sopenharmony_ci struct vgic_vmcr vmcr; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci vgic_get_vmcr(vcpu, &vmcr); 19162306a36Sopenharmony_ci vmcr.grpen1 = FIELD_GET(ICC_IGRPEN1_EL1_MASK, val); 19262306a36Sopenharmony_ci vgic_set_vmcr(vcpu, &vmcr); 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci return 0; 19562306a36Sopenharmony_ci} 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_cistatic int get_gic_grpen1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, 19862306a36Sopenharmony_ci u64 *val) 19962306a36Sopenharmony_ci{ 20062306a36Sopenharmony_ci struct vgic_vmcr vmcr; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci vgic_get_vmcr(vcpu, &vmcr); 20362306a36Sopenharmony_ci *val = FIELD_GET(ICC_IGRPEN1_EL1_MASK, vmcr.grpen1); 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci return 0; 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic void set_apr_reg(struct kvm_vcpu *vcpu, u64 val, u8 apr, u8 idx) 20962306a36Sopenharmony_ci{ 21062306a36Sopenharmony_ci struct vgic_v3_cpu_if *vgicv3 = &vcpu->arch.vgic_cpu.vgic_v3; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci if (apr) 21362306a36Sopenharmony_ci vgicv3->vgic_ap1r[idx] = val; 21462306a36Sopenharmony_ci else 21562306a36Sopenharmony_ci vgicv3->vgic_ap0r[idx] = val; 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_cistatic u64 get_apr_reg(struct kvm_vcpu *vcpu, u8 apr, u8 idx) 21962306a36Sopenharmony_ci{ 22062306a36Sopenharmony_ci struct vgic_v3_cpu_if *vgicv3 = &vcpu->arch.vgic_cpu.vgic_v3; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci if (apr) 22362306a36Sopenharmony_ci return vgicv3->vgic_ap1r[idx]; 22462306a36Sopenharmony_ci else 22562306a36Sopenharmony_ci return vgicv3->vgic_ap0r[idx]; 22662306a36Sopenharmony_ci} 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_cistatic int set_gic_ap0r(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, 22962306a36Sopenharmony_ci u64 val) 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci{ 23262306a36Sopenharmony_ci u8 idx = r->Op2 & 3; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci if (idx > vgic_v3_max_apr_idx(vcpu)) 23562306a36Sopenharmony_ci return -EINVAL; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci set_apr_reg(vcpu, val, 0, idx); 23862306a36Sopenharmony_ci return 0; 23962306a36Sopenharmony_ci} 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic int get_gic_ap0r(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, 24262306a36Sopenharmony_ci u64 *val) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci u8 idx = r->Op2 & 3; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci if (idx > vgic_v3_max_apr_idx(vcpu)) 24762306a36Sopenharmony_ci return -EINVAL; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci *val = get_apr_reg(vcpu, 0, idx); 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci return 0; 25262306a36Sopenharmony_ci} 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_cistatic int set_gic_ap1r(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, 25562306a36Sopenharmony_ci u64 val) 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci{ 25862306a36Sopenharmony_ci u8 idx = r->Op2 & 3; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci if (idx > vgic_v3_max_apr_idx(vcpu)) 26162306a36Sopenharmony_ci return -EINVAL; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci set_apr_reg(vcpu, val, 1, idx); 26462306a36Sopenharmony_ci return 0; 26562306a36Sopenharmony_ci} 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_cistatic int get_gic_ap1r(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, 26862306a36Sopenharmony_ci u64 *val) 26962306a36Sopenharmony_ci{ 27062306a36Sopenharmony_ci u8 idx = r->Op2 & 3; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci if (idx > vgic_v3_max_apr_idx(vcpu)) 27362306a36Sopenharmony_ci return -EINVAL; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci *val = get_apr_reg(vcpu, 1, idx); 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci return 0; 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cistatic int set_gic_sre(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, 28162306a36Sopenharmony_ci u64 val) 28262306a36Sopenharmony_ci{ 28362306a36Sopenharmony_ci /* Validate SRE bit */ 28462306a36Sopenharmony_ci if (!(val & ICC_SRE_EL1_SRE)) 28562306a36Sopenharmony_ci return -EINVAL; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci return 0; 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic int get_gic_sre(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, 29162306a36Sopenharmony_ci u64 *val) 29262306a36Sopenharmony_ci{ 29362306a36Sopenharmony_ci struct vgic_v3_cpu_if *vgicv3 = &vcpu->arch.vgic_cpu.vgic_v3; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci *val = vgicv3->vgic_sre; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci return 0; 29862306a36Sopenharmony_ci} 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_cistatic const struct sys_reg_desc gic_v3_icc_reg_descs[] = { 30162306a36Sopenharmony_ci { SYS_DESC(SYS_ICC_PMR_EL1), 30262306a36Sopenharmony_ci .set_user = set_gic_pmr, .get_user = get_gic_pmr, }, 30362306a36Sopenharmony_ci { SYS_DESC(SYS_ICC_BPR0_EL1), 30462306a36Sopenharmony_ci .set_user = set_gic_bpr0, .get_user = get_gic_bpr0, }, 30562306a36Sopenharmony_ci { SYS_DESC(SYS_ICC_AP0R0_EL1), 30662306a36Sopenharmony_ci .set_user = set_gic_ap0r, .get_user = get_gic_ap0r, }, 30762306a36Sopenharmony_ci { SYS_DESC(SYS_ICC_AP0R1_EL1), 30862306a36Sopenharmony_ci .set_user = set_gic_ap0r, .get_user = get_gic_ap0r, }, 30962306a36Sopenharmony_ci { SYS_DESC(SYS_ICC_AP0R2_EL1), 31062306a36Sopenharmony_ci .set_user = set_gic_ap0r, .get_user = get_gic_ap0r, }, 31162306a36Sopenharmony_ci { SYS_DESC(SYS_ICC_AP0R3_EL1), 31262306a36Sopenharmony_ci .set_user = set_gic_ap0r, .get_user = get_gic_ap0r, }, 31362306a36Sopenharmony_ci { SYS_DESC(SYS_ICC_AP1R0_EL1), 31462306a36Sopenharmony_ci .set_user = set_gic_ap1r, .get_user = get_gic_ap1r, }, 31562306a36Sopenharmony_ci { SYS_DESC(SYS_ICC_AP1R1_EL1), 31662306a36Sopenharmony_ci .set_user = set_gic_ap1r, .get_user = get_gic_ap1r, }, 31762306a36Sopenharmony_ci { SYS_DESC(SYS_ICC_AP1R2_EL1), 31862306a36Sopenharmony_ci .set_user = set_gic_ap1r, .get_user = get_gic_ap1r, }, 31962306a36Sopenharmony_ci { SYS_DESC(SYS_ICC_AP1R3_EL1), 32062306a36Sopenharmony_ci .set_user = set_gic_ap1r, .get_user = get_gic_ap1r, }, 32162306a36Sopenharmony_ci { SYS_DESC(SYS_ICC_BPR1_EL1), 32262306a36Sopenharmony_ci .set_user = set_gic_bpr1, .get_user = get_gic_bpr1, }, 32362306a36Sopenharmony_ci { SYS_DESC(SYS_ICC_CTLR_EL1), 32462306a36Sopenharmony_ci .set_user = set_gic_ctlr, .get_user = get_gic_ctlr, }, 32562306a36Sopenharmony_ci { SYS_DESC(SYS_ICC_SRE_EL1), 32662306a36Sopenharmony_ci .set_user = set_gic_sre, .get_user = get_gic_sre, }, 32762306a36Sopenharmony_ci { SYS_DESC(SYS_ICC_IGRPEN0_EL1), 32862306a36Sopenharmony_ci .set_user = set_gic_grpen0, .get_user = get_gic_grpen0, }, 32962306a36Sopenharmony_ci { SYS_DESC(SYS_ICC_IGRPEN1_EL1), 33062306a36Sopenharmony_ci .set_user = set_gic_grpen1, .get_user = get_gic_grpen1, }, 33162306a36Sopenharmony_ci}; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_cistatic u64 attr_to_id(u64 attr) 33462306a36Sopenharmony_ci{ 33562306a36Sopenharmony_ci return ARM64_SYS_REG(FIELD_GET(KVM_REG_ARM_VGIC_SYSREG_OP0_MASK, attr), 33662306a36Sopenharmony_ci FIELD_GET(KVM_REG_ARM_VGIC_SYSREG_OP1_MASK, attr), 33762306a36Sopenharmony_ci FIELD_GET(KVM_REG_ARM_VGIC_SYSREG_CRN_MASK, attr), 33862306a36Sopenharmony_ci FIELD_GET(KVM_REG_ARM_VGIC_SYSREG_CRM_MASK, attr), 33962306a36Sopenharmony_ci FIELD_GET(KVM_REG_ARM_VGIC_SYSREG_OP2_MASK, attr)); 34062306a36Sopenharmony_ci} 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ciint vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci if (get_reg_by_id(attr_to_id(attr->attr), gic_v3_icc_reg_descs, 34562306a36Sopenharmony_ci ARRAY_SIZE(gic_v3_icc_reg_descs))) 34662306a36Sopenharmony_ci return 0; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci return -ENXIO; 34962306a36Sopenharmony_ci} 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ciint vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, 35262306a36Sopenharmony_ci struct kvm_device_attr *attr, 35362306a36Sopenharmony_ci bool is_write) 35462306a36Sopenharmony_ci{ 35562306a36Sopenharmony_ci struct kvm_one_reg reg = { 35662306a36Sopenharmony_ci .id = attr_to_id(attr->attr), 35762306a36Sopenharmony_ci .addr = attr->addr, 35862306a36Sopenharmony_ci }; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci if (is_write) 36162306a36Sopenharmony_ci return kvm_sys_reg_set_user(vcpu, ®, gic_v3_icc_reg_descs, 36262306a36Sopenharmony_ci ARRAY_SIZE(gic_v3_icc_reg_descs)); 36362306a36Sopenharmony_ci else 36462306a36Sopenharmony_ci return kvm_sys_reg_get_user(vcpu, ®, gic_v3_icc_reg_descs, 36562306a36Sopenharmony_ci ARRAY_SIZE(gic_v3_icc_reg_descs)); 36662306a36Sopenharmony_ci} 367