mirror of
https://github.com/hermitcore/libhermit.git
synced 2025-03-30 00:00:15 +01:00
determine frequency from cpu brand, revise code
=> move all helper functions to utils.c
This commit is contained in:
parent
e8d202e68a
commit
18e0f3034b
5 changed files with 188 additions and 96 deletions
|
@ -5,7 +5,7 @@ include(../cmake/HermitCore-Paths.cmake)
|
||||||
|
|
||||||
add_compile_options(-std=c99)
|
add_compile_options(-std=c99)
|
||||||
|
|
||||||
add_executable(proxy proxy.c uhyve.c uhyve-net.c)
|
add_executable(proxy proxy.c utils.c uhyve.c uhyve-net.c)
|
||||||
target_compile_options(proxy PUBLIC -pthread)
|
target_compile_options(proxy PUBLIC -pthread)
|
||||||
target_link_libraries(proxy -pthread)
|
target_link_libraries(proxy -pthread)
|
||||||
|
|
||||||
|
|
|
@ -129,33 +129,13 @@ static void exit_handler(int sig)
|
||||||
|
|
||||||
static char* get_append_string(void)
|
static char* get_append_string(void)
|
||||||
{
|
{
|
||||||
char line[2048];
|
uint32_t freq = get_cpufreq();
|
||||||
char* match;
|
if (freq == 0)
|
||||||
char* point;
|
return "-freq0 -proxy";
|
||||||
|
|
||||||
FILE* fp = fopen("/proc/cpuinfo", "r");
|
snprintf(cmdline, MAX_PATH, "\"-freq%u -proxy\"", freq);
|
||||||
if (!fp)
|
|
||||||
return "-freq0";
|
|
||||||
|
|
||||||
while(fgets(line, 2048, fp)) {
|
return cmdline;
|
||||||
if ((match = strstr(line, "cpu MHz")) == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// scan strinf for the next number
|
|
||||||
for(; (*match < 0x30) || (*match > 0x39); match++)
|
|
||||||
;
|
|
||||||
|
|
||||||
for(point = match; ((*point != '.') && (*point != '\0')); point++)
|
|
||||||
;
|
|
||||||
*point = '\0';
|
|
||||||
|
|
||||||
snprintf(cmdline, MAX_PATH, "\"-freq%s -proxy\"", match);
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
return cmdline;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "-freq0";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int env_init(char *path)
|
static int env_init(char *path)
|
||||||
|
|
|
@ -28,6 +28,12 @@
|
||||||
#ifndef __PROXY_H__
|
#ifndef __PROXY_H__
|
||||||
#define __PROXY_H__
|
#define __PROXY_H__
|
||||||
|
|
||||||
|
#ifndef _GNU_SOURCE
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define HERMIT_ELFOSABI 0x42
|
#define HERMIT_ELFOSABI 0x42
|
||||||
|
@ -42,4 +48,8 @@
|
||||||
int uhyve_init(char *path);
|
int uhyve_init(char *path);
|
||||||
int uhyve_loop(void);
|
int uhyve_loop(void);
|
||||||
|
|
||||||
|
// define some helper functions
|
||||||
|
uint32_t get_cpufreq(void);
|
||||||
|
ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
* remove memory limit
|
* remove memory limit
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -288,75 +288,6 @@ static void uhyve_atexit(void)
|
||||||
close_fd(&kvm);
|
close_fd(&kvm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t get_cpufreq(void)
|
|
||||||
{
|
|
||||||
char line[128];
|
|
||||||
uint32_t freq = 0;
|
|
||||||
char* match;
|
|
||||||
|
|
||||||
FILE* fp = fopen("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", "r");
|
|
||||||
if (fp != NULL) {
|
|
||||||
if (fgets(line, sizeof(line), fp) != NULL) {
|
|
||||||
// cpuinfo_max_freq is in kHz
|
|
||||||
freq = (uint32_t) atoi(line) / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
} else if( (fp = fopen("/proc/cpuinfo", "r")) ) {
|
|
||||||
// Resorting to /proc/cpuinfo, however on most systems this will only
|
|
||||||
// return the current frequency that might change over time.
|
|
||||||
// Currently only needed when running inside a VM
|
|
||||||
|
|
||||||
// read until we find the line indicating cpu frequency
|
|
||||||
while(fgets(line, sizeof(line), fp) != NULL) {
|
|
||||||
match = strstr(line, "cpu MHz");
|
|
||||||
|
|
||||||
if(match != NULL) {
|
|
||||||
// advance pointer to beginning of number
|
|
||||||
while( ((*match < '0') || (*match > '9')) && (*match != '\0') )
|
|
||||||
match++;
|
|
||||||
|
|
||||||
freq = (uint32_t) atoi(match);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return freq;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset)
|
|
||||||
{
|
|
||||||
ssize_t total = 0;
|
|
||||||
char *p = buf;
|
|
||||||
|
|
||||||
if (count > SSIZE_MAX) {
|
|
||||||
errno = E2BIG;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (count > 0) {
|
|
||||||
ssize_t nr;
|
|
||||||
|
|
||||||
nr = pread(fd, p, count, offset);
|
|
||||||
if (nr == 0)
|
|
||||||
return total;
|
|
||||||
else if (nr == -1 && errno == EINTR)
|
|
||||||
continue;
|
|
||||||
else if (nr == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
count -= nr;
|
|
||||||
total += nr;
|
|
||||||
p += nr;
|
|
||||||
offset += nr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int load_kernel(uint8_t* mem, char* path)
|
static int load_kernel(uint8_t* mem, char* path)
|
||||||
{
|
{
|
||||||
Elf64_Ehdr hdr;
|
Elf64_Ehdr hdr;
|
||||||
|
|
171
tools/utils.c
Normal file
171
tools/utils.c
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, Stefan Lankes, RWTH Aachen University
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this
|
||||||
|
* software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "proxy.h"
|
||||||
|
|
||||||
|
inline static void __cpuid(uint32_t code, uint32_t* a, uint32_t* b, uint32_t* c, uint32_t* d)
|
||||||
|
{
|
||||||
|
__asm volatile ("cpuid" : "=a"(*a), "=b"(*b), "=c"(*c), "=d"(*d) : "0"(code), "2"(*c));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to determine the frequency from the CPU brand.
|
||||||
|
// Code is derived from the manual "Intel Processor
|
||||||
|
// Identification and the CPUID Instruction".
|
||||||
|
static uint32_t get_frequency_from_brand(void)
|
||||||
|
{
|
||||||
|
char cpu_brand[4*3*sizeof(uint32_t)+1] = {[0 ... 4*3*sizeof(uint32_t)] = 0};
|
||||||
|
uint32_t* bint = (uint32_t*) cpu_brand;
|
||||||
|
uint32_t index, multiplier = 0;
|
||||||
|
uint32_t cpu_freq = 0;
|
||||||
|
uint32_t extended;
|
||||||
|
|
||||||
|
__cpuid(0x80000000, &extended, bint+1, bint+2, bint+3);
|
||||||
|
if (extended < 0x80000004)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
__cpuid(0x80000002, bint+0, bint+1, bint+2, bint+3);
|
||||||
|
__cpuid(0x80000003, bint+4, bint+5, bint+6, bint+7);
|
||||||
|
__cpuid(0x80000004, bint+8, bint+9, bint+10, bint+11);
|
||||||
|
|
||||||
|
for(index=0; index<sizeof(cpu_brand)-2; index++)
|
||||||
|
{
|
||||||
|
if ((cpu_brand[index+1] == 'H') && (cpu_brand[index+2] == 'z'))
|
||||||
|
{
|
||||||
|
if (cpu_brand[index] == 'M')
|
||||||
|
multiplier = 1;
|
||||||
|
else if (cpu_brand[index] == 'G')
|
||||||
|
multiplier = 1000;
|
||||||
|
else if (cpu_brand[index] == 'T')
|
||||||
|
multiplier = 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multiplier > 0) {
|
||||||
|
uint32_t freq;
|
||||||
|
|
||||||
|
// Compute frequency (in MHz) from brand string
|
||||||
|
if (cpu_brand[index-3] == '.') { // If format is “x.xx”
|
||||||
|
freq = (uint32_t)(cpu_brand[index-4] - '0') * multiplier;
|
||||||
|
freq += (uint32_t)(cpu_brand[index-2] - '0') * (multiplier / 10);
|
||||||
|
freq += (uint32_t)(cpu_brand[index-1] - '0') * (multiplier / 100);
|
||||||
|
} else { // If format is xxxx
|
||||||
|
freq = (uint32_t)(cpu_brand[index-4] - '0') * 1000;
|
||||||
|
freq += (uint32_t)(cpu_brand[index-3] - '0') * 100;
|
||||||
|
freq += (uint32_t)(cpu_brand[index-2] - '0') * 10;
|
||||||
|
freq += (uint32_t)(cpu_brand[index-1] - '0');
|
||||||
|
freq *= multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
return freq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get_cpufreq(void)
|
||||||
|
{
|
||||||
|
char line[128];
|
||||||
|
uint32_t freq = 0;
|
||||||
|
char* match;
|
||||||
|
|
||||||
|
freq = get_frequency_from_brand();
|
||||||
|
if (freq > 0)
|
||||||
|
return freq;
|
||||||
|
|
||||||
|
// TODO: fallback solution, on some systems is cpuinfo_max_freq the turbo frequency
|
||||||
|
// => wrong value
|
||||||
|
FILE* fp = fopen("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", "r");
|
||||||
|
if (fp != NULL) {
|
||||||
|
if (fgets(line, sizeof(line), fp) != NULL) {
|
||||||
|
// cpuinfo_max_freq is in kHz
|
||||||
|
freq = (uint32_t) atoi(line) / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
} else if( (fp = fopen("/proc/cpuinfo", "r")) ) {
|
||||||
|
// Resorting to /proc/cpuinfo, however on most systems this will only
|
||||||
|
// return the current frequency that might change over time.
|
||||||
|
// Currently only needed when running inside a VM
|
||||||
|
|
||||||
|
// read until we find the line indicating cpu frequency
|
||||||
|
while(fgets(line, sizeof(line), fp) != NULL) {
|
||||||
|
match = strstr(line, "cpu MHz");
|
||||||
|
|
||||||
|
if(match != NULL) {
|
||||||
|
// advance pointer to beginning of number
|
||||||
|
while( ((*match < '0') || (*match > '9')) && (*match != '\0') )
|
||||||
|
match++;
|
||||||
|
|
||||||
|
freq = (uint32_t) atoi(match);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset)
|
||||||
|
{
|
||||||
|
ssize_t total = 0;
|
||||||
|
char *p = buf;
|
||||||
|
|
||||||
|
if (count > SSIZE_MAX) {
|
||||||
|
errno = E2BIG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (count > 0) {
|
||||||
|
ssize_t nr;
|
||||||
|
|
||||||
|
nr = pread(fd, p, count, offset);
|
||||||
|
if (nr == 0)
|
||||||
|
return total;
|
||||||
|
else if (nr == -1 && errno == EINTR)
|
||||||
|
continue;
|
||||||
|
else if (nr == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
count -= nr;
|
||||||
|
total += nr;
|
||||||
|
p += nr;
|
||||||
|
offset += nr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue