qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 0/4] alpha-softmmu improvements
@ 2013-08-17  6:20 Richard Henderson
  2013-08-17  6:20 ` [Qemu-devel] [PULL 1/4] target-alpha: Implement call_pal without an exception Richard Henderson
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Richard Henderson @ 2013-08-17  6:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

No changes since the patch set was first posted, but rebased against head.


r~



The following changes since commit f202039811d8746b0586d2fd5f61de6c8cf68056:

  Open up 1.7 development branch (2013-08-15 15:41:13 -0500)

are available in the git repository at:

  git://github.com/rth7680/qemu.git axp-next

for you to fetch changes up to b83c4db89561e78ca5a1808329cbf937c6d75cc3:

  target-alpha: Implement the typhoon iommu (2013-08-16 11:17:23 -0700)

----------------------------------------------------------------
Richard Henderson (4):
      target-alpha: Implement call_pal without an exception
      target-alpha: Use goto_tb in call_pal
      target-alpha: Consider the superpage when threading and ending TBs
      target-alpha: Implement the typhoon iommu

 hw/alpha/typhoon.c        | 202 +++++++++++++++++++++++++++++++++++++++-------
 target-alpha/helper.h     |   2 +
 target-alpha/sys_helper.c |  17 ++++
 target-alpha/translate.c  |  82 ++++++++++++++++---
 4 files changed, 264 insertions(+), 39 deletions(-)

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

* [Qemu-devel] [PULL 1/4] target-alpha: Implement call_pal without an exception
  2013-08-17  6:20 [Qemu-devel] [PULL 0/4] alpha-softmmu improvements Richard Henderson
@ 2013-08-17  6:20 ` Richard Henderson
  2013-08-17  6:20 ` [Qemu-devel] [PULL 2/4] target-alpha: Use goto_tb in call_pal Richard Henderson
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Richard Henderson @ 2013-08-17  6:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

The destination of the call_pal, and the cpu state, is very predictable;
there's no need for exiting the cpu loop.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-alpha/helper.h     |  1 +
 target-alpha/sys_helper.c | 12 ++++++++++++
 target-alpha/translate.c  | 25 ++++++++++++++++++++++---
 3 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 0e425cf..5529c17 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -99,6 +99,7 @@ DEF_HELPER_FLAGS_2(ieee_input_cmp, TCG_CALL_NO_WG, void, env, i64)
 
 #if !defined (CONFIG_USER_ONLY)
 DEF_HELPER_2(hw_ret, void, env, i64)
+DEF_HELPER_3(call_pal, void, env, i64, i64)
 
 DEF_HELPER_1(ldl_phys, i64, i64)
 DEF_HELPER_1(ldq_phys, i64, i64)
diff --git a/target-alpha/sys_helper.c b/target-alpha/sys_helper.c
index bd94597..ce51ed6 100644
--- a/target-alpha/sys_helper.c
+++ b/target-alpha/sys_helper.c
@@ -51,6 +51,17 @@ void helper_hw_ret(CPUAlphaState *env, uint64_t a)
     }
 }
 
+void helper_call_pal(CPUAlphaState *env, uint64_t pc, uint64_t entry_ofs)
+{
+    int pal_mode = env->pal_mode;
+    env->exc_addr = pc | pal_mode;
+    env->pc = env->palbr + entry_ofs;
+    if (!pal_mode) {
+        env->pal_mode = 1;
+        swap_shadow_regs(env);
+    }
+}
+
 void helper_tbia(CPUAlphaState *env)
 {
     tlb_flush(env, 1);
@@ -91,4 +102,5 @@ void helper_set_alarm(CPUAlphaState *env, uint64_t expire)
         qemu_del_timer(cpu->alarm_timer);
     }
 }
+
 #endif /* CONFIG_USER_ONLY */
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 0efd559..59389a2 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1521,7 +1521,8 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
             tcg_gen_mov_i64(cpu_unique, cpu_ir[IR_A0]);
             break;
         default:
-            return gen_excp(ctx, EXCP_CALL_PAL, palcode & 0xbf);
+            palcode &= 0xbf;
+            goto do_call_pal;
         }
         return NO_EXIT;
     }
@@ -1586,13 +1587,31 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
             break;
 
         default:
-            return gen_excp(ctx, EXCP_CALL_PAL, palcode & 0x3f);
+            palcode &= 0x3f;
+            goto do_call_pal;
         }
         return NO_EXIT;
     }
 #endif
-
     return gen_invalid(ctx);
+
+ do_call_pal:
+#ifdef CONFIG_USER_ONLY
+    return gen_excp(ctx, EXCP_CALL_PAL, palcode);
+#else
+    {
+        TCGv pc = tcg_const_i64(ctx->pc);
+        TCGv entry = tcg_const_i64(palcode & 0x80
+                                   ? 0x2000 + (palcode - 0x80) * 64
+                                   : 0x1000 + palcode * 64);
+
+        gen_helper_call_pal(cpu_env, pc, entry);
+
+        tcg_temp_free(entry);
+        tcg_temp_free(pc);
+        return EXIT_PC_UPDATED;
+    }
+#endif
 }
 
 #ifndef CONFIG_USER_ONLY
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 2/4] target-alpha: Use goto_tb in call_pal
  2013-08-17  6:20 [Qemu-devel] [PULL 0/4] alpha-softmmu improvements Richard Henderson
  2013-08-17  6:20 ` [Qemu-devel] [PULL 1/4] target-alpha: Implement call_pal without an exception Richard Henderson
