revert between 56095 -> 55830 in arch
[AROS.git] / arch / arm-linux / processor / arch_init.c
bloba44e92637b26fad20d3c0960adbc22276e4b1770
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/symbolsets.h>
7 #include <resources/processor.h>
8 #include <proto/alib.h>
9 #include <proto/exec.h>
10 #include <proto/hostlib.h>
12 #include <ctype.h>
13 #include <stdlib.h>
14 #include <string.h>
16 #include "arch_intern.h"
17 #include "processor_intern.h"
19 static char *getval(const char *key, char *s)
21 while (*key)
23 if (*key++ != *s++)
24 return NULL;
27 /* Skip whitespaces and colon */
28 while (*s && (isspace(*s) || (*s == ':')))
29 s++;
31 return s;
34 static ULONG ParseFlags(char *opts, const char * const *FlagNames)
36 ULONG ret = 0;
37 unsigned int i;
39 while (*opts)
41 /* Remember beginning of the word */
42 char *p = opts;
44 /* Find end of the word */
45 while (*opts && (!isspace(*opts)))
46 opts++;
48 if (*opts)
51 * If this is not the end of line, split the string and advance to the next char.
52 * Feature names are separated with one whitespace.
54 *opts++ = 0;
57 /* Decode flag name */
58 for (i = 0; FlagNames[i]; i++)
60 if (!strcmp(p, FlagNames[i]))
62 /* Set bit corresponding to number of flag name in the list */
63 ret |= (1UL << i);
64 break;
69 return ret;
73 * This is what can be reported by Linux kernel (see their arch/arm/kernel/setup.c).
74 * Order of these must be the same as order of family IDs.
76 static const char *arch_ids[] =
78 "3",
79 "4",
80 "4T",
81 "5",
82 "5T",
83 "5TE",
84 "5TEJ",
85 "6TEJ",
86 "7",
87 NULL
91 * Feature flags as reported by kernel (quote not everything is supported).
92 * Again, order of these repeats order of feature ID tags.
94 static const char *feature_ids[] =
96 "vfp",
97 "vfpv3",
98 "neon",
99 "thumb",
100 "thumbee",
101 NULL
104 #ifdef HOST_OS_android
105 #define LIBC_NAME "libc.so"
106 #else
107 #define LIBC_NAME "libc.so.6"
108 #endif
110 static const char *libc_symbols[] =
112 "fopen",
113 "fclose",
114 "fgets",
115 NULL
119 * Unfortunately CPU identification instructions on ARM requires supervisor privileges,
120 * so we can't use them on hosted. We can only ask host OS about our CPU.
121 * On Linux (and Android) we can do this only by parsing human-readable text in /proc/cpuinfo.
122 * We don't use unixio.hidd here because we want to start up as early as possible.
124 static ULONG arch_Init(struct ProcessorBase *ProcessorBase)
126 APTR HostLibBase, libc;
127 struct LibCInterface *iface;
128 ULONG i;
129 struct LinuxArmProcessor *data = NULL;
131 HostLibBase = OpenResource("hostlib.resource");
132 if (!HostLibBase)
133 return FALSE;
135 libc = HostLib_Open(LIBC_NAME, NULL);
136 if (!libc)
137 return FALSE;
139 iface = (struct LibCInterface *)HostLib_GetInterface(libc, libc_symbols, &i);
140 if (iface)
142 if (!i)
144 char *buf = AllocMem(BUFFER_SIZE, MEMF_ANY);
146 if (buf)
148 data = AllocMem(sizeof(struct LinuxArmProcessor), MEMF_CLEAR);
149 if (data)
151 UWORD variant = 0;
152 UWORD revision = 0;
153 void *file;
155 HostLib_Lock();
156 file = iface->fopen("/proc/cpuinfo", "r");
157 HostLib_Unlock();
159 if (file)
161 char *res;
165 HostLib_Lock();
166 res = iface->fgets(buf, BUFFER_SIZE - 1, file);
167 HostLib_Unlock();
169 if (res)
171 char *val;
173 i = strlen(buf);
174 if (i)
176 /* Strip the newline */
177 i--;
178 if (buf[i] == 0x0A)
179 buf[i] = 0;
181 if ((val = getval("Processor", buf)))
183 data->Model = StrDup(val);
185 else if ((val = getval("Features", buf)))
187 data->Features = ParseFlags(val, feature_ids);
189 else if ((val = getval("CPU implementer", buf)))
191 data->Implementer = strtoul(val, NULL, 0);
193 else if ((val = getval("CPU architecture", buf)))
195 ULONG family;
197 for (family = 0; arch_ids[family]; family++)
199 if (!strcmp(arch_ids[family], val))
201 data->Arch = family + CPUFAMILY_ARM_3;
202 break;
206 else if ((val = getval("CPU variant", buf)))
208 variant = strtoul(val, NULL, 0);
210 else if ((val = getval("CPU part", buf)))
212 data->Part = strtoul(val, NULL, 0);
214 else if ((val = getval("CPU revision", buf)))
216 revision = strtoul(val, NULL, 0);
220 } while (res);
222 HostLib_Lock();
223 iface->fclose(file);
224 HostLib_Unlock();
226 data->Version = (revision << 16) | variant;
228 /* Hack for qemu-arm support */
229 if (data->Arch == 0) {
230 data->Arch = CPUFAMILY_ARM_6;
231 data->Features |= FF_VFP;
235 FreeMem(buf, BUFFER_SIZE);
238 HostLib_DropInterface((void **)iface);
241 HostLib_Close(libc, NULL);
243 ProcessorBase->Private1 = data;
244 if (data)
246 if (data->Features & (FF_VFP | FF_VFPv3))
249 * Perhaps rather late, but i really would not like to duplicate this
250 * code in kernel.resource.
251 * Actually this definition can be used only by math code, i hope no
252 * floating-point operations are performed at early startup.
254 SysBase->AttnFlags |= AFF_FPU;
256 return TRUE;
258 else
259 return FALSE;
262 ADD2INITLIB(arch_Init, 1);