All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/11] PPC64 Linux bringup patches v3
@ 2009-03-06 15:35 Alexander Graf
  2009-03-06 15:35 ` [Qemu-devel] [PATCH 01/11] PPC64: Implement slbmte Alexander Graf
  2009-03-07 10:04 ` [Qemu-devel] Re: [PATCH 00/11] PPC64 Linux bringup patches v3 Blue Swirl
  0 siblings, 2 replies; 18+ messages in thread
From: Alexander Graf @ 2009-03-06 15:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: blauwirbel

After spending even more time trying to get qemu-system-ppc64 to run Linux, I
get up to userspace now :-).

I am aware that this patchset is not 100% accurate and perfect for emulation,
but I think that it can't get worse than it is now.

This patchset enhances MMU support to work with large pages, implement tlbiel,
and fixes random issues I ran into while getting closer to the kernel running
userspace code :).

Keep in mind that this also requires an OpenBIOS update, as the current code
is not aware that it gets run in 64 bit mode.

For now booting into userspace from an initrd works fine. I didn't try to get
IDE working, but it looks like that's broken. Also console=ttyPZ0 doesn't work
for me, because the pmz doesn't initialize properly (probably an OpenBIOS issue).

So as long as you use graphical mode and run code from an initrd, you're fine.

I also removed the lwsync patch from this patchset, as it only fixed symptoms
and no causes. It would be great if anyone would step up to find out how to
fix that, as it's not a ppc-only problem.

Alexander Graf (11):
  PPC64: Implement slbmte
  PPC64: Implement large pages
  PPC64: Implment tlbiel
  Activate uninorth AGP bridge
  PPC64: Nop some SPRs on 970fx
  PPC64: Enable 64bit mode on interrupts
  PPC64: Implement mtfsf.L encoding
  PPC64: Fix RFI(d)
  PPC64: Fix NX bit
  PPC64: Keep SLB in-CPU
  PPC64: Disable BAT for 970

 hw/unin_pci.c               |   27 ++---
 target-ppc/cpu.h            |   11 ++-
 target-ppc/helper.c         |  276 ++++++++++++++++++++++++++-----------------
 target-ppc/op_helper.c      |   12 +-
 target-ppc/translate.c      |   45 ++++++-
 target-ppc/translate_init.c |   14 ++-
 6 files changed, 245 insertions(+), 140 deletions(-)

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH 01/11] PPC64: Implement slbmte
  2009-03-06 15:35 [Qemu-devel] [PATCH 00/11] PPC64 Linux bringup patches v3 Alexander Graf
@ 2009-03-06 15:35 ` Alexander Graf
  2009-03-06 15:35   ` [Qemu-devel] [PATCH 02/11] PPC64: Implement large pages Alexander Graf
  2009-03-07  9:57   ` [Qemu-devel] Re: [PATCH 01/11] PPC64: Implement slbmte Blue Swirl
  2009-03-07 10:04 ` [Qemu-devel] Re: [PATCH 00/11] PPC64 Linux bringup patches v3 Blue Swirl
  1 sibling, 2 replies; 18+ messages in thread
From: Alexander Graf @ 2009-03-06 15:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: blauwirbel, Alexander Graf

In order to modify SLB entries on recent PPC64 machines, the slbmte
instruction is used.

This patch implements the slbmte instruction and makes the "bridge"
mode code use the slb set functions, so we can move the SLB into
the CPU struct later.

This is required for Linux to run on PPC64.

Signed-off-by: Alexander Graf <alex@csgraf.de>
---
 target-ppc/cpu.h       |    3 +-
 target-ppc/helper.c    |   57 ++++++++++++++++++++++++++++++++++++-----------
 target-ppc/op_helper.c |    6 +++-
 target-ppc/translate.c |   23 ++++++++++++++++---
 4 files changed, 68 insertions(+), 21 deletions(-)

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index bdc3cf9..f53be5a 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -714,7 +714,8 @@ void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
 #if defined(TARGET_PPC64)
 void ppc_store_asr (CPUPPCState *env, target_ulong value);
 target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr);
-void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs);
+target_ulong ppc_load_sr (CPUPPCState *env, int sr_nr);
+void ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs);
 #endif /* defined(TARGET_PPC64) */
 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value);
 #endif /* !defined(CONFIG_USER_ONLY) */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index e02dcb0..9461daf 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -821,27 +821,34 @@ target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
     return rt;
 }
 
-void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs)
+void ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
 {
     target_phys_addr_t sr_base;
     uint64_t tmp64;
     uint32_t tmp;
 
+    uint64_t vsid;
+    uint64_t esid;
+    int flags, valid, slb_nr;
+
+    vsid = rs >> 12;
+    flags = ((rs >> 8) & 0xf);
+
+    esid = rb >> 28;
+    valid = (rb & (1 << 27));
+    slb_nr = rb & 0xfff;
+
+    tmp64 = (esid << 28) | valid | (vsid >> 24);
+    tmp = (vsid << 8) | (flags << 3);
+
+    /* Write SLB entry to memory */
     sr_base = env->spr[SPR_ASR];
     sr_base += 12 * slb_nr;
-    /* Copy Rs bits 37:63 to SLB 62:88 */
-    tmp = rs << 8;
-    tmp64 = (rs >> 24) & 0x7;
-    /* Copy Rs bits 33:36 to SLB 89:92 */
-    tmp |= ((rs >> 27) & 0xF) << 4;
-    /* Set the valid bit */
-    tmp64 |= 1 << 27;
-    /* Set ESID */
-    tmp64 |= (uint32_t)slb_nr << 28;
-    LOG_SLB("%s: %d " ADDRX " => " PADDRX " %016" PRIx64
+
+    LOG_SLB("%s: %d " ADDRX " - " ADDRX " => " PADDRX " %016" PRIx64
                 " %08" PRIx32 "\n", __func__,
-                slb_nr, rs, sr_base, tmp64, tmp);
-    /* Write SLB entry to memory */
+                slb_nr, rb, rs, sr_base, tmp64, tmp);
+
     stq_phys(sr_base, tmp64);
     stl_phys(sr_base + 8, tmp);
 }
@@ -1945,11 +1952,33 @@ void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
     }
 }
 
+target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr)
+{
+    // XXX
+    return 0;
+}
+
 void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
 {
     LOG_MMU("%s: reg=%d " ADDRX " " ADDRX "\n",
                 __func__, srnum, value, env->sr[srnum]);
-    if (env->sr[srnum] != value) {
+    if (env->mmu_model & POWERPC_MMU_64) {
+        uint64_t rb = 0, rs = 0;
+
+        /* ESID = srnum */
+        rb |= ((uint32_t)srnum & 0xf) << 28;
+        /* Set the valid bit */
+        rb |= 1 << 27;
+        /* Index = ESID */
+        rb |= (uint32_t)srnum;
+
+        /* VSID = VSID */
+        rs |= (value & 0xfffffff) << 12;
+        /* flags = flags */
+        rs |= ((value >> 27) & 0xf) << 9;
+
+        ppc_store_slb(env, rb, rs);
+    } else if (env->sr[srnum] != value) {
         env->sr[srnum] = value;
 #if !defined(FLUSH_ALL_TLBS) && 0
         {
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 3afd217..527f8de 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -3752,6 +3752,8 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
 /* Segment registers load and store */
 target_ulong helper_load_sr (target_ulong sr_num)
 {
+    if (env->mmu_model & POWERPC_MMU_64)
+        return ppc_load_sr(env, sr_num);
     return env->sr[sr_num];
 }
 
@@ -3767,9 +3769,9 @@ target_ulong helper_load_slb (target_ulong slb_nr)
     return ppc_load_slb(env, slb_nr);
 }
 
-void helper_store_slb (target_ulong slb_nr, target_ulong rs)
+void helper_store_slb (target_ulong rb, target_ulong rs)
 {
-    ppc_store_slb(env, slb_nr, rs);
+    ppc_store_slb(env, rb, rs);
 }
 
 void helper_slbia (void)
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 489ba09..f48ab20 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -4296,7 +4296,7 @@ GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B)
         return;
     }
     t0 = tcg_const_tl(SR(ctx->opcode));
-    gen_helper_load_slb(cpu_gpr[rD(ctx->opcode)], t0);
+    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
     tcg_temp_free(t0);
 #endif
 }
