about summary refs log tree commit diff stats
path: root/src/os/my_cpuid_linux.c
blob: 5979975a05250c93f759553181e97f73f7dacd4c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sched.h>

#include "my_cpuid.h"
#include "debug.h"
#include "x64emu.h"

int get_cpuMhz()
{
    int MHz = 0;
    char *p = NULL;
    if((p=getenv("BOX64_CPUMHZ"))) {
        MHz = atoi(p);
        return MHz;
    }
    char cpumhz[200];
    sprintf(cpumhz, "%d", MHz?:1000);
    setenv("BOX64_CPUMHZ", cpumhz, 1);  // set temp value incase box64 gets recursively called

    int cpucore = 0;
    while(cpucore!=-1) {
        char cpufreq[4096];
        sprintf(cpufreq, "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", cpucore);
        FILE *f = fopen(cpufreq, "r");
        if(f) {
            int r;
            if(1==fscanf(f, "%d", &r)) {
                r /= 1000;
                if(MHz<r)
                    MHz = r;
            }
            fclose(f);
            ++cpucore;
        }
        else
            cpucore = -1;
    }
    #ifndef STATICBUILD
    if(!MHz) {
        // try with lscpu, grabbing the max frequency
        FILE* f = popen("lscpu | grep \"CPU max MHz:\" | sed -r 's/CPU max MHz:\\s{1,}//g'", "r");
        if(f) {
            char tmp[200] = "";
            ssize_t s = fread(tmp, 1, 200, f);
            pclose(f);
            if(s>0) {
                // worked! (unless it's saying "lscpu: command not found" or something like that)
                if(!strstr(tmp, "lscpu")) {
                    // trim ending
                    while(strlen(tmp) && tmp[strlen(tmp)-1]=='\n')
                        tmp[strlen(tmp)-1] = 0;
                    // incase multiple cpu type are present, there will be multiple lines
                    while(strchr(tmp, '\n'))
                        *strchr(tmp,'\n') = ' ';
                    // cut the float part (so '.' or ','), it's not needed
                    if(strchr(tmp, '.'))
                        *strchr(tmp, '.')= '\0';
                    if(strchr(tmp, ','))
                        *strchr(tmp, ',')= '\0';
                    int mhz;
                    if(sscanf(tmp, "%d", &mhz)==1)
                        MHz = mhz;
                }
            }
        }
    }
    #endif
    if(!MHz)
        MHz = 1000; // default to 1Ghz...
    sprintf(cpumhz, "%d", MHz);
    setenv("BOX64_CPUMHZ", cpumhz, 1);  // set actual value
    return MHz;
}
static int nCPU = 0;
static double bogoMips = 100.;
static int read_ncpu = 0;

void grabNCpu() {
    nCPU = 1;  // default number of CPU to 1
    FILE *f = fopen("/proc/cpuinfo", "r");
    ssize_t dummy;
    if(f) {
        nCPU = 0;
        int bogo = 0;
        size_t len = 500;
        char* line = malloc(len);
        while ((dummy = getline(&line, &len, f)) != (ssize_t)-1) {
            if(!strncmp(line, "processor\t", strlen("processor\t")))
                ++nCPU;
            if(!bogo && !strncmp(line, "BogoMIPS\t", strlen("BogoMIPS\t"))) {
                // grab 1st BogoMIPS
                float tmp;
                if(sscanf(line, "BogoMIPS\t: %g", &tmp)==1) {
                    bogoMips = tmp;
                    bogo = 1;
                }
            }
        }
        free(line);
        fclose(f);
        if(!nCPU) nCPU=1;
    }
}
int getNCpu()
{
    if(!nCPU)
        grabNCpu();
    read_ncpu = 1;
    if(BOX64ENV(maxcpu) && nCPU>BOX64ENV(maxcpu))
        return BOX64ENV(maxcpu);
    return nCPU;
}
int getNCpuUnmasked()
{
    if(!nCPU)
        grabNCpu();
    return nCPU;
}
int canNCpuBeChanged()
{
    return read_ncpu?0:1;
}

