Commit 0124311e00452fa1555968dfe794dc8feed1a67c

Authored by bellard
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,7 +77,7 @@ int cpu_restore_state(struct TranslationBlock *tb,
77 CPUState *env, unsigned long searched_pc); 77 CPUState *env, unsigned long searched_pc);
78 void cpu_exec_init(void); 78 void cpu_exec_init(void);
79 int page_unprotect(unsigned long address); 79 int page_unprotect(unsigned long address);
80 -void page_unmap(void); 80 +void tb_invalidate_page(unsigned long address);
81 void tlb_flush_page(CPUState *env, uint32_t addr); 81 void tlb_flush_page(CPUState *env, uint32_t addr);
82 void tlb_flush_page_write(CPUState *env, uint32_t addr); 82 void tlb_flush_page_write(CPUState *env, uint32_t addr);
83 void tlb_flush(CPUState *env); 83 void tlb_flush(CPUState *env);
@@ -127,7 +127,7 @@ static inline unsigned int tb_hash_func(unsigned long pc) @@ -127,7 +127,7 @@ static inline unsigned int tb_hash_func(unsigned long pc)
127 } 127 }
128 128
129 TranslationBlock *tb_alloc(unsigned long pc); 129 TranslationBlock *tb_alloc(unsigned long pc);
130 -void tb_flush(void); 130 +void tb_flush(CPUState *env);
131 void tb_link(TranslationBlock *tb); 131 void tb_link(TranslationBlock *tb);
132 132
133 extern TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE]; 133 extern TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
@@ -62,7 +62,6 @@ typedef struct PageDesc { @@ -62,7 +62,6 @@ typedef struct PageDesc {
62 #define L1_SIZE (1 << L1_BITS) 62 #define L1_SIZE (1 << L1_BITS)
63 #define L2_SIZE (1 << L2_BITS) 63 #define L2_SIZE (1 << L2_BITS)
64 64
65 -static void tb_invalidate_page(unsigned long address);  
66 static void io_mem_init(void); 65 static void io_mem_init(void);
67 66
68 unsigned long real_host_page_size; 67 unsigned long real_host_page_size;
@@ -229,15 +228,19 @@ static void page_flush_tb(void) @@ -229,15 +228,19 @@ static void page_flush_tb(void)
229 228
230 /* flush all the translation blocks */ 229 /* flush all the translation blocks */
231 /* XXX: tb_flush is currently not thread safe */ 230 /* XXX: tb_flush is currently not thread safe */
232 -void tb_flush(void) 231 +void tb_flush(CPUState *env)
233 { 232 {
234 int i; 233 int i;
235 -#ifdef DEBUG_FLUSH 234 +#if defined(DEBUG_FLUSH)
236 printf("qemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n", 235 printf("qemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n",
237 code_gen_ptr - code_gen_buffer, 236 code_gen_ptr - code_gen_buffer,
238 nb_tbs, 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 #endif 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 nb_tbs = 0; 244 nb_tbs = 0;
242 for(i = 0;i < CODE_GEN_HASH_SIZE; i++) 245 for(i = 0;i < CODE_GEN_HASH_SIZE; i++)
243 tb_hash[i] = NULL; 246 tb_hash[i] = NULL;
@@ -402,7 +405,7 @@ static inline void tb_invalidate(TranslationBlock *tb, int parity) @@ -402,7 +405,7 @@ static inline void tb_invalidate(TranslationBlock *tb, int parity)
402 } 405 }
403 406
404 /* invalidate all TBs which intersect with the target page starting at addr */ 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 TranslationBlock *tb_next, *tb; 410 TranslationBlock *tb_next, *tb;
408 unsigned int page_index; 411 unsigned int page_index;
@@ -626,7 +629,7 @@ static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n) @@ -626,7 +629,7 @@ static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
626 /* suppress the jump to next tb in generated code */ 629 /* suppress the jump to next tb in generated code */
627 tb_reset_jump(tb, n); 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 tb_reset_jump_recursive(tb_next); 633 tb_reset_jump_recursive(tb_next);
631 } 634 }
632 } 635 }
@@ -688,7 +691,7 @@ void cpu_single_step(CPUState *env, int enabled) @@ -688,7 +691,7 @@ void cpu_single_step(CPUState *env, int enabled)
688 if (env->singlestep_enabled != enabled) { 691 if (env->singlestep_enabled != enabled) {
689 env->singlestep_enabled = enabled; 692 env->singlestep_enabled = enabled;
690 /* must flush all the translated code to avoid inconsistancies */ 693 /* must flush all the translated code to avoid inconsistancies */
691 - tb_flush(); 694 + tb_flush(env);
692 } 695 }
693 #endif 696 #endif
694 } 697 }
@@ -712,7 +715,7 @@ void cpu_set_log_filename(const char *filename) @@ -712,7 +715,7 @@ void cpu_set_log_filename(const char *filename)
712 logfilename = strdup(filename); 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 void cpu_interrupt(CPUState *env, int mask) 719 void cpu_interrupt(CPUState *env, int mask)
717 { 720 {
718 TranslationBlock *tb; 721 TranslationBlock *tb;
@@ -742,9 +745,10 @@ void cpu_abort(CPUState *env, const char *fmt, ...) @@ -742,9 +745,10 @@ void cpu_abort(CPUState *env, const char *fmt, ...)
742 abort(); 745 abort();
743 } 746 }
744 747
745 -#ifdef TARGET_I386 748 +#if !defined(CONFIG_USER_ONLY)
  749 +