@@ -4316,7 +4316,7 @@ GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
     t0 = tcg_temp_new();
     tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
     tcg_gen_andi_tl(t0, t0, 0xF);
-    gen_helper_load_slb(cpu_gpr[rD(ctx->opcode)], t0);
+    gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
     tcg_temp_free(t0);
 #endif
 }
@@ -4333,7 +4333,7 @@ GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
         return;
     }
     t0 = tcg_const_tl(SR(ctx->opcode));
-    gen_helper_store_slb(t0, cpu_gpr[rS(ctx->opcode)]);
+    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
     tcg_temp_free(t0);
 #endif
 }
@@ -4353,10 +4353,25 @@ GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
     t0 = tcg_temp_new();
     tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
     tcg_gen_andi_tl(t0, t0, 0xF);
-    gen_helper_store_slb(t0, cpu_gpr[rS(ctx->opcode)]);
+    gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
     tcg_temp_free(t0);
 #endif
 }
+
+/* slbmte */
+GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x00000000, PPC_SEGMENT_64B)
+{
+#if defined(CONFIG_USER_ONLY)
+    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
+#else
+    if (unlikely(!ctx->mem_idx)) {
+        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
+        return;
+    }
+    gen_helper_store_slb(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
+#endif
+}
+
 #endif /* defined(TARGET_PPC64) */
 
 /***                      Lookaside buffer management                      ***/
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH 02/11] PPC64: Implement large pages
  2009-03-06 15:35 ` [Qemu-devel] [PATCH 01/11] PPC64: Implement slbmte Alexander Graf
@ 2009-03-06 15:35   ` Alexander Graf
  2009-03-06 15:35     ` [Qemu-devel] [PATCH 03/11] PPC64: Implment tlbiel Alexander Graf
  2009-03-07  9:57   ` [Qemu-devel] Re: [PATCH 01/11] PPC64: Implement slbmte Blue Swirl
  1 sibling, 1 reply; 18+ messages in thread
From: Alexander Graf @ 2009-03-06 15:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: blauwirbel, Alexander Graf

The current SLB/PTE code does not support large pages, which are
required by Linux, as it boots up with the kernel regions up as large.

This patch implements large page support, so we can run Linux.

