aboutsummaryrefslogtreecommitdiffstats
path: root/tools/firmware/hvmloader/util.h
blob: 9ccb905dcbe6cf41828b3b977bf53f70ba041621 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
#ifndef __HVMLOADER_UTIL_H__
#define __HVMLOADER_UTIL_H__

#include <stdarg.h>
#include <stdint.h>
#include <xen/xen.h>
#include <xen/hvm/hvm_info_table.h>

#define __STR(...) #__VA_ARGS__
#define STR(...) __STR(__VA_ARGS__)

/* GDT selector values. */
#define SEL_CODE16          0x0008
#define SEL_DATA16          0x0010
#define SEL_CODE32          0x0018
#define SEL_DATA32          0x0020
#define SEL_CODE64          0x0028

#undef offsetof
#define offsetof(t, m) ((unsigned long)&((t *)0)->m)

#undef NULL
#define NULL ((void*)0)

void __assert_failed(char *assertion, char *file, int line)
    __attribute__((noreturn));
#define ASSERT(p) \
    do { if (!(p)) __assert_failed(#p, __FILE__, __LINE__); } while (0)
void __bug(char *file, int line) __attribute__((noreturn));
#define BUG() __bug(__FILE__, __LINE__)
#define BUG_ON(p) do { if (p) BUG(); } while (0)
#define BUILD_BUG_ON(p) ((void)sizeof(char[1 - 2 * !!(p)]))

#define min_t(type,x,y) \
        ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
#define max_t(type,x,y) \
        ({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })

static inline int test_bit(unsigned int b, void *p)
{
    return !!(((uint8_t *)p)[b>>3] & (1u<<(b&7)));
}

static inline int test_and_clear_bit(int nr, volatile void *addr)
{
    int oldbit;
    asm volatile (
        "lock ; btrl %2,%1 ; sbbl %0,%0"
        : "=r" (oldbit), "=m" (*(volatile long *)addr)
        : "Ir" (nr), "m" (*(volatile long *)addr) : "memory");
    return oldbit;
}

/* MSR access */
void wrmsr(uint32_t idx, uint64_t v);
uint64_t rdmsr(uint32_t idx);

/* I/O output */
void outb(uint16_t addr, uint8_t  val);
void outw(uint16_t addr, uint16_t val);
void outl(uint16_t addr, uint32_t val);

/* I/O input */
uint8_t  inb(uint16_t addr);
uint16_t inw(uint16_t addr);
uint32_t inl(uint16_t addr);

/* CMOS access */
uint8_t cmos_inb(uint8_t idx);
void cmos_outb(uint8_t idx, uint8_t val);

/* APIC access */
uint32_t ioapic_read(uint32_t reg);
void ioapic_write(uint32_t reg, uint32_t val);
uint32_t lapic_read(uint32_t reg);
void lapic_write(uint32_t reg, uint32_t val);

/* PCI access */
uint32_t pci_read(uint32_t devfn, uint32_t reg, uint32_t len);
#define pci_readb(devfn, reg) ((uint8_t) pci_read(devfn, reg, 1))
#define pci_readw(devfn, reg) ((uint16_t)pci_read(devfn, reg, 2))
#define pci_readl(devfn, reg) ((uint32_t)pci_read(devfn, reg, 4))
void pci_write(uint32_t devfn, uint32_t reg, uint32_t len, uint32_t val);
#define pci_writeb(devfn, reg, val) (pci_write(devfn, reg, 1, (uint8_t) val))
#define pci_writew(devfn, reg, val) (pci_write(devfn, reg, 2, (uint16_t)val))
#define pci_writel(devfn, reg, val) (pci_write(devfn, reg, 4, (uint32_t)val))

/* Get a pointer to the shared-info page */
struct shared_info *get_shared_info(void) __attribute__ ((const));

/* Get CPU speed in MHz. */
uint16_t get_cpu_mhz(void);

/* Hardware detection. */
int uart_exists(uint16_t uart_base);
int lpt_exists(uint16_t lpt_base);
int hpet_exists(unsigned long hpet_base);

/* Do cpuid instruction, with operation 'idx' */
void cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx,
           uint32_t *ecx, uint32_t *edx);

/* Read the TSC register. */
static inline uint64_t rdtsc(void)
{
    uint64_t tsc;
    asm volatile ( "rdtsc" : "=A" (tsc) );
    return tsc;
}

/* Relax the CPU and let the compiler know that time passes. */
static inline void cpu_relax(void)
{
    asm volatile ( "rep ; nop" : : : "memory" );
}

/* Memory barriers. */
#define barrier() asm volatile ( "" : : : "memory" )
#define rmb()     barrier()
#define wmb()     barrier()
#define mb()      asm volatile ( "lock; addl $0,0(%%esp)" : : : "memory" )

/*
 * Divide a 64-bit dividend by a 32-bit divisor.
 * (1) Overwrites the 64-bit dividend _in_place_ with the quotient
 * (2) Returns the 32-bit remainder
 */
#define do_div(n, base) ({                                      \
    unsigned long __upper, __low, __high, __mod, __base;        \
    __base = (base);                                            \
    asm ( "" : "=a" (__low), "=d" (__high) : "A" (n) );         \
    __upper = __high;                                           \
    if ( __high )                                               \
    {                                                           \
        __upper = __high % (__base);                            \
        __high = __high / (__base);                             \
    }                                                           \
    asm ( "divl %2"                                             \
          : "=a" (__low), "=d" (__mod)                          \
          : "rm" (__base), "0" (__low), "1" (__upper) );        \
    asm ( "" : "=A" (n) : "a" (__low), "d" (__high) );          \
    __mod;                                                      \
})

