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