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