2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
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>
16 #include "arch_intern.h"
17 #include "processor_intern.h"
19 static char *getval(const char *key
, char *s
)
27 /* Skip whitespaces and colon */
28 while (*s
&& (isspace(*s
) || (*s
== ':')))
34 static ULONG
ParseFlags(char *opts
, const char * const *FlagNames
)
41 /* Remember beginning of the word */
44 /* Find end of the word */
45 while (*opts
&& (!isspace(*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.
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 */
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
[] =
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
[] =
104 #ifdef HOST_OS_android
105 #define LIBC_NAME "libc.so"
107 #define LIBC_NAME "libc.so.6"
110 static const char *libc_symbols
[] =
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
;
129 struct LinuxArmProcessor
*data
= NULL
;
131 HostLibBase
= OpenResource("hostlib.resource");
135 libc
= HostLib_Open(LIBC_NAME
, NULL
);
139 iface
= (struct LibCInterface
*)HostLib_GetInterface(libc
, libc_symbols
, &i
);
144 char *buf
= AllocMem(BUFFER_SIZE
, MEMF_ANY
);
148 data
= AllocMem(sizeof(struct LinuxArmProcessor
), MEMF_CLEAR
);
156 file
= iface
->fopen("/proc/cpuinfo", "r");
166 res
= iface
->fgets(buf
, BUFFER_SIZE
- 1, file
);
176 /* Strip the newline */
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
)))
197 for (family
= 0; arch_ids
[family
]; family
++)
199 if (!strcmp(arch_ids
[family
], val
))
201 data
->Arch
= family
+ CPUFAMILY_ARM_3
;
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);
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
;
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
;
262 ADD2INITLIB(arch_Init
, 1);