Commit 0124311e00452fa1555968dfe794dc8feed1a67c
1 parent
f5155289
more generic TLB support - began to fix unlikely interrupt issues
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@492 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
52 additions
and
20 deletions
exec-all.h
... | ... | @@ -77,7 +77,7 @@ int cpu_restore_state(struct TranslationBlock *tb, |
77 | 77 | CPUState *env, unsigned long searched_pc); |
78 | 78 | void cpu_exec_init(void); |
79 | 79 | int page_unprotect(unsigned long address); |
80 | -void page_unmap(void); | |
80 | +void tb_invalidate_page(unsigned long address); | |
81 | 81 | void tlb_flush_page(CPUState *env, uint32_t addr); |
82 | 82 | void tlb_flush_page_write(CPUState *env, uint32_t addr); |
83 | 83 | void tlb_flush(CPUState *env); |
... | ... | @@ -127,7 +127,7 @@ static inline unsigned int tb_hash_func(unsigned long pc) |
127 | 127 | } |
128 | 128 | |
129 | 129 | TranslationBlock *tb_alloc(unsigned long pc); |
130 | -void tb_flush(void); | |
130 | +void tb_flush(CPUState *env); | |
131 | 131 | void tb_link(TranslationBlock *tb); |
132 | 132 | |
133 | 133 | extern TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE]; | ... | ... |
exec.c
... | ... | @@ -62,7 +62,6 @@ typedef struct PageDesc { |
62 | 62 | #define L1_SIZE (1 << L1_BITS) |
63 | 63 | #define L2_SIZE (1 << L2_BITS) |
64 | 64 | |
65 | -static void tb_invalidate_page(unsigned long address); | |
66 | 65 | static void io_mem_init(void); |
67 | 66 | |
68 | 67 | unsigned long real_host_page_size; |
... | ... | @@ -229,15 +228,19 @@ static void page_flush_tb(void) |
229 | 228 | |
230 | 229 | /* flush all the translation blocks */ |
231 | 230 | /* XXX: tb_flush is currently not thread safe */ |
232 | -void tb_flush(void) | |
231 | +void tb_flush(CPUState *env) | |
233 | 232 | { |
234 | 233 | int i; |
235 | -#ifdef DEBUG_FLUSH | |
234 | +#if defined(DEBUG_FLUSH) | |
236 | 235 | printf("qemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n", |
237 | 236 | code_gen_ptr - code_gen_buffer, |
238 | 237 | nb_tbs, |
239 | - (code_gen_ptr - code_gen_buffer) / nb_tbs); | |
238 | + nb_tbs > 0 ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0); | |
240 | 239 | #endif |
240 | + /* must reset current TB so that interrupts cannot modify the | |
241 | + links while we are modifying them */ | |
242 | + env->current_tb = NULL; | |
243 | + | |
241 | 244 | nb_tbs = 0; |
242 | 245 | for(i = 0;i < CODE_GEN_HASH_SIZE; i++) |
243 | 246 | tb_hash[i] = NULL; |
... | ... | @@ -402,7 +405,7 @@ static inline void tb_invalidate(TranslationBlock *tb, int parity) |
402 | 405 | } |
403 | 406 | |
404 | 407 | /* invalidate all TBs which intersect with the target page starting at addr */ |
405 | -static void tb_invalidate_page(unsigned long address) | |
408 | +void tb_invalidate_page(unsigned long address) | |
406 | 409 | { |
407 | 410 | TranslationBlock *tb_next, *tb; |
408 | 411 | unsigned int page_index; |
... | ... | @@ -626,7 +629,7 @@ static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n) |
626 | 629 | /* suppress the jump to next tb in generated code */ |
627 | 630 | tb_reset_jump(tb, n); |
628 | 631 | |
629 | - /* suppress jumps in the tb on which we could have jump */ | |
632 | + /* suppress jumps in the tb on which we could have jumped */ | |
630 | 633 | tb_reset_jump_recursive(tb_next); |
631 | 634 | } |
632 | 635 | } |
... | ... | @@ -688,7 +691,7 @@ void cpu_single_step(CPUState *env, int enabled) |
688 | 691 | if (env->singlestep_enabled != enabled) { |
689 | 692 | env->singlestep_enabled = enabled; |
690 | 693 | /* must flush all the translated code to avoid inconsistancies */ |
691 | - tb_flush(); | |
694 | + tb_flush(env); | |
692 | 695 | } |
693 | 696 | #endif |
694 | 697 | } |
... | ... | @@ -712,7 +715,7 @@ void cpu_set_log_filename(const char *filename) |
712 | 715 | logfilename = strdup(filename); |
713 | 716 | } |
714 | 717 | |
715 | -/* mask must never be zero */ | |
718 | +/* mask must never be zero, except for A20 change call */ | |
716 | 719 | void cpu_interrupt(CPUState *env, int mask) |
717 | 720 | { |
718 | 721 | TranslationBlock *tb; |
... | ... | @@ -742,9 +745,10 @@ void cpu_abort(CPUState *env, const char *fmt, ...) |
742 | 745 | abort(); |
743 | 746 | } |
744 | 747 | |
745 | -#ifdef TARGET_I386 | |
748 | +#if !defined(CONFIG_USER_ONLY) | |
749 | + | |
746 | 750 | /* unmap all maped pages and flush all associated code */ |
747 | -void page_unmap(void) | |
751 | +static void page_unmap(CPUState *env) | |
748 | 752 | { |
749 | 753 | PageDesc *pmap; |
750 | 754 | int i; |
... | ... | @@ -784,21 +788,25 @@ void page_unmap(void) |
784 | 788 | l1_map[i] = NULL; |
785 | 789 | } |
786 | 790 | } |
787 | - tb_flush(); | |
791 | + tb_flush(env); | |
788 | 792 | } |
789 | -#endif | |
790 | 793 | |
791 | 794 | void tlb_flush(CPUState *env) |
792 | 795 | { |
793 | -#if !defined(CONFIG_USER_ONLY) | |
794 | 796 | int i; |
797 | + | |
798 | + /* must reset current TB so that interrupts cannot modify the | |
799 | + links while we are modifying them */ | |
800 | + env->current_tb = NULL; | |
801 | + | |
795 | 802 | for(i = 0; i < CPU_TLB_SIZE; i++) { |
796 | 803 | env->tlb_read[0][i].address = -1; |
797 | 804 | env->tlb_write[0][i].address = -1; |
798 | 805 | env->tlb_read[1][i].address = -1; |
799 | 806 | env->tlb_write[1][i].address = -1; |
800 | 807 | } |
801 | -#endif | |
808 | + /* XXX: avoid flushing the TBs */ | |
809 | + page_unmap(env); | |
802 | 810 | } |
803 | 811 | |
804 | 812 | static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, uint32_t addr) |
... | ... | @@ -810,8 +818,11 @@ static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, uint32_t addr) |
810 | 818 | |
811 | 819 | void tlb_flush_page(CPUState *env, uint32_t addr) |
812 | 820 | { |
813 | -#if !defined(CONFIG_USER_ONLY) | |
814 | - int i; | |
821 | + int i, flags; | |
822 | + | |
823 | + /* must reset current TB so that interrupts cannot modify the | |
824 | + links while we are modifying them */ | |
825 | + env->current_tb = NULL; | |
815 | 826 | |
816 | 827 | addr &= TARGET_PAGE_MASK; |
817 | 828 | i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
... | ... | @@ -819,23 +830,44 @@ void tlb_flush_page(CPUState *env, uint32_t addr) |
819 | 830 | tlb_flush_entry(&env->tlb_write[0][i], addr); |
820 | 831 | tlb_flush_entry(&env->tlb_read[1][i], addr); |
821 | 832 | tlb_flush_entry(&env->tlb_write[1][i], addr); |
833 | + | |
834 | + flags = page_get_flags(addr); | |
835 | + if (flags & PAGE_VALID) { | |
836 | +#if !defined(CONFIG_SOFTMMU) | |
837 | + munmap((void *)addr, TARGET_PAGE_SIZE); | |
822 | 838 | #endif |
839 | + page_set_flags(addr, addr + TARGET_PAGE_SIZE, 0); | |
840 | + } | |
823 | 841 | } |
824 | 842 | |
825 | 843 | /* make all write to page 'addr' trigger a TLB exception to detect |
826 | 844 | self modifying code */ |
827 | 845 | void tlb_flush_page_write(CPUState *env, uint32_t addr) |
828 | 846 | { |
829 | -#if !defined(CONFIG_USER_ONLY) | |
830 | 847 | int i; |
831 | 848 | |
832 | 849 | addr &= TARGET_PAGE_MASK; |
833 | 850 | i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); |
834 | 851 | tlb_flush_entry(&env->tlb_write[0][i], addr); |
835 | 852 | tlb_flush_entry(&env->tlb_write[1][i], addr); |
836 | -#endif | |
837 | 853 | } |
838 | 854 | |
855 | +#else | |
856 | + | |
857 | +void tlb_flush(CPUState *env) | |
858 | +{ | |
859 | +} | |
860 | + | |
861 | +void tlb_flush_page(CPUState *env, uint32_t addr) | |
862 | +{ | |
863 | +} | |
864 | + | |
865 | +void tlb_flush_page_write(CPUState *env, uint32_t addr) | |
866 | +{ | |
867 | +} | |
868 | + | |
869 | +#endif /* defined(CONFIG_USER_ONLY) */ | |
870 | + | |
839 | 871 | static inline unsigned long *physpage_find_alloc(unsigned int page) |
840 | 872 | { |
841 | 873 | unsigned long **lp, *p; | ... | ... |