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