diff --git a/cpu-all.h b/cpu-all.h index 3df0fb8a9590125ed2047957acaae9a58c259eec..968323db263fbbe0666e64f90fc5b637de4293c5 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -787,6 +787,20 @@ void cpu_set_log(int log_flags); void cpu_set_log_filename(const char *filename); int cpu_str_to_log_mask(const char *str); +#define CPU_SETTING_NO_CACHE (1 << 0) + +/* define translation settings */ +typedef struct CPUTranslationSetting { + int mask; + const char *name; + const char *help; +} CPUTranslationSetting; + +extern CPUTranslationSetting cpu_translation_settings[]; + +void cpu_set_translation_settings(int translation_flags); +int cpu_str_to_translation_mask(const char *str); + /* IO ports API */ /* NOTE: as these functions may be even used when there is an isa diff --git a/cpu-exec.c b/cpu-exec.c index 8134c229c5ea0cee864da59daf11a26b75b5bd5c..af5c58f8a74760e845b5c28cc2e101a10d6c9ade 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -20,6 +20,7 @@ #include "config.h" #include "exec.h" #include "disas.h" +#include #if !defined(CONFIG_SOFTMMU) #undef EAX @@ -40,6 +41,9 @@ int tb_invalidated_flag; //#define DEBUG_EXEC //#define DEBUG_SIGNAL +/* translation settings */ +int translation_settings = 0; + #define SAVE_GLOBALS() #define RESTORE_GLOBALS() @@ -120,6 +124,56 @@ void cpu_resume_from_signal(CPUState *env1, void *puc) longjmp(env->jmp_env, 1); } +CPUTranslationSetting cpu_translation_settings[] = { + { CPU_SETTING_NO_CACHE, "no-cache", + "Do not use translation blocks cache (very slow!)" }, + { 0, NULL, NULL }, +}; + +void cpu_set_translation_settings(int translation_flags) +{ + translation_settings = translation_flags; +} + +static int cmp1(const char *s1, int n, const char *s2) +{ + if (strlen(s2) != n) + return 0; + return memcmp(s1, s2, n) == 0; +} + +/* takes a comma separated list of translation settings. Return 0 if error. */ +int cpu_str_to_translation_mask(const char *str) +{ + CPUTranslationSetting *setting; + int mask; + const char *p, *p1; + + p = str; + mask = 0; + for(;;) { + p1 = strchr(p, ','); + if (!p1) + p1 = p + strlen(p); + if(cmp1(p,p1-p,"all")) { + for(setting = cpu_translation_settings; setting->mask != 0; setting++) { + mask |= setting->mask; + } + } else { + for(setting = cpu_translation_settings; setting->mask != 0; setting++) { + if (cmp1(p, p1 - p, setting->name)) + goto found; + } + return 0; + } + found: + mask |= setting->mask; + if (*p1 != ',') + break; + p = p1 + 1; + } + return mask; +} static TranslationBlock *tb_find_slow(target_ulong pc, target_ulong cs_base, @@ -141,6 +195,9 @@ static TranslationBlock *tb_find_slow(target_ulong pc, phys_pc = get_phys_addr_code(env, pc); phys_page1 = phys_pc & TARGET_PAGE_MASK; phys_page2 = -1; + if (translation_settings & CPU_SETTING_NO_CACHE) + goto not_found; + h = tb_phys_hash_func(phys_pc); ptb1 = &tb_phys_hash[h]; for(;;) { @@ -264,7 +321,10 @@ static inline TranslationBlock *tb_find_fast(void) #else #error unsupported CPU #endif - tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)]; + if (translation_settings & CPU_SETTING_NO_CACHE) + tb = NULL; + else + tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)]; if (__builtin_expect(!tb || tb->pc != pc || tb->cs_base != cs_base || tb->flags != flags, 0)) { tb = tb_find_slow(pc, cs_base, flags); diff --git a/qemu-doc.texi b/qemu-doc.texi index 4b9ea606dbab4e9a8949e5053b878963c63b8e62..a18d3d0b0d25bdaaa77b74f73c2d477cff8e1e44 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -363,6 +363,17 @@ Set the initial date of the real time clock. Valid format for @var{date} are: @code{now} or @code{2006-06-17T16:01:21} or @code{2006-06-17}. The default value is @code{now}. +@item -translation @var{setting1[,...]} +Select dynamic translation options @var{setting}, @code{-translation ?} +shows a list of settings. Valid settings are: + +@table @code +@item @var{no-cache} +This option disables caching of translated code. Is useful for low-level +debugging of the emulated environment. This option incurs a massive +slow-down in emulation speed. +@end table + @item -pidfile @var{file} Store the QEMU process PID in @var{file}. It is useful if you launch QEMU from a script. diff --git a/vl.c b/vl.c index 19cd928d766a03b3b7f5d20d501ed769c623c4bc..8c63ad953a0ec8ddc165233478d72f94bfdbdba9 100644 --- a/vl.c +++ b/vl.c @@ -240,6 +240,8 @@ static CPUState *cur_cpu; static CPUState *next_cpu; static int event_pending = 1; +extern char *logfilename; + #define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR) /***********************************************************/ @@ -7661,6 +7663,9 @@ static void help(int exitcode) #endif "-clock force the use of the given methods for timer alarm.\n" " To see what timers are available use -clock help\n" + "-startdate select initial date of the Qemu clock\n" + "-translation setting1,... configures code translation\n" + " (use -translation ? for a list of settings)\n" "\n" "During emulation, the following keys are useful:\n" "ctrl-alt-f toggle full screen\n" @@ -7676,7 +7681,7 @@ static void help(int exitcode) DEFAULT_NETWORK_DOWN_SCRIPT, #endif DEFAULT_GDBSTUB_PORT, - "/tmp/qemu.log"); + logfilename); exit(exitcode); } @@ -7763,6 +7768,7 @@ enum { QEMU_OPTION_old_param, QEMU_OPTION_clock, QEMU_OPTION_startdate, + QEMU_OPTION_translation, }; typedef struct QEMUOption { @@ -7871,6 +7877,7 @@ const QEMUOption qemu_options[] = { #endif { "clock", HAS_ARG, QEMU_OPTION_clock }, { "startdate", HAS_ARG, QEMU_OPTION_startdate }, + { "translation", HAS_ARG, QEMU_OPTION_translation }, { NULL }, }; @@ -8713,6 +8720,22 @@ int main(int argc, char **argv) } } break; + case QEMU_OPTION_translation: + { + int mask; + CPUTranslationSetting *setting; + + mask = cpu_str_to_translation_mask(optarg); + if (!mask) { + printf("Translation settings (comma separated):\n"); + for(setting = cpu_translation_settings; setting->mask != 0; setting++) { + printf("%-10s %s\n", setting->name, setting->help); + } + exit(1); + } + cpu_set_translation_settings(mask); + } + break; } } }