@ 2013-08-17  6:20 ` Richard Henderson
  2013-08-17  6:20 ` [Qemu-devel] [PULL 3/4] target-alpha: Consider the superpage when threading and ending TBs Richard Henderson
  2013-08-17  6:20 ` [Qemu-devel] [PULL 4/4] target-alpha: Implement the typhoon iommu Richard Henderson
  3 siblings, 0 replies; 5+ messages in thread
From: Richard Henderson @ 2013-08-17  6:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

With appropriate flushing when the PALBR changes, the target of
a CALL_PAL is so predictable we can chain to it.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-alpha/helper.h     |  1 +
 target-alpha/sys_helper.c |  5 +++++
 target-alpha/translate.c  | 20 ++++++++++++++++++++
 3 files changed, 26 insertions(+)

diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 5529c17..732b701 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -112,6 +112,7 @@ DEF_HELPER_3(stq_c_phys, i64, env, i64, i64)
 
 DEF_HELPER_FLAGS_1(tbia, TCG_CALL_NO_RWG, void, env)
 DEF_HELPER_FLAGS_2(tbis, TCG_CALL_NO_RWG, void, env, i64)
+DEF_HELPER_FLAGS_1(tb_flush, TCG_CALL_NO_RWG, void, env)
 
 DEF_HELPER_1(halt, void, i64);
 
diff --git a/target-alpha/sys_helper.c b/target-alpha/sys_helper.c
index ce51ed6..97cf9eb 100644
--- a/target-alpha/sys_helper.c
+++ b/target-alpha/sys_helper.c
@@ -72,6 +72,11 @@ void helper_tbis(CPUAlphaState *env, uint64_t p)
     tlb_flush_page(env, p);
 }
 
+void helper_tb_flush(CPUAlphaState *env)
+{
+    tb_flush(env);
+}
+
 void helper_halt(uint64_t restart)
 {
     if (restart) {
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 59389a2..f172670 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1609,6 +1609,17 @@ static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
 
         tcg_temp_free(entry);
         tcg_temp_free(pc);
+
+        /* Since the destination is running in PALmode, we don't really
+           need the page permissions check.  We'll see the existance of
+           the page when we create the TB, and we'll flush all TBs if
+           we change the PAL base register.  */
+        if (!ctx->singlestep_enabled && !(ctx->tb->cflags & CF_LAST_IO)) {
+            tcg_gen_goto_tb(0);
+            tcg_gen_exit_tb((tcg_target_long)ctx->tb);
+            return EXIT_GOTO_TB;
+        }
+
         return EXIT_PC_UPDATED;
     }
 #endif
@@ -1727,6 +1738,15 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
         gen_helper_set_alarm(cpu_env, tmp);
         break;
 
+    case 7:
+        /* PALBR */
+        tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUAlphaState, palbr));
+        /* Changing the PAL base register implies un-chaining all of the TBs
+           that ended with a CALL_PAL.  Since the base register usually only
+           changes during boot, flushing everything works well.  */
+        gen_helper_tb_flush(cpu_env);
+        return EXIT_PC_STALE;
+
     default:
         /* The basic registers are data only, and unknown registers
            are read-zero, write-ignore.  */
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 3/4] target-alpha: Consider the superpage when threading and ending TBs
  2013-08-17  6:20 [Qemu-devel] [PULL 0/4] alpha-softmmu improvements Richard Henderson
  2013-08-17  6:20 ` [Qemu-devel] [PULL 1/4] target-alpha: Implement call_pal without an exception Richard Henderson
  2013-08-17  6:20 ` [Qemu-devel] [PULL 2/4] target-alpha: Use goto_tb in call_pal Richard Henderson
@ 2013-08-17  6:20 ` Richard Henderson
  2013-08-17  6:20 ` [Qemu-devel] [PULL 4/4] target-alpha: Implement the typhoon iommu Richard Henderson
  3 siblings, 0 replies; 5+ messages in thread
From: Richard Henderson @ 2013-08-17  6:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

This allows significantly more threading, and occasionally larger TBs,
when processing code for the kernel and PALcode.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-alpha/translate.c | 37 +++++++++++++++++++++++++++++--------
 1 file changed, 29 insertions(+), 8 deletions(-)

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index f172670..309dea6 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -379,13 +379,26 @@ static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
 #endif
 }
 
-static int use_goto_tb(DisasContext *ctx, uint64_t dest)
+static bool in_superpage(DisasContext *ctx, int64_t addr)
 {
-    /* Check for the dest on the same page as the start of the TB.  We
-       also want to suppress goto_tb in the case of single-steping and IO.  */
-    return (((ctx->tb->pc ^ dest) & TARGET_PAGE_MASK) == 0
-            && !ctx->singlestep_enabled
-            && !(ctx->tb->cflags & CF_LAST_IO));
+    return ((ctx->tb->flags & TB_FLAGS_USER_MODE) == 0
+            && addr < 0
+            && ((addr >> 41) & 3) == 2
+            && addr >> TARGET_VIRT_ADDR_SPACE_BITS == addr >> 63);
+}
+
+static bool use_goto_tb(DisasContext *ctx, uint64_t dest)
+{
+    /* Suppress goto_tb in the case of single-steping and IO.  */
+    if (ctx->singlestep_enabled || (ctx->tb->cflags & CF_LAST_IO)) {
+        return false;
+    }
+    /* If the destination is in the superpage, the page perms can't change.  */
+    if (in_superpage(ctx, dest)) {
+        return true;
+    }
+    /* Check for the dest on the same page as the start of the TB.  */
+    return ((ctx->tb->pc ^ dest) & TARGET_PAGE_MASK) == 0;
 }
 
 static ExitStatus gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
@@ -3431,6 +3444,7 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
     CPUAlphaState *env = &cpu->env;
     DisasContext ctx, *ctxp = &ctx;
     target_ulong pc_start;
+    target_ulong pc_mask;
     uint32_t insn;
     uint16_t *gen_opc_end;
     CPUBreakpoint *bp;
@@ -3460,8 +3474,15 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
 
     num_insns = 0;
     max_insns = tb->cflags & CF_COUNT_MASK;
-    if (max_insns == 0)
+    if (max_insns == 0) {
         max_insns = CF_COUNT_MASK;
+    }
+
+    if (in_superpage(&ctx, pc_start)) {
+        pc_mask = (1ULL << 41) - 1;
+    } else {
+        pc_mask = ~TARGET_PAGE_MASK;
+    }
 
     gen_tb_start();
     do {
@@ -3499,7 +3520,7 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
         /* If we reach a page boundary, are single stepping,
            or exhaust instruction count, stop generation.  */
         if (ret == NO_EXIT
-            && ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0
+            && ((ctx.pc & pc_mask) == 0
                 || tcg_ctx.gen_opc_ptr >= gen_opc_end
                 || num_insns >= max_insns
                 || singlestep
-- 
1.8.1.4

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

* [Qemu-devel] [PULL 4/4] target-alpha: Implement the typhoon iommu
  2013-08-17  6:20 [Qemu-devel] [PULL 0/4] alpha-softmmu improvements Richard Henderson
                   ` (2 preceding siblings ...)
  2013-08-17  6:20 ` [Qemu-devel] [PULL 3/4] target-alpha: Consider the superpage when threading and ending TBs Richard Henderson
@ 2013-08-17  6:20 ` Richard Henderson
  3 siblings, 0 replies; 5+ messages in thread
