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 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];
... ...
... ... @@ -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;
... ...