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