1
// Basic x86 asm functions and function defs.
3
// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
5
// This file may be distributed under the terms of the GNU LGPLv3 license.
9
#include "types.h" // u32
11
static inline void irq_disable(void)
13
asm volatile("cli": : :"memory");
16
static inline void irq_enable(void)
18
asm volatile("sti": : :"memory");
21
static inline unsigned long irq_save(void)
24
asm volatile("pushfl ; popl %0" : "=g" (flags): :"memory");
29
static inline void irq_restore(unsigned long flags)
31
asm volatile("pushl %0 ; popfl" : : "g" (flags) : "memory", "cc");
34
static inline void cpu_relax(void)
36
asm volatile("rep ; nop": : :"memory");
39
static inline void nop(void)
44
static inline void hlt(void)
46
asm volatile("hlt": : :"memory");
49
static inline void wbinvd(void)
51
asm volatile("wbinvd": : :"memory");
54
#define CPUID_MSR (1 << 5)
55
#define CPUID_APIC (1 << 9)
56
#define CPUID_MTRR (1 << 12)
57
static inline void cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
60
: "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
64
static inline u64 rdmsr(u32 index)
67
asm ("rdmsr" : "=A"(ret) : "c"(index));
71
static inline void wrmsr(u32 index, u64 val)
73
asm volatile ("wrmsr" : : "c"(index), "A"(val));
76
static inline u64 rdtscll(void)
79
asm volatile("rdtsc" : "=A" (val));
83
static inline u32 __ffs(u32 word)
90
static inline u32 __fls(u32 word)
98
static inline u16 __htons_constant(u16 val) {
99
return (val<<8) | (val>>8);
101
static inline u32 __htonl_constant(u32 val) {
102
return (val<<24) | ((val&0xff00)<<8) | ((val&0xff0000)>>8) | (val>>24);
104
static inline u32 __htonl(u32 val) {
105
asm("bswapl %0" : "+r"(val));
108
#define htonl(x) (__builtin_constant_p((u32)(x)) ? __htonl_constant(x) : __htonl(x))
109
#define ntohl(x) htonl(x)
110
#define htons(x) __htons_constant(x)
111
#define ntohs(x) htons(x)
113
static inline u32 getesp(void) {
115
asm("movl %%esp, %0" : "=rm"(esp));
119
static inline void writel(void *addr, u32 val) {
120
*(volatile u32 *)addr = val;
122
static inline void writew(void *addr, u16 val) {
123
*(volatile u16 *)addr = val;
125
static inline void writeb(void *addr, u8 val) {
126
*(volatile u8 *)addr = val;
128
static inline u32 readl(const void *addr) {
129
return *(volatile const u32 *)addr;
131
static inline u16 readw(const void *addr) {
132
return *(volatile const u16 *)addr;
134
static inline u8 readb(const void *addr) {
135
return *(volatile const u8 *)addr;
138
#define call16_simpint(nr, peax, pflags) do { \
150
: "+a"(*peax), "=c"(*pflags) \
152
: "ebx", "edx", "esi", "edi", "cc", "memory"); \
155
// GDT bit manipulation
156
#define GDT_BASE(v) ((((u64)(v) & 0xff000000) << 32) \
157
| (((u64)(v) & 0x00ffffff) << 16))
158
#define GDT_LIMIT(v) ((((u64)(v) & 0x000f0000) << 32) \
159
| (((u64)(v) & 0x0000ffff) << 0))
160
#define GDT_CODE (0x9bULL << 40) // Code segment - P,R,A bits also set
161
#define GDT_DATA (0x93ULL << 40) // Data segment - W,A bits also set
162
#define GDT_B (0x1ULL << 54) // Big flag
163
#define GDT_G (0x1ULL << 55) // Granularity flag
172
inline void call16(struct bregs *callregs);
173
inline void call16big(struct bregs *callregs);
174
inline void __call16_int(struct bregs *callregs, u16 offset);
175
#define call16_int(nr, callregs) do { \
176
extern void irq_trampoline_ ##nr (); \
177
__call16_int((callregs), (u32)&irq_trampoline_ ##nr ); \
179
u8 checksum_far(u16 buf_seg, void *buf_far, u32 len);
180
u8 checksum(void *buf, u32 len);
181
size_t strlen(const char *s);
182
int memcmp(const void *s1, const void *s2, size_t n);
183
int strcmp(const char *s1, const char *s2);
184
inline void memset_far(u16 d_seg, void *d_far, u8 c, size_t len);
185
inline void memset16_far(u16 d_seg, void *d_far, u16 c, size_t len);
186
void *memset(void *s, int c, size_t n);
187
inline void memcpy_far(u16 d_seg, void *d_far
188
, u16 s_seg, const void *s_far, size_t len);
189
void *memcpy(void *d1, const void *s1, size_t len);
191
#define memcpy __builtin_memcpy
193
void iomemcpy(void *d, const void *s, u32 len);
194
void *memmove(void *d, const void *s, size_t len);
195
char *strtcpy(char *dest, const char *src, size_t len);
196
int get_keystroke(int msec);
199
inline u32 stack_hop(u32 eax, u32 edx, void *func);
200
extern struct thread_info MainThread;
201
void thread_setup(void);
202
struct thread_info *getCurThread(void);
205
void run_thread(void (*func)(void*), void *data);
206
void wait_threads(void);
207
struct mutex_s { u32 isLocked; };
208
void mutex_lock(struct mutex_s *mutex);
209
void mutex_unlock(struct mutex_s *mutex);
210
void start_preempt(void);
211
void finish_preempt(void);
212
int wait_preempt(void);
213
void check_preempt(void);
216
void debug_serial_setup(void);
217
void panic(const char *fmt, ...)
218
__attribute__ ((format (printf, 1, 2))) __noreturn;
219
void printf(const char *fmt, ...)
220
__attribute__ ((format (printf, 1, 2)));
221
int snprintf(char *str, size_t size, const char *fmt, ...)
222
__attribute__ ((format (printf, 3, 4)));
223
void __dprintf(const char *fmt, ...)
224
__attribute__ ((format (printf, 1, 2)));
225
void __debug_enter(struct bregs *regs, const char *fname);
226
void __debug_isr(const char *fname);
227
void __debug_stub(struct bregs *regs, int lineno, const char *fname);
228
void __warn_invalid(struct bregs *regs, int lineno, const char *fname);
229
void __warn_unimplemented(struct bregs *regs, int lineno, const char *fname);
230
void __warn_internalerror(int lineno, const char *fname);
231
void __warn_noalloc(int lineno, const char *fname);
232
void __warn_timeout(int lineno, const char *fname);
233
void __set_invalid(struct bregs *regs, int lineno, const char *fname);
234
void __set_unimplemented(struct bregs *regs, int lineno, const char *fname);
235
void __set_code_invalid(struct bregs *regs, u32 linecode, const char *fname);
236
void __set_code_unimplemented(struct bregs *regs, u32 linecode
237
, const char *fname);
238
void hexdump(const void *d, int len);
240
#define dprintf(lvl, fmt, args...) do { \
241
if (CONFIG_DEBUG_LEVEL && (lvl) <= CONFIG_DEBUG_LEVEL) \
242
__dprintf((fmt) , ##args ); \
244
#define debug_enter(regs, lvl) do { \
245
if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL) \
246
__debug_enter((regs), __func__); \
248
#define debug_isr(lvl) do { \
249
if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL) \
250
__debug_isr(__func__); \
252
#define debug_stub(regs) \
253
__debug_stub((regs), __LINE__, __func__)
254
#define warn_invalid(regs) \
255
__warn_invalid((regs), __LINE__, __func__)
256
#define warn_unimplemented(regs) \
257
__warn_unimplemented((regs), __LINE__, __func__)
258
#define warn_internalerror() \
259
__warn_internalerror(__LINE__, __func__)
260
#define warn_noalloc() \
261
__warn_noalloc(__LINE__, __func__)
262
#define warn_timeout() \
263
__warn_timeout(__LINE__, __func__)
264
#define set_invalid(regs) \
265
__set_invalid((regs), __LINE__, __func__)
266
#define set_code_invalid(regs, code) \
267
__set_code_invalid((regs), (code) | (__LINE__ << 8), __func__)
268
#define set_unimplemented(regs) \
269
__set_unimplemented((regs), __LINE__, __func__)
270
#define set_code_unimplemented(regs, code) \
271
__set_code_unimplemented((regs), (code) | (__LINE__ << 8), __func__)
274
void kbd_setup(void);
275
void handle_15c2(struct bregs *regs);
276
void process_key(u8 key);
279
void mouse_setup(void);
280
void process_mouse(u8 data);
284
extern u64 RamSizeOver4G;
285
void mathcp_setup(void);
288
void serial_setup(void);
289
void lpt_setup(void);
292
#define PIT_TICK_RATE 1193180 // Underlying HZ of PIT
293
#define PIT_TICK_INTERVAL 65536 // Default interval for 18.2Hz timer
294
static inline int check_tsc(u64 end) {
295
return (s64)(rdtscll() - end) > 0;
297
void timer_setup(void);
298
void ndelay(u32 count);
299
void udelay(u32 count);
300
void mdelay(u32 count);
301
void nsleep(u32 count);
302
void usleep(u32 count);
303
void msleep(u32 count);
304
u64 calc_future_tsc(u32 msecs);
305
u64 calc_future_tsc_usec(u32 usecs);
306
u32 calc_future_timer_ticks(u32 count);
307
u32 calc_future_timer(u32 msecs);
308
int check_timer(u32 end);
309
void handle_1583(struct bregs *regs);
310
void handle_1586(struct bregs *regs);
312
void releaseRTC(void);
315
void handle_1553(struct bregs *regs);
318
void handle_1ab1(struct bregs *regs);
319
void bios32_setup(void);
322
void make_bios_writable(void);
323
void make_bios_readonly(void);
326
void pci_setup(void);
332
extern u32 CountCPUs;
333
extern u32 MaxCountCPUs;
334
void wrmsr_smp(u32 index, u64 val);
335
void smp_probe(void);
336
void smp_probe_setup(void);
340
struct cbfs_file *cbfs_findprefix(const char *prefix, struct cbfs_file *last);
341
u32 cbfs_datasize(struct cbfs_file *file);
342
const char *cbfs_filename(struct cbfs_file *file);
343
int cbfs_copyfile(struct cbfs_file *file, void *dst, u32 maxlen);
344
int cbfs_copy_optionrom(void *dst, u32 maxlen, u32 vendev);
345
void cbfs_run_payload(struct cbfs_file *file);
347
void coreboot_copy_biostable(void);
348
void coreboot_setup(void);
352
void handle_155f(struct bregs *regs);
353
void vgahook_setup(const char *vendor, const char *part);
356
void call_bcv(u16 seg, u16 ip);
357
void optionrom_setup(void);
358
void vga_setup(void);
359
void s3_resume_vga_init(void);
366
#define PNP_SIGNATURE 0x506e5024 // $PnP
367
u16 get_pnp_offset(void);
368
void pnp_setup(void);
371
extern struct zone_s ZoneLow, ZoneHigh, ZoneFSeg, ZoneTmpLow, ZoneTmpHigh;
372
void malloc_setup(void);
373
void malloc_finalize(void);
374
void *pmm_malloc(struct zone_s *zone, u32 handle, u32 size, u32 align);
375
int pmm_free(void *data);
376
void pmm_setup(void);
377
void pmm_finalize(void);
378
#define PMM_DEFAULT_HANDLE 0xFFFFFFFF
379
// Minimum alignment of malloc'd memory
380
#define MALLOC_MIN_ALIGN 16
381
// Helper functions for memory allocation.
382
static inline void *malloc_low(u32 size) {
383
return pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
385
static inline void *malloc_high(u32 size) {
386
return pmm_malloc(&ZoneHigh, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
388
static inline void *malloc_fseg(u32 size) {
389
return pmm_malloc(&ZoneFSeg, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
391
static inline void *malloc_tmphigh(u32 size) {
392
return pmm_malloc(&ZoneTmpHigh, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
394
static inline void *malloc_tmp(u32 size) {
395
void *ret = malloc_tmphigh(size);
398
return pmm_malloc(&ZoneTmpLow, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
400
static inline void *memalign_low(u32 align, u32 size) {
401
return pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, align);
403
static inline void *memalign_high(u32 align, u32 size) {
404
return pmm_malloc(&ZoneHigh, PMM_DEFAULT_HANDLE, size, align);
406
static inline void *memalign_tmphigh(u32 align, u32 size) {
407
return pmm_malloc(&ZoneTmpHigh, PMM_DEFAULT_HANDLE, size, align);
409
static inline void free(void *data) {
414
void mtrr_setup(void);
417
void reset_vector(void) __noreturn;
420
extern u8 BiosChecksum;
422
// version (auto generated file out/version.c)
423
extern const char VERSION[];