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