/* HVM-builder info. */
struct hvm_info_table *get_hvm_info_table(void) __attribute__ ((const));
#define hvm_info (get_hvm_info_table())

/* String and memory functions */
int strcmp(const char *cs, const char *ct);
int strncmp(const char *s1, const char *s2, uint32_t n);
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, unsigned n);
unsigned strlen(const char *s);
long long strtoll(const char *s, char **end, int base);
int memcmp(const void *s1, const void *s2, unsigned n);
void *memcpy(void *dest, const void *src, unsigned n);
void *memmove(void *dest, const void *src, unsigned n);
void *memset(void *s, int c, unsigned n);
char *itoa(char *a, unsigned int i);

/* convert a byte to two lowercase hex digits, with no terminating NUL 
   character.  digits[] must have at least two elements. */
void byte_to_hex(char *digits, uint8_t byte);

/* Convert an array of 16 unsigned bytes to a DCE/OSF formatted UUID
   string. Pre-condition: sizeof(dest) >= 37 */
void uuid_to_string(char *dest, uint8_t *uuid);

/* Debug output */
#define PRIllx "%x%08x"
#define PRIllx_arg(ll) (uint32_t)((ll)>>32), (uint32_t)(ll)
int printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
int vprintf(const char *fmt, va_list ap);

/* Buffer output */
typedef unsigned long size_t;
int snprintf(char *buf, size_t size, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));

/* Populate specified memory hole with RAM. */
void mem_hole_populate_ram(xen_pfn_t mfn, uint32_t nr_mfns);

/* Allocate a memory hole below 4GB. */
xen_pfn_t mem_hole_alloc(uint32_t nr_mfns);

/* Allocate memory in a reserved region below 4GB. */
void *mem_alloc(uint32_t size, uint32_t align);
#define virt_to_phys(v) ((unsigned long)(v))

/* Allocate memory in a scratch region */
void *scratch_alloc(uint32_t size, uint32_t align);

/* Connect our xenbus client to the backend.  
 * Call once, before any other xenbus actions. */
void xenbus_setup(void);

/* Reset the xenbus connection so the next kernel can start again. */
void xenbus_shutdown(void);

/* Read a xenstore key.  Returns a nul-terminated string (even if the XS
 * data wasn't nul-terminated) or NULL.  The returned string is in a
 * static buffer, so only valid until the next xenstore/xenbus operation.
 * If @default_resp is specified, it is returned in preference to a NULL or
 * empty string received from xenstore.
 */
const char *xenstore_read(const char *path, const char *default_resp);

/* Write a xenstore key.  @value must be a nul-terminated string. Returns
 * zero on success or a xenstore error code on failure.
 */
int xenstore_write(const char *path, const char *value);

/* Setup PCI bus */
void pci_setup(void);

/* Prepare the 32bit BIOS */
uint32_t rombios_highbios_setup(void);

/* Miscellaneous. */
unsigned int cpu_phys_addr(void);
void cacheattr_init(void);
unsigned long create_mp_tables(void *table);
void hvm_write_smbios_tables(
    unsigned long ep, unsigned long smbios_start, unsigned long smbios_end);
unsigned long create_pir_tables(void);

void smp_initialise(void);

#include "e820.h"
int build_e820_table(struct e820entry *e820,
                     unsigned int lowmem_reserved_base,
                     unsigned int bios_image_base);
void dump_e820_table(struct e820entry *e820, unsigned int nr);

#ifndef NDEBUG
void perform_tests(void);
#else
#define perform_tests() ((void)0)
#endif

extern char _start[], _end[];

#endif /* __HVMLOADER_UTIL_H__ */

/*
 * Local variables:
 * mode: C
 * c-file-style: "BSD"
 * c-basic-offset: 4
 * tab-width: 4
 * indent-tabs-mode: nil
 * End:
 */