]> git.proxmox.com Git - qemu.git/blobdiff - target-cris/mmu.c
Merge remote-tracking branch 'rth/tcg-pull' into staging
[qemu.git] / target-cris / mmu.c
index f270d5b8fc79aa2dff641775e482c7a179de461a..512e28b4813f4e4940d19e890ea4c158c38fc92d 100644 (file)
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifndef CONFIG_USER_ONLY
 
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "config.h"
 #include "cpu.h"
 #include "mmu.h"
-#include "exec-all.h"
 
 #ifdef DEBUG
 #define D(x) x
+#define D_LOG(...) qemu_log(__VA_ARGS__)
 #else
-#define D(x)
+#define D(x) do { } while (0)
+#define D_LOG(...) do { } while (0)
 #endif
 
-void cris_mmu_init(CPUState *env)
+void cris_mmu_init(CPUCRISState *env)
 {
        env->mmu_rand_lfsr = 0xcccc;
 }
@@ -54,6 +49,17 @@ static inline unsigned int compute_polynom(unsigned int sr)
        return f;
 }
 
+static void cris_mmu_update_rand_lfsr(CPUCRISState *env)
+{
+       unsigned int f;
+
+       /* Update lfsr at every fault.  */
+       f = compute_polynom(env->mmu_rand_lfsr);
+       env->mmu_rand_lfsr >>= 1;
+       env->mmu_rand_lfsr |= (f << 15);
+       env->mmu_rand_lfsr &= 0xffff;
+}
+
 static inline int cris_mmu_enabled(uint32_t rw_gc_cfg)
 {
        return (rw_gc_cfg & 12) != 0;
@@ -64,7 +70,7 @@ static inline int cris_mmu_segmented_addr(int seg, uint32_t rw_mm_cfg)
        return (1 << seg) & rw_mm_cfg;
 }
 