Signed-off-by: Alexander Graf <alex@csgraf.de>
---
 target-ppc/cpu.h    |    1 +
 target-ppc/helper.c |   78 +++++++++++++++++++++++++++++++-------------------
 2 files changed, 49 insertions(+), 30 deletions(-)

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index f53be5a..c88f81b 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -675,6 +675,7 @@ struct CPUPPCState {
 typedef struct mmu_ctx_t mmu_ctx_t;
 struct mmu_ctx_t {
     target_phys_addr_t raddr;      /* Real address              */
+    target_phys_addr_t eaddr;      /* Effective address         */
     int prot;                      /* Protection bits           */
     target_phys_addr_t pg_addr[2]; /* PTE tables base addresses */
     target_ulong ptem;             /* Virtual segment ID | API  */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 9461daf..0fa87dc 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -582,7 +582,8 @@ static always_inline int get_bat (CPUState *env, mmu_ctx_t *ctx,
 
 /* PTE table lookup */
 static always_inline int _find_pte (mmu_ctx_t *ctx, int is_64b, int h,
-                                    int rw, int type)
+                                    int rw, int type,
+                                    int target_page_bits)
 {
     target_ulong base, pte0, pte1;
     int i, good = -1;
@@ -594,7 +595,14 @@ static always_inline int _find_pte (mmu_ctx_t *ctx, int is_64b, int h,
 #if defined(TARGET_PPC64)
         if (is_64b) {
             pte0 = ldq_phys(base + (i * 16));
-            pte1 =  ldq_phys(base + (i * 16) + 8);
+            pte1 = ldq_phys(base + (i * 16) + 8);
+
+            /* We have a TLB that saves 4K pages, so let's
+             * split a huge page to 4k chunks */
+            if (target_page_bits != TARGET_PAGE_BITS)
+                pte1 |= (ctx->eaddr & (( 1 << target_page_bits ) - 1))
+                        & TARGET_PAGE_MASK;
+
             r = pte64_check(ctx, pte0, pte1, h, rw, type);
             LOG_MMU("Load pte from " ADDRX " => " ADDRX " " ADDRX
                         " %d %d %d " ADDRX "\n",
@@ -658,27 +666,30 @@ static always_inline int _find_pte (mmu_ctx_t *ctx, int is_64b, int h,
     return ret;
 }
 
-static always_inline int find_pte32 (mmu_ctx_t *ctx, int h, int rw, int type)
+static always_inline int find_pte32 (mmu_ctx_t *ctx, int h, int rw,
+                                     int type, int target_page_bits)
 {
-    return _find_pte(ctx, 0, h, rw, type);
+    return _find_pte(ctx, 0, h, rw, type, target_page_bits);
 }
 
 #if defined(TARGET_PPC64)
-static always_inline int find_pte64 (mmu_ctx_t *ctx, int h, int rw, int type)
+static always_inline int find_pte64 (mmu_ctx_t *ctx, int h, int rw,
+                                     int type, int target_page_bits)
 {
-    return _find_pte(ctx, 1, h, rw, type);
+    return _find_pte(ctx, 1, h, rw, type, target_page_bits);
 }
 #endif
 
 static always_inline int find_pte (CPUState *env, mmu_ctx_t *ctx,
-                                   int h, int rw, int type)
+                                   int h, int rw, int type,
+                                   int target_page_bits)
 {
 #if defined(TARGET_PPC64)
     if (env->mmu_model & POWERPC_MMU_64)
-        return find_pte64(ctx, h, rw, type);
+        return find_pte64(ctx, h, rw, type, target_page_bits);
 #endif
 
-    return find_pte32(ctx, h, rw, type);
+    return find_pte32(ctx, h, rw, type, target_page_bits);
 }
 
 #if defined(TARGET_PPC64)
@@ -694,7 +705,8 @@ static always_inline void slb_invalidate (uint64_t *slb64)
 
 static always_inline int slb_lookup (CPUPPCState *env, target_ulong eaddr,
                                      target_ulong *vsid,
-                                     target_ulong *page_mask, int *attr)
+                                     target_ulong *page_mask, int *attr,
+                                     int *target_page_bits)
 {
     target_phys_addr_t sr_base;
     target_ulong mask;
@@ -714,19 +726,16 @@ static always_inline int slb_lookup (CPUPPCState *env, target_ulong eaddr,
                     PRIx32 "\n", __func__, n, sr_base, tmp64, tmp);
         if (slb_is_valid(tmp64)) {
             /* SLB entry is valid */
-            switch (tmp64 & 0x0000000006000000ULL) {
-            case 0x0000000000000000ULL:
-                /* 256 MB segment */
-                mask = 0xFFFFFFFFF0000000ULL;
-                break;
-            case 0x0000000002000000ULL:
-                /* 1 TB segment */
+            if (tmp & 0x8) {
+                /* 1 TB Segment */
                 mask = 0xFFFF000000000000ULL;
-                break;
-            case 0x0000000004000000ULL:
-            case 0x0000000006000000ULL:
-                /* Reserved => segment is invalid */
-                continue;
+                if (target_page_bits)
+                    *target_page_bits = 24; // XXX 16M pages?
+            } else {
+                /* 256MB Segment */
+                mask = 0xFFFFFFFFF0000000ULL;
+                if (target_page_bits)
+                    *target_page_bits = TARGET_PAGE_BITS;
             }
             if ((eaddr & mask) == (tmp64 & mask)) {
                 /* SLB match */
@@ -777,7 +786,7 @@ void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
     int attr;
     int n;
 
-    n = slb_lookup(env, T0, &vsid, &page_mask, &attr);
+    n = slb_lookup(env, T0, &vsid, &page_mask, &attr, NULL);
     if (n >= 0) {
         sr_base = env->spr[SPR_ASR];
         sr_base += 12 * n;
@@ -871,20 +880,22 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,
 #if defined(TARGET_PPC64)
     int attr;
 #endif
-    int ds, vsid_sh, sdr_sh, pr;
+    int ds, vsid_sh, sdr_sh, pr, target_page_bits;
     int ret, ret2;
 
     pr = msr_pr;
 #if defined(TARGET_PPC64)
     if (env->mmu_model & POWERPC_MMU_64) {
         LOG_MMU("Check SLBs\n");
-        ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr);
+        ret = slb_lookup(env, eaddr, &vsid, &page_mask, &attr,
+                         &target_page_bits);
         if (ret < 0)
             return ret;
         ctx->key = ((attr & 0x40) && (pr != 0)) ||
             ((attr & 0x80) && (pr == 0)) ? 1 : 0;
         ds = 0;
-        ctx->nx = attr & 0x20 ? 1 : 0;
+        ctx->nx = attr & 0x10 ? 1 : 0;
+        ctx->eaddr = eaddr;
         vsid_mask = 0x00003FFFFFFFFF80ULL;
         vsid_sh = 7;
         sdr_sh = 18;
@@ -903,6 +914,7 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,
         vsid_sh = 6;
         sdr_sh = 16;
         sdr_mask = 0xFFC0;
+        target_page_bits = TARGET_PAGE_BITS;
         LOG_MMU("Check segment v=" ADDRX " %d " ADDRX
                     " nip=" ADDRX " lr=" ADDRX " ir=%d dr=%d pr=%d %d t=%d\n",
                     eaddr, (int)(eaddr >> 28), sr, env->nip,
@@ -918,7 +930,7 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,
             /* Page address translation */
             /* Primary table address */
             sdr = env->sdr1;
-            pgidx = (eaddr & page_mask) >> TARGET_PAGE_BITS;
+            pgidx = (eaddr & page_mask) >> target_page_bits;
 #if defined(TARGET_PPC64)
             if (env->mmu_model & POWERPC_MMU_64) {
                 htab_mask = 0x0FFFFFFF >> (28 - (sdr & 0x1F));
@@ -944,7 +956,12 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,
 #if defined(TARGET_PPC64)
             if (env->mmu_model & POWERPC_MMU_64) {
                 /* Only 5 bits of the page index are used in the AVPN */
-                ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
+                if (target_page_bits > 23) {
+                    ctx->ptem = (vsid << 12) |
+                                ((pgidx << (target_page_bits - 16)) & 0xF80);
+                } else {
+                    ctx->ptem = (vsid << 12) | ((pgidx >> 4) & 0x0F80);
+                }
             } else
 #endif
             {
@@ -962,7 +979,7 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,
                             " pg_addr=" PADDRX "\n",
                             sdr, vsid, pgidx, hash, ctx->pg_addr[0]);
                 /* Primary table lookup */
-                ret = find_pte(env, ctx, 0, rw, type);
+                ret = find_pte(env, ctx, 0, rw, type, target_page_bits);
                 if (ret < 0) {
                     /* Secondary table lookup */
                     if (eaddr != 0xEFFFFFFF)
@@ -970,7 +987,8 @@ static always_inline int get_segment (CPUState *env, mmu_ctx_t *ctx,
                                 "api=" ADDRX " hash=" PADDRX
                                 " pg_addr=" PADDRX "\n",
                                 sdr, vsid, pgidx, hash, ctx->pg_addr[1]);
-                    ret2 = find_pte(env, ctx, 1, rw, type);
+                    ret2 = find_pte(env, ctx, 1, rw, type,
+                                    target_page_bits);
                     if (ret2 != -1)
                         ret = ret2;
                 }
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH 03/11] PPC64: Implment tlbiel
  2009-03-06 15:35   ` [Qemu-devel] [PATCH 02/11] PPC64: Implement large pages Alexander Graf
@ 2009-03-06 15:35     ` Alexander Graf
  2009-03-06 15:35       ` [Qemu-devel] [PATCH 04/11] Activate uninorth AGP bridge Alexander Graf
  0 siblings, 1 reply; 18+ messages in thread
From: Alexander Graf @ 2009-03-06 15:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: blauwirbel, Alexander Graf

Linux uses tlbiel to flush TLB entries in PPC64 mode. This special TLB
flush opcode only flushes an entry for the CPU it runs on, not across
all CPUs in the system.

Signed-off-by: Alexander Graf <alex@csgraf.de>
---
 target-ppc/translate.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index f48ab20..b5de33b 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -4390,6 +4390,20 @@ GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
 #endif
 }
 
+/* tlbiel */
+GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x03FF0001, PPC_MEM_TLBIE)
+{
+#if defined(CONFIG_USER_ONLY)
+    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+#else
+    if (unlikely(!ctx->mem_idx)) {
+        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+        return;
+    }
+    gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
+#endif
+}
+
 /* tlbie */
 GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
 {
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH 04/11] Activate uninorth AGP bridge
  2009-03-06 15:35     ` [Qemu-devel] [PATCH 03/11] PPC64: Implment tlbiel Alexander Graf
@ 2009-03-06 15:35       ` Alexander Graf
  2009-03-06 15:35         ` [Qemu-devel] [PATCH 05/11] PPC64: Nop some SPRs on 970fx Alexander Graf
  0 siblings, 1 reply; 18+ messages in thread
From: Alexander Graf @ 2009-03-06 15:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: blauwirbel, Alexander Graf

Linux tries to poke the AGP bridge port and is pretty sad when it can't,
so let's activate the old code again and throw out the bit modifications,
as we don't really do anything with the values anyways.

Signed-off-by: Alexander Graf <alex@csgraf.de>
---
 hw/unin_pci.c |   27 ++++++++-------------------
 1 files changed, 8 insertions(+), 19 deletions(-)

diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index 949e63f..c734f1c 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -92,17 +92,12 @@ static CPUReadMemoryFunc *pci_unin_main_read[] = {
     &pci_host_data_readl,
 };
 
-#if 0
-
 static void pci_unin_config_writel (void *opaque, target_phys_addr_t addr,
                                     uint32_t val)
 {
     UNINState *s = opaque;
 
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-    s->config_reg = 0x80000000 | (val & ~0x00000001);
+    s->config_reg = val;
 }
 
 static uint32_t pci_unin_config_readl (void *opaque,
@@ -111,12 +106,7 @@ static uint32_t pci_unin_config_readl (void *opaque,
     UNINState *s = opaque;
     uint32_t val;
 
-    val = (s->config_reg | 0x00000001) & ~0x80000000;
-#ifdef TARGET_WORDS_BIGENDIAN
-    val = bswap32(val);
-#endif
-
-    return val;
+    return s->config_reg;
 }
 
 static CPUWriteMemoryFunc *pci_unin_config_write[] = {
@@ -131,6 +121,7 @@ static CPUReadMemoryFunc *pci_unin_config_read[] = {
     &pci_unin_config_readl,
 };
 
+#if 0
 static CPUWriteMemoryFunc *pci_unin_write[] = {
     &pci_host_pci_writeb,
     &pci_host_pci_writew,
@@ -233,18 +224,17 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
     d->config[0x27] = 0x7F;
     // d->config[0x34] = 0xdc // capabilities_pointer
 #endif
-#if 0 // XXX: not needed for now
+
     /* Uninorth AGP bus */
-    s = &pci_bridge[1];
     pci_mem_config = cpu_register_io_memory(0, pci_unin_config_read,
                                             pci_unin_config_write, s);
-    pci_mem_data = cpu_register_io_memory(0, pci_unin_read,
-                                          pci_unin_write, s);
+    pci_mem_data = cpu_register_io_memory(0, pci_unin_main_read,
+                                          pci_unin_main_write, s);
     cpu_register_physical_memory(0xf0800000, 0x1000, pci_mem_config);
     cpu_register_physical_memory(0xf0c00000, 0x1000, pci_mem_data);
 
-    d = pci_register_device("Uni-north AGP", sizeof(PCIDevice), 0, 11 << 3,
-                            NULL, NULL);
+    d = pci_register_device(s->bus, "Uni-north AGP", sizeof(PCIDevice),
+                            11 << 3, NULL, NULL);
     pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_APPLE);
     pci_config_set_device_id(d->config, PCI_DEVICE_ID_APPLE_UNI_N_AGP);
     d->config[0x08] = 0x00; // revision
@@ -253,7 +243,6 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
     d->config[0x0D] = 0x10; // latency_timer
     d->config[0x0E] = 0x00; // header_type
     //    d->config[0x34] = 0x80; // capabilities_pointer
-#endif
 
 #if 0 // XXX: not needed for now
     /* Uninorth internal bus */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH 05/11] PPC64: Nop some SPRs on 970fx
  2009-03-06 15:35       ` [Qemu-devel] [PATCH 04/11] Activate uninorth AGP bridge Alexander Graf
@ 2009-03-06 15:35         ` Alexander Graf
  2009-03-06 15:36           ` [Qemu-devel] [PATCH 06/11] PPC64: Enable 64bit mode on interrupts Alexander Graf
  0 siblings, 1 reply; 18+ messages in thread
From: Alexander Graf @ 2009-03-06 15:35 UTC (permalink / raw)
  To: qemu-devel; +Cc: blauwirbel, Alexander Graf

Linux tries to access some SPRs on PPC64 boot. Let's just ignore those
for the 970fx for now to make it happy.

Signed-off-by: Alexander Graf <alex@csgraf.de>
---
 target-ppc/translate_init.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 6b7ab98..42e62be 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -6043,6 +6043,18 @@ static void init_proc_970FX (CPUPPCState *env)
                  SPR_NOACCESS, SPR_NOACCESS,
                  &spr_read_hior, &spr_write_hior,
                  0x00000000);
+    spr_register(env, SPR_CTRL, "SPR_CTRL",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_UCTRL, "SPR_UCTRL",
+                 SPR_NOACCESS, SPR_NOACCESS,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
+    spr_register(env, SPR_VRSAVE, "SPR_VRSAVE",
+                 &spr_read_generic, &spr_write_generic,
+                 &spr_read_generic, &spr_write_generic,
+                 0x00000000);
 #if !defined(CONFIG_USER_ONLY)
     env->slb_nr = 32;
 #endif
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH 06/11] PPC64: Enable 64bit mode on interrupts
  2009-03-06 15:35         ` [Qemu-devel] [PATCH 05/11] PPC64: Nop some SPRs on 970fx Alexander Graf
@ 2009-03-06 15:36           ` Alexander Graf
  2009-03-06 15:36             ` [Qemu-devel] [PATCH 07/11] PPC64: Implement mtfsf.L encoding Alexander Graf
  0 siblings, 1 reply; 18+ messages in thread
From: Alexander Graf @ 2009-03-06 15:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: blauwirbel, Alexander Graf

Real 970s enable MSR_SF on all interrupts. The current code didn't do
this until now, so let's activate it!

Signed-off-by: Alexander Graf <alex@csgraf.de>
---
 target-ppc/helper.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 0fa87dc..7fe3f8f 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -2607,7 +2607,7 @@ static always_inline void powerpc_excp (CPUState *env,
             new_msr |= (target_ulong)1 << MSR_CM;
         }
     } else {
-        if (!msr_isf) {
+        if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
             new_msr &= ~((target_ulong)1 << MSR_SF);
             vector = (uint32_t)vector;
         } else {
@@ -2788,6 +2788,10 @@ void cpu_ppc_reset (void *opaque)
         ppc_tlb_invalidate_all(env);
 #endif
     env->msr = msr & env->msr_mask;
+#if defined(TARGET_PPC64)
+    if (env->mmu_model & POWERPC_MMU_64)
+        env->msr |= (1ULL << MSR_SF);
+#endif
     hreg_compute_hflags(env);
     env->reserve = (target_ulong)-1ULL;
     /* Be sure no exception or interrupt is pending */
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH 07/11] PPC64: Implement mtfsf.L encoding
  2009-03-06 15:36           ` [Qemu-devel] [PATCH 06/11] PPC64: Enable 64bit mode on interrupts Alexander Graf
@ 2009-03-06 15:36             ` Alexander Graf
  2009-03-06 15:36               ` [Qemu-devel] [PATCH 08/11] PPC64: Fix RFI(d) Alexander Graf
  0 siblings, 1 reply; 18+ messages in thread
From: Alexander Graf @ 2009-03-06 15:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: blauwirbel, Alexander Graf

Mtfsf can have the L bit set, so all the register contents get stored
in FPSCR. Linux uses it, so let's implement it.

Signed-off-by: Alexander Graf <alex@csgraf.de>
---
 target-ppc/translate.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index b5de33b..1ea3830 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2416,9 +2416,10 @@ GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
 }
 
 /* mtfsf */
-GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
+GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00010000, PPC_FLOAT)
 {
     TCGv_i32 t0;
+    int L = ctx->opcode & 0x02000000;
 
     if (unlikely(!ctx->fpu_enabled)) {
         gen_exception(ctx, POWERPC_EXCP_FPU);
@@ -2427,7 +2428,10 @@ GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
     /* NIP cannot be restored if the memory exception comes from an helper */
     gen_update_nip(ctx, ctx->nip - 4);
     gen_reset_fpstatus();
-    t0 = tcg_const_i32(FM(ctx->opcode));
+    if (L)
+        t0 = tcg_const_i32(0xff);
+    else
+        t0 = tcg_const_i32(FM(ctx->opcode));
     gen_helper_store_fpscr(cpu_fpr[rB(ctx->opcode)], t0);
     tcg_temp_free_i32(t0);
     if (unlikely(Rc(ctx->opcode) != 0)) {
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH 08/11] PPC64: Fix RFI(d)
  2009-03-06 15:36             ` [Qemu-devel] [PATCH 07/11] PPC64: Implement mtfsf.L encoding Alexander Graf
@ 2009-03-06 15:36               ` Alexander Graf
  2009-03-06 15:36                 ` [Qemu-devel] [PATCH 09/11] PPC64: Fix NX bit Alexander Graf
  0 siblings, 1 reply; 18+ messages in thread
From: Alexander Graf @ 2009-03-06 15:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: blauwirbel, Alexander Graf

The current implementation masks some MSR bits from SRR1 as it is
given on rfi(d). This looks pretty wrong and breaks Altivec.

Signed-off-by: Alexander Graf <alex@csgraf.de>
---
 target-ppc/op_helper.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 527f8de..d831aa9 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -1671,20 +1671,20 @@ static always_inline void do_rfi (target_ulong nip, target_ulong msr,
 void helper_rfi (void)
 {
     do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
-           ~((target_ulong)0xFFFF0000), 1);
+           ~((target_ulong)0x0), 1);
 }
 
 #if defined(TARGET_PPC64)
 void helper_rfid (void)
 {
     do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
-           ~((target_ulong)0xFFFF0000), 0);
+           ~((target_ulong)0x0), 0);
 }
 
 void helper_hrfid (void)
 {
     do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
-           ~((target_ulong)0xFFFF0000), 0);
+           ~((target_ulong)0x0), 0);
 }
 #endif
 #endif
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH 09/11] PPC64: Fix NX bit
  2009-03-06 15:36               ` [Qemu-devel] [PATCH 08/11] PPC64: Fix RFI(d) Alexander Graf
@ 2009-03-06 15:36                 ` Alexander Graf
  2009-03-06 15:36                   ` [Qemu-devel] [PATCH 10/11] PPC64: Keep SLB in-CPU Alexander Graf
  2009-03-06 19:31                   ` [Qemu-devel] [PATCH 09/11] PPC64: Fix NX bit Hollis Blanchard
  0 siblings, 2 replies; 18+ messages in thread
From: Alexander Graf @ 2009-03-06 15:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: blauwirbel, Alexander Graf

This patch fixes two issues with the NX bit:

1) The guarded bit has nothing to do with NX.
2) ctx->nx only got ORed, but never reset. So when one page in the
   lifetime of the VM was ever NX, all later pages were too.

Signed-off-by: Alexander Graf <alex@csgraf.de>
---
 target-ppc/helper.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 7fe3f8f..58b7fe2 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -226,8 +226,7 @@ static always_inline int _pte_check (mmu_ctx_t *ctx, int is_64b,
             ptem = pte0 & PTE64_PTEM_MASK;
             mmask = PTE64_CHECK_MASK;
             pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
-            ctx->nx |= (pte1 >> 2) & 1; /* No execute bit */
-            ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit    */
+            ctx->nx = (pte1 >> 2) & 1; /* No execute bit */
         } else
 #endif
         {
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH 10/11] PPC64: Keep SLB in-CPU
  2009-03-06 15:36                 ` [Qemu-devel] [PATCH 09/11] PPC64: Fix NX bit Alexander Graf
@ 2009-03-06 15:36                   ` Alexander Graf
  2009-03-06 15:36                     ` [Qemu-devel] [PATCH 11/11] PPC64: Disable BAT for 970 Alexander Graf
  2009-03-06 19:55                     ` [Qemu-devel] [PATCH 10/11] PPC64: Keep SLB in-CPU Hollis Blanchard
  2009-03-06 19:31                   ` [Qemu-devel] [PATCH 09/11] PPC64: Fix NX bit Hollis Blanchard
  1 sibling, 2 replies; 18+ messages in thread
From: Alexander Graf @ 2009-03-06 15:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: blauwirbel, Alexander Graf

Real 970 CPUs have the SLB not memory backed, but inside the CPU.
This breaks bridge mode for 970 for now, but at least keeps us from
overwriting physical addresses 0x0 - 0x300, rendering our interrupt
handlers useless.

I put in some stubs for bridge mode operation that could be enabled
easily, but for now it's safer to leave that off I guess (970fx doesn't
have bridge mode AFAIK).

Signed-off-by: Alexander Graf <alex@csgraf.de>
---
 target-ppc/cpu.h            |    7 ++
 target-ppc/helper.c         |  136 +++++++++++++++++++++++--------------------
 target-ppc/translate_init.c |    2 +-
 3 files changed, 81 insertions(+), 64 deletions(-)

diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index c88f81b..4a12dab 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -342,6 +342,12 @@ union ppc_tlb_t {
     ppcemb_tlb_t tlbe;
 };
 
+typedef struct ppc_slb_t ppc_slb_t;
+struct ppc_slb_t {
+    uint64_t tmp64;
+    uint32_t tmp;
+};
+
 /*****************************************************************************/
 /* Machine state register bits definition                                    */
 #define MSR_SF   63 /* Sixty-four-bit mode                            hflags */
@@ -582,6 +588,7 @@ struct CPUPPCState {
     /* Address space register */
     target_ulong asr;
     /* PowerPC 64 SLB area */
+    ppc_slb_t slb[64];
     int slb_nr;
 #endif
     /* segment registers */
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 58b7fe2..95958d4 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -692,14 +692,48 @@ static always_inline int find_pte (CPUState *env, mmu_ctx_t *ctx,
 }
 
 #if defined(TARGET_PPC64)
-static always_inline int slb_is_valid (uint64_t slb64)
+static ppc_slb_t *slb_get_entry(CPUPPCState *env, int nr)
+{
+    ppc_slb_t *retval = &env->slb[nr];
+#if 0 // XXX implement bridge mode?
+    if (bridge_mode) {
+        target_phys_addr_t sr_base = env->spr[SPR_ASR] + (12 * nr);
+        
+        retval->tmp64 = ldq_phys(sr_base);
+        retval->tmp = ldl_phys(sr_base + 8);
+    }
+#endif
+
+    return retval;
+}
+
+static void slb_set_entry(CPUPPCState *env, int nr, ppc_slb_t *slb)
+{
+    ppc_slb_t *entry = &env->slb[nr];
+
+#if 0 // XXX implement bridge mode?
+    if (bridge_mode) {
+        target_phys_addr_t sr_base = env->spr[SPR_ASR] + (12 * nr);
+        
+        stq_phys(sr_base, slb->tmp64);
+        stl_phys(sr_base + 8, slb->tmp);
+    } else
+#endif
+    if (slb == entry)
+        return;
+
+    entry->tmp64 = slb->tmp64;
+    entry->tmp = slb->tmp;
+}
+
+static always_inline int slb_is_valid (ppc_slb_t *slb)
 {
-    return slb64 & 0x0000000008000000ULL ? 1 : 0;
+    return (int)(slb->tmp64 & 0x0000000008000000ULL);
 }
 
-static always_inline void slb_invalidate (uint64_t *slb64)
+static always_inline void slb_invalidate (ppc_slb_t *slb)
 {
-    *slb64 &= ~0x0000000008000000ULL;
+    slb->tmp64 &= ~0x0000000008000000ULL;
 }
 
 static always_inline int slb_lookup (CPUPPCState *env, target_ulong eaddr,
@@ -707,25 +741,20 @@ static always_inline int slb_lookup (CPUPPCState *env, target_ulong eaddr,
                                      target_ulong *page_mask, int *attr,
                                      int *target_page_bits)
 {
-    target_phys_addr_t sr_base;
     target_ulong mask;
-    uint64_t tmp64;
-    uint32_t tmp;
     int n, ret;
 
     ret = -5;
-    sr_base = env->spr[SPR_ASR];
-    LOG_SLB("%s: eaddr " ADDRX " base " PADDRX "\n",
-                __func__, eaddr, sr_base);
+    LOG_SLB("%s: eaddr " ADDRX "\n", __func__, eaddr);
     mask = 0x0000000000000000ULL; /* Avoid gcc warning */
     for (n = 0; n < env->slb_nr; n++) {
-        tmp64 = ldq_phys(sr_base);
-        tmp = ldl_phys(sr_base + 8);
-        LOG_SLB("%s: seg %d " PADDRX " %016" PRIx64 " %08"
-                    PRIx32 "\n", __func__, n, sr_base, tmp64, tmp);
-        if (slb_is_valid(tmp64)) {
+        ppc_slb_t *slb = slb_get_entry(env, n);
+
+        LOG_SLB("%s: seg %d %016" PRIx64 " %08"
+                    PRIx32 "\n", __func__, n, slb->tmp64, slb->tmp);
+        if (slb_is_valid(slb)) {
             /* SLB entry is valid */
-            if (tmp & 0x8) {
+            if (slb->tmp & 0x8) {
                 /* 1 TB Segment */
                 mask = 0xFFFF000000000000ULL;
                 if (target_page_bits)
@@ -736,16 +765,15 @@ static always_inline int slb_lookup (CPUPPCState *env, target_ulong eaddr,
                 if (target_page_bits)
                     *target_page_bits = TARGET_PAGE_BITS;
             }
-            if ((eaddr & mask) == (tmp64 & mask)) {
+            if ((eaddr & mask) == (slb->tmp64 & mask)) {
                 /* SLB match */
-                *vsid = ((tmp64 << 24) | (tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;
+                *vsid = ((slb->tmp64 << 24) | (slb->tmp >> 8)) & 0x0003FFFFFFFFFFFFULL;
                 *page_mask = ~mask;
-                *attr = tmp & 0xFF;
+                *attr = slb->tmp & 0xFF;
                 ret = n;
                 break;
             }
         }
-        sr_base += 12;
     }
 
     return ret;
@@ -753,25 +781,22 @@ static always_inline int slb_lookup (CPUPPCState *env, target_ulong eaddr,
 
 void ppc_slb_invalidate_all (CPUPPCState *env)
 {
-    target_phys_addr_t sr_base;
-    uint64_t tmp64;
     int n, do_invalidate;
 
     do_invalidate = 0;
-    sr_base = env->spr[SPR_ASR];
     /* XXX: Warning: slbia never invalidates the first segment */
     for (n = 1; n < env->slb_nr; n++) {
-        tmp64 = ldq_phys(sr_base);
-        if (slb_is_valid(tmp64)) {
-            slb_invalidate(&tmp64);
-            stq_phys(sr_base, tmp64);
+        ppc_slb_t *slb = slb_get_entry(env, n);
+
+        if (slb_is_valid(slb)) {
+            slb_invalidate(slb);
+            slb_set_entry(env, n, slb);
             /* XXX: given the fact that segment size is 256 MB or 1TB,
              *      and we still don't have a tlb_flush_mask(env, n, mask)
              *      in Qemu, we just invalidate all TLBs
              */
             do_invalidate = 1;
         }
-        sr_base += 12;
     }
     if (do_invalidate)
         tlb_flush(env, 1);
@@ -779,20 +804,17 @@ void ppc_slb_invalidate_all (CPUPPCState *env)
 
 void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
 {
-    target_phys_addr_t sr_base;
     target_ulong vsid, page_mask;
-    uint64_t tmp64;
     int attr;
     int n;
 
     n = slb_lookup(env, T0, &vsid, &page_mask, &attr, NULL);
     if (n >= 0) {
-        sr_base = env->spr[SPR_ASR];
-        sr_base += 12 * n;
-        tmp64 = ldq_phys(sr_base);
-        if (slb_is_valid(tmp64)) {
-            slb_invalidate(&tmp64);
-            stq_phys(sr_base, tmp64);
+        ppc_slb_t *slb = slb_get_entry(env, n);
+
+        if (slb_is_valid(slb)) {
+            slb_invalidate(slb);
+            slb_set_entry(env, n, slb);
             /* XXX: given the fact that segment size is 256 MB or 1TB,
              *      and we still don't have a tlb_flush_mask(env, n, mask)
              *      in Qemu, we just invalidate all TLBs
@@ -804,36 +826,28 @@ void ppc_slb_invalidate_one (CPUPPCState *env, uint64_t T0)
 
 target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr)
 {
-    target_phys_addr_t sr_base;
     target_ulong rt;
-    uint64_t tmp64;
-    uint32_t tmp;
-
-    sr_base = env->spr[SPR_ASR];
-    sr_base += 12 * slb_nr;
-    tmp64 = ldq_phys(sr_base);
-    tmp = ldl_phys(sr_base + 8);
-    if (tmp64 & 0x0000000008000000ULL) {
+    ppc_slb_t *slb = slb_get_entry(env, slb_nr);
+
+    if (slb_is_valid(slb)) {
         /* SLB entry is valid */
         /* Copy SLB bits 62:88 to Rt 37:63 (VSID 23:49) */
-        rt = tmp >> 8;             /* 65:88 => 40:63 */
-        rt |= (tmp64 & 0x7) << 24; /* 62:64 => 37:39 */
+        rt = slb->tmp >> 8;             /* 65:88 => 40:63 */
+        rt |= (slb->tmp64 & 0x7) << 24; /* 62:64 => 37:39 */
         /* Copy SLB bits 89:92 to Rt 33:36 (KsKpNL) */
-        rt |= ((tmp >> 4) & 0xF) << 27;
+        rt |= ((slb->tmp >> 4) & 0xF) << 27;
     } else {
         rt = 0;
     }
-    LOG_SLB("%s: " PADDRX " %016" PRIx64 " %08" PRIx32 " => %d "
-                ADDRX "\n", __func__, sr_base, tmp64, tmp, slb_nr, rt);
+    LOG_SLB("%s: %016" PRIx64 " %08" PRIx32 " => %d "
+                ADDRX "\n", __func__, slb->tmp64, slb->tmp, slb_nr, rt);
 
     return rt;
 }
 
 void ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
 {
-    target_phys_addr_t sr_base;
-    uint64_t tmp64;
-    uint32_t tmp;
+    ppc_slb_t *slb;
 
     uint64_t vsid;
     uint64_t esid;
@@ -846,19 +860,15 @@ void ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs)
     valid = (rb & (1 << 27));
     slb_nr = rb & 0xfff;
 
-    tmp64 = (esid << 28) | valid | (vsid >> 24);
-    tmp = (vsid << 8) | (flags << 3);
-
-    /* Write SLB entry to memory */
-    sr_base = env->spr[SPR_ASR];
-    sr_base += 12 * slb_nr;
+    slb = slb_get_entry(env, slb_nr);
+    slb->tmp64 = (esid << 28) | valid | (vsid >> 24);
+    slb->tmp = (vsid << 8) | (flags << 3);
 
-    LOG_SLB("%s: %d " ADDRX " - " ADDRX " => " PADDRX " %016" PRIx64
+    LOG_SLB("%s: %d " ADDRX " - " ADDRX " => %016" PRIx64
                 " %08" PRIx32 "\n", __func__,
-                slb_nr, rb, rs, sr_base, tmp64, tmp);
+                slb_nr, rb, rs, tmp64, tmp);
 
-    stq_phys(sr_base, tmp64);
-    stl_phys(sr_base + 8, tmp);
+    slb_set_entry(env, slb_nr, slb);
 }
 #endif /* defined(TARGET_PPC64) */
 
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 42e62be..2fa6515 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -6056,7 +6056,7 @@ static void init_proc_970FX (CPUPPCState *env)
                  &spr_read_generic, &spr_write_generic,
                  0x00000000);
 #if !defined(CONFIG_USER_ONLY)
-    env->slb_nr = 32;
+    env->slb_nr = 64;
 #endif
     init_excp_970(env);
     env->dcache_line_size = 128;
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [Qemu-devel] [PATCH 11/11] PPC64: Disable BAT for 970
  2009-03-06 15:36                   ` [Qemu-devel] [PATCH 10/11] PPC64: Keep SLB in-CPU Alexander Graf
@ 2009-03-06 15:36                     ` Alexander Graf
  2009-03-06 19:55                     ` [Qemu-devel] [PATCH 10/11] PPC64: Keep SLB in-CPU Hollis Blanchard
  1 sibling, 0 replies; 18+ messages in thread
From: Alexander Graf @ 2009-03-06 15:36 UTC (permalink / raw)
  To: qemu-devel; +Cc: blauwirbel, Alexander Graf

The 970 doesn't know BAT, so let's not search BATs there.
This was only in as a hack for OpenHackWare so it would
work on PPC64.

Signed-off-by: Alexander Graf <alex@csgraf.de>
---
 target-ppc/helper.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 95958d4..e7923b4 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -1360,13 +1360,13 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
         case POWERPC_MMU_601:
         case POWERPC_MMU_SOFT_6xx:
         case POWERPC_MMU_SOFT_74xx:
+            /* Try to find a BAT */
+            if (env->nb_BATs != 0)
+                ret = get_bat(env, ctx, eaddr, rw, access_type);
 #if defined(TARGET_PPC64)
         case POWERPC_MMU_620:
         case POWERPC_MMU_64B:
 #endif
-            /* Try to find a BAT */
-            if (env->nb_BATs != 0)
-                ret = get_bat(env, ctx, eaddr, rw, access_type);
             if (ret < 0) {
                 /* We didn't match any BAT entry or don't have BATs */
                 ret = get_segment(env, ctx, eaddr, rw, access_type);
-- 
1.6.0.2

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH 09/11] PPC64: Fix NX bit
  2009-03-06 15:36                 ` [Qemu-devel] [PATCH 09/11] PPC64: Fix NX bit Alexander Graf
  2009-03-06 15:36                   ` [Qemu-devel] [PATCH 10/11] PPC64: Keep SLB in-CPU Alexander Graf
@ 2009-03-06 19:31                   ` Hollis Blanchard
  2009-03-06 19:41                     ` Alexander Graf
  1 sibling, 1 reply; 18+ messages in thread
From: Hollis Blanchard @ 2009-03-06 19:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: blauwirbel, Alexander Graf

On Fri, 2009-03-06 at 16:36 +0100, Alexander Graf wrote:
> This patch fixes two issues with the NX bit:
> 
> 1) The guarded bit has nothing to do with NX.

It turns out that instruction access is not allowed from mappings that
have either N *or* G bits set. (There are also N bits in the segment
entry; not sure how/if those are handled in this path.)

> 2) ctx->nx only got ORed, but never reset. So when one page in the
>    lifetime of the VM was ever NX, all later pages were too.
> 
> Signed-off-by: Alexander Graf <alex@csgraf.de>
> ---
>  target-ppc/helper.c |    3 +--
>  1 files changed, 1 insertions(+), 2 deletions(-)
> 
> diff --git a/target-ppc/helper.c b/target-ppc/helper.c
> index 7fe3f8f..58b7fe2 100644
> --- a/target-ppc/helper.c
> +++ b/target-ppc/helper.c
> @@ -226,8 +226,7 @@ static always_inline int _pte_check (mmu_ctx_t *ctx, int is_64b,
>              ptem = pte0 & PTE64_PTEM_MASK;
>              mmask = PTE64_CHECK_MASK;
>              pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
> -            ctx->nx |= (pte1 >> 2) & 1; /* No execute bit */
> -            ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit    */
> +            ctx->nx = (pte1 >> 2) & 1; /* No execute bit */
>          } else
>  #endif
>          {

-- 
Hollis Blanchard
IBM Linux Technology Center

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH 09/11] PPC64: Fix NX bit
  2009-03-06 19:31                   ` [Qemu-devel] [PATCH 09/11] PPC64: Fix NX bit Hollis Blanchard
@ 2009-03-06 19:41                     ` Alexander Graf
  0 siblings, 0 replies; 18+ messages in thread
From: Alexander Graf @ 2009-03-06 19:41 UTC (permalink / raw)
  To: Hollis Blanchard; +Cc: blauwirbel, qemu-devel


On 06.03.2009, at 20:31, Hollis Blanchard wrote:

> On Fri, 2009-03-06 at 16:36 +0100, Alexander Graf wrote:
>> This patch fixes two issues with the NX bit:
>>
>> 1) The guarded bit has nothing to do with NX.
>
> It turns out that instruction access is not allowed from mappings that
> have either N *or* G bits set. (There are also N bits in the segment
> entry; not sure how/if those are handled in this path.)