double getBogoMips()
{
    if(!nCPU)
        grabNCpu();
    return bogoMips;
}

const char* getCpuName()
{
    static char name[200] = "Unknown CPU";
    static int done = 0;
    if(done)
        return name;
    done = 1;
    char *p = NULL;
    if((p=getenv("BOX64_CPUNAME"))) {
        strcpy(name, p);
        return name;
    }
    setenv("BOX64_CPUNAME", name, 1);   // temporary set
    #ifndef STATICBUILD
    FILE* f = popen("LC_ALL=C lscpu | grep -i \"model name:\" | head -n 1 | sed -r 's/(model name:)\\s{1,}//gi'", "r");
    if(f) {
        char tmp[200] = "";
        ssize_t s = fread(tmp, 1, 200, f);
        pclose(f);
        if(s>0) {
            // worked! (unless it's saying "lscpu: command not found" or something like that)
            if(!strstr(tmp, "lscpu")) {
                // trim ending
                while(strlen(tmp) && tmp[strlen(tmp)-1]=='\n')
                    tmp[strlen(tmp)-1] = 0;
                strncpy(name, tmp, 199);
            }
            setenv("BOX64_CPUNAME", name, 1);
            return name;
        }
    }
    // failled, try to get architecture at least
    f = popen("uname -m", "r");
    if(f) {
        char tmp[200] = "";
        ssize_t s = fread(tmp, 1, 200, f);
        pclose(f);
        if(s>0) {
            // worked!
            // trim ending
            while(strlen(tmp) && tmp[strlen(tmp)-1]=='\n')
                tmp[strlen(tmp)-1] = 0;
            snprintf(name, 199, "unknown %s cpu", tmp);
            setenv("BOX64_CPUNAME", name, 1);
            return name;
        }
    }
    #endif
    // Nope, bye
    return name;
}

const char* getBoxCpuName()
{
    static char branding[3*4*4+1] = "";
    static int done = 0;
    if(!done) {
        done = 1;
        const char* name = getCpuName();
        if(strstr(name, "MHz") || strstr(name, "GHz")) {
            // name already have the speed in it
            snprintf(branding, sizeof(branding), "Box64 on %.*s", 39, name);
        } else {
            unsigned int MHz = get_cpuMhz();
            if(MHz>1500) { // swiches to GHz display...
                snprintf(branding, sizeof(branding), "Box64 on %.*s @%1.2f GHz", 28, name, MHz/1000.);
            } else {
                snprintf(branding, sizeof(branding), "Box64 on %.*s @%04d MHz", 28, name, MHz);
            }
        }
    }
    return branding;
}

uint32_t helper_getcpu(x64emu_t* emu) {
    #if defined(__GLIBC__) && defined(__GLIBC_MINOR__) && !defined(ANDROID)
    #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 28)
    uint32_t cpu, node;
    if(!getcpu(&cpu, &node))
        return (node&0xff)<<12 | (cpu&0xff);
    #endif
    #endif
    return 0;
}

uint32_t fallback_random32()
{
    return random() ^ (random()<<1);
}

uint32_t get_random32()
{
    uint32_t ret;
    FILE* f = fopen("/dev/urandom", "rb");
    if(f) {
        if(fread(&ret, sizeof(ret), 1, f)!=1)
            ret = fallback_random32();
        fclose(f);
    } else
        ret = fallback_random32();
    return ret;
}
uint64_t fallback_random64()
{
    return random() ^ (((uint64_t)random())<<18) ^ (((uint64_t)random())<<41);
}

uint64_t get_random64()
{
    uint64_t ret;
    FILE* f = fopen("/dev/urandom", "rb");
    if(f) {
        if(fread(&ret, sizeof(ret), 1, f)!=1)
            ret = fallback_random64();
        fclose(f);
    } else
        ret = fallback_random64();
    return ret;
}