1 /*
2 * util.c: Helper library functions for HVMLoader.
3 *
4 * Leendert van Doorn, leendert@watson.ibm.com
5 * Copyright (c) 2005, International Business Machines Corporation.
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "util.h"
21 #include "config.h"
22 #include "hypercall.h"
23 #include "ctype.h"
24 #include "vnuma.h"
25 #include <acpi2_0.h>
26 #include <libacpi.h>
27 #include <stdint.h>
28 #include <xen/xen.h>
29 #include <xen/memory.h>
30 #include <xen/sched.h>
31 #include <xen/hvm/hvm_xs_strings.h>
32 #include <xen/hvm/params.h>
33
34 /*
35 * Check whether there exists overlap in the specified memory range.
36 * Returns true if exists, else returns false.
37 */
check_overlap(uint64_t start,uint64_t size,uint64_t reserved_start,uint64_t reserved_size)38 bool check_overlap(uint64_t start, uint64_t size,
39 uint64_t reserved_start, uint64_t reserved_size)
40 {
41 return (start + size > reserved_start) &&
42 (start < reserved_start + reserved_size);
43 }
44
wrmsr(uint32_t idx,uint64_t v)45 void wrmsr(uint32_t idx, uint64_t v)
46 {
47 asm volatile (
48 "wrmsr"
49 : : "c" (idx), "a" ((uint32_t)v), "d" ((uint32_t)(v>>32)) );
50 }
51
rdmsr(uint32_t idx)52 uint64_t rdmsr(uint32_t idx)
53 {
54 uint32_t lo, hi;
55
56 asm volatile (
57 "rdmsr"
58 : "=a" (lo), "=d" (hi) : "c" (idx) );
59
60 return (lo | ((uint64_t)hi << 32));
61 }
62
outb(uint16_t addr,uint8_t val)63 void outb(uint16_t addr, uint8_t val)
64 {
65 asm volatile ( "outb %%al, %%dx" : : "d" (addr), "a" (val) );
66 }
67
outw(uint16_t addr,uint16_t val)68 void outw(uint16_t addr, uint16_t val)
69 {
70 asm volatile ( "outw %%ax, %%dx" : : "d" (addr), "a" (val) );
71 }
72
outl(uint16_t addr,uint32_t val)73 void outl(uint16_t addr, uint32_t val)
74 {
75 asm volatile ( "outl %%eax, %%dx" : : "d" (addr), "a" (val) );
76 }
77
inb(uint16_t addr)78 uint8_t inb(uint16_t addr)
79 {
80 uint8_t val;
81 asm volatile ( "inb %%dx,%%al" : "=a" (val) : "d" (addr) );
82 return val;
83 }
84
inw(uint16_t addr)85 uint16_t inw(uint16_t addr)
86 {
87 uint16_t val;
88 asm volatile ( "inw %%dx,%%ax" : "=a" (val) : "d" (addr) );
89 return val;
90 }
91
inl(uint16_t addr)92 uint32_t inl(uint16_t addr)
93 {
94 uint32_t val;
95 asm volatile ( "inl %%dx,%%eax" : "=a" (val) : "d" (addr) );
96 return val;
97 }
98
cmos_inb(uint8_t idx)99 uint8_t cmos_inb(uint8_t idx)
100 {
101 outb(0x70, idx);
102 return inb(0x71);
103 }
104
cmos_outb(uint8_t idx,uint8_t val)105 void cmos_outb(uint8_t idx, uint8_t val)
106 {
107 outb(0x70, idx);
108 outb(0x71, val);
109 }
110
itoa(char * a,unsigned int i)111 char *itoa(char *a, unsigned int i)
112 {
113 unsigned int _i = i, x = 0;
114
115 do {
116 x++;
117 _i /= 10;
118 } while ( _i != 0 );
119
120 a += x;
121 *a-- = '\0';
122
123 do {
124 *a-- = (i % 10) + '0';
125 i /= 10;
126 } while ( i != 0 );
127
128 return a + 1;
129 }
130
strcmp(const char * cs,const char * ct)131 int strcmp(const char *cs, const char *ct)
132 {
133 signed char res;
134
135 while ( ((res = *cs - *ct++) == 0) && (*cs++ != '\0') )
136 continue;
137
138 return res;
139 }
140
strncmp(const char * s1,const char * s2,uint32_t n)141 int strncmp(const char *s1, const char *s2, uint32_t n)
142 {
143 uint32_t ctr;
144 for (ctr = 0; ctr < n; ctr++)
145 if (s1[ctr] != s2[ctr])
146 return (int)(s1[ctr] - s2[ctr]);
147 return 0;
148 }
149
memcpy(void * dest,const void * src,unsigned n)150 void *memcpy(void *dest, const void *src, unsigned n)
151 {
152 int t0, t1, t2;
153
154 asm volatile (
155 "cld\n"
156 "rep; movsl\n"
157 "testb $2,%b4\n"
158 "je 1f\n"
159 "movsw\n"
160 "1: testb $1,%b4\n"
161 "je 2f\n"
162 "movsb\n"
163 "2:"
164 : "=&c" (t0), "=&D" (t1), "=&S" (t2)
165 : "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src)
166 : "memory" );
167 return dest;
168 }
169
memmove(void * dest,const void * src,unsigned n)170 void *memmove(void *dest, const void *src, unsigned n)
171 {
172 if ( (unsigned long)dest > (unsigned long)src )
173 while ( n-- != 0 )
174 ((char *)dest)[n] = ((char *)src)[n];
175 else
176 memcpy(dest, src, n);
177 return dest;
178 }
179
180 char *
strcpy(char * dest,const char * src)181 strcpy(char *dest, const char *src)
182 {
183 char *p = dest;
184 while ( *src )
185 *p++ = *src++;
186 *p = 0;
187 return dest;
188 }
189
190 char *
strncpy(char * dest,const char * src,unsigned n)191 strncpy(char *dest, const char *src, unsigned n)
192 {
193 int i = 0;
194 char *p = dest;
195
196 /* write non-NUL characters from src into dest until we run
197 out of room in dest or encounter a NUL in src */
198 while ( (i < n) && *src )
199 {
200 *p++ = *src++;
201 i++;
202 }
203
204 /* pad remaining bytes of dest with NUL bytes */
205 while ( i < n )
206 {
207 *p++ = 0;
208 i++;
209 }
210
211 return dest;
212 }
213
214 unsigned
strlen(const char * s)215 strlen(const char *s)
216 {
217 int i = 0;
218 while ( *s++ )
219 i++;
220 return i;
221 }
222
__digit(char c,int base)223 static inline int __digit(char c, int base)
224 {
225 int d = -1;
226
227 if ( (c >= '0') && (c <= '9') )
228 d = c - '0';
229
230 if ( (c >= 'A') && (c <= 'Z') )
231 d = c - 'A' + 10;
232
233 if ( (c >= 'a') && (c <= 'z') )
234 d = c - 'a' + 10;
235
236 if (d >= base)
237 d = -1;
238
239 return d;
240 }
241
242 long long
strtoll(const char * s,char ** end,int base)243 strtoll(const char *s, char **end, int base)
244 {
245 long long v = 0;
246 int sign = 1;
247
248 while ( (*s != '\0') && isspace(*s) )
249 s++;
250
251 if ( *s == '\0' ) goto out;
252
253 if ( *s == '-' ) {
254 sign = -1;
255 s++;
256 } else {
257 if ( *s == '+' )
258 s++;
259 }
260
261 if ( *s == '\0' ) goto out;
262
263 if ( *s == '0' ) {
264 s++;
265 if ( *s == '\0' ) goto out;
266
267 if ( *s == 'x' ) {
268 if ( base != 0 && base != 16) goto out;
269 base = 16;
270 s++;
271 } else {
272 if ( base != 0 && base != 8) goto out;
273 base = 8;
274 }
275 } else {
276 if (base != 0 && base != 10) goto out;
277 base = 10;
278 }
279
280 while ( *s != '\0' ) {
281 int d = __digit(*s, base);
282
283 if ( d < 0 ) goto out;
284
285 v = (v * base) + d;
286 s++;
287 }
288
289 out:
290 if (end) *end = (char *)s;
291
292 return sign * v;
293 }
294
295 void *
memset(void * s,int c,unsigned n)296 memset(void *s, int c, unsigned n)
297 {
298 uint8_t b = (uint8_t) c;
299 uint8_t *p = (uint8_t *)s;
300 int i;
301 for ( i = 0; i < n; i++ )
302 *p++ = b;
303 return s;
304 }
305
306 int
memcmp(const void * s1,const void * s2,unsigned n)307 memcmp(const void *s1, const void *s2, unsigned n)
308 {
309 unsigned i;
310 uint8_t *p1 = (uint8_t *) s1;
311 uint8_t *p2 = (uint8_t *) s2;
312
313 for ( i = 0; i < n; i++ )
314 {
315 if ( p1[i] < p2[i] )
316 return -1;
317 else if ( p1[i] > p2[i] )
318 return 1;
319 }
320
321 return 0;
322 }
323
324 void
cpuid(uint32_t idx,uint32_t * eax,uint32_t * ebx,uint32_t * ecx,uint32_t * edx)325 cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
326 {
327 asm volatile (
328 "cpuid"
329 : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
330 : "0" (idx) );
331 }
332
333 static const char hex_digits[] = "0123456789abcdef";
334
335 /* Write a two-character hex representation of 'byte' to digits[].
336 Pre-condition: sizeof(digits) >= 2 */
337 void
byte_to_hex(char * digits,uint8_t byte)338 byte_to_hex(char *digits, uint8_t byte)
339 {
340 digits[0] = hex_digits[byte >> 4];
341 digits[1] = hex_digits[byte & 0x0f];
342 }
343
344 /* Convert an array of 16 unsigned bytes to a DCE/OSF formatted UUID
345 string.
346
347 Pre-condition: sizeof(dest) >= 37 */
348 void
uuid_to_string(char * dest,uint8_t * uuid)349 uuid_to_string(char *dest, uint8_t *uuid)
350 {
351 int i = 0;
352 char *p = dest;
353
354 for ( i = 0; i < 4; i++ )
355 {
356 byte_to_hex(p, uuid[i]);
357 p += 2;
358 }
359 *p++ = '-';
360 for ( i = 4; i < 6; i++ )
361 {
362 byte_to_hex(p, uuid[i]);
363 p += 2;
364 }
365 *p++ = '-';
366 for ( i = 6; i < 8; i++ )
367 {
368 byte_to_hex(p, uuid[i]);
369 p += 2;
370 }
371 *p++ = '-';
372 for ( i = 8; i < 10; i++ )
373 {
374 byte_to_hex(p, uuid[i]);
375 p += 2;
376 }
377 *p++ = '-';
378 for ( i = 10; i < 16; i++ )
379 {
380 byte_to_hex(p, uuid[i]);
381 p += 2;
382 }
383 *p = '\0';
384 }
385
get_mem_mapping_layout(struct e820entry entries[],uint32_t * max_entries)386 int get_mem_mapping_layout(struct e820entry entries[], uint32_t *max_entries)
387 {
388 int rc;
389 struct xen_memory_map memmap = {
390 .nr_entries = *max_entries
391 };
392
393 set_xen_guest_handle(memmap.buffer, entries);
394
395 rc = hypercall_memory_op(XENMEM_memory_map, &memmap);
396 *max_entries = memmap.nr_entries;
397
398 return rc;
399 }
400
mem_hole_populate_ram(xen_pfn_t mfn,uint32_t nr_mfns)401 void mem_hole_populate_ram(xen_pfn_t mfn, uint32_t nr_mfns)
402 {
403 static int over_allocated;
404 struct xen_add_to_physmap xatp;
405 struct xen_memory_reservation xmr;
406
407 for ( ; nr_mfns-- != 0; mfn++ )
408 {
409 /* Try to allocate a brand new page in the reserved area. */
410 if ( !over_allocated )
411 {
412 xmr.domid = DOMID_SELF;
413 xmr.mem_flags = 0;
414 xmr.extent_order = 0;
415 xmr.nr_extents = 1;
416 set_xen_guest_handle(xmr.extent_start, &mfn);
417 if ( hypercall_memory_op(XENMEM_populate_physmap, &xmr) == 1 )
418 continue;
419 over_allocated = 1;
420 }
421
422 /* Otherwise, relocate a page from the ordinary RAM map. */
423 if ( hvm_info->high_mem_pgend )
424 {
425 xatp.idx = --hvm_info->high_mem_pgend;
426 if ( xatp.idx == (1ull << (32 - PAGE_SHIFT)) )
427 hvm_info->high_mem_pgend = 0;
428 }
429 else
430 {
431 xatp.idx = --hvm_info->low_mem_pgend;
432 }
433 xatp.domid = DOMID_SELF;
434 xatp.space = XENMAPSPACE_gmfn;
435 xatp.gpfn = mfn;
436 if ( hypercall_memory_op(XENMEM_add_to_physmap, &xatp) != 0 )
437 BUG();
438 }
439
440 /* Sync memory map[]. */
441 adjust_memory_map();
442 }
443
444 static uint32_t alloc_up = RESERVED_MEMORY_DYNAMIC_START - 1;
445 static uint32_t alloc_down = RESERVED_MEMORY_DYNAMIC_END;
446
mem_hole_alloc(uint32_t nr_mfns)447 xen_pfn_t mem_hole_alloc(uint32_t nr_mfns)
448 {
449 alloc_down -= nr_mfns << PAGE_SHIFT;
450 BUG_ON(alloc_up >= alloc_down);
451 return alloc_down >> PAGE_SHIFT;
452 }
453
mem_alloc(uint32_t size,uint32_t align)454 void *mem_alloc(uint32_t size, uint32_t align)
455 {
456 uint32_t s, e;
457
458 /* Align to at least 16 bytes. */
459 if ( align < 16 )
460 align = 16;
461
462 s = (alloc_up + align) & ~(align - 1);
463 e = s + size - 1;
464
465 BUG_ON((e < s) || (e >= alloc_down));
466
467 while ( (alloc_up >> PAGE_SHIFT) != (e >> PAGE_SHIFT) )
468 {
469 alloc_up += PAGE_SIZE;
470 mem_hole_populate_ram(alloc_up >> PAGE_SHIFT, 1);
471 }
472
473 alloc_up = e;
474
475 return (void *)(unsigned long)s;
476 }
477
scratch_alloc(uint32_t size,uint32_t align)478 void *scratch_alloc(uint32_t size, uint32_t align)
479 {
480 uint32_t s, e;
481
482 /* Align to at least 16 bytes. */
483 if ( align < 16 )
484 align = 16;
485
486 s = (scratch_start + align) & ~(align - 1);
487 e = s + size - 1;
488
489 BUG_ON(e < s);
490
491 scratch_start = e;
492
493 return (void *)(unsigned long)s;
494 }
495
ioapic_read(uint32_t reg)496 uint32_t ioapic_read(uint32_t reg)
497 {
498 *(volatile uint32_t *)(ioapic_base_address + 0x00) = reg;
499 return *(volatile uint32_t *)(ioapic_base_address + 0x10);
500 }
501
ioapic_write(uint32_t reg,uint32_t val)502 void ioapic_write(uint32_t reg, uint32_t val)
503 {
504 *(volatile uint32_t *)(ioapic_base_address + 0x00) = reg;
505 *(volatile uint32_t *)(ioapic_base_address + 0x10) = val;
506 }
507
lapic_read(uint32_t reg)508 uint32_t lapic_read(uint32_t reg)
509 {
510 return *(volatile uint32_t *)(LAPIC_BASE_ADDRESS + reg);
511 }
512
lapic_write(uint32_t reg,uint32_t val)513 void lapic_write(uint32_t reg, uint32_t val)
514 {
515 *(volatile uint32_t *)(LAPIC_BASE_ADDRESS + reg) = val;
516 }
517
518 #define PCI_CONF1_ADDRESS(bus, devfn, reg) \
519 (0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))
520
pci_read(uint32_t devfn,uint32_t reg,uint32_t len)521 uint32_t pci_read(uint32_t devfn, uint32_t reg, uint32_t len)
522 {
523 outl(0xcf8, PCI_CONF1_ADDRESS(0, devfn, reg));
524
525 switch ( len )
526 {
527 case 1: return inb(0xcfc + (reg & 3));
528 case 2: return inw(0xcfc + (reg & 2));
529 }
530
531 return inl(0xcfc);
532 }
533
pci_write(uint32_t devfn,uint32_t reg,uint32_t len,uint32_t val)534 void pci_write(uint32_t devfn, uint32_t reg, uint32_t len, uint32_t val)
535 {
536 outl(0xcf8, PCI_CONF1_ADDRESS(0, devfn, reg));
537
538 switch ( len )
539 {
540 case 1: outb(0xcfc + (reg & 3), val); break;
541 case 2: outw(0xcfc + (reg & 2), val); break;
542 case 4: outl(0xcfc, val); break;
543 }
544 }
545
printnum(char * p,unsigned long num,unsigned base)546 static char *printnum(char *p, unsigned long num, unsigned base)
547 {
548 unsigned long n;
549
550 if ( (n = num/base) > 0 )
551 p = printnum(p, n, base);
552 *p++ = hex_digits[num % base];
553 *p = '\0';
554 return p;
555 }
556
_doprint(void (* emit)(void *,char),void * arg,const char * fmt,va_list ap)557 static void _doprint(void (*emit)(void *, char), void *arg, const char *fmt, va_list ap)
558 {
559 char *str, c;
560 int lflag, zflag, nflag;
561 char buffer[17];
562 unsigned long value;
563 int i, slen, pad;
564
565 for ( ; *fmt != '\0'; fmt++ )
566 {
567 if ( *fmt != '%' )
568 {
569 emit(arg, *fmt);
570 continue;
571 }
572
573 pad = zflag = nflag = lflag = 0;
574 c = *++fmt;
575 if ( (c == '-') || isdigit(c) )
576 {
577 if ( c == '-' )
578 {
579 nflag = 1;
580 c = *++fmt;
581 }
582 zflag = c == '0';
583 for ( pad = 0; isdigit(c); c = *++fmt )
584 pad = (pad * 10) + c - '0';
585 }
586 if ( c == 'l' ) /* long extension */
587 {
588 lflag = 1;
589 c = *++fmt;
590 }
591 if ( (c == 'd') || (c == 'u') || (c == 'o') ||
592 (c == 'x') || (c == 'X') )
593 {
594 if ( lflag )
595 {
596 value = va_arg(ap, unsigned long);
597 if ( (c == 'd') && ((long)value < 0) )
598 {
599 value = -value;
600 emit(arg, '-');
601 }
602 }
603 else
604 {
605 value = va_arg(ap, unsigned int);
606 if ( (c == 'd') && ((int)value < 0) )
607 {
608 value = -(int)value;
609 emit(arg, '-');
610 }
611 }
612 str = buffer;
613 printnum(str, value,
614 c == 'o' ? 8 : ((c == 'x') || (c == 'X') ? 16 : 10));
615 slen = strlen(str);
616 for ( i = pad - slen; i > 0; i-- )
617 emit(arg, zflag ? '0' : ' ');
618 while ( *str )
619 {
620 char ch = *str++;
621 if ( (ch >= 'a') && (c == 'X') )
622 ch += 'A'-'a';
623 emit(arg, ch);
624 }
625 }
626 else if ( c == 's' )
627 {
628 str = va_arg(ap, char *);
629 slen = strlen(str);
630 if ( nflag == 0 )
631 for ( i = pad - slen; i > 0; i-- )
632 emit(arg, ' ');
633 while ( *str )
634 emit(arg, *str++);
635 if ( nflag )
636 for ( i = pad - slen; i > 0; i-- )
637 emit(arg, ' ');
638 }
639 else if ( c == 'c' )
640 {
641 emit(arg, va_arg(ap, int));
642 }
643 else
644 {
645 emit(arg, *fmt);
646 }
647 }
648 }
649
putchar(char c)650 static void putchar(char c)
651 {
652 outb(0xe9, c);
653 }
654
__put(void * arg,char c)655 static void __put(void *arg, char c)
656 {
657 putchar(c);
658 }
659
printf(const char * fmt,...)660 int printf(const char *fmt, ...)
661 {
662 va_list ap;
663
664 va_start(ap, fmt);
665 _doprint(__put, NULL, fmt, ap);
666 va_end(ap);
667
668 return 0;
669 }
670
vprintf(const char * fmt,va_list ap)671 int vprintf(const char *fmt, va_list ap)
672 {
673 _doprint(__put, NULL, fmt, ap);
674 return 0;
675 }
676
677 struct __copy_context {
678 char *ptr;
679 size_t emitted;
680 size_t remaining;
681 };
682
__copy(void * arg,char c)683 static void __copy(void *arg, char c)
684 {
685 struct __copy_context *ctxt = arg;
686
687 ctxt->emitted++;
688
689 if (ctxt->remaining == 0)
690 return;
691
692 *(ctxt->ptr++) = c;
693 --ctxt->remaining;
694 }
695
snprintf(char * buf,size_t size,const char * fmt,...)696 int snprintf(char *buf, size_t size, const char *fmt, ...)
697 {
698 va_list ap;
699 struct __copy_context ctxt;
700
701 ctxt.ptr = buf;
702 ctxt.emitted = 0;
703 ctxt.remaining = size;
704
705 va_start(ap, fmt);
706 _doprint(__copy, &ctxt, fmt, ap);
707 va_end(ap);
708
709 if (ctxt.remaining != 0)
710 *ctxt.ptr = '\0';
711
712 return ctxt.emitted;
713 }
714
crash(void)715 static void __attribute__((noreturn)) crash(void)
716 {
717 struct sched_shutdown shutdown = { .reason = SHUTDOWN_crash };
718 printf("*** HVMLoader crashed.\n");
719 hypercall_sched_op(SCHEDOP_shutdown, &shutdown);
720 printf("*** Failed to crash. Halting.\n");
721 for ( ; ; )
722 asm volatile ( "hlt" );
723 }
724
__assert_failed(char * assertion,char * file,int line)725 void __assert_failed(char *assertion, char *file, int line)
726 {
727 printf("*** HVMLoader assertion '%s' failed at %s:%d\n",
728 assertion, file, line);
729 crash();
730 }
731
__bug(char * file,int line)732 void __bug(char *file, int line)
733 {
734 printf("*** HVMLoader bug at %s:%d\n", file, line);
735 crash();
736 }
737
validate_hvm_info(struct hvm_info_table * t)738 static void validate_hvm_info(struct hvm_info_table *t)
739 {
740 uint8_t *ptr = (uint8_t *)t;
741 uint8_t sum = 0;
742 int i;
743
744 if ( strncmp(t->signature, "HVM INFO", 8) )
745 {
746 printf("Bad hvm info signature\n");
747 BUG();
748 }
749
750 if ( t->length < sizeof(struct hvm_info_table) )
751 {
752 printf("Bad hvm info length\n");
753 BUG();
754 }
755
756 for ( i = 0; i < t->length; i++ )
757 sum += ptr[i];
758
759 if ( sum != 0 )
760 {
761 printf("Bad hvm info checksum\n");
762 BUG();
763 }
764 }
765
get_hvm_info_table(void)766 struct hvm_info_table *get_hvm_info_table(void)
767 {
768 static struct hvm_info_table *table;
769 struct hvm_info_table *t;
770
771 if ( table != NULL )
772 return table;
773
774 t = (struct hvm_info_table *)HVM_INFO_PADDR;
775
776 validate_hvm_info(t);
777
778 table = t;
779
780 return table;
781 }
782
get_shared_info(void)783 struct shared_info *get_shared_info(void)
784 {
785 static struct shared_info *shared_info = NULL;
786 struct xen_add_to_physmap xatp;
787
788 if ( shared_info != NULL )
789 return shared_info;
790
791 xatp.domid = DOMID_SELF;
792 xatp.space = XENMAPSPACE_shared_info;
793 xatp.idx = 0;
794 xatp.gpfn = mem_hole_alloc(1);
795 shared_info = (struct shared_info *)(xatp.gpfn << PAGE_SHIFT);
796 if ( hypercall_memory_op(XENMEM_add_to_physmap, &xatp) != 0 )
797 BUG();
798
799 return shared_info;
800 }
801
get_cpu_mhz(void)802 uint16_t get_cpu_mhz(void)
803 {
804 struct shared_info *shared_info = get_shared_info();
805 struct vcpu_time_info *info = &shared_info->vcpu_info[0].time;
806 uint64_t cpu_khz;
807 uint32_t tsc_to_nsec_mul, version;
808 int8_t tsc_shift;
809
810 static uint16_t cpu_mhz;
811 if ( cpu_mhz != 0 )
812 return cpu_mhz;
813
814 /* Get a consistent snapshot of scale factor (multiplier and shift). */
815 do {
816 version = info->version;
817 rmb();
818 tsc_to_nsec_mul = info->tsc_to_system_mul;
819 tsc_shift = info->tsc_shift;
820 rmb();
821 } while ((version & 1) | (version ^ info->version));
822
823 /* Compute CPU speed in kHz. */
824 cpu_khz = 1000000ull << 32;
825 do_div(cpu_khz, tsc_to_nsec_mul);
826 if ( tsc_shift < 0 )
827 cpu_khz = cpu_khz << -tsc_shift;
828 else
829 cpu_khz = cpu_khz >> tsc_shift;
830
831 cpu_mhz = (uint16_t)(((uint32_t)cpu_khz + 500) / 1000);
832 return cpu_mhz;
833 }
834
uart_exists(uint16_t uart_base)835 int uart_exists(uint16_t uart_base)
836 {
837 uint16_t ier = uart_base + 1;
838 uint8_t a, b, c;
839
840 a = inb(ier);
841 outb(ier, 0);
842 b = inb(ier);
843 outb(ier, 0xf);
844 c = inb(ier);
845 outb(ier, a);
846
847 return ((b == 0) && (c == 0xf));
848 }
849
lpt_exists(uint16_t lpt_base)850 int lpt_exists(uint16_t lpt_base)
851 {
852 /* Idea taken from linux-2.6.31.5:parport_pc.c */
853 uint16_t control = lpt_base + 2;
854 outb(control, 0xc);
855 return ((inb(control) & 0xf) == 0xc);
856 }
857
hpet_exists(unsigned long hpet_base)858 int hpet_exists(unsigned long hpet_base)
859 {
860 uint32_t hpet_id = *(uint32_t *)hpet_base;
861 return ((hpet_id >> 16) == 0x8086);
862 }
863
battery_port_exists(void)864 static uint8_t battery_port_exists(void)
865 {
866 return (inb(0x88) == 0x1F);
867 }
868
acpi_v2p(struct acpi_ctxt * ctxt,void * v)869 static unsigned long acpi_v2p(struct acpi_ctxt *ctxt, void *v)
870 {
871 return virt_to_phys(v);
872 }
873
874 static unsigned long acpi_alloc_up = ACPI_MEMORY_DYNAMIC_START - 1;
875
acpi_pages_allocated(void)876 unsigned long acpi_pages_allocated(void)
877 {
878 return (acpi_alloc_up >> PAGE_SHIFT) -
879 ((ACPI_MEMORY_DYNAMIC_START - 1) >> PAGE_SHIFT);
880 }
881
acpi_mem_alloc(struct acpi_ctxt * ctxt,uint32_t size,uint32_t align)882 static void *acpi_mem_alloc(struct acpi_ctxt *ctxt,
883 uint32_t size, uint32_t align)
884 {
885 unsigned long s, e;
886
887 /* Align to at least 16 bytes. */
888 if ( align < 16 )
889 align = 16;
890
891 s = (acpi_alloc_up + align) & ~(align - 1);
892 e = s + size - 1;
893
894 BUG_ON((e < s) || (e >= RESERVED_MEMORY_DYNAMIC_START));
895
896 while ( (acpi_alloc_up >> PAGE_SHIFT) != (e >> PAGE_SHIFT) )
897 {
898 acpi_alloc_up += PAGE_SIZE;
899 mem_hole_populate_ram(acpi_alloc_up >> PAGE_SHIFT, 1);
900 }
901
902 acpi_alloc_up = e;
903
904 return (void *)s;
905 }
906
acpi_mem_free(struct acpi_ctxt * ctxt,void * v,uint32_t size)907 static void acpi_mem_free(struct acpi_ctxt *ctxt,
908 void *v, uint32_t size)
909 {
910 /* ACPI builder currently doesn't free memory so this is just a stub */
911 }
912
acpi_lapic_id(unsigned cpu)913 static uint32_t acpi_lapic_id(unsigned cpu)
914 {
915 return LAPIC_ID(cpu);
916 }
917
hvmloader_acpi_build_tables(struct acpi_config * config,unsigned int physical)918 void hvmloader_acpi_build_tables(struct acpi_config *config,
919 unsigned int physical)
920 {
921 const char *s;
922 struct acpi_ctxt ctxt;
923
924 /* Allocate and initialise the acpi info area. */
925 mem_hole_populate_ram(ACPI_INFO_PHYSICAL_ADDRESS >> PAGE_SHIFT, 1);
926
927 /* If the device model is specified switch to the corresponding tables */
928 s = xenstore_read("platform/device-model", "");
929 if ( !strncmp(s, "qemu_xen_traditional", 21) )
930 {
931 config->dsdt_anycpu = dsdt_anycpu;
932 config->dsdt_anycpu_len = dsdt_anycpu_len;
933 config->dsdt_15cpu = dsdt_15cpu;
934 config->dsdt_15cpu_len = dsdt_15cpu_len;
935 }
936 else if ( !strncmp(s, "qemu_xen", 9) )
937 {
938 config->dsdt_anycpu = dsdt_anycpu_qemu_xen;
939 config->dsdt_anycpu_len = dsdt_anycpu_qemu_xen_len;
940 config->dsdt_15cpu = NULL;
941 config->dsdt_15cpu_len = 0;
942 }
943
944 config->lapic_base_address = LAPIC_BASE_ADDRESS;
945 config->lapic_id = acpi_lapic_id;
946 config->ioapic_base_address = ioapic_base_address;
947 config->ioapic_id = IOAPIC_ID;
948 config->pci_isa_irq_mask = PCI_ISA_IRQ_MASK;
949
950 if ( uart_exists(0x3f8) )
951 config->table_flags |= ACPI_HAS_COM1;
952 if ( uart_exists(0x2f8) )
953 config->table_flags |= ACPI_HAS_COM2;
954 if ( lpt_exists(0x378) )
955 config->table_flags |= ACPI_HAS_LPT1;
956 if ( hpet_exists(ACPI_HPET_ADDRESS) )
957 config->table_flags |= ACPI_HAS_HPET;
958
959 config->pci_start = pci_mem_start;
960 config->pci_len = pci_mem_end - pci_mem_start;
961 if ( pci_hi_mem_end > pci_hi_mem_start )
962 {
963 config->pci_hi_start = pci_hi_mem_start;
964 config->pci_hi_len = pci_hi_mem_end - pci_hi_mem_start;
965 }
966
967 s = xenstore_read("platform/generation-id", "0:0");
968 if ( s )
969 {
970 char *end;
971
972 config->vm_gid[0] = strtoll(s, &end, 0);
973 config->vm_gid[1] = 0;
974 if ( end && end[0] == ':' )
975 config->vm_gid[1] = strtoll(end+1, NULL, 0);
976 }
977
978 s = xenstore_read(HVM_XS_ACPI_PT_ADDRESS, NULL);
979 if ( s )
980 {
981 config->pt.addr = strtoll(s, NULL, 0);
982
983 s = xenstore_read(HVM_XS_ACPI_PT_LENGTH, NULL);
984 if ( s )
985 config->pt.length = strtoll(s, NULL, 0);
986 }
987
988 if ( battery_port_exists() )
989 config->table_flags |= ACPI_HAS_SSDT_PM;
990 if ( !strncmp(xenstore_read("platform/acpi_s3", "1"), "1", 1) )
991 config->table_flags |= ACPI_HAS_SSDT_S3;
992 if ( !strncmp(xenstore_read("platform/acpi_s4", "1"), "1", 1) )
993 config->table_flags |= ACPI_HAS_SSDT_S4;
994 if ( !strncmp(xenstore_read("platform/acpi_laptop_slate", "0"), "1", 1) )
995 config->table_flags |= ACPI_HAS_SSDT_LAPTOP_SLATE;
996
997 config->table_flags |= (ACPI_HAS_TCPA | ACPI_HAS_IOAPIC |
998 ACPI_HAS_WAET | ACPI_HAS_PMTIMER |
999 ACPI_HAS_BUTTONS | ACPI_HAS_VGA |
1000 ACPI_HAS_8042 | ACPI_HAS_CMOS_RTC);
1001 config->acpi_revision = 4;
1002
1003 config->tis_hdr = (uint16_t *)ACPI_TIS_HDR_ADDRESS;
1004
1005 config->numa.nr_vmemranges = nr_vmemranges;
1006 config->numa.nr_vnodes = nr_vnodes;
1007 config->numa.vcpu_to_vnode = vcpu_to_vnode;
1008 config->numa.vdistance = vdistance;
1009 config->numa.vmemrange = vmemrange;
1010
1011 config->hvminfo = hvm_info;
1012
1013 config->rsdp = physical;
1014 config->infop = ACPI_INFO_PHYSICAL_ADDRESS;
1015
1016 ctxt.mem_ops.alloc = acpi_mem_alloc;
1017 ctxt.mem_ops.free = acpi_mem_free;
1018 ctxt.mem_ops.v2p = acpi_v2p;
1019
1020 acpi_build_tables(&ctxt, config);
1021
1022 hvm_param_set(HVM_PARAM_VM_GENERATION_ID_ADDR, config->vm_gid_addr);
1023 }
1024
1025 /*
1026 * Local variables:
1027 * mode: C
1028 * c-file-style: "BSD"
1029 * c-basic-offset: 4
1030 * tab-width: 4
1031 * indent-tabs-mode: nil
1032 * End:
1033 */
1034