Oh, good to know.

Whoever applies this then, please keep the ORing for the guard  
bit :-). I don't think it's worth sending a new version here.

Alex

>
>
>> 2) ctx->nx only got ORed, but never reset. So when one page in the
>>   lifetime of the VM was ever NX, all later pages were too.
>>
>> Signed-off-by: Alexander Graf <alex@csgraf.de>
>> ---
>> target-ppc/helper.c |    3 +--
>> 1 files changed, 1 insertions(+), 2 deletions(-)
>>
>> diff --git a/target-ppc/helper.c b/target-ppc/helper.c
>> index 7fe3f8f..58b7fe2 100644
>> --- a/target-ppc/helper.c
>> +++ b/target-ppc/helper.c
>> @@ -226,8 +226,7 @@ static always_inline int _pte_check (mmu_ctx_t  
>> *ctx, int is_64b,
>>             ptem = pte0 & PTE64_PTEM_MASK;
>>             mmask = PTE64_CHECK_MASK;
>>             pp = (pte1 & 0x00000003) | ((pte1 >> 61) & 0x00000004);
>> -            ctx->nx |= (pte1 >> 2) & 1; /* No execute bit */
>> -            ctx->nx |= (pte1 >> 3) & 1; /* Guarded bit    */
>> +            ctx->nx = (pte1 >> 2) & 1; /* No execute bit */
>>         } else
>> #endif
>>         {
>
> -- 
> Hollis Blanchard
> IBM Linux Technology Center
>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [Qemu-devel] [PATCH 10/11] PPC64: Keep SLB in-CPU
  2009-03-06 15:36                   ` [Qemu-devel] [PATCH 10/11] PPC64: Keep SLB in-CPU Alexander Graf
  2009-03-06 15:36                     ` [Qemu-devel] [PATCH 11/11] PPC64: Disable BAT for 970 Alexander Graf
@ 2009-03-06 19:55                     ` Hollis Blanchard
  1 sibling, 0 replies; 18+ messages in thread
From: Hollis Blanchard @ 2009-03-06 19:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: blauwirbel, Alexander Graf

On Fri, 2009-03-06 at 16:36 +0100, Alexander Graf wrote:
> Real 970 CPUs have the SLB not memory backed, but inside the CPU.
> This breaks bridge mode for 970 for now, but at least keeps us from
> overwriting physical addresses 0x0 - 0x300, rendering our interrupt
> handlers useless.
> 
> I put in some stubs for bridge mode operation that could be enabled
> easily, but for now it's safer to leave that off I guess (970fx doesn't
> have bridge mode AFAIK).

The original code below is absolutely crazy. The architecture never
provided for hardware to write into memory like this in the first place.
In other words, the ifdefed "bridge" code should be removed with
prejudice.

For backwards compatibility, the architecture does allow for
implementations with an SLB to optionally do *lookups* in the (legacy)
segment table.

> diff --git a/target-ppc/helper.c b/target-ppc/helper.c
> index 58b7fe2..95958d4 100644
> --- a/target-ppc/helper.c
> +++ b/target-ppc/helper.c
> @@ -692,14 +692,48 @@ static always_inline int find_pte (CPUState *env, mmu_ctx_t *ctx,
...
> +static void slb_set_entry(CPUPPCState *env, int nr, ppc_slb_t *slb)
> +{
> +    ppc_slb_t *entry = &env->slb[nr];
> +
> +#if 0 // XXX implement bridge mode?
> +    if (bridge_mode) {
> +        target_phys_addr_t sr_base = env->spr[SPR_ASR] + (12 * nr);
> +        
> +        stq_phys(sr_base, slb->tmp64);
> +        stl_phys(sr_base + 8, slb->tmp);
> +    } else
> +#endif
> +    if (slb == entry)
> +        return;
> +
> +    entry->tmp64 = slb->tmp64;
> +    entry->tmp = slb->tmp;
> +}

-- 
Hollis Blanchard
IBM Linux Technology Center

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [Qemu-devel] Re: [PATCH 01/11] PPC64: Implement slbmte
  2009-03-06 15:35 ` [Qemu-devel] [PATCH 01/11] PPC64: Implement slbmte Alexander Graf
  2009-03-06 15:35   ` [Qemu-devel] [PATCH 02/11] PPC64: Implement large pages Alexander Graf
@ 2009-03-07  9:57   ` Blue Swirl
  2009-03-07 12:10     ` Alexander Graf
  1 sibling, 1 reply; 18+ messages in thread
From: Blue Swirl @ 2009-03-07  9:57 UTC (permalink / raw)
  To: Alexander Graf; +Cc: Alexander Graf, qemu-devel

On 3/6/09, Alexander Graf <agraf@suse.de> wrote:
> In order to modify SLB entries on recent PPC64 machines, the slbmte
>  instruction is used.

>   void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
>   {
>      LOG_MMU("%s: reg=%d " ADDRX " " ADDRX "\n",
>                  __func__, srnum, value, env->sr[srnum]);
>  -    if (env->sr[srnum] != value) {
>  +    if (env->mmu_model & POWERPC_MMU_64) {
>  +        uint64_t rb = 0, rs = 0;

This part does not compile because POWERPC_MMU_64 is not defined, is
the patch sequence correct?

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [Qemu-devel] Re: [PATCH 00/11] PPC64 Linux bringup patches v3
  2009-03-06 15:35 [Qemu-devel] [PATCH 00/11] PPC64 Linux bringup patches v3 Alexander Graf
  2009-03-06 15:35 ` [Qemu-devel] [PATCH 01/11] PPC64: Implement slbmte Alexander Graf
@ 2009-03-07 10:04 ` Blue Swirl
  1 sibling, 0 replies; 18+ messages in thread
From: Blue Swirl @ 2009-03-07 10:04 UTC (permalink / raw)
  To: Alexander Graf; +Cc: qemu-devel

On 3/6/09, Alexander Graf <agraf@suse.de> wrote:
> After spending even more time trying to get qemu-system-ppc64 to run Linux, I
>  get up to userspace now :-).
>
>  I am aware that this patchset is not 100% accurate and perfect for emulation,
>  but I think that it can't get worse than it is now.

Nice work. The patches in general look OK to me, though I could not
test them because of the problems with the first one.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [Qemu-devel] Re: [PATCH 01/11] PPC64: Implement slbmte
  2009-03-07  9:57   ` [Qemu-devel] Re: [PATCH 01/11] PPC64: Implement slbmte Blue Swirl
@ 2009-03-07 12:10     ` Alexander Graf
  0 siblings, 0 replies; 18+ messages in thread
From: Alexander Graf @ 2009-03-07 12:10 UTC (permalink / raw)
  To: Blue Swirl; +Cc: qemu-devel


On 07.03.2009, at 10:57, Blue Swirl wrote:

> On 3/6/09, Alexander Graf <agraf@suse.de> wrote:
>> In order to modify SLB entries on recent PPC64 machines, the slbmte
>> instruction is used.
>
>>  void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
>>  {
>>     LOG_MMU("%s: reg=%d " ADDRX " " ADDRX "\n",
>>                 __func__, srnum, value, env->sr[srnum]);
>> -    if (env->sr[srnum] != value) {
>> +    if (env->mmu_model & POWERPC_MMU_64) {
>> +        uint64_t rb = 0, rs = 0;
>
> This part does not compile because POWERPC_MMU_64 is not defined, is
> the patch sequence correct?

Eh - I guess it doesn't compile for ppc-softmmu (32 bit)? I used the  
patches with --target-list=ppc64-softmmu, so that's probably why.
I'll go and check what I did wrong to break ppc32 compilation (using a  
G4 in ppc64 emulation works) :-).

Alex

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2009-03-07 12:10 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-06 15:35 [Qemu-devel] [PATCH 00/11] PPC64 Linux bringup patches v3 Alexander Graf
2009-03-06 15:35 ` [Qemu-devel] [PATCH 01/11] PPC64: Implement slbmte Alexander Graf
2009-03-06 15:35   ` [Qemu-devel] [PATCH 02/11] PPC64: Implement large pages Alexander Graf
2009-03-06 15:35     ` [Qemu-devel] [PATCH 03/11] PPC64: Implment tlbiel Alexander Graf
2009-03-06 15:35       ` [Qemu-devel] [PATCH 04/11] Activate uninorth AGP bridge Alexander Graf
2009-03-06 15:35         ` [Qemu-devel] [PATCH 05/11] PPC64: Nop some SPRs on 970fx Alexander Graf
2009-03-06 15:36           ` [Qemu-devel] [PATCH 06/11] PPC64: Enable 64bit mode on interrupts Alexander Graf
2009-03-06 15:36             ` [Qemu-devel] [PATCH 07/11] PPC64: Implement mtfsf.L encoding Alexander Graf
2009-03-06 15:36               ` [Qemu-devel] [PATCH 08/11] PPC64: Fix RFI(d) Alexander Graf
2009-03-06 15:36                 ` [Qemu-devel] [PATCH 09/11] PPC64: Fix NX bit Alexander Graf
2009-03-06 15:36                   ` [Qemu-devel] [PATCH 10/11] PPC64: Keep SLB in-CPU Alexander Graf
2009-03-06 15:36                     ` [Qemu-devel] [PATCH 11/11] PPC64: Disable BAT for 970 Alexander Graf
2009-03-06 19:55                     ` [Qemu-devel] [PATCH 10/11] PPC64: Keep SLB in-CPU Hollis Blanchard
2009-03-06 19:31                   ` [Qemu-devel] [PATCH 09/11] PPC64: Fix NX bit Hollis Blanchard
2009-03-06 19:41                     ` Alexander Graf
2009-03-07  9:57   ` [Qemu-devel] Re: [PATCH 01/11] PPC64: Implement slbmte Blue Swirl
2009-03-07 12:10     ` Alexander Graf
2009-03-07 10:04 ` [Qemu-devel] Re: [PATCH 00/11] PPC64 Linux bringup patches v3 Blue Swirl

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.