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