1 #include <aros/symbolsets.h>
2 #include <resources/processor.h>
3 #include <proto/alib.h>
4 #include <proto/exec.h>
5 #include <proto/hostlib.h>
11 #include "arch_intern.h"
12 #include "processor_intern.h"
14 static char *getval(const char *key
, char *s
)
22 /* Skip whitespaces and colon */
23 while (*s
&& (isspace(*s
) || (*s
== ':')))
29 static ULONG
ParseFlags(char *opts
, const char * const *FlagNames
)
36 /* Remember beginning of the word */
39 /* Find end of the word */
40 while (*opts
&& (!isspace(*opts
)))
46 * If this is not the end of line, split the string and advance to the next char.
47 * Feature names are separated with one whitespace.
52 /* Decode flag name */
53 for (i
= 0; FlagNames
[i
]; i
++)
55 if (!strcmp(p
, FlagNames
[i
]))
57 /* Set bit corresponding to number of flag name in the list */
68 * This is what can be reported by Linux kernel (see their arch/arm/kernel/setup.c).
69 * Order of these must be the same as order of family IDs.
71 static const char *arch_ids
[] =
86 * Feature flags as reported by kernel (quote not everything is supported).
87 * Again, order of these repeats order of feature ID tags.
89 static const char *feature_ids
[] =
99 #ifdef HOST_OS_android
100 #define LIBC_NAME "libc.so"
102 #define LIBC_NAME "libc.so.6"
105 static const char *libc_symbols
[] =
114 * Unfortunately CPU identification instructions on ARM requires supervisor privileges,
115 * so we can't use them on hosted. We can only ask host OS about our CPU.
116 * On Linux (and Android) we can do this only by parsing human-readable text in /proc/cpuinfo.
117 * We don't use unixio.hidd here because we want to start up as early as possible.
119 static ULONG
arch_Init(struct ProcessorBase
*ProcessorBase
)
121 APTR HostLibBase
, libc
;
122 struct LibCInterface
*iface
;
124 struct LinuxArmProcessor
*data
= NULL
;
126 HostLibBase
= OpenResource("hostlib.resource");
130 libc
= HostLib_Open(LIBC_NAME
, NULL
);
134 iface
= (struct LibCInterface
*)HostLib_GetInterface(libc
, libc_symbols
, &i
);
139 char *buf
= AllocMem(BUFFER_SIZE
, MEMF_ANY
);
143 data
= AllocMem(sizeof(struct LinuxArmProcessor
), MEMF_CLEAR
);
151 file
= iface
->fopen("/proc/cpuinfo", "r");
161 res
= iface
->fgets(buf
, BUFFER_SIZE
- 1, file
);
171 /* Strip the newline */
176 if ((val
= getval("Processor", buf
)))
178 data
->Model
= StrDup(val
);
180 else if ((val
= getval("Features", buf
)))
182 data
->Features
= ParseFlags(val
, feature_ids
);
184 else if ((val
= getval("CPU implementer", buf
)))
186 data
->Implementer
= strtoul(val
, NULL
, 0);
188 else if ((val
= getval("CPU architecture", buf
)))
192 for (family
= 0; arch_ids
[family
]; family
++)
194 if (!strcmp(arch_ids
[family
], val
))
196 data
->Arch
= family
+ CPUFAMILY_ARM_3
;
201 else if ((val
= getval("CPU variant", buf
)))
203 variant
= strtoul(val
, NULL
, 0);
205 else if ((val
= getval("CPU part", buf
)))
207 data
->Part
= strtoul(val
, NULL
, 0);
209 else if ((val
= getval("CPU revision", buf
)))
211 revision
= strtoul(val
, NULL
, 0);
221 data
->Version
= (revision
<< 16) | variant
;
223 /* Hack for qemu-arm support */
224 if (data
->Arch
== 0) {
225 data
->Arch
= CPUFAMILY_ARM_6
;
226 data
->Features
|= FF_VFP
;
230 FreeMem(buf
, BUFFER_SIZE
);
233 HostLib_DropInterface((void **)iface
);
236 HostLib_Close(libc
, NULL
);
238 ProcessorBase
->Private1
= data
;
241 if (data
->Features
& (FF_VFP
| FF_VFPv3
))
244 * Perhaps rather late, but i really would not like to duplicate this
245 * code in kernel.resource.
246 * Actually this definition can be used only by math code, i hope no
247 * floating-point operations are performed at early startup.
249 SysBase
->AttnFlags
|= AFF_FPU
;
257 ADD2INITLIB(arch_Init
, 1);