746 /* unmap all maped pages and flush all associated code */ 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 PageDesc *pmap; 753 PageDesc *pmap;
750 int i; 754 int i;
@@ -784,21 +788,25 @@ void page_unmap(void) @@ -784,21 +788,25 @@ void page_unmap(void)
784 l1_map[i] = NULL; 788 l1_map[i] = NULL;
785 } 789 }
786 } 790 }
787 - tb_flush(); 791 + tb_flush(env);
788 } 792 }
789 -#endif  
790 793
791 void tlb_flush(CPUState *env) 794 void tlb_flush(CPUState *env)
792 { 795 {
793 -#if !defined(CONFIG_USER_ONLY)  
794 int i; 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 for(i = 0; i < CPU_TLB_SIZE; i++) { 802 for(i = 0; i < CPU_TLB_SIZE; i++) {
796 env->tlb_read[0][i].address = -1; 803 env->tlb_read[0][i].address = -1;
797 env->tlb_write[0][i].address = -1; 804 env->tlb_write[0][i].address = -1;
798 env->tlb_read[1][i].address = -1; 805 env->tlb_read[1][i].address = -1;
799 env->tlb_write[1][i].address = -1; 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 static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, uint32_t addr) 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,8 +818,11 @@ static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, uint32_t addr)
810 818
811 void tlb_flush_page(CPUState *env, uint32_t addr) 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 addr &= TARGET_PAGE_MASK; 827 addr &= TARGET_PAGE_MASK;
817 i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); 828 i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
@@ -819,23 +830,44 @@ void tlb_flush_page(CPUState *env, uint32_t addr) @@ -819,23 +830,44 @@ void tlb_flush_page(CPUState *env, uint32_t addr)
819 tlb_flush_entry(&env->tlb_write[0][i], addr); 830 tlb_flush_entry(&env->tlb_write[0][i], addr);
820 tlb_flush_entry(&env->tlb_read[1][i], addr); 831 tlb_flush_entry(&env->tlb_read[1][i], addr);
821 tlb_flush_entry(&env->tlb_write[1][i], addr); 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 #endif 838 #endif
  839 + page_set_flags(addr, addr + TARGET_PAGE_SIZE, 0);
  840 + }
823 } 841 }
824 842
825 /* make all write to page 'addr' trigger a TLB exception to detect 843 /* make all write to page 'addr' trigger a TLB exception to detect
826 self modifying code */ 844 self modifying code */
827 void tlb_flush_page_write(CPUState *env, uint32_t addr) 845 void tlb_flush_page_write(CPUState *env, uint32_t addr)
828 { 846 {
829 -#if !defined(CONFIG_USER_ONLY)  
830 int i; 847 int i;
831 848
832 addr &= TARGET_PAGE_MASK; 849 addr &= TARGET_PAGE_MASK;
833 i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); 850 i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
834 tlb_flush_entry(&env->tlb_write[0][i], addr); 851 tlb_flush_entry(&env->tlb_write[0][i], addr);
835 tlb_flush_entry(&env->tlb_write[1][i], addr); 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 static inline unsigned long *physpage_find_alloc(unsigned int page) 871 static inline unsigned long *physpage_find_alloc(unsigned int page)
840 { 872 {
841 unsigned long **lp, *p; 873 unsigned long **lp, *p;