1 #ifndef __HVMLOADER_UTIL_H__
2 #define __HVMLOADER_UTIL_H__
3
4 #include <stdarg.h>
5 #include <stdint.h>
6 #include <stddef.h>
7 #include <stdbool.h>
8 #include <xen/xen.h>
9 #include <xen/hvm/hvm_info_table.h>
10 #include "config.h"
11 #include "e820.h"
12
13 #include <xen-tools/common-macros.h>
14
15 /* Request un-prefixed values from errno.h. */
16 #define XEN_ERRNO(name, value) name = value,
17 enum {
18 #include <xen/errno.h>
19 };
20
21 /* Cause xs_wire.h to give us xsd_errors[]. */
22 #define EINVAL EINVAL
23
24 /* GDT selector values. */
25 #define SEL_CODE16 0x0008
26 #define SEL_DATA16 0x0010
27 #define SEL_CODE32 0x0018
28 #define SEL_DATA32 0x0020
29 #define SEL_CODE64 0x0028
30
31 void __assert_failed(const char *assertion, const char *file, int line)
32 __attribute__((noreturn));
33 #define ASSERT(p) \
34 do { if (!(p)) __assert_failed(#p, __FILE__, __LINE__); } while (0)
35 void __bug(const char *file, int line) __attribute__((noreturn));
36 #define BUG() __bug(__FILE__, __LINE__)
37 #define BUG_ON(p) do { if (p) BUG(); } while (0)
38
test_bit(unsigned int b,const void * p)39 static inline int test_bit(unsigned int b, const void *p)
40 {
41 return !!(((const uint8_t *)p)[b>>3] & (1u<<(b&7)));
42 }
43
test_and_clear_bit(int nr,volatile void * addr)44 static inline int test_and_clear_bit(int nr, volatile void *addr)
45 {
46 int oldbit;
47 asm volatile (
48 "lock ; btrl %2,%1 ; sbbl %0,%0"
49 : "=r" (oldbit), "=m" (*(volatile long *)addr)
50 : "Ir" (nr), "m" (*(volatile long *)addr) : "memory");
51 return oldbit;
52 }
53
54 /* MSR access */
wrmsr(uint32_t idx,uint64_t v)55 static inline void wrmsr(uint32_t idx, uint64_t v)
56 {
57 asm volatile ( "wrmsr" :: "c" (idx), "A" (v) );
58 }
59
rdmsr(uint32_t idx)60 static inline uint64_t rdmsr(uint32_t idx)
61 {
62 uint64_t res;
63
64 asm volatile ( "rdmsr" : "=A" (res) : "c" (idx) );
65
66 return res;
67 }
68
69 /* I/O output */
outb(uint16_t port,uint8_t val)70 static inline void outb(uint16_t port, uint8_t val)
71 {
72 asm volatile ( "outb %[val], %[port]"
73 :
74 : [port] "Nd" (port),
75 [val] "a" (val)
76 : "memory" );
77 }
78
outw(uint16_t port,uint16_t val)79 static inline void outw(uint16_t port, uint16_t val)
80 {
81 asm volatile ( "outw %[val], %[port]"
82 :
83 : [port] "Nd" (port),
84 [val] "a" (val)
85 : "memory" );
86 }
87
outl(uint16_t port,uint32_t val)88 static inline void outl(uint16_t port, uint32_t val)
89 {
90 asm volatile ( "outl %[val], %[port]"
91 :
92 : [port] "Nd" (port),
93 [val] "a" (val)
94 : "memory" );
95 }
96
97 /* I/O input */
inb(uint16_t port)98 static inline uint8_t inb(uint16_t port)
99 {
100 uint8_t val;
101
102 asm volatile ( "inb %[port], %[val]"
103 : [val] "=a" (val)
104 : [port] "Nd" (port)
105 : "memory" );
106
107 return val;
108 }
109
inw(uint16_t port)110 static inline uint16_t inw(uint16_t port)
111 {
112 uint16_t val;
113
114 asm volatile ( "inw %[port], %[val]"
115 : [val] "=a" (val)
116 : [port] "Nd" (port)
117 : "memory" );
118
119 return val;
120 }
121
inl(uint16_t port)122 static inline uint32_t inl(uint16_t port)
123 {
124 uint32_t val;
125
126 asm volatile ( "inl %[port], %[val]"
127 : [val] "=a" (val)
128 : [port] "Nd" (port)
129 : "memory" );
130
131 return val;
132 }
133
134 /* CMOS access */
135 uint8_t cmos_inb(uint8_t idx);
136 void cmos_outb(uint8_t idx, uint8_t val);
137
138 /* APIC access */
139 #define IOAPIC_BASE_ADDRESS 0xfec00000
ioapic_read(uint32_t reg)140 static inline uint32_t ioapic_read(uint32_t reg)
141 {
142 *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x00) = reg;
143 return *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x10);
144 }
145
ioapic_write(uint32_t reg,uint32_t val)146 static inline void ioapic_write(uint32_t reg, uint32_t val)
147 {
148 *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x00) = reg;
149 *(volatile uint32_t *)(IOAPIC_BASE_ADDRESS + 0x10) = val;
150 }
151
152 #define LAPIC_BASE_ADDRESS 0xfee00000
lapic_read(uint32_t reg)153 static inline uint32_t lapic_read(uint32_t reg)
154 {
155 return *(volatile uint32_t *)(LAPIC_BASE_ADDRESS + reg);
156 }
157
lapic_write(uint32_t reg,uint32_t val)158 static inline void lapic_write(uint32_t reg, uint32_t val)
159 {
160 *(volatile uint32_t *)(LAPIC_BASE_ADDRESS + reg) = val;
161 }
162
163 /* PCI access */
164 uint32_t pci_read(uint32_t devfn, uint32_t reg, uint32_t len);
165 #define pci_readb(devfn, reg) ((uint8_t) pci_read(devfn, reg, 1))
166 #define pci_readw(devfn, reg) ((uint16_t)pci_read(devfn, reg, 2))
167 #define pci_readl(devfn, reg) ((uint32_t)pci_read(devfn, reg, 4))
168 void pci_write(uint32_t devfn, uint32_t reg, uint32_t len, uint32_t val);
169 #define pci_writeb(devfn, reg, val) pci_write(devfn, reg, 1, (uint8_t) (val))
170 #define pci_writew(devfn, reg, val) pci_write(devfn, reg, 2, (uint16_t)(val))
171 #define pci_writel(devfn, reg, val) pci_write(devfn, reg, 4, (uint32_t)(val))
172
173 /* Get a pointer to the shared-info page */
174 struct shared_info *get_shared_info(void) __attribute__ ((const));
175
176 /* Get CPU speed in MHz. */
177 uint16_t get_cpu_mhz(void);
178
179 /* Hardware detection. */
180 int uart_exists(uint16_t uart_base);
181 int lpt_exists(uint16_t lpt_base);
182 int hpet_exists(unsigned long hpet_base);
183
184 /* Some CPUID calls want 'count' to be placed in ecx */
cpuid_count(uint32_t leaf,uint32_t subleaf,uint32_t * eax,uint32_t * ebx,uint32_t * ecx,uint32_t * edx)185 static inline void cpuid_count(
186 uint32_t leaf,
187 uint32_t subleaf,
188 uint32_t *eax,
189 uint32_t *ebx,
190 uint32_t *ecx,
191 uint32_t *edx)
192 {
193 uint32_t tmp;
194
195 if ( !eax )
196 eax = &tmp;
197 if ( !ebx )
198 ebx = &tmp;
199 if ( !ecx )
200 ecx = &tmp;
201 if ( !edx )
202 edx = &tmp;
203
204 asm volatile ( "cpuid"
205 : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
206 : "a" (leaf), "c" (subleaf) );
207 }
208
209 /* Generic CPUID function (subleaf 0) */
cpuid(uint32_t leaf,uint32_t * eax,uint32_t * ebx,uint32_t * ecx,uint32_t * edx)210 static inline void cpuid(
211 uint32_t leaf,
212 uint32_t *eax,
213 uint32_t *ebx,
214 uint32_t *ecx,
215 uint32_t *edx)
216 {
217 cpuid_count(leaf, 0, eax, ebx, ecx, edx);
218 }
219
220 /* Read the TSC register. */
rdtsc(void)221 static inline uint64_t rdtsc(void)
222 {
223 uint64_t tsc;
224 asm volatile ( "rdtsc" : "=A" (tsc) );
225 return tsc;
226 }
227
228 /* Relax the CPU and let the compiler know that time passes. */
cpu_relax(void)229 static inline void cpu_relax(void)
230 {
231 asm volatile ( "rep ; nop" : : : "memory" );
232 }
233
234 /* Memory barriers. */
235 #define barrier() asm volatile ( "" : : : "memory" )
236 #define rmb() barrier()
237 #define wmb() barrier()
238 #define mb() asm volatile ( "lock addl $0, -4(%%esp)" ::: "memory" )
239
240 /*
241 * Divide a 64-bit dividend by a 32-bit divisor.
242 * (1) Overwrites the 64-bit dividend _in_place_ with the quotient
243 * (2) Returns the 32-bit remainder
244 */
245 #define do_div(n, base) ({ \
246 unsigned long __upper, __low, __high, __mod, __base; \
247 __base = (base); \
248 asm ( "" : "=a" (__low), "=d" (__high) : "A" (n) ); \
249 __upper = __high; \
250 if ( __high ) \
251 { \
252 __upper = __high % (__base); \
253 __high = __high / (__base); \
254 } \
255 asm ( "divl %2" \
256 : "=a" (__low), "=d" (__mod) \
257 : "rm" (__base), "0" (__low), "1" (__upper) ); \
258 asm ( "" : "=A" (n) : "a" (__low), "d" (__high) ); \
259 __mod; \
260 })
261
262 /* HVM-builder info. */
263 struct hvm_info_table *get_hvm_info_table(void) __attribute__ ((const));
264 #define hvm_info (get_hvm_info_table())
265
266 /* HVM start info */
267 extern const struct hvm_start_info *hvm_start_info;
268
269 /* String and memory functions */
270 int strcmp(const char *cs, const char *ct);
271 int strncmp(const char *s1, const char *s2, uint32_t n);
272 char *strcpy(char *dest, const char *src);
273 char *strncpy(char *dest, const char *src, unsigned n);
274 unsigned strlen(const char *s);
275 long long strtoll(const char *s, char **end, int base);
276 int memcmp(const void *s1, const void *s2, unsigned n);
277 void *memcpy(void *dest, const void *src, unsigned n);
278 void *memmove(void *dest, const void *src, unsigned n);
279 void *memset(void *s, int c, unsigned n);
280 char *itoa(char *a, unsigned int i);
281
282 /* convert a byte to two lowercase hex digits, with no terminating NUL
283 character. digits[] must have at least two elements. */
284 void byte_to_hex(char *digits, uint8_t byte);
285
286 /* Convert an array of 16 unsigned bytes to a DCE/OSF formatted UUID
287 string. Pre-condition: sizeof(dest) >= 37 */
288 void uuid_to_string(char *dest, uint8_t *uuid);
289
290 /* Debug output */
291 #define PRIllx "%x%08x"
292 #define PRIllx_arg(ll) (uint32_t)((ll)>>32), (uint32_t)(ll)
293 int printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
294 int vprintf(const char *fmt, va_list ap);
295
296 /* Buffer output */
297 int snprintf(char *buf, size_t size, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
298
299 /* Populate specified memory hole with RAM. */
300 void mem_hole_populate_ram(xen_pfn_t mfn, uint32_t nr_mfns);
301
302 /* Allocate a memory hole below 4GB. */
303 xen_pfn_t mem_hole_alloc(uint32_t nr_mfns);
304
305 /* Allocate memory in a reserved region below 4GB. */
306 void *mem_alloc(uint32_t size, uint32_t align);
307 #define virt_to_phys(v) ((unsigned long)(v))
308
309 /* Allocate memory in a scratch region */
310 void *scratch_alloc(uint32_t size, uint32_t align);
311
312 /* Connect our xenbus client to the backend.
313 * Call once, before any other xenbus actions. */
314 void xenbus_setup(void);
315
316 /* Reset the xenbus connection so the next kernel can start again. */
317 void xenbus_shutdown(void);
318
319 /* Read a xenstore key. Returns a nul-terminated string (even if the XS
320 * data wasn't nul-terminated) or NULL. The returned string is in a
321 * static buffer, so only valid until the next xenstore/xenbus operation.
322 * If @default_resp is specified, it is returned in preference to a NULL or
323 * empty string received from xenstore.
324 */
325 const char *xenstore_read(const char *path, const char *default_resp);
326
327 /* Write a xenstore key. @value must be a nul-terminated string. Returns
328 * zero on success or a xenstore error code on failure.
329 */
330 int xenstore_write(const char *path, const char *value);
331
332
333 /* Get a HVM param.
334 */
335 int hvm_param_get(uint32_t index, uint64_t *value);
336
337 /* Set a HVM param.
338 */
339 int hvm_param_set(uint32_t index, uint64_t value);
340
341 /* Setup PCI bus */
342 void pci_setup(void);
343
344 /* Setup memory map */
345 void memory_map_setup(void);
346
347 /* Sync memory map */
348 void adjust_memory_map(void);
349
350 /* Prepare the 32bit BIOS */
351 uint32_t rombios_highbios_setup(void);
352
353 /* Miscellaneous. */
354 unsigned int cpu_phys_addr(void);
355 void cacheattr_init(void);
356 unsigned long create_mp_tables(void *table);
357 void hvm_write_smbios_tables(
358 unsigned long ep, unsigned long smbios_start, unsigned long smbios_end);
359 unsigned long create_pir_tables(void);
360
361 void smp_initialise(void);
362
363 #include "e820.h"
364 int build_e820_table(struct e820entry *e820,
365 unsigned int lowmem_reserved_base,
366 unsigned int bios_image_base);
367 void dump_e820_table(struct e820entry *e820, unsigned int nr);
368
369 #ifndef NDEBUG
370 void perform_tests(void);
371 #else
372 #define perform_tests() ((void)0)
373 #endif
374
375 extern char _start[], _end[];
376
377 int get_mem_mapping_layout(struct e820entry entries[],
378 unsigned int *max_entries);
379
380 extern struct e820map memory_map;
381 bool check_overlap(uint64_t start, uint64_t size,
382 uint64_t reserved_start, uint64_t reserved_size);
383
384 extern const unsigned char dsdt_anycpu_qemu_xen[], dsdt_anycpu[], dsdt_15cpu[];
385 extern const int dsdt_anycpu_qemu_xen_len, dsdt_anycpu_len, dsdt_15cpu_len;
386
387 unsigned long acpi_pages_allocated(void);
388
389 struct acpi_config;
390 void hvmloader_acpi_build_tables(struct acpi_config *config,
391 unsigned int physical);
392
393 #endif /* __HVMLOADER_UTIL_H__ */
394
395 /*
396 * Local variables:
397 * mode: C
398 * c-file-style: "BSD"
399 * c-basic-offset: 4
400 * tab-width: 4
401 * indent-tabs-mode: nil
402 * End:
403 */
404