From: Richard Henderson @ 2013-08-17  6:20 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 hw/alpha/typhoon.c | 202 +++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 174 insertions(+), 28 deletions(-)

diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c
index b7fb044..2450045 100644
--- a/hw/alpha/typhoon.c
+++ b/hw/alpha/typhoon.c
@@ -26,9 +26,9 @@ typedef struct TyphoonCchip {
 } TyphoonCchip;
 
 typedef struct TyphoonWindow {
-    uint32_t base_addr;
-    uint32_t mask;
-    uint32_t translated_base_pfn;
+    uint64_t wba;
+    uint64_t wsm;
+    uint64_t tba;
 } TyphoonWindow;
  
 typedef struct TyphoonPchip {
@@ -37,6 +37,10 @@ typedef struct TyphoonPchip {
     MemoryRegion reg_mem;
     MemoryRegion reg_io;
     MemoryRegion reg_conf;
+
+    AddressSpace iommu_as;
+    MemoryRegion iommu;
+
     uint64_t ctl;
     TyphoonWindow win[4];
 } TyphoonPchip;
@@ -209,53 +213,53 @@ static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size)
     switch (addr) {
     case 0x0000:
         /* WSBA0: Window Space Base Address Register.  */
-        ret = s->pchip.win[0].base_addr;
+        ret = s->pchip.win[0].wba;
         break;
     case 0x0040:
         /* WSBA1 */
-        ret = s->pchip.win[1].base_addr;
+        ret = s->pchip.win[1].wba;
         break;
     case 0x0080:
         /* WSBA2 */
-        ret = s->pchip.win[2].base_addr;
+        ret = s->pchip.win[2].wba;
         break;
     case 0x00c0:
         /* WSBA3 */
-        ret = s->pchip.win[3].base_addr;
+        ret = s->pchip.win[3].wba;
         break;
 
     case 0x0100:
         /* WSM0: Window Space Mask Register.  */
-        ret = s->pchip.win[0].mask;
+        ret = s->pchip.win[0].wsm;
         break;
     case 0x0140:
         /* WSM1 */
-        ret = s->pchip.win[1].mask;
+        ret = s->pchip.win[1].wsm;
         break;
     case 0x0180:
         /* WSM2 */
-        ret = s->pchip.win[2].mask;
+        ret = s->pchip.win[2].wsm;
         break;
     case 0x01c0:
         /* WSM3 */
-        ret = s->pchip.win[3].mask;
+        ret = s->pchip.win[3].wsm;
         break;
 
     case 0x0200:
         /* TBA0: Translated Base Address Register.  */
-        ret = (uint64_t)s->pchip.win[0].translated_base_pfn << 10;
+        ret = s->pchip.win[0].tba;
         break;
     case 0x0240:
         /* TBA1 */
-        ret = (uint64_t)s->pchip.win[1].translated_base_pfn << 10;
+        ret = s->pchip.win[1].tba;
         break;
     case 0x0280:
         /* TBA2 */
-        ret = (uint64_t)s->pchip.win[2].translated_base_pfn << 10;
+        ret = s->pchip.win[2].tba;
         break;
     case 0x02c0:
         /* TBA3 */
-        ret = (uint64_t)s->pchip.win[3].translated_base_pfn << 10;
+        ret = s->pchip.win[3].tba;
         break;
 
     case 0x0300:
@@ -458,53 +462,53 @@ static void pchip_write(void *opaque, hwaddr addr,
     switch (addr) {
     case 0x0000:
         /* WSBA0: Window Space Base Address Register.  */
-        s->pchip.win[0].base_addr = val;
+        s->pchip.win[0].wba = val & 0xfff00003u;
         break;
     case 0x0040:
         /* WSBA1 */
-        s->pchip.win[1].base_addr = val;
+        s->pchip.win[1].wba = val & 0xfff00003u;
         break;
     case 0x0080:
         /* WSBA2 */
-        s->pchip.win[2].base_addr = val;
+        s->pchip.win[2].wba = val & 0xfff00003u;
         break;
     case 0x00c0:
         /* WSBA3 */
-        s->pchip.win[3].base_addr = val;
+        s->pchip.win[3].wba = (val & 0x80fff00001ull) | 2;
         break;
 
     case 0x0100:
         /* WSM0: Window Space Mask Register.  */
-        s->pchip.win[0].mask = val;
+        s->pchip.win[0].wsm = val & 0xfff00000u;
         break;
     case 0x0140:
         /* WSM1 */
-        s->pchip.win[1].mask = val;
+        s->pchip.win[1].wsm = val & 0xfff00000u;
         break;
     case 0x0180:
         /* WSM2 */
-        s->pchip.win[2].mask = val;
+        s->pchip.win[2].wsm = val & 0xfff00000u;
         break;
     case 0x01c0:
         /* WSM3 */
-        s->pchip.win[3].mask = val;
+        s->pchip.win[3].wsm = val & 0xfff00000u;
         break;
 
     case 0x0200:
         /* TBA0: Translated Base Address Register.  */
-        s->pchip.win[0].translated_base_pfn = val >> 10;
+        s->pchip.win[0].tba = val & 0x7fffffc00ull;
         break;
     case 0x0240:
         /* TBA1 */
-        s->pchip.win[1].translated_base_pfn = val >> 10;
+        s->pchip.win[1].tba = val & 0x7fffffc00ull;
         break;
     case 0x0280:
         /* TBA2 */
-        s->pchip.win[2].translated_base_pfn = val >> 10;
+        s->pchip.win[2].tba = val & 0x7fffffc00ull;
         break;
     case 0x02c0:
         /* TBA3 */
-        s->pchip.win[3].translated_base_pfn = val >> 10;
+        s->pchip.win[3].tba = val & 0x7fffffc00ull;
         break;
 
     case 0x0300:
@@ -512,7 +516,6 @@ static void pchip_write(void *opaque, hwaddr addr,
         oldval = s->pchip.ctl;
         oldval &= ~0x00001cff0fc7ffull;       /* RW fields */
         oldval |= val & 0x00001cff0fc7ffull;
-
         s->pchip.ctl = oldval;
         break;
 
@@ -593,6 +596,140 @@ static const MemoryRegionOps pchip_ops = {
     },
 };
 
+/* A subroutine of typhoon_translate_iommu that builds an IOMMUTLBEntry
+   using the given translated address and mask.  */
+static bool make_iommu_tlbe(hwaddr taddr, hwaddr mask, IOMMUTLBEntry *ret)
+{
+    *ret = (IOMMUTLBEntry) {
+        .target_as = &address_space_memory,
+        .translated_addr = taddr,
+        .addr_mask = mask,
+        .perm = IOMMU_RW,
+    };
+    return true;
+}
+
+/* A subroutine of typhoon_translate_iommu that handles scatter-gather
+   translation, given the address of the PTE.  */
+static bool pte_translate(hwaddr pte_addr, IOMMUTLBEntry *ret)
+{
+    uint64_t pte = ldq_phys(pte_addr);
+
+    /* Check valid bit.  */
+    if ((pte & 1) == 0) {
+        return false;
+    }
+
+    return make_iommu_tlbe((pte & 0x3ffffe) << 12, 0x1fff, ret);
+}
+
+/* A subroutine of typhoon_translate_iommu that handles one of the
+   four single-address-cycle translation windows.  */
+static bool window_translate(TyphoonWindow *win, hwaddr addr,
+                             IOMMUTLBEntry *ret)
+{
+    uint32_t wba = win->wba;
+    uint64_t wsm = win->wsm;
+    uint64_t tba = win->tba;
+    uint64_t wsm_ext = wsm | 0xfffff;
+
+    /* Check for window disabled.  */
+    if ((wba & 1) == 0) {
+        return false;
+    }
+
+    /* Check for window hit.  */
+    if ((addr & ~wsm_ext) != (wba & 0xfff00000u)) {
+        return false;
+    }
+
+    if (wba & 2) {
+        /* Scatter-gather translation.  */
+        hwaddr pte_addr;
+
+        /* See table 10-6, Generating PTE address for PCI DMA Address.  */
+        pte_addr  = tba & ~(wsm >> 10);
+        pte_addr |= (addr & (wsm | 0xfe000)) >> 10;
+        return pte_translate(pte_addr, ret);
+    } else {
+	/* Direct-mapped translation.  */
+	return make_iommu_tlbe(tba & ~wsm_ext, wsm_ext, ret);
+    }
+}
+
+/* Handle PCI-to-system address translation.  */
+/* TODO: A translation failure here ought to set PCI error codes on the
+   Pchip and generate a machine check interrupt.  */
+static IOMMUTLBEntry typhoon_translate_iommu(MemoryRegion *iommu, hwaddr addr)
+{
+    TyphoonPchip *pchip = container_of(iommu, TyphoonPchip, iommu);
+    IOMMUTLBEntry ret;
+    int i;
+
+    if (addr <= 0xffffffffu) {
+        /* Single-address cycle.  */
+
+        /* Check for the Window Hole, inhibiting matching.  */
+        if ((pchip->ctl & 0x20)
+            && addr >= 0x80000
+            && addr <= 0xfffff) {
+            goto failure;
+        }
+
+        /* Check the first three windows.  */
+        for (i = 0; i < 3; ++i) {
+            if (window_translate(&pchip->win[i], addr, &ret)) {
+                goto success;
+            }
+        }
+
+        /* Check the fourth window for DAC disable.  */
+        if ((pchip->win[3].wba & 0x80000000000ull) == 0
+	    && window_translate(&pchip->win[3], addr, &ret)) {
+            goto success;
+        }
+    } else {
+        /* Double-address cycle.  */
+
+        if (addr >= 0x10000000000ull && addr < 0x20000000000ull) {
+            /* Check for the DMA monster window.  */
+            if (pchip->ctl & 0x40) {
+                /* See 10.1.4.4; in particular <39:35> is ignored.  */
+                make_iommu_tlbe(0, 0x007ffffffffull, &ret);
+		goto success;
+            }
+        }
+
+        if (addr >= 0x80000000000 && addr <= 0xfffffffffff) {
+            /* Check the fourth window for DAC enable and window enable.  */
+            if ((pchip->win[3].wba & 0x80000000001ull) == 0x80000000001ull) {
+                uint64_t pte_addr;
+
+                pte_addr  = pchip->win[3].tba & 0x7ffc00000ull;
+                pte_addr |= (addr & 0xffffe000u) >> 10;
+                if (pte_translate(pte_addr, &ret)) {
+			goto success;
+		}
+            }
+        }
+    }
+
+ failure:
+    ret = (IOMMUTLBEntry) { .perm = IOMMU_NONE };
+ success:
+    return ret;
+}
+
+static const MemoryRegionIOMMUOps typhoon_iommu_ops = {
+    .translate = typhoon_translate_iommu,
+};
+
+static AddressSpace *typhoon_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
+{
+    TyphoonState *s = opaque;
+    return &s->pchip.iommu_as;
+}
+
 static void typhoon_set_irq(void *opaque, int irq, int level)
 {
     TyphoonState *s = opaque;
@@ -688,6 +825,9 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
     s = TYPHOON_PCI_HOST_BRIDGE(dev);
     phb = PCI_HOST_BRIDGE(dev);
 
+    s->cchip.misc = 0x800000000ull; /* Revision: Typhoon.  */
+    s->pchip.win[3].wba = 2;        /* Window 3 SG always enabled. */
+
     /* Remember the CPUs so that we can deliver interrupts to them.  */
     for (i = 0; i < 4; i++) {
         AlphaCPU *cpu = cpus[i];
@@ -746,6 +886,12 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
                          0, 64, TYPE_PCI_BUS);
     phb->bus = b;
 
+    /* Host memory as seen from the PCI side, via the IOMMU.  */
+    memory_region_init_iommu(&s->pchip.iommu, OBJECT(s), &typhoon_iommu_ops,
+                             "iommu-typhoon", UINT64_MAX);
+    address_space_init(&s->pchip.iommu_as, &s->pchip.iommu, "pchip0-pci");
+    pci_setup_iommu(b, typhoon_pci_dma_iommu, s);
+
     /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB.  */
     memory_region_init_io(&s->pchip.reg_iack, OBJECT(s), &alpha_pci_iack_ops,
                           b, "pci0-iack", 64*MB);
-- 
1.8.1.4

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

end of thread, other threads:[~2013-08-17  6:21 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-17  6:20 [Qemu-devel] [PULL 0/4] alpha-softmmu improvements Richard Henderson
2013-08-17  6:20 ` [Qemu-devel] [PULL 1/4] target-alpha: Implement call_pal without an exception Richard Henderson
2013-08-17  6:20 ` [Qemu-devel] [PULL 2/4] target-alpha: Use goto_tb in call_pal Richard Henderson
2013-08-17  6:20 ` [Qemu-devel] [PULL 3/4] target-alpha: Consider the superpage when threading and ending TBs Richard Henderson
2013-08-17  6:20 ` [Qemu-devel] [PULL 4/4] target-alpha: Implement the typhoon iommu Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).