1 /*
2  * Contains CPU feature definitions
3  *
4  * Copyright (C) 2015 ARM Ltd.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include <xen/types.h>
20 #include <xen/init.h>
21 #include <xen/smp.h>
22 #include <xen/stop_machine.h>
23 #include <asm/cpufeature.h>
24 
25 DECLARE_BITMAP(cpu_hwcaps, ARM_NCAPS);
26 
update_cpu_capabilities(const struct arm_cpu_capabilities * caps,const char * info)27 void update_cpu_capabilities(const struct arm_cpu_capabilities *caps,
28                              const char *info)
29 {
30     int i;
31 
32     for ( i = 0; caps[i].matches; i++ )
33     {
34         if ( !caps[i].matches(&caps[i]) )
35             continue;
36 
37         if ( !cpus_have_cap(caps[i].capability) && caps[i].desc )
38             printk(XENLOG_INFO "%s: %s\n", info, caps[i].desc);
39         cpus_set_cap(caps[i].capability);
40     }
41 }
42 
43 /*
44  * Run through the enabled capabilities and enable() it on all active
45  * CPUs.
46  */
enable_cpu_capabilities(const struct arm_cpu_capabilities * caps)47 void __init enable_cpu_capabilities(const struct arm_cpu_capabilities *caps)
48 {
49     for ( ; caps->matches; caps++ )
50     {
51         if ( !cpus_have_cap(caps->capability) )
52             continue;
53 
54         if ( caps->enable )
55         {
56             int ret;
57 
58             /*
59              * Use stop_machine_run() as it schedules the work allowing
60              * us to modify PSTATE, instead of on_each_cpu() which uses
61              * an IPI, giving us a PSTATE that disappears when we
62              * return.
63              */
64             ret = stop_machine_run(caps->enable, (void *)caps, NR_CPUS);
65             /* stop_machine_run should never fail at this stage of the boot. */
66             BUG_ON(ret);
67         }
68     }
69 }
70 
71 /*
72  * Run through the enabled capabilities and enable() them on the calling CPU.
73  * If enabling of any capability fails the error is returned. After enabling a
74  * capability fails the error will be remembered into 'rc' and the remaining
75  * capabilities will be enabled. If enabling multiple capabilities fail the
76  * error returned by this function represents the error code of the last
77  * failure.
78  */
enable_nonboot_cpu_caps(const struct arm_cpu_capabilities * caps)79 int enable_nonboot_cpu_caps(const struct arm_cpu_capabilities *caps)
80 {
81     int rc = 0;
82 
83     for ( ; caps->matches; caps++ )
84     {
85         if ( !cpus_have_cap(caps->capability) )
86             continue;
87 
88         if ( caps->enable )
89         {
90             int ret = caps->enable((void *)caps);
91 
92             if ( ret )
93                 rc = ret;
94         }
95     }
96 
97     return rc;
98 }
99 
identify_cpu(struct cpuinfo_arm * c)100 void identify_cpu(struct cpuinfo_arm *c)
101 {
102         c->midr.bits = READ_SYSREG32(MIDR_EL1);
103         c->mpidr.bits = READ_SYSREG(MPIDR_EL1);
104 
105 #ifdef CONFIG_ARM_64
106         c->pfr64.bits[0] = READ_SYSREG64(ID_AA64PFR0_EL1);
107         c->pfr64.bits[1] = READ_SYSREG64(ID_AA64PFR1_EL1);
108 
109         c->dbg64.bits[0] = READ_SYSREG64(ID_AA64DFR0_EL1);
110         c->dbg64.bits[1] = READ_SYSREG64(ID_AA64DFR1_EL1);
111 
112         c->aux64.bits[0] = READ_SYSREG64(ID_AA64AFR0_EL1);
113         c->aux64.bits[1] = READ_SYSREG64(ID_AA64AFR1_EL1);
114 
115         c->mm64.bits[0]  = READ_SYSREG64(ID_AA64MMFR0_EL1);
116         c->mm64.bits[1]  = READ_SYSREG64(ID_AA64MMFR1_EL1);
117 
118         c->isa64.bits[0] = READ_SYSREG64(ID_AA64ISAR0_EL1);
119         c->isa64.bits[1] = READ_SYSREG64(ID_AA64ISAR1_EL1);
120 #endif
121 
122         c->pfr32.bits[0] = READ_SYSREG32(ID_PFR0_EL1);
123         c->pfr32.bits[1] = READ_SYSREG32(ID_PFR1_EL1);
124 
125         c->dbg32.bits[0] = READ_SYSREG32(ID_DFR0_EL1);
126 
127         c->aux32.bits[0] = READ_SYSREG32(ID_AFR0_EL1);
128 
129         c->mm32.bits[0]  = READ_SYSREG32(ID_MMFR0_EL1);
130         c->mm32.bits[1]  = READ_SYSREG32(ID_MMFR1_EL1);
131         c->mm32.bits[2]  = READ_SYSREG32(ID_MMFR2_EL1);
132         c->mm32.bits[3]  = READ_SYSREG32(ID_MMFR3_EL1);
133 
134         c->isa32.bits[0] = READ_SYSREG32(ID_ISAR0_EL1);
135         c->isa32.bits[1] = READ_SYSREG32(ID_ISAR1_EL1);
136         c->isa32.bits[2] = READ_SYSREG32(ID_ISAR2_EL1);
137         c->isa32.bits[3] = READ_SYSREG32(ID_ISAR3_EL1);
138         c->isa32.bits[4] = READ_SYSREG32(ID_ISAR4_EL1);
139         c->isa32.bits[5] = READ_SYSREG32(ID_ISAR5_EL1);
140 }
141 
142 /*
143  * Local variables:
144  * mode: C
145  * c-file-style: "BSD"
146  * c-basic-offset: 4
147  * indent-tabs-mode: nil
148  * End:
149  */
150