-static uint32_t cris_mmu_translate_seg(CPUState *env, int seg)
+static uint32_t cris_mmu_translate_seg(CPUCRISState *env, int seg)
 {
        uint32_t base;
        int i;
@@ -100,7 +106,7 @@ static inline void set_field(uint32_t *dst, unsigned int val,
 }
 
 #ifdef DEBUG
-static void dump_tlb(CPUState *env, int mmu)
+static void dump_tlb(CPUCRISState *env, int mmu)
 {
        int set;
        int idx;
@@ -121,9 +127,9 @@ static void dump_tlb(CPUState *env, int mmu)
 #endif
 
 /* rw 0 = read, 1 = write, 2 = exec.  */
-static int cris_mmu_translate_page(struct cris_mmu_result_t *res,
-                                  CPUState *env, uint32_t vaddr,
-                                  int rw, int usermode)
+static int cris_mmu_translate_page(struct cris_mmu_result *res,
+                                  CPUCRISState *env, uint32_t vaddr,
+                                  int rw, int usermode, int debug)
 {
        unsigned int vpage;
        unsigned int idx;
@@ -180,9 +186,8 @@ static int cris_mmu_translate_page(struct cris_mmu_result_t *res,
                tlb_pid = EXTRACT_FIELD(hi, 0, 7);
                tlb_g  = EXTRACT_FIELD(lo, 4, 4);
 
-               D(fprintf(logfile, 
-                        "TLB[%d][%d][%d] v=%x vpage=%x lo=%x hi=%x\n", 
-                        mmu, set, idx, tlb_vpn, vpage, lo, hi));
+               D_LOG("TLB[%d][%d][%d] v=%x vpage=%x lo=%x hi=%x\n", 
+                        mmu, set, idx, tlb_vpn, vpage, lo, hi);
                if ((tlb_g || (tlb_pid == pid))
                    && tlb_vpn == vpage) {
                        match = 1;
@@ -240,7 +245,7 @@ static int cris_mmu_translate_page(struct cris_mmu_result_t *res,
                        res->prot |= PAGE_READ;
                        if (tlb_w)
                                res->prot |= PAGE_WRITE;
-                       if (tlb_x)
+                       if (mmu == 0 && (cfg_x || tlb_x))
                                res->prot |= PAGE_EXEC;
                }
                else
@@ -250,15 +255,9 @@ static int cris_mmu_translate_page(struct cris_mmu_result_t *res,
                set = env->mmu_rand_lfsr & 3;
        }
 
-       if (!match) {
-               unsigned int f;
+       if (!match && !debug) {
+               cris_mmu_update_rand_lfsr(env);
 
-               /* Update lfsr at every fault.  */
-               f = compute_polynom(env->mmu_rand_lfsr);
-               env->mmu_rand_lfsr >>= 1;
-               env->mmu_rand_lfsr |= (f << 15);
-               env->mmu_rand_lfsr &= 0xffff;
-               
                /* Compute index.  */
                idx = vpage & 15;
 
@@ -285,17 +284,17 @@ static int cris_mmu_translate_page(struct cris_mmu_result_t *res,
                  env->sregs[SFR_RW_MM_TLB_SEL],
                  env->regs[R_SP], env->pregs[PR_USP], env->ksp));
 
-       res->pfn = tlb_pfn;
+       res->phy = tlb_pfn << TARGET_PAGE_BITS;
        return !match;
 }
 
-void cris_mmu_flush_pid(CPUState *env, uint32_t pid)
+void cris_mmu_flush_pid(CPUCRISState *env, uint32_t pid)
 {
        target_ulong vaddr;
        unsigned int idx;
        uint32_t lo, hi;
        uint32_t tlb_vpn;
-       int tlb_pid, tlb_g, tlb_v, tlb_k;
+       int tlb_pid, tlb_g, tlb_v;
        unsigned int set;
        unsigned int mmu;
 
@@ -311,15 +310,11 @@ void cris_mmu_flush_pid(CPUState *env, uint32_t pid)
                                tlb_pid = EXTRACT_FIELD(hi, 0, 7);
                                tlb_g  = EXTRACT_FIELD(lo, 4, 4);
                                tlb_v = EXTRACT_FIELD(lo, 3, 3);
-                               tlb_k = EXTRACT_FIELD(lo, 2, 2);
 
-                               /* Kernel protected areas need to be flushed
-                                  as well.  */
-                               if (tlb_v && !tlb_g && (tlb_pid == pid || tlb_k)) {
+                               if (tlb_v && !tlb_g && (tlb_pid == pid)) {
                                        vaddr = tlb_vpn << TARGET_PAGE_BITS;
-                                       D(fprintf(logfile,
-                                                 "flush pid=%x vaddr=%x\n", 
-                                                 pid, vaddr));
+                                       D_LOG("flush pid=%x vaddr=%x\n", 
+                                                 pid, vaddr);
                                        tlb_flush_page(env, vaddr);
                                }
                        }
@@ -327,11 +322,10 @@ void cris_mmu_flush_pid(CPUState *env, uint32_t pid)
        }
 }
 
-int cris_mmu_translate(struct cris_mmu_result_t *res,
-                      CPUState *env, uint32_t vaddr,
-                      int rw, int mmu_idx)
+int cris_mmu_translate(struct cris_mmu_result *res,
+                      CPUCRISState *env, uint32_t vaddr,
+                      int rw, int mmu_idx, int debug)
 {
-       uint32_t phy = vaddr;
        int seg;
        int miss = 0;
        int is_user = mmu_idx == MMU_USER_IDX;
@@ -349,21 +343,17 @@ int cris_mmu_translate(struct cris_mmu_result_t *res,
        }
 
        seg = vaddr >> 28;
-       if (cris_mmu_segmented_addr(seg, env->sregs[SFR_RW_MM_CFG]))
+       if (!is_user && cris_mmu_segmented_addr(seg, env->sregs[SFR_RW_MM_CFG]))
        {
                uint32_t base;
 
                miss = 0;
                base = cris_mmu_translate_seg(env, seg);
-               phy = base | (0x0fffffff & vaddr);
-               res->phy = phy;
+                res->phy = base | (0x0fffffff & vaddr);
                res->prot = PAGE_BITS;
-       }
-       else
-       {
-               miss = cris_mmu_translate_page(res, env, vaddr, rw, is_user);
-               phy = (res->pfn << 13);
-               res->phy = phy;
+       } else {
+               miss = cris_mmu_translate_page(res, env, vaddr, rw,
+                                              is_user, debug);
        }
   done:
        env->pregs[PR_SRS] = old_srs;