mirror of
https://github.com/hermitcore/libhermit.git
synced 2025-03-09 00:00:03 +01:00
merged with master
This commit is contained in:
commit
dd2850e35e
20 changed files with 310 additions and 184 deletions
|
@ -13,7 +13,7 @@
|
|||
},
|
||||
|
||||
"version": {
|
||||
"name": "0.2.3",
|
||||
"name": "0.2.5",
|
||||
"desc": "HermitCore's kernel as libOS",
|
||||
"gpgSign": false
|
||||
},
|
||||
|
|
|
@ -199,7 +199,7 @@ set(CPACK_SYSTEM_NAME all)
|
|||
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR 0)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 2)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 3)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 5)
|
||||
|
||||
set(CPACK_PACKAGE_CONTACT "Stefan Lankes <slankes@eonerc.rwth-aachen.de>")
|
||||
|
||||
|
|
|
@ -51,26 +51,26 @@ extern "C" {
|
|||
#define GDT_FLAG_TSS_BUSY 0x02
|
||||
|
||||
#define GDT_FLAG_SEGMENT 0x10
|
||||
/// Privilege level: Ring 0
|
||||
/// Privilege level: Ring 0
|
||||
#define GDT_FLAG_RING0 0x00
|
||||
/// Privilege level: Ring 1
|
||||
#define GDT_FLAG_RING1 0x20
|
||||
/// Privilege level: Ring 2
|
||||
/// Privilege level: Ring 2
|
||||
#define GDT_FLAG_RING2 0x40
|
||||
/// Privilege level: Ring 3
|
||||
/// Privilege level: Ring 3
|
||||
#define GDT_FLAG_RING3 0x60
|
||||
/// Segment is present
|
||||
#define GDT_FLAG_PRESENT 0x80
|
||||
/// Segment was accessed
|
||||
#define GDT_FLAG_ACCESSED 0x01
|
||||
/**
|
||||
* @brief Granularity of segment limit
|
||||
/**
|
||||
* @brief Granularity of segment limit
|
||||
* - set: segment limit unit is 4 KB (page size)
|
||||
* - not set: unit is bytes
|
||||
*/
|
||||
#define GDT_FLAG_4K_GRAN 0x80
|
||||
/**
|
||||
* @brief Default operand size
|
||||
* @brief Default operand size
|
||||
* - set: 32 bit
|
||||
* - not set: 16 bit
|
||||
*/
|
||||
|
@ -78,7 +78,7 @@ extern "C" {
|
|||
#define GDT_FLAG_32_BIT 0x40
|
||||
#define GDT_FLAG_64_BIT 0x20
|
||||
|
||||
/** @brief Defines a GDT entry
|
||||
/** @brief Defines a GDT entry
|
||||
*
|
||||
* A global descriptor table entry consists of:
|
||||
* - 32 bit base address (chunkwise embedded into this structure)
|
||||
|
@ -115,16 +115,16 @@ typedef struct {
|
|||
|
||||
#if GDT_ENTRIES > 8192
|
||||
#error Too many GDT entries!
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** @brief Installs the global descriptor table
|
||||
*
|
||||
* The installation involves the following steps:
|
||||
* - set up the special GDT pointer
|
||||
* - set up the special GDT pointer
|
||||
* - set up the entries in our GDT
|
||||
* - finally call gdt_flush() in our assembler file
|
||||
* - finally call gdt_flush() in our assembler file
|
||||
* in order to tell the processor where the new GDT is
|
||||
* - update the new segment registers
|
||||
* - update the new segment registers
|
||||
*/
|
||||
void gdt_install(void);
|
||||
|
||||
|
@ -143,6 +143,10 @@ void gdt_set_gate(int num, unsigned long base, unsigned long limit,
|
|||
void configure_gdt_entry(gdt_entry_t *dest_entry, unsigned long base, unsigned long limit,
|
||||
unsigned char access, unsigned char gran);
|
||||
|
||||
/** @brief Initialize the task state segments
|
||||
*/
|
||||
void tss_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -256,6 +256,7 @@ extern "C" {
|
|||
#define MSR_HWP_REQUEST 0x00000774
|
||||
#define MSR_HWP_STATUS 0x00000777
|
||||
|
||||
#define MSR_IA32_MISC_ENABLE_FAST_STRING (1ULL << 0)
|
||||
#define MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP (1ULL << 16)
|
||||
#define MSR_IA32_MISC_ENABLE_SPEEDSTEP_LOCK (1ULL << 20)
|
||||
#define MSR_IA32_MISC_ENABLE_TURBO_DISABLE (1ULL << 38)
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <hermit/tasks.h>
|
||||
#include <hermit/errno.h>
|
||||
#include <hermit/processor.h>
|
||||
#include <hermit/logging.h>
|
||||
#include <asm/gdt.h>
|
||||
#include <asm/tss.h>
|
||||
#include <asm/page.h>
|
||||
|
@ -41,7 +42,6 @@ gdt_ptr_t gp;
|
|||
// currently, our kernel has full access to the ioports
|
||||
static gdt_entry_t gdt[GDT_ENTRIES] = {[0 ... GDT_ENTRIES-1] = {0, 0, 0, 0, 0, 0}};
|
||||
static tss_t task_state_segments[MAX_CORES] __attribute__ ((aligned (PAGE_SIZE)));
|
||||
static uint8_t stack_table[MAX_CORES][KERNEL_STACK_SIZE*MAX_IST] __attribute__ ((aligned (PAGE_SIZE)));
|
||||
|
||||
extern const void boot_stack;
|
||||
|
||||
|
@ -94,7 +94,8 @@ void gdt_install(void)
|
|||
{
|
||||
int i, num = 0;
|
||||
|
||||
memset(task_state_segments, 0x00, MAX_CORES*sizeof(tss_t));
|
||||
// part of bss => already initialized
|
||||
//memset(task_state_segments, 0x00, MAX_CORES*sizeof(tss_t));
|
||||
|
||||
/* Setup the GDT pointer and limit */
|
||||
gp.limit = (sizeof(gdt_entry_t) * GDT_ENTRIES) - 1;
|
||||
|
@ -148,10 +149,6 @@ void gdt_install(void)
|
|||
*/
|
||||
for(i=0; i<MAX_CORES; i++) {
|
||||
task_state_segments[i].rsp0 = (size_t)&boot_stack + (i+1) * KERNEL_STACK_SIZE - 0x10;
|
||||
task_state_segments[i].ist1 = 0; // ist will created per task
|
||||
task_state_segments[i].ist2 = (size_t) stack_table[i] + (2 /*IST number */ - 1) * KERNEL_STACK_SIZE - 0x10;
|
||||
task_state_segments[i].ist3 = (size_t) stack_table[i] + (3 /*IST number */ - 1) * KERNEL_STACK_SIZE - 0x10;
|
||||
task_state_segments[i].ist4 = (size_t) stack_table[i] + (4 /*IST number */ - 1) * KERNEL_STACK_SIZE - 0x10;
|
||||
|
||||
gdt_set_gate(num+i*2, (unsigned long) (task_state_segments+i), sizeof(tss_t),
|
||||
GDT_FLAG_PRESENT | GDT_FLAG_TSS | GDT_FLAG_RING0, 0);
|
||||
|
@ -160,3 +157,20 @@ void gdt_install(void)
|
|||
/* Flush out the old GDT and install the new changes! */
|
||||
gdt_flush();
|
||||
}
|
||||
|
||||
void tss_init(void)
|
||||
{
|
||||
LOG_INFO("Initialized the task state segments\n");
|
||||
|
||||
for(int i=0; i<MAX_CORES; i++) {
|
||||
// ist1 will created per task
|
||||
if (task_state_segments[i].ist2 == 0)
|
||||
task_state_segments[i].ist2 = (size_t) create_stack(KERNEL_STACK_SIZE) + KERNEL_STACK_SIZE - 0x10;
|
||||
if (task_state_segments[i].ist2 == 0)
|
||||
task_state_segments[i].ist2 = (size_t) create_stack(KERNEL_STACK_SIZE) + KERNEL_STACK_SIZE - 0x10;
|
||||
if (task_state_segments[i].ist3 == 0)
|
||||
task_state_segments[i].ist3 = (size_t) create_stack(KERNEL_STACK_SIZE) + KERNEL_STACK_SIZE - 0x10;
|
||||
if (task_state_segments[i].ist4 == 0)
|
||||
task_state_segments[i].ist4 = (size_t) create_stack(KERNEL_STACK_SIZE) + KERNEL_STACK_SIZE - 0x10;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -416,7 +416,7 @@ int cpu_detection(void) {
|
|||
cpuid(0x80000000, &extended, &b, &c, &d);
|
||||
if (extended >= 0x80000001)
|
||||
cpuid(0x80000001, &a, &b, &c, &cpu_info.feature3);
|
||||
if (extended >= 0x80000008) {
|
||||
if (extended >= 0x80000004) {
|
||||
uint32_t* bint = (uint32_t*) cpu_brand;
|
||||
|
||||
cpuid(0x80000002, bint+0, bint+1, bint+2, bint+3);
|
||||
|
@ -451,7 +451,7 @@ int cpu_detection(void) {
|
|||
kprintf("Syscall instruction: %s\n", (cpu_info.feature3 & CPU_FEATURE_SYSCALL) ? "available" : "unavailable");
|
||||
}
|
||||
|
||||
//TODO: add check for SMEP and SMAP
|
||||
//TODO: add check for SMEP, PCE and SMAP
|
||||
|
||||
// be sure that AM, NE and MP is enabled
|
||||
cr0 = read_cr0();
|
||||
|
@ -476,7 +476,9 @@ int cpu_detection(void) {
|
|||
cr4 |= CR4_MCE; // enable machine check exceptions
|
||||
//if (has_vmx())
|
||||
// cr4 |= CR4_VMXE;
|
||||
cr4 &= ~CR4_TSD; // => every privilege level is able to use rdtsc
|
||||
cr4 &= ~(CR4_PCE|CR4_TSD); // disable performance monitoring counter
|
||||
// clear TSD => every privilege level is able
|
||||
// to use rdtsc
|
||||
write_cr4(cr4);
|
||||
|
||||
|
||||
|
@ -633,6 +635,7 @@ int cpu_detection(void) {
|
|||
LOG_INFO("Maximum input value for hypervisor: 0x%x\n", a);
|
||||
}
|
||||
|
||||
|
||||
if (first_time) {
|
||||
LOG_INFO("CR0 0x%llx, CR4 0x%llx\n", read_cr0(), read_cr4());
|
||||
LOG_INFO("size of xsave_t: %d\n", sizeof(xsave_t));
|
||||
|
|
|
@ -367,6 +367,9 @@ int memory_init(void)
|
|||
}
|
||||
}
|
||||
|
||||
// Ok, we are now able to use our memory management => update tss
|
||||
tss_init();
|
||||
|
||||
return ret;
|
||||
|
||||
oom:
|
||||
|
|
|
@ -96,7 +96,7 @@ static uint8_t expect_zeroed_pages = 0;
|
|||
size_t virt_to_phys(size_t addr)
|
||||
{
|
||||
if ((addr > (size_t) &kernel_start) &&
|
||||
(addr <= PAGE_2M_FLOOR((size_t) &kernel_start + image_size)))
|
||||
(addr <= PAGE_2M_CEIL((size_t) &kernel_start + image_size)))
|
||||
{
|
||||
size_t vpn = addr >> (PAGE_2M_BITS); // virtual page number
|
||||
size_t entry = self[1][vpn]; // page table entry
|
||||
|
@ -400,7 +400,8 @@ int page_init(void)
|
|||
|
||||
while(((size_t) cmdline + i) <= ((size_t) cmdline + cmdsize))
|
||||
{
|
||||
page_map(((size_t) cmdline + i) & PAGE_MASK, ((size_t) cmdline + i) & PAGE_MASK, 1, PG_GLOBAL|PG_RW|PG_PRESENT);
|
||||
page_map(((size_t) cmdline + i) & PAGE_MASK, ((size_t) cmdline + i) & PAGE_MASK,
|
||||
1, PG_NX|PG_GLOBAL|PG_RW|PG_PRESENT);
|
||||
i += PAGE_SIZE;
|
||||
}
|
||||
} else cmdline = 0;
|
||||
|
|
|
@ -35,18 +35,20 @@ int vma_arch_init(void)
|
|||
int ret = 0;
|
||||
|
||||
if (mb_info) {
|
||||
ret = vma_add((size_t)mb_info & PAGE_MASK, ((size_t)mb_info & PAGE_MASK) + PAGE_SIZE, VMA_READ|VMA_WRITE);
|
||||
ret = vma_add((size_t)mb_info & PAGE_MASK, ((size_t)mb_info & PAGE_MASK) + PAGE_SIZE,
|
||||
VMA_READ|VMA_WRITE|VMA_CACHEABLE);
|
||||
if (BUILTIN_EXPECT(ret, 0))
|
||||
goto out;
|
||||
|
||||
if ((mb_info->flags & MULTIBOOT_INFO_CMDLINE) && cmdline) {
|
||||
LOG_INFO("vma_arch_init: map cmdline %p (size 0x%zd)", cmdline, cmdsize);
|
||||
LOG_INFO("vma_arch_init: map cmdline %p (size 0x%zd)\n", cmdline, cmdsize);
|
||||
|
||||
size_t i = 0;
|
||||
while(((size_t) cmdline + i) < ((size_t) cmdline + cmdsize))
|
||||
{
|
||||
if ((((size_t)cmdline + i) & PAGE_MASK) != ((size_t) mb_info & PAGE_MASK)) {
|
||||
ret = vma_add(((size_t)cmdline + i) & PAGE_MASK, (((size_t)cmdline + i) & PAGE_MASK) + PAGE_SIZE, VMA_READ|VMA_WRITE);
|
||||
ret = vma_add(((size_t)cmdline + i) & PAGE_MASK, (((size_t)cmdline + i) & PAGE_MASK) + PAGE_SIZE,
|
||||
VMA_READ|VMA_WRITE|VMA_CACHEABLE);
|
||||
if (BUILTIN_EXPECT(ret, 0))
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
set(PACKAGE_VERSION "0.2.2" CACHE STRING
|
||||
set(PACKAGE_VERSION "0.2.5" CACHE STRING
|
||||
"HermitCore current version")
|
||||
|
||||
set(MAX_CORES "512" CACHE STRING
|
||||
|
|
|
@ -63,7 +63,7 @@ then
|
|||
fi
|
||||
|
||||
echo "-- Local CMake v${MAJOR}.${MINOR} installed to ${CMAKE_DIR_REL}"
|
||||
echo "-- Next time you source this script, no download will be neccessary"
|
||||
echo "-- Next time you source this script, no download will be necessary"
|
||||
fi
|
||||
|
||||
export PATH="${CMAKE_DIR}/bin:${PATH}"
|
||||
|
|
|
@ -50,6 +50,9 @@
|
|||
#define TX_BUF_LEN 4096
|
||||
#define MIN(a, b) (a) < (b) ? (a) : (b)
|
||||
|
||||
static uint8_t rx_buffer[RX_BUF_LEN+16 /* header size */] __attribute__ ((aligned (PAGE_SIZE)));
|
||||
static uint8_t tx_buffer[4][TX_BUF_LEN] __attribute__ ((aligned (PAGE_SIZE)));
|
||||
|
||||
/*
|
||||
* To set the RTL8139 to accept only the Transmit OK (TOK) and Receive OK (ROK)
|
||||
* interrupts, we would have the TOK and ROK bits of the IMR high and leave the
|
||||
|
@ -328,26 +331,15 @@ err_t rtl8139if_init(struct netif* netif)
|
|||
rtl8139if->irq = pci_info.irq;
|
||||
|
||||
/* allocate the receive buffer */
|
||||
rtl8139if->rx_buffer = page_alloc(RX_BUF_LEN + 16 /* header size */, VMA_READ|VMA_WRITE);
|
||||
if (!(rtl8139if->rx_buffer)) {
|
||||
LOG_ERROR("rtl8139if_init: out of memory\n");
|
||||
kfree(rtl8139if);
|
||||
return ERR_MEM;
|
||||
}
|
||||
memset(rtl8139if->rx_buffer, 0x00, RX_BUF_LEN + 16);
|
||||
rtl8139if->rx_buffer = rx_buffer;
|
||||
//memset(rtl8139if->rx_buffer, 0x00, RX_BUF_LEN + 16);
|
||||
|
||||
/* allocate the send buffers */
|
||||
rtl8139if->tx_buffer[0] = page_alloc(4*TX_BUF_LEN, VMA_READ|VMA_WRITE);
|
||||
if (!(rtl8139if->tx_buffer[0])) {
|
||||
LOG_ERROR("rtl8139if_init: out of memory\n");
|
||||
page_free(rtl8139if->rx_buffer, RX_BUF_LEN + 16);
|
||||
kfree(rtl8139if);
|
||||
return ERR_MEM;
|
||||
}
|
||||
memset(rtl8139if->tx_buffer[0], 0x00, 4*TX_BUF_LEN);
|
||||
rtl8139if->tx_buffer[1] = rtl8139if->tx_buffer[0] + 1*TX_BUF_LEN;
|
||||
rtl8139if->tx_buffer[2] = rtl8139if->tx_buffer[0] + 2*TX_BUF_LEN;
|
||||
rtl8139if->tx_buffer[3] = rtl8139if->tx_buffer[0] + 3*TX_BUF_LEN;
|
||||
rtl8139if->tx_buffer[0] = tx_buffer[0];
|
||||
//memset(rtl8139if->tx_buffer[0], 0x00, 4*TX_BUF_LEN);
|
||||
rtl8139if->tx_buffer[1] = tx_buffer[1];
|
||||
rtl8139if->tx_buffer[2] = tx_buffer[2];
|
||||
rtl8139if->tx_buffer[3] = tx_buffer[3];
|
||||
|
||||
netif->state = rtl8139if;
|
||||
mynetif = netif;
|
||||
|
@ -355,8 +347,6 @@ err_t rtl8139if_init(struct netif* netif)
|
|||
tmp32 = inportl(rtl8139if->iobase + TCR);
|
||||
if (tmp32 == 0xFFFFFF) {
|
||||
LOG_ERROR("rtl8139if_init: ERROR\n");
|
||||
page_free(rtl8139if->rx_buffer, RX_BUF_LEN + 16);
|
||||
page_free(rtl8139if->tx_buffer[0], 4*TX_BUF_LEN);
|
||||
kfree(rtl8139if);
|
||||
memset(netif, 0x00, sizeof(struct netif));
|
||||
mynetif = NULL;
|
||||
|
@ -400,8 +390,6 @@ err_t rtl8139if_init(struct netif* netif)
|
|||
if (!tmp16) {
|
||||
// it seems not to work
|
||||
LOG_ERROR("RTL8139 reset failed\n");
|
||||
page_free(rtl8139if->rx_buffer, RX_BUF_LEN + 16);
|
||||
page_free(rtl8139if->tx_buffer[0], 4*TX_BUF_LEN);
|
||||
kfree(rtl8139if);
|
||||
memset(netif, 0x00, sizeof(struct netif));
|
||||
mynetif = NULL;
|
||||
|
|
|
@ -56,14 +56,15 @@ extern "C" {
|
|||
* - 0 on success
|
||||
* - -EINVAL on invalid argument
|
||||
*/
|
||||
inline static int sem_init(sem_t* s, unsigned int v) {
|
||||
inline static int sem_init(sem_t* s, unsigned int v)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
return -EINVAL;
|
||||
|
||||
s->value = v;
|
||||
s->pos = 0;
|
||||
s->rpos = s->wpos = 0;
|
||||
for(i=0; i<MAX_TASKS; i++)
|
||||
s->queue[i] = MAX_TASKS;
|
||||
spinlock_irqsave_init(&s->lock);
|
||||
|
@ -76,7 +77,8 @@ inline static int sem_init(sem_t* s, unsigned int v) {
|
|||
* - 0 on success
|
||||
* - -EINVAL on invalid argument
|
||||
*/
|
||||
inline static int sem_destroy(sem_t* s) {
|
||||
inline static int sem_destroy(sem_t* s)
|
||||
{
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -94,7 +96,8 @@ inline static int sem_destroy(sem_t* s) {
|
|||
* - -EINVAL on invalid argument
|
||||
* - -ECANCELED on failure (You still have to wait)
|
||||
*/
|
||||
inline static int sem_trywait(sem_t* s) {
|
||||
inline static int sem_trywait(sem_t* s)
|
||||
{
|
||||
int ret = -ECANCELED;
|
||||
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
|
@ -114,12 +117,13 @@ inline static int sem_trywait(sem_t* s) {
|
|||
*
|
||||
* @param s Address of the according sem_t structure
|
||||
* @param ms Timeout in milliseconds
|
||||
* @return
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL on invalid argument
|
||||
* - -ETIME on timer expired
|
||||
*/
|
||||
inline static int sem_wait(sem_t* s, uint32_t ms) {
|
||||
inline static int sem_wait(sem_t* s, uint32_t ms)
|
||||
{
|
||||
task_t* curr_task = per_core(current_task);
|
||||
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
|
@ -132,8 +136,8 @@ next_try1:
|
|||
s->value--;
|
||||
spinlock_irqsave_unlock(&s->lock);
|
||||
} else {
|
||||
s->queue[s->pos] = curr_task->id;
|
||||
s->pos = (s->pos + 1) % MAX_TASKS;
|
||||
s->queue[s->wpos] = curr_task->id;
|
||||
s->wpos = (s->wpos + 1) % MAX_TASKS;
|
||||
block_current_task();
|
||||
spinlock_irqsave_unlock(&s->lock);
|
||||
reschedule();
|
||||
|
@ -157,8 +161,8 @@ next_try2:
|
|||
spinlock_irqsave_unlock(&s->lock);
|
||||
goto timeout;
|
||||
}
|
||||
s->queue[s->pos] = curr_task->id;
|
||||
s->pos = (s->pos + 1) % MAX_TASKS;
|
||||
s->queue[s->wpos] = curr_task->id;
|
||||
s->wpos = (s->wpos + 1) % MAX_TASKS;
|
||||
set_timer(deadline);
|
||||
spinlock_irqsave_unlock(&s->lock);
|
||||
reschedule();
|
||||
|
@ -181,28 +185,23 @@ timeout:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Give back resource
|
||||
/** @brief Give back resource
|
||||
* @return
|
||||
* - 0 on success
|
||||
* - -EINVAL on invalid argument
|
||||
*/
|
||||
inline static int sem_post(sem_t* s) {
|
||||
unsigned int k, i;
|
||||
|
||||
inline static int sem_post(sem_t* s)
|
||||
{
|
||||
if (BUILTIN_EXPECT(!s, 0))
|
||||
return -EINVAL;
|
||||
|
||||
spinlock_irqsave_lock(&s->lock);
|
||||
|
||||
s->value++;
|
||||
i = s->pos;
|
||||
for(k=0; k<MAX_TASKS; k++) {
|
||||
if (s->queue[i] < MAX_TASKS) {
|
||||
wakeup_task(s->queue[i]);
|
||||
s->queue[i] = MAX_TASKS;
|
||||
break;
|
||||
}
|
||||
i = (i + 1) % MAX_TASKS;
|
||||
if (s->queue[s->rpos] < MAX_TASKS) {
|
||||
wakeup_task(s->queue[s->rpos]);
|
||||
s->queue[s->rpos] = MAX_TASKS;
|
||||
s->rpos = (s->rpos + 1) % MAX_TASKS;
|
||||
}
|
||||
|
||||
spinlock_irqsave_unlock(&s->lock);
|
||||
|
|
|
@ -46,8 +46,10 @@ typedef struct sem {
|
|||
unsigned int value;
|
||||
/// Queue of waiting tasks
|
||||
tid_t queue[MAX_TASKS];
|
||||
/// Position in queue
|
||||
unsigned int pos;
|
||||
/// Position in queue to add a task
|
||||
unsigned int wpos;
|
||||
/// Position in queue to get a task
|
||||
unsigned int rpos;
|
||||
/// Access lock
|
||||
spinlock_irqsave_t lock;
|
||||
} sem_t;
|
||||
|
|
31
mm/vma.c
31
mm/vma.c
|
@ -91,6 +91,8 @@ size_t vma_alloc(size_t size, uint32_t flags)
|
|||
size_t base = VMA_MIN;
|
||||
size_t limit = VMA_MAX;
|
||||
|
||||
size = PAGE_CEIL(size);
|
||||
|
||||
spinlock_irqsave_lock(lock);
|
||||
|
||||
// first fit search for free memory area
|
||||
|
@ -237,7 +239,7 @@ int vma_add(size_t start, size_t end, uint32_t flags)
|
|||
|
||||
if (pred && (pred->end == start) && (pred->flags == flags)) {
|
||||
pred->end = end; // resize VMA
|
||||
LOG_DEBUG("vma_alloc: resize vma, start 0x%zx, pred->start 0x%zx, pred->end 0x%zx\n", start, pred->start, pred->end);
|
||||
LOG_DEBUG("vma_add: resize vma, start 0x%zx, pred->start 0x%zx, pred->end 0x%zx\n", start, pred->start, pred->end);
|
||||
} else {
|
||||
// insert new VMA
|
||||
vma_t* new = kmalloc(sizeof(vma_t));
|
||||
|
@ -251,9 +253,11 @@ int vma_add(size_t start, size_t end, uint32_t flags)
|
|||
new->flags = flags;
|
||||
new->next = succ;
|
||||
new->prev = pred;
|
||||
LOG_DEBUG("vma_add: create new vma, new->start 0x%zx, new->end 0x%zx\n", new->start, new->end);
|
||||
|
||||
if (succ)
|
||||
succ->prev = new;
|
||||
|
||||
if (pred)
|
||||
pred->next = new;
|
||||
else
|
||||
|
@ -266,21 +270,22 @@ fail:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void print_vma(vma_t *vma)
|
||||
{
|
||||
while (vma) {
|
||||
LOG_INFO("0x%lx - 0x%lx: size=0x%x, flags=%c%c%c%s\n", vma->start, vma->end, vma->end - vma->start,
|
||||
(vma->flags & VMA_READ) ? 'r' : '-',
|
||||
(vma->flags & VMA_WRITE) ? 'w' : '-',
|
||||
(vma->flags & VMA_EXECUTE) ? 'x' : '-',
|
||||
(vma->flags & VMA_CACHEABLE) ? "" : " (uncached)");
|
||||
vma = vma->next;
|
||||
}
|
||||
}
|
||||
|
||||
void vma_dump(void)
|
||||
{
|
||||
void print_vma(vma_t *vma) {
|
||||
while (vma) {
|
||||
LOG_INFO("0x%lx - 0x%lx: size=0x%x, flags=%c%c%c%s\n", vma->start, vma->end, vma->end - vma->start,
|
||||
(vma->flags & VMA_READ) ? 'r' : '-',
|
||||
(vma->flags & VMA_WRITE) ? 'w' : '-',
|
||||
(vma->flags & VMA_EXECUTE) ? 'x' : '-',
|
||||
(vma->flags & VMA_CACHEABLE) ? "" : " (uncached)");
|
||||
vma = vma->next;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_INFO("VMAs:\n");
|
||||
spinlock_irqsave_lock(&hermit_mm_lock);
|
||||
print_vma(&vma_boot);
|
||||
print_vma(vma_list);
|
||||
spinlock_irqsave_unlock(&hermit_mm_lock);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ include(../cmake/HermitCore-Paths.cmake)
|
|||
|
||||
add_compile_options(-std=c99)
|
||||
|
||||
add_executable(proxy proxy.c uhyve.c uhyve-ibv.c uhyve-net.c)
|
||||
add_executable(proxy proxy.c uhyve-ibv.c utils.c uhyve.c uhyve-net.c)
|
||||
target_compile_options(proxy PUBLIC -pthread)
|
||||
target_link_libraries(proxy pthread ibverbs)
|
||||
|
||||
|
|
|
@ -129,33 +129,13 @@ static void exit_handler(int sig)
|
|||
|
||||
static char* get_append_string(void)
|
||||
{
|
||||
char line[2048];
|
||||
char* match;
|
||||
char* point;
|
||||
uint32_t freq = get_cpufreq();
|
||||
if (freq == 0)
|
||||
return "-freq0 -proxy";
|
||||
|
||||
FILE* fp = fopen("/proc/cpuinfo", "r");
|
||||
if (!fp)
|
||||
return "-freq0";
|
||||
snprintf(cmdline, MAX_PATH, "\"-freq%u -proxy\"", freq);
|
||||
|
||||
while(fgets(line, 2048, fp)) {
|
||||
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";
|
||||
return cmdline;
|
||||
}
|
||||
|
||||
static int env_init(char *path)
|
||||
|
|
|
@ -28,6 +28,12 @@
|
|||
#ifndef __PROXY_H__
|
||||
#define __PROXY_H__
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define HERMIT_ELFOSABI 0x42
|
||||
|
@ -42,4 +48,8 @@
|
|||
int uhyve_init(char *path);
|
||||
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
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
* remove memory limit
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
@ -291,75 +291,6 @@ static void uhyve_atexit(void)
|
|||
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)
|
||||
{
|
||||
Elf64_Ehdr hdr;
|
||||
|
@ -1289,9 +1220,21 @@ static int vcpu_init(void)
|
|||
kvm_ioctl(vcpufd, KVM_SET_XSAVE, &xsave);
|
||||
kvm_ioctl(vcpufd, KVM_SET_VCPU_EVENTS, &events);
|
||||
} else {
|
||||
struct {
|
||||
struct kvm_msrs info;
|
||||
struct kvm_msr_entry entries[MAX_MSR_ENTRIES];
|
||||
} msr_data;
|
||||
struct kvm_msr_entry *msrs = msr_data.entries;
|
||||
|
||||
// be sure that the multiprocessor is runable
|
||||
kvm_ioctl(vcpufd, KVM_SET_MP_STATE, &mp_state);
|
||||
|
||||
// enable fast string operations
|
||||
msrs[0].index = MSR_IA32_MISC_ENABLE;
|
||||
msrs[0].data = 1;
|
||||
msr_data.info.nmsrs = 1;
|
||||
kvm_ioctl(vcpufd, KVM_SET_MSRS, &msr_data);
|
||||
|
||||
/* Setup registers and memory. */
|
||||
setup_system(vcpufd, guest_mem, cpuid);
|
||||
kvm_ioctl(vcpufd, KVM_SET_REGS, ®s);
|
||||
|
|
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