⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 util.c

📁 xen虚拟机源代码安装包
💻 C
字号:
/* * util.c: Helper library functions for HVMLoader. * * Leendert van Doorn, leendert@watson.ibm.com * Copyright (c) 2005, International Business Machines Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307 USA. */#include "util.h"#include "config.h"#include "e820.h"#include "hypercall.h"#include <stdint.h>#include <xen/xen.h>#include <xen/memory.h>#include <xen/hvm/hvm_info_table.h>void wrmsr(uint32_t idx, uint64_t v){    asm volatile (        "wrmsr"        : : "c" (idx), "a" ((uint32_t)v), "d" ((uint32_t)(v>>32)) );}uint64_t rdmsr(uint32_t idx){    uint32_t lo, hi;    asm volatile (        "rdmsr"        : "=a" (lo), "=d" (hi) : "c" (idx) );    return (lo | ((uint64_t)hi << 32));}void outb(uint16_t addr, uint8_t val){    asm volatile ( "outb %%al, %%dx" : : "d" (addr), "a" (val) );}void outw(uint16_t addr, uint16_t val){    asm volatile ( "outw %%ax, %%dx" : : "d" (addr), "a" (val) );}void outl(uint16_t addr, uint32_t val){    asm volatile ( "outl %%eax, %%dx" : : "d" (addr), "a" (val) );}uint8_t inb(uint16_t addr){    uint8_t val;    asm volatile ( "inb %%dx,%%al" : "=a" (val) : "d" (addr) );    return val;}uint16_t inw(uint16_t addr){    uint16_t val;    asm volatile ( "inw %%dx,%%ax" : "=a" (val) : "d" (addr) );    return val;}uint32_t inl(uint16_t addr){    uint32_t val;    asm volatile ( "inl %%dx,%%eax" : "=a" (val) : "d" (addr) );    return val;}uint8_t cmos_inb(uint8_t idx){    outb(0x70, idx);    return inb(0x71);}void cmos_outb(uint8_t idx, uint8_t val){    outb(0x70, idx);    outb(0x71, val);}char *itoa(char *a, unsigned int i){    unsigned int _i = i, x = 0;    do {        x++;        _i /= 10;    } while ( _i != 0 );    a += x;    *a-- = '\0';    do {        *a-- = (i % 10) + '0';        i /= 10;    } while ( i != 0 );    return a + 1;}int strcmp(const char *cs, const char *ct){    signed char res;    while ( ((res = *cs - *ct++) == 0) && (*cs++ != '\0') )        continue;    return res;}int strncmp(const char *s1, const char *s2, uint32_t n){	uint32_t ctr;	for (ctr = 0; ctr < n; ctr++)		if (s1[ctr] != s2[ctr])			return (int)(s1[ctr] - s2[ctr]);	return 0;}void *memcpy(void *dest, const void *src, unsigned n){    int t0, t1, t2;    asm volatile (        "cld\n"        "rep; movsl\n"        "testb $2,%b4\n"        "je 1f\n"        "movsw\n"        "1: testb $1,%b4\n"        "je 2f\n"        "movsb\n"        "2:"        : "=&c" (t0), "=&D" (t1), "=&S" (t2)        : "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src)        : "memory" );    return dest;}void *memmove(void *dest, const void *src, unsigned n){    if ( (unsigned long)dest > (unsigned long)src )        while ( n-- != 0 )            ((char *)dest)[n] = ((char *)src)[n];    else        memcpy(dest, src, n);    return dest;}char *strcpy(char *dest, const char *src){    char *p = dest;    while ( *src )        *p++ = *src++;    *p = 0;    return dest;}char *strncpy(char *dest, const char *src, unsigned n){    int i = 0;    char *p = dest;    /* write non-NUL characters from src into dest until we run       out of room in dest or encounter a NUL in src */    while ( (i < n) && *src )    {        *p++ = *src++;        i++;    }    /* pad remaining bytes of dest with NUL bytes */    while ( i < n )    {        *p++ = 0;        i++;    }    return dest;}unsignedstrlen(const char *s){    int i = 0;    while ( *s++ )        i++;    return i;}void *memset(void *s, int c, unsigned n){    uint8_t b = (uint8_t) c;    uint8_t *p = (uint8_t *)s;    int i;    for ( i = 0; i < n; i++ )        *p++ = b;    return s;}intmemcmp(const void *s1, const void *s2, unsigned n){    unsigned i;    uint8_t *p1 = (uint8_t *) s1;    uint8_t *p2 = (uint8_t *) s2;    for ( i = 0; i < n; i++ )    {        if ( p1[i] < p2[i] )            return -1;        else if ( p1[i] > p2[i] )            return 1;    }    return 0;}voidcpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx){    asm volatile (        "cpuid"        : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)        : "0" (idx) );}/* Write a two-character hex representation of 'byte' to digits[].   Pre-condition: sizeof(digits) >= 2 */voidbyte_to_hex(char *digits, uint8_t byte){    uint8_t nybbel = byte >> 4;    if ( nybbel > 9 )        digits[0] = 'a' + nybbel-10;    else        digits[0] = '0' + nybbel;    nybbel = byte & 0x0f;    if ( nybbel > 9 )        digits[1] = 'a' + nybbel-10;    else        digits[1] = '0' + nybbel;}/* Convert an array of 16 unsigned bytes to a DCE/OSF formatted UUID   string.   Pre-condition: sizeof(dest) >= 37 */voiduuid_to_string(char *dest, uint8_t *uuid){    int i = 0;    char *p = dest;    for ( i = 0; i < 4; i++ )    {        byte_to_hex(p, uuid[i]);        p += 2;    }    *p++ = '-';    for ( i = 4; i < 6; i++ )    {        byte_to_hex(p, uuid[i]);        p += 2;    }    *p++ = '-';    for ( i = 6; i < 8; i++ )    {        byte_to_hex(p, uuid[i]);        p += 2;    }    *p++ = '-';    for ( i = 8; i < 10; i++ )    {        byte_to_hex(p, uuid[i]);        p += 2;    }    *p++ = '-';    for ( i = 10; i < 16; i++ )    {        byte_to_hex(p, uuid[i]);        p += 2;    }    *p = '\0';}static void e820_collapse(void){    int i = 0;    struct e820entry *ent = (struct e820entry *)HVM_E820;    while ( i < (*HVM_E820_NR-1) )    {        if ( (ent[i].type == ent[i+1].type) &&             ((ent[i].addr + ent[i].size) == ent[i+1].addr) )        {            ent[i].size += ent[i+1].size;            memcpy(&ent[i+1], &ent[i+2], (*HVM_E820_NR-i-2) * sizeof(*ent));            (*HVM_E820_NR)--;        }        else        {            i++;        }    }}uint32_t e820_malloc(uint32_t size){    uint32_t addr;    int i;    struct e820entry *ent = (struct e820entry *)HVM_E820;    /* Align allocation request to a reasonable boundary (1kB). */    size = (size + 1023) & ~1023;    for ( i = *HVM_E820_NR - 1; i >= 0; i-- )    {        addr = ent[i].addr;        if ( (ent[i].type != E820_RAM) || /* not ram? */             (ent[i].size < size) ||      /* too small? */             (addr != ent[i].addr) ||     /* starts above 4gb? */             ((addr + size) < addr) )     /* ends above 4gb? */            continue;        if ( ent[i].size != size )        {            memmove(&ent[i+1], &ent[i], (*HVM_E820_NR-i) * sizeof(*ent));            (*HVM_E820_NR)++;            ent[i].size -= size;            addr += ent[i].size;            i++;        }        ent[i].addr = addr;        ent[i].size = size;        ent[i].type = E820_RESERVED;        e820_collapse();        return addr;    }    return 0;}uint32_t ioapic_read(uint32_t reg){    *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x00) = reg;    return *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x10);}void ioapic_write(uint32_t reg, uint32_t val){    *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x00) = reg;    *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x10) = val;}uint32_t lapic_read(uint32_t reg){    return *(volatile uint32_t *)(LAPIC_BASE_ADDRESS + reg);}void lapic_write(uint32_t reg, uint32_t val){    *(volatile uint32_t *)(LAPIC_BASE_ADDRESS + reg) = val;}#define PCI_CONF1_ADDRESS(bus, devfn, reg) \    (0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))uint32_t pci_read(uint32_t devfn, uint32_t reg, uint32_t len){    outl(0xcf8, PCI_CONF1_ADDRESS(0, devfn, reg));    switch ( len )    {    case 1: return inb(0xcfc + (reg & 3));    case 2: return inw(0xcfc + (reg & 2));    }    return inl(0xcfc);}void pci_write(uint32_t devfn, uint32_t reg, uint32_t len, uint32_t val){    outl(0xcf8, PCI_CONF1_ADDRESS(0, devfn, reg));    switch ( len )    {    case 1: outb(0xcfc + (reg & 3), val); break;    case 2: outw(0xcfc + (reg & 2), val); break;    case 4: outl(0xcfc,             val); break;    }}static char *printnum(char *p, unsigned long num, int base){    unsigned long n;    if ( (n = num/base) > 0 )        p = printnum(p, n, base);    *p++ = "0123456789abcdef"[(int)(num % base)];    *p = '\0';    return p;}static void _doprint(void (*put)(char), const char *fmt, va_list ap){    register char *str, c;    int lflag, zflag, nflag;    char buffer[17];    unsigned value;    int i, slen, pad;    for ( ; *fmt != '\0'; fmt++ )    {        if ( *fmt != '%' )        {            put(*fmt);            continue;        }        pad = zflag = nflag = lflag = 0;        c = *++fmt;        if ( (c == '-') || isdigit(c) )        {            if ( c == '-' )            {                nflag = 1;                c = *++fmt;            }            zflag = c == '0';            for ( pad = 0; isdigit(c); c = *++fmt )                pad = (pad * 10) + c - '0';        }        if ( c == 'l' ) /* long extension */        {            lflag = 1;            c = *++fmt;        }        if ( (c == 'd') || (c == 'u') || (c == 'o') || (c == 'x') )        {            if ( lflag )                value = va_arg(ap, unsigned);            else                value = (unsigned) va_arg(ap, unsigned int);            str = buffer;            printnum(str, value,                     c == 'o' ? 8 : (c == 'x' ? 16 : 10));            goto printn;        }        else if ( (c == 'O') || (c == 'D') || (c == 'X') )        {            value = va_arg(ap, unsigned);            str = buffer;            printnum(str, value,                     c == 'O' ? 8 : (c == 'X' ? 16 : 10));        printn:            slen = strlen(str);            for ( i = pad - slen; i > 0; i-- )                put(zflag ? '0' : ' ');            while ( *str )                put(*str++);        }        else if ( c == 's' )        {            str = va_arg(ap, char *);            slen = strlen(str);            if ( nflag == 0 )                for ( i = pad - slen; i > 0; i-- )                    put(' ');            while ( *str )                put(*str++);            if ( nflag )                for ( i = pad - slen; i > 0; i-- )                    put(' ');        }        else if ( c == 'c' )        {            put(va_arg(ap, int));        }        else        {            put(*fmt);        }    }}static void putchar(char c){    outb(0xe9, c);}int printf(const char *fmt, ...){    va_list ap;    va_start(ap, fmt);    _doprint(putchar, fmt, ap);    va_end(ap);    return 0;}int vprintf(const char *fmt, va_list ap){    _doprint(putchar, fmt, ap);    return 0;}void __assert_failed(char *assertion, char *file, int line){    printf("HVMLoader assertion '%s' failed at %s:%d\n",           assertion, file, line);    for ( ; ; )        asm volatile ( "ud2" );}void __bug(char *file, int line){    printf("HVMLoader bug at %s:%d\n", file, line);    for ( ; ; )        asm volatile ( "ud2" );}static int validate_hvm_info(struct hvm_info_table *t){    char signature[] = "HVM INFO";    uint8_t *ptr = (uint8_t *)t;    uint8_t sum = 0;    int i;    /* strncmp(t->signature, "HVM INFO", 8) */    for ( i = 0; i < 8; i++ )    {        if ( signature[i] != t->signature[i] )        {            printf("Bad hvm info signature\n");            return 0;        }    }    for ( i = 0; i < t->length; i++ )        sum += ptr[i];    return (sum == 0);}static struct hvm_info_table *get_hvm_info_table(void){    static struct hvm_info_table *table;    struct hvm_info_table *t;    if ( table != NULL )        return table;    t = (struct hvm_info_table *)HVM_INFO_PADDR;    if ( !validate_hvm_info(t) )    {        printf("Bad hvm info table\n");        return NULL;    }    table = t;    return table;}int get_vcpu_nr(void){    struct hvm_info_table *t = get_hvm_info_table();    return (t ? t->nr_vcpus : 1);}int get_acpi_enabled(void){    struct hvm_info_table *t = get_hvm_info_table();    return (t ? t->acpi_enabled : 1);}int get_apic_mode(void){    struct hvm_info_table *t = get_hvm_info_table();    return (t ? t->apic_mode : 1);}uint16_t get_cpu_mhz(void){    struct xen_add_to_physmap xatp;    struct shared_info *shared_info = (struct shared_info *)0xfffff000;    struct vcpu_time_info *info = &shared_info->vcpu_info[0].time;    uint64_t cpu_khz;    uint32_t tsc_to_nsec_mul, version;    int8_t tsc_shift;    static uint16_t cpu_mhz;    if ( cpu_mhz != 0 )        return cpu_mhz;    /* Map shared-info page. */    xatp.domid = DOMID_SELF;    xatp.space = XENMAPSPACE_shared_info;    xatp.idx   = 0;    xatp.gpfn  = (unsigned long)shared_info >> 12;    if ( hypercall_memory_op(XENMEM_add_to_physmap, &xatp) != 0 )        BUG();    /* Get a consistent snapshot of scale factor (multiplier and shift). */    do {        version = info->version;        rmb();        tsc_to_nsec_mul = info->tsc_to_system_mul;        tsc_shift       = info->tsc_shift;        rmb();    } while ((version & 1) | (version ^ info->version));    /* Compute CPU speed in kHz. */    cpu_khz = 1000000ull << 32;    do_div(cpu_khz, tsc_to_nsec_mul);    if ( tsc_shift < 0 )        cpu_khz = cpu_khz << -tsc_shift;    else        cpu_khz = cpu_khz >> tsc_shift;    cpu_mhz = (uint16_t)(((uint32_t)cpu_khz + 500) / 1000);    return cpu_mhz;}/* * Local variables: * mode: C * c-set-style: "BSD" * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: nil * End: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -