1 /////////////////////////////////////////////////////////////////////////
2 // $Id: bochs.h,v 1.207 2007/04/19 16:12:12 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2002 MandrakeSoft S.A.
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 // bochs.h is the master header file for all C++ code. It includes all
29 // the system header files needed by bochs, and also includes all the bochs
30 // C++ header files. Because bochs.h and the files that it includes has
31 // structure and class definitions, it cannot be called from C code.
37 #include "config.h" /* generated by configure script from config.h.in */
44 // In a win32 compile (including cygwin), windows.h is required for several
45 // files in gui and iodev. It is important to include it here in a header
46 // file so that WIN32-specific data types can be used in fields of classes.
85 # include <sys/types.h>
86 # include <sys/stat.h>
87 # include <sys/param.h> /* for MAXPATHLEN */
91 # include <sys/time.h>
93 # include <sys/types.h>
94 # include <sys/stat.h>
101 # define SuperDrive "[fd:]"
108 #include "osdep.h" /* platform dependent includes and defines */
109 #include "bx_debug/debug.h"
110 #include "bxversion.h"
112 #include "gui/siminterface.h"
114 // BX_SHARE_PATH should be defined by the makefile. If not, give it
115 // a value of NULL to avoid compile problems.
116 #ifndef BX_SHARE_PATH
117 #define BX_SHARE_PATH NULL
121 int bx_begin_simulation(int argc
, char *argv
[]);
122 void bx_stop_simulation();
123 char *bx_find_bochsrc(void);
124 int bx_parse_cmdline(int arg
, int argc
, char *argv
[]);
125 int bx_read_configuration(const char *rcfile
);
126 int bx_write_configuration(const char *rcfile
, int overwrite
);
127 void bx_reset_options(void);
128 Bit32u
crc32(const Bit8u
*buf
, int len
);
129 // for param-tree testing only
130 void print_tree(bx_param_c
*node
, int level
= 0);
133 // some macros to interface the CPU and memory to external environment
134 // so that these functions can be redirected to the debugger when
138 #if BX_SUPPORT_SAVE_RESTORE
140 #define BXRS_PARAM_SPECIAL(parent, name, maxvalue, save_handler, restore_handler) { \
141 bx_param_num_c *param = new bx_param_num_c(parent, #name, "", "", 0, maxvalue, 0); \
142 param->set_base(BASE_HEX); \
143 param->set_sr_handlers(this, save_handler, restore_handler); \
146 #define BXRS_PARAM_SPECIAL64(parent, name, save_handler, restore_handler) \
147 BXRS_PARAM_SPECIAL(parent, name, BX_MAX_BIT64U, save_handler, restore_handler)
148 #define BXRS_PARAM_SPECIAL32(parent, name, save_handler, restore_handler) \
149 BXRS_PARAM_SPECIAL(parent, name, BX_MAX_BIT32U, save_handler, restore_handler)
150 #define BXRS_PARAM_SPECIAL16(parent, name, save_handler, restore_handler) \
151 BXRS_PARAM_SPECIAL(parent, name, BX_MAX_BIT16U, save_handler, restore_handler)
152 #define BXRS_PARAM_SPECIAL8(parent, name, save_handler, restore_handler) \
153 BXRS_PARAM_SPECIAL(parent, name, BX_MAX_BIT8U, save_handler, restore_handler)
155 #define BXRS_HEX_PARAM_SIMPLE(parent, name) \
156 new bx_shadow_num_c(parent, #name, &(name), BASE_HEX)
157 #define BXRS_HEX_PARAM_FIELD(parent, name, field) \
158 new bx_shadow_num_c(parent, #name, &(field), BASE_HEX)
160 #define BXRS_DEC_PARAM_SIMPLE(parent, name) \
161 new bx_shadow_num_c(parent, #name, &(name), BASE_DEC)
162 #define BXRS_DEC_PARAM_FIELD(parent, name, field) \
163 new bx_shadow_num_c(parent, #name, &(field), BASE_DEC)
165 #define BXRS_PARAM_BOOL(parent, name, field) \
166 new bx_shadow_bool_c(parent, #name, (bx_bool*)(&(field)))
170 // =-=-=-=-=-=-=- Normal optimized use -=-=-=-=-=-=-=-=-=-=-=-=-=-=
171 // some pc_systems functions just redirect to the IO devices so optimize
172 // by eliminating call here
174 // #define BX_INP(addr, len) bx_pc_system.inp(addr, len)
175 // #define BX_OUTP(addr, val, len) bx_pc_system.outp(addr, val, len)
176 #define BX_INP(addr, len) bx_devices.inp(addr, len)
177 #define BX_OUTP(addr, val, len) bx_devices.outp(addr, val, len)
178 #define BX_TICK1() bx_pc_system.tick1()
179 #define BX_TICKN(n) bx_pc_system.tickn(n)
180 #define BX_INTR bx_pc_system.INTR
181 #define BX_SET_INTR(b) bx_pc_system.set_INTR(b)
182 #define BX_CPU_C bx_cpu_c
183 #define BX_MEM_C bx_mem_c
184 #define BX_HRQ (bx_pc_system.HRQ)
187 #define BX_CPU(x) (bx_cpu_array[x])
189 #define BX_CPU(x) (&bx_cpu)
192 #if BX_ADDRESS_SPACES==1
193 #define BX_MEM(x) (&bx_mem)
195 #define BX_MEM(x) (&bx_mem_array[x])
198 #define BX_SET_ENABLE_A20(enabled) bx_pc_system.set_enable_a20(enabled)
199 #define BX_GET_ENABLE_A20() bx_pc_system.get_enable_a20()
202 # define A20ADDR(x) ((x) & bx_pc_system.a20_mask)
204 # define A20ADDR(x) (x)
208 # define BX_TICK1_IF_SINGLE_PROCESSOR() \
209 if (BX_SMP_PROCESSORS == 1) BX_TICK1()
211 # define BX_TICK1_IF_SINGLE_PROCESSOR() BX_TICK1()
214 // you can't use static member functions on the CPU, if there are going
215 // to be 2 cpus. Check this early on.
218 # error For SMP simulation, BX_USE_CPU_SMF must be 0.
223 // Ways for the the external environment to report back information
228 # define BX_DBG_ASYNC_INTR bx_guard.async.irq
229 # define BX_DBG_ASYNC_DMA bx_guard.async.dma
231 # define BX_DBG_DMA_REPORT(addr, len, what, val) \
232 if (bx_guard.report.dma) bx_dbg_dma_report(addr, len, what, val)
233 # define BX_DBG_IAC_REPORT(vector, irq) \
234 if (bx_guard.report.irq) bx_dbg_iac_report(vector, irq)
235 # define BX_DBG_A20_REPORT(val) \
236 if (bx_guard.report.a20) bx_dbg_a20_report(val)
237 # define BX_DBG_IO_REPORT(addr, size, op, val) \
238 if (bx_guard.report.io) bx_dbg_io_report(addr, size, op, val)
239 # define BX_DBG_UCMEM_REPORT(addr, size, op, val) \
240 if (bx_guard.report.ucmem) bx_dbg_ucmem_report(addr, size, op, val)
241 #else // #if BX_DEBUGGER
242 // debugger not compiled in, use empty stubs
243 # define BX_DBG_ASYNC_INTR 1
244 # define BX_DBG_ASYNC_DMA 1
245 # define BX_DBG_DMA_REPORT(addr, len, what, val)
246 # define BX_DBG_IAC_REPORT(vector, irq)
247 # define BX_DBG_A20_REPORT(val)
248 # define BX_DBG_IO_REPORT(addr, size, op, val)
249 # define BX_DBG_UCMEM_REPORT(addr, size, op, val)
250 #endif // #if BX_DEBUGGER
252 #define MAGIC_LOGNUM 0x12345678
254 typedef class BOCHSAPI logfunctions
{
257 // values of onoff: 0=ignore, 1=report, 2=ask, 3=fatal
264 class iofunctions
*logio
;
265 // default log actions for all devices, declared and initialized
267 BOCHSAPI_CYGONLY
static int default_onoff
[N_LOGLEV
];
270 logfunctions(class iofunctions
*);
273 void info(const char *fmt
, ...) BX_CPP_AttrPrintf(2, 3);
274 void error(const char *fmt
, ...) BX_CPP_AttrPrintf(2, 3);
275 void panic(const char *fmt
, ...) BX_CPP_AttrPrintf(2, 3);
276 void pass(const char *fmt
, ...) BX_CPP_AttrPrintf(2, 3);
277 void ldebug(const char *fmt
, ...) BX_CPP_AttrPrintf(2, 3);
278 void fatal (const char *prefix
, const char *fmt
, va_list ap
, int exit_status
);
279 #if BX_EXTERNAL_DEBUGGER
280 virtual void ask (int level
, const char *prefix
, const char *fmt
, va_list ap
);
282 void ask (int level
, const char *prefix
, const char *fmt
, va_list ap
);
286 void setio(class iofunctions
*);
287 void setonoff(int loglev
, int value
) {
288 assert (loglev
>= 0 && loglev
< N_LOGLEV
);
289 onoff
[loglev
] = value
;
291 char *getprefix () { return prefix
; }
292 int getonoff(int level
) {
293 assert (level
>=0 && level
<N_LOGLEV
);
296 static void set_default_action (int loglev
, int action
) {
297 assert (loglev
>= 0 && loglev
< N_LOGLEV
);
298 assert (action
>= 0 && action
< N_ACT
);
299 default_onoff
[loglev
] = action
;
301 static int get_default_action (int loglev
) {
302 assert (loglev
>= 0 && loglev
< N_LOGLEV
);
303 return default_onoff
[loglev
];
307 #define BX_LOGPREFIX_SIZE 51
310 IOLOG
=0, FDLOG
, GENLOG
, CMOSLOG
, CDLOG
, DMALOG
, ETHLOG
, G2HLOG
, HDLOG
, KBDLOG
,
311 NE2KLOG
, PARLOG
, PCILOG
, PICLOG
, PITLOG
, SB16LOG
, SERLOG
, VGALOG
,
312 DEVLOG
, MEMLOG
, DISLOG
, GUILOG
, IOAPICLOG
, APICLOG
, CPU0LOG
, CPU1LOG
,
313 CPU2LOG
, CPU3LOG
, CPU4LOG
, CPU5LOG
, CPU6LOG
, CPU7LOG
, CPU8LOG
, CPU9LOG
,
314 CPU10LOG
, CPU11LOG
, CPU12LOG
, CPU13LOG
, CPU14LOG
, CPU15LOG
, CTRLLOG
,
315 UNMAPLOG
, SERRLOG
, BIOSLOG
, PIT81LOG
, PIT82LOG
, IODEBUGLOG
, PCI2ISALOG
,
316 PLUGINLOG
, EXTFPUIRQLOG
, PCIVGALOG
, PCIUSBLOG
, VTIMERLOG
, STIMERLOG
,
317 PCIIDELOG
, PCIDEVLOG
, PCIPNICLOG
, SPEAKERLOG
, BUSMLOG
, GAMELOG
, ACPILOG
320 class BOCHSAPI iofunctions
{
322 char logprefix
[BX_LOGPREFIX_SIZE
];
324 class logfunctions
*log
;
333 iofunctions(const char *);
336 void out(int facility
, int level
, const char *pre
, const char *fmt
, va_list ap
);
338 void init_log(const char *fn
);
339 void init_log(int fd
);
340 void init_log(FILE *fs
);
342 void set_log_prefix(const char *prefix
);
343 int get_n_logfns() { return n_logfn
; }
344 logfunc_t
*get_logfn(int index
) { return logfn_list
[index
]; }
345 void add_logfn(logfunc_t
*fn
);
346 void remove_logfn(logfunc_t
*fn
);
347 void set_log_action(int loglevel
, int action
);
348 const char *getlevel(int i
) {
349 static const char *loglevel
[N_LOGLEV
] = {
356 if (i
>=0 && i
<N_LOGLEV
) return loglevel
[i
];
359 char *getaction(int i
) {
360 static char *name
[] = { "ignore", "report", "ask", "fatal" };
361 assert (i
>=ACT_IGNORE
&& i
<N_ACT
);
367 #define MAX_LOGFNS 128
368 logfunc_t
*logfn_list
[MAX_LOGFNS
];
372 typedef class BOCHSAPI iofunctions iofunc_t
;
375 #define SAFE_GET_IOFUNC() \
376 ((io==NULL)? (io=new iofunc_t("/dev/stderr")) : io)
377 #define SAFE_GET_GENLOG() \
378 ((genlog==NULL)? (genlog=new logfunc_t(SAFE_GET_IOFUNC())) : genlog)
379 /* #define NO_LOGGING */
382 #define BX_INFO(x) (LOG_THIS info) x
383 #define BX_DEBUG(x) (LOG_THIS ldebug) x
384 #define BX_ERROR(x) (LOG_THIS error) x
385 #define BX_PANIC(x) (LOG_THIS panic) x
386 #define BX_PASS(x) (LOG_THIS pass) x
390 #define EMPTY do { } while(0)
392 #define BX_INFO(x) EMPTY
393 #define BX_DEBUG(x) EMPTY
394 #define BX_ERROR(x) EMPTY
395 #define BX_PANIC(x) (LOG_THIS panic) x
396 #define BX_PASS(x) (LOG_THIS pass) x
400 BOCHSAPI
extern iofunc_t
*io
;
401 BOCHSAPI
extern logfunc_t
*genlog
;
404 # define UNUSED(x) ((void)x)
407 #if BX_SUPPORT_X86_64
408 #define FMT_ADDRX FMT_ADDRX64
410 #define FMT_ADDRX FMT_ADDRX32
414 // defines for GDB stub
415 void bx_gdbstub_init(void);
416 void bx_gdbstub_break(void);
417 int bx_gdbstub_check(unsigned int eip
);
418 #define GDBSTUB_STOP_NO_REASON (0xac0)
421 #error GDB stub was written for single processor support. If multiprocessor support is added, then we can remove this check.
422 // The big problem is knowing which CPU gdb is referring to. In other words,
423 // what should we put for "n" in BX_CPU(n)->dbg_xlate_linear2phy() and
424 // BX_CPU(n)->dword.eip, etc.
452 bx_bool unsupported_io
;
455 #if BX_MAGIC_BREAKPOINT
456 bx_bool magic_break_enabled
;
457 #endif /* BX_MAGIC_BREAKPOINT */
459 bx_bool gdbstub_enabled
;
466 bx_bool linux_syscall
;
471 #define BX_ASSERT(x) do {if (!(x)) BX_PANIC(("failed assertion \"%s\" at %s:%d\n", #x, __FILE__, __LINE__));} while (0)
472 void bx_signal_handler (int signum
);
474 BOCHSAPI
extern bx_debug_t bx_dbg
;
477 // memory access type (read/write/rw)
482 #define DATA_ACCESS 0
483 #define CODE_ACCESS 1
485 #include "memory/memory.h"
486 #include "pc_system.h"
489 #include "gui/textconfig.h"
490 #include "gui/keymap.h"
492 /* --- EXTERNS --- */
494 #if BX_GUI_SIGHANDLER
495 extern bx_bool bx_gui_sighandler
;
498 // This value controls how often each I/O device's periodic() method
499 // gets called. The timer is set up in iodev/devices.cc.
500 #define BX_IODEV_HANDLER_PERIOD 100 // microseconds
501 //#define BX_IODEV_HANDLER_PERIOD 10 // microseconds
503 #define BX_PATHNAME_LEN 512
505 #define BX_KBD_XT_TYPE 0
506 #define BX_KBD_AT_TYPE 1
507 #define BX_KBD_MF_TYPE 2
509 #define BX_N_OPTROM_IMAGES 4
510 #define BX_N_OPTRAM_IMAGES 4
511 #define BX_N_SERIAL_PORTS 4
512 #define BX_N_PARALLEL_PORTS 2
513 #define BX_N_USB_HUBS 1
514 #define BX_N_PCI_SLOTS 5
517 #define BX_SMP_PROCESSORS (bx_cpu_count)
519 #define BX_SMP_PROCESSORS 1
522 void bx_init_options();
524 void bx_center_print (FILE *file
, char *line
, int maxwidth
);
526 #define BX_USE_PS2_MOUSE 1
528 int bx_init_hardware ();
530 #include "instrument.h"
532 // These are some convenience macros which abstract out accesses between
533 // a variable in native byte ordering to/from guest (x86) memory, which is
534 // always in little endian format. You must deal with alignment (if your
535 // system cares) and endian rearranging. Don't assume anything. You could
536 // put some platform specific asm() statements here, to make use of native
537 // instructions to help perform these operations more efficiently than C++.
542 #define WriteHostWordToLittleEndian(hostPtr, nativeVar16) \
543 *((Bit16u*)(hostPtr)) = (nativeVar16)
544 #define WriteHostDWordToLittleEndian(hostPtr, nativeVar32) \
545 *((Bit32u*)(hostPtr)) = (nativeVar32)
546 #define WriteHostQWordToLittleEndian(hostPtr, nativeVar64) \
547 *((Bit64u*)(hostPtr)) = (nativeVar64)
548 #define ReadHostWordFromLittleEndian(hostPtr, nativeVar16) \
549 (nativeVar16) = *((Bit16u*)(hostPtr))
550 #define ReadHostDWordFromLittleEndian(hostPtr, nativeVar32) \
551 (nativeVar32) = *((Bit32u*)(hostPtr))
552 #define ReadHostQWordFromLittleEndian(hostPtr, nativeVar64) \
553 (nativeVar64) = *((Bit64u*)(hostPtr))
557 #define WriteHostWordToLittleEndian(hostPtr, nativeVar16) { \
558 ((Bit8u *)(hostPtr))[0] = (Bit8u) (nativeVar16); \
559 ((Bit8u *)(hostPtr))[1] = (Bit8u) ((nativeVar16)>>8); \
561 #define WriteHostDWordToLittleEndian(hostPtr, nativeVar32) { \
562 ((Bit8u *)(hostPtr))[0] = (Bit8u) (nativeVar32); \
563 ((Bit8u *)(hostPtr))[1] = (Bit8u) ((nativeVar32)>>8); \
564 ((Bit8u *)(hostPtr))[2] = (Bit8u) ((nativeVar32)>>16); \
565 ((Bit8u *)(hostPtr))[3] = (Bit8u) ((nativeVar32)>>24); \
567 #define WriteHostQWordToLittleEndian(hostPtr, nativeVar64) { \
568 ((Bit8u *)(hostPtr))[0] = (Bit8u) (nativeVar64); \
569 ((Bit8u *)(hostPtr))[1] = (Bit8u) ((nativeVar64)>>8); \
570 ((Bit8u *)(hostPtr))[2] = (Bit8u) ((nativeVar64)>>16); \
571 ((Bit8u *)(hostPtr))[3] = (Bit8u) ((nativeVar64)>>24); \
572 ((Bit8u *)(hostPtr))[4] = (Bit8u) ((nativeVar64)>>32); \
573 ((Bit8u *)(hostPtr))[5] = (Bit8u) ((nativeVar64)>>40); \
574 ((Bit8u *)(hostPtr))[6] = (Bit8u) ((nativeVar64)>>48); \
575 ((Bit8u *)(hostPtr))[7] = (Bit8u) ((nativeVar64)>>56); \
577 #define ReadHostWordFromLittleEndian(hostPtr, nativeVar16) { \
578 (nativeVar16) = ((Bit16u) ((Bit8u *)(hostPtr))[0]) | \
579 (((Bit16u) ((Bit8u *)(hostPtr))[1])<<8) ; \
581 #define ReadHostDWordFromLittleEndian(hostPtr, nativeVar32) { \
582 (nativeVar32) = ((Bit32u) ((Bit8u *)(hostPtr))[0]) | \
583 (((Bit32u) ((Bit8u *)(hostPtr))[1])<<8) | \
584 (((Bit32u) ((Bit8u *)(hostPtr))[2])<<16) | \
585 (((Bit32u) ((Bit8u *)(hostPtr))[3])<<24); \
587 #define ReadHostQWordFromLittleEndian(hostPtr, nativeVar64) { \
588 (nativeVar64) = ((Bit64u) ((Bit8u *)(hostPtr))[0]) | \
589 (((Bit64u) ((Bit8u *)(hostPtr))[1])<<8) | \
590 (((Bit64u) ((Bit8u *)(hostPtr))[2])<<16) | \
591 (((Bit64u) ((Bit8u *)(hostPtr))[3])<<24) | \
592 (((Bit64u) ((Bit8u *)(hostPtr))[4])<<32) | \
593 (((Bit64u) ((Bit8u *)(hostPtr))[5])<<40) | \
594 (((Bit64u) ((Bit8u *)(hostPtr))[6])<<48) | \
595 (((Bit64u) ((Bit8u *)(hostPtr))[7])<<56); \
600 #endif /* BX_BOCHS_H */