X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=bios%2Fvmxassist%2Futil.c;fp=bios%2Fvmxassist%2Futil.c;h=0181fe702c1399afe07bd9808954c5dd6777111c;hp=0000000000000000000000000000000000000000;hb=d34450b1e6fe3c2e1295c268c1722c669ba8d545;hpb=1a24d4e8fb3918a42b124777db5b41940150023e diff --git a/bios/vmxassist/util.c b/bios/vmxassist/util.c new file mode 100644 index 0000000..0181fe7 --- /dev/null +++ b/bios/vmxassist/util.c @@ -0,0 +1,406 @@ +/* + * util.c: Commonly used utility functions. + * + * 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 + +#include "util.h" +#include "machine.h" + +#define isdigit(c) ((c) >= '0' && (c) <= '9') +#define min(a, b) ((a) < (b) ? (a) : (b)) + +static void putchar(int); +static char *printnum(char *, unsigned long, int); +static void _doprint(void (*)(int), char const *, va_list); + + +void +dump_regs(struct regs *regs) +{ + printf("eax %8x ecx %8x edx %8x ebx %8x\n", + regs->eax, regs->ecx, regs->edx, regs->ebx); + printf("esp %8x ebp %8x esi %8x edi %8x\n", + regs->esp, regs->ebp, regs->esi, regs->edi); + printf("eip %8x eflags %8x cs %8x ds %8x\n", + regs->eip, regs->eflags, regs->cs, regs->ds); + printf("es %8x fs %8x uss %8x uesp %8x\n", + regs->es, regs->fs, regs->uss, regs->uesp); + printf("ves %8x vds %8x vfs %8x vgs %8x\n", + regs->ves, regs->vds, regs->vfs, regs->vgs); + if (regs->trapno != -1 || regs->errno != -1) + printf("trapno %8x errno %8x\n", regs->trapno, regs->errno); + + printf("cr0 %8lx cr2 %8x cr3 %8lx cr4 %8lx\n", + (long)oldctx.cr0, get_cr2(), + (long)oldctx.cr3, (long)oldctx.cr4); +} + +#ifdef DEBUG +void +hexdump(unsigned char *data, int sz) +{ + unsigned char *d; + int i; + + for (d = data; sz > 0; d += 16, sz -= 16) { + int n = sz > 16 ? 16 : sz; + + printf("%08x: ", (unsigned)d); + for (i = 0; i < n; i++) + printf("%02x%c", d[i], i == 7 ? '-' : ' '); + for (; i < 16; i++) + printf(" %c", i == 7 ? '-' : ' '); + printf(" "); + for (i = 0; i < n; i++) + printf("%c", d[i] >= ' ' && d[i] <= '~' ? d[i] : '.'); + printf("\n"); + } +} + +void +print_e820_map(struct e820entry *map, int entries) +{ + struct e820entry *m; + + if (entries > 32) + entries = 32; + + for (m = map; m < &map[entries]; m++) { + printf("%08lx%08lx - %08lx%08lx ", + (unsigned long) (m->addr >> 32), + (unsigned long) (m->addr), + (unsigned long) ((m->addr+m->size) >> 32), + (unsigned long) ((m->addr+m->size))); + + switch (m->type) { + case E820_RAM: + printf("(RAM)\n"); break; + case E820_RESERVED: + printf("(Reserved)\n"); break; + case E820_ACPI: + printf("(ACPI Data)\n"); break; + case E820_NVS: + printf("(ACPI NVS)\n"); break; + default: + printf("(Type %ld)\n", m->type); break; + } + } +} + +void +dump_dtr(unsigned long addr, unsigned long size) +{ + unsigned long long entry; + unsigned long base, limit; + int i; + + for (i = 0; i < size; i += 8) { + entry = ((unsigned long long *) addr)[i >> 3]; + base = (((entry >> (56-24)) & 0xFF000000) | + ((entry >> (32-16)) & 0x00FF0000) | + ((entry >> ( 16)) & 0x0000FFFF)); + limit = (((entry >> (48-16)) & 0x000F0000) | + ((entry ) & 0x0000FFFF)); + if (entry & (1ULL << (23+32))) /* G */ + limit = (limit << 12) | 0xFFF; + + printf("[0x%x] = 0x%08x%08x, base 0x%lx, limit 0x%lx\n", i, + (unsigned)(entry >> 32), (unsigned)(entry), + base, limit); + } +} + +void +dump_vmx_context(struct vmx_assist_context *c) +{ + printf("eip 0x%lx, esp 0x%lx, eflags 0x%lx\n", + (long) c->eip, (long) c->esp, (long) c->eflags); + + printf("cr0 0x%lx, cr3 0x%lx, cr4 0x%lx\n", + (long)c->cr0, (long)c->cr3, (long)c->cr4); + + printf("idtr: limit 0x%lx, base 0x%lx\n", + (long)c->idtr_limit, (long)c->idtr_base); + + printf("gdtr: limit 0x%lx, base 0x%lx\n", + (long)c->gdtr_limit, (long)c->gdtr_base); + + printf("cs: sel 0x%lx, limit 0x%lx, base 0x%lx\n", + (long)c->cs_sel, (long)c->cs_limit, (long)c->cs_base); + printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n", + c->cs_arbytes.fields.seg_type, + c->cs_arbytes.fields.s, + c->cs_arbytes.fields.dpl, + c->cs_arbytes.fields.p, + c->cs_arbytes.fields.avl, + c->cs_arbytes.fields.default_ops_size, + c->cs_arbytes.fields.g, + c->cs_arbytes.fields.null_bit); + + printf("ds: sel 0x%lx, limit 0x%lx, base 0x%lx\n", + (long)c->ds_sel, (long)c->ds_limit, (long)c->ds_base); + printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n", + c->ds_arbytes.fields.seg_type, + c->ds_arbytes.fields.s, + c->ds_arbytes.fields.dpl, + c->ds_arbytes.fields.p, + c->ds_arbytes.fields.avl, + c->ds_arbytes.fields.default_ops_size, + c->ds_arbytes.fields.g, + c->ds_arbytes.fields.null_bit); + + printf("es: sel 0x%lx, limit 0x%lx, base 0x%lx\n", + (long)c->es_sel, (long)c->es_limit, (long)c->es_base); + printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n", + c->es_arbytes.fields.seg_type, + c->es_arbytes.fields.s, + c->es_arbytes.fields.dpl, + c->es_arbytes.fields.p, + c->es_arbytes.fields.avl, + c->es_arbytes.fields.default_ops_size, + c->es_arbytes.fields.g, + c->es_arbytes.fields.null_bit); + + printf("ss: sel 0x%lx, limit 0x%lx, base 0x%lx\n", + (long)c->ss_sel, (long)c->ss_limit, (long)c->ss_base); + printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n", + c->ss_arbytes.fields.seg_type, + c->ss_arbytes.fields.s, + c->ss_arbytes.fields.dpl, + c->ss_arbytes.fields.p, + c->ss_arbytes.fields.avl, + c->ss_arbytes.fields.default_ops_size, + c->ss_arbytes.fields.g, + c->ss_arbytes.fields.null_bit); + + printf("fs: sel 0x%lx, limit 0x%lx, base 0x%lx\n", + (long)c->fs_sel, (long)c->fs_limit, (long)c->fs_base); + printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n", + c->fs_arbytes.fields.seg_type, + c->fs_arbytes.fields.s, + c->fs_arbytes.fields.dpl, + c->fs_arbytes.fields.p, + c->fs_arbytes.fields.avl, + c->fs_arbytes.fields.default_ops_size, + c->fs_arbytes.fields.g, + c->fs_arbytes.fields.null_bit); + + printf("gs: sel 0x%lx, limit 0x%lx, base 0x%lx\n", + (long)c->gs_sel, (long)c->gs_limit, (long)c->gs_base); + printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n", + c->gs_arbytes.fields.seg_type, + c->gs_arbytes.fields.s, + c->gs_arbytes.fields.dpl, + c->gs_arbytes.fields.p, + c->gs_arbytes.fields.avl, + c->gs_arbytes.fields.default_ops_size, + c->gs_arbytes.fields.g, + c->gs_arbytes.fields.null_bit); + + printf("tr: sel 0x%lx, limit 0x%lx, base 0x%lx\n", + (long)c->tr_sel, (long)c->tr_limit, (long)c->tr_base); + printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n", + c->tr_arbytes.fields.seg_type, + c->tr_arbytes.fields.s, + c->tr_arbytes.fields.dpl, + c->tr_arbytes.fields.p, + c->tr_arbytes.fields.avl, + c->tr_arbytes.fields.default_ops_size, + c->tr_arbytes.fields.g, + c->tr_arbytes.fields.null_bit); + + printf("ldtr: sel 0x%lx, limit 0x%lx, base 0x%lx\n", + (long)c->ldtr_sel, (long)c->ldtr_limit, (long)c->ldtr_base); + printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n", + c->ldtr_arbytes.fields.seg_type, + c->ldtr_arbytes.fields.s, + c->ldtr_arbytes.fields.dpl, + c->ldtr_arbytes.fields.p, + c->ldtr_arbytes.fields.avl, + c->ldtr_arbytes.fields.default_ops_size, + c->ldtr_arbytes.fields.g, + c->ldtr_arbytes.fields.null_bit); + + printf("GDTR <0x%lx,0x%lx>:\n", + (long)c->gdtr_base, (long)c->gdtr_limit); + dump_dtr(c->gdtr_base, c->gdtr_limit); +} +#endif /* DEBUG */ + +/* + * Lightweight printf that doesn't drag in everything under the sun. + */ +int +printf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _doprint(putchar, fmt, ap); + va_end(ap); + return 0; /* for gcc compat */ +} + +int +vprintf(const char *fmt, va_list ap) +{ + _doprint(putchar, fmt, ap); + return 0; /* for gcc compat */ +} + +void +panic(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _doprint(putchar, fmt, ap); + putchar('\n'); + va_end(ap); + halt(); +} + +unsigned +strlen(const char *s) +{ + const char *q = s; + + while (*s++) + /* void */; + return s - q - 1; +} + +static void +putchar(int ch) +{ + outb(0xE9, ch); +} + +/* + * A stripped down version of doprint, + * but still powerful enough for most tasks. + */ +static void +_doprint(void (*put)(int), char const *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++) { + pad = zflag = nflag = lflag = 0; + if (*fmt == '%') { + 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); + } else + put(*fmt); + } +} + +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; +} + +void * +memset(void *s, int c, unsigned n) +{ + int t0, t1; + + __asm__ __volatile__ ("cld; rep; stosb" + : "=&c" (t0), "=&D" (t1) + : "a" (c), "1" (s), "0" (n) + : "memory"); + return s; +} + +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; +} +