qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/20]: add alpha es40 system emulation (v4)
@ 2009-03-30 14:36 Tristan Gingold
  2009-03-30 14:36 ` [Qemu-devel] [PATCH 01/19] Add support for multi-level phys map Tristan Gingold
  2009-03-30 15:46 ` [Qemu-devel] [PATCH 0/20]: add alpha es40 system emulation (v4) Brian Wheeler
  0 siblings, 2 replies; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

new version of alpha system emulation.

I have followed Paul Brook's advice and now patch 02 has only one code paths.
For 32 bits address spaces the code looks equivalent to the current one.
For address spaces lager than 32 bits, only the size of level may have
changed.

I have also fixed the comment (thanks to Aurelien) in path 05.

Two new bugs in alpha tcg code have been fixed (see pathes 07 and 08)

Some bugs have also been fixed in system emulation code.  I am making
progress...  With some additionnal patches, I can now run AlphaBIOS.

Comments and reviews are welcome,
Tristan.

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

* [Qemu-devel] [PATCH 01/19] Add support for multi-level phys map.
  2009-03-30 14:36 [Qemu-devel] [PATCH 0/20]: add alpha es40 system emulation (v4) Tristan Gingold
@ 2009-03-30 14:36 ` Tristan Gingold
  2009-03-30 14:36   ` [Qemu-devel] [PATCH 02/19] Increase Alpha physical address size to 44 bits Tristan Gingold
  2009-04-15 16:23   ` [Qemu-devel] [PATCH 01/19] Add support for multi-level phys map Aurelien Jarno
  2009-03-30 15:46 ` [Qemu-devel] [PATCH 0/20]: add alpha es40 system emulation (v4) Brian Wheeler
  1 sibling, 2 replies; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

As Alpha physical addresses are 44 bits, l1_phys_map can't be anymore 2 levels.
Use a more generic multi-level approach and explain why we don't need to
extend l1_map.

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 exec.c |   50 ++++++++++++++++++++++++++------------------------
 1 files changed, 26 insertions(+), 24 deletions(-)

diff --git a/exec.c b/exec.c
index df22c79..4b2ebc2 100644
--- a/exec.c
+++ b/exec.c
@@ -147,15 +147,14 @@ typedef struct PhysPageDesc {
 } PhysPageDesc;
 
 #define L2_BITS 10
-#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
-/* XXX: this is a temporary hack for alpha target.
- *      In the future, this is to be replaced by a multi-level table
- *      to actually be able to handle the complete 64 bits address space.
- */
-#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
+
+#define L1_BITS_ ((TARGET_PHYS_ADDR_SPACE_BITS - TARGET_PAGE_BITS) % L2_BITS)
+#if L1_BITS_ < 4 /* avoid ridiculous small l1 */
+#define L1_BITS (L1_BITS_ + L2_BITS)
 #else
-#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
+#define L1_BITS L1_BITS_
 #endif
+#define L1_SHIFT (TARGET_PHYS_ADDR_SPACE_BITS - TARGET_PAGE_BITS - L1_BITS)
 
 #define L1_SIZE (1 << L1_BITS)
 #define L2_SIZE (1 << L2_BITS)
@@ -165,7 +164,9 @@ unsigned long qemu_host_page_bits;
 unsigned long qemu_host_page_size;
 unsigned long qemu_host_page_mask;
 
-/* XXX: for system emulation, it could just be an array */
+/* XXX: for system emulation, it could just be an array.  As this is currently
+   a two level map this limits the size of RAM memory that can contains
+   target code.  In practice this is large enough (>= 4GB) */
 static PageDesc *l1_map[L1_SIZE];
 static PhysPageDesc **l1_phys_map;
 
@@ -338,25 +339,26 @@ static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
 {
     void **lp, **p;
     PhysPageDesc *pd;
+    int i;
 
+    /* Level 1.  */
     p = (void **)l1_phys_map;
-#if TARGET_PHYS_ADDR_SPACE_BITS > 32
+    lp = p + ((index >> L1_SHIFT) & (L1_SIZE - 1));
 
-#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
-#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
-#endif
-    lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
-    p = *lp;
-    if (!p) {
-        /* allocate if not found */
-        if (!alloc)
-            return NULL;
-        p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
-        memset(p, 0, sizeof(void *) * L1_SIZE);
-        *lp = p;
+    /* Level 2..n-1 */
+    for (i = (L1_SHIFT / L2_BITS) - 1; i > 0; i--) {
+        p = *lp;
+        if (!p) {
+            /* allocate if not found */
+            if (!alloc)
+                return NULL;
+            p = qemu_vmalloc(sizeof(void *) * L2_SIZE);
+            memset(p, 0, sizeof(void *) * L2_SIZE);
+            *lp = p;
+        }
+        lp = p + ((index >> (i * L2_BITS)) & (L2_SIZE - 1));
     }
-#endif
-    lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
+
     pd = *lp;
     if (!pd) {
         int i;
-- 
1.6.2

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

* [Qemu-devel] [PATCH 02/19] Increase Alpha physical address size to 44 bits.
  2009-03-30 14:36 ` [Qemu-devel] [PATCH 01/19] Add support for multi-level phys map Tristan Gingold
@ 2009-03-30 14:36   ` Tristan Gingold
  2009-03-30 14:36     ` [Qemu-devel] [PATCH 03/19] Alpha: set target page size to 13 bits Tristan Gingold
  2009-04-15 16:23   ` [Qemu-devel] [PATCH 01/19] Add support for multi-level phys map Aurelien Jarno
  1 sibling, 1 reply; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

Remove unused target virt addr.

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 exec.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/exec.c b/exec.c
index 4b2ebc2..5dc6bc7 100644
--- a/exec.c
+++ b/exec.c
@@ -68,8 +68,7 @@
 #elif defined(TARGET_SPARC)
 #define TARGET_PHYS_ADDR_SPACE_BITS 36
 #elif defined(TARGET_ALPHA)
-#define TARGET_PHYS_ADDR_SPACE_BITS 42
-#define TARGET_VIRT_ADDR_SPACE_BITS 42
+#define TARGET_PHYS_ADDR_SPACE_BITS 44
 #elif defined(TARGET_PPC64)
 #define TARGET_PHYS_ADDR_SPACE_BITS 42
 #elif defined(TARGET_X86_64) && !defined(USE_KQEMU)
-- 
1.6.2

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

* [Qemu-devel] [PATCH 03/19] Alpha: set target page size to 13 bits.
  2009-03-30 14:36   ` [Qemu-devel] [PATCH 02/19] Increase Alpha physical address size to 44 bits Tristan Gingold
@ 2009-03-30 14:36     ` Tristan Gingold
  2009-03-30 14:36       ` [Qemu-devel] [PATCH 04/19] Allow 5 mmu indexes Tristan Gingold
  2009-04-07 21:47       ` [Qemu-devel] [PATCH 03/19] Alpha: set target page size to 13 bits Aurelien Jarno
  0 siblings, 2 replies; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

(As defined by the alpha arch ref).

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 target-alpha/cpu.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index a9f1c0f..582827e 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -40,7 +40,7 @@
 #define ICACHE_LINE_SIZE 32
 #define DCACHE_LINE_SIZE 32
 
-#define TARGET_PAGE_BITS 12
+#define TARGET_PAGE_BITS 13
 
 #define VA_BITS 43
 
-- 
1.6.2

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

* [Qemu-devel] [PATCH 04/19] Allow 5 mmu indexes.
  2009-03-30 14:36     ` [Qemu-devel] [PATCH 03/19] Alpha: set target page size to 13 bits Tristan Gingold
@ 2009-03-30 14:36       ` Tristan Gingold
  2009-03-30 14:36         ` [Qemu-devel] [PATCH 05/19] Split cpu_mmu_index into cpu_mmu_index_data and cpu_mmu_index_code Tristan Gingold
  2009-04-07 21:48         ` [Qemu-devel] [PATCH 04/19] Allow 5 mmu indexes Aurelien Jarno
  2009-04-07 21:47       ` [Qemu-devel] [PATCH 03/19] Alpha: set target page size to 13 bits Aurelien Jarno
  1 sibling, 2 replies; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

This is necessary for alpha because it has 4 protection levels and pal mode.

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 exec.c         |   30 +++++++++++++++++++++++++-----
 softmmu_exec.h |   29 ++++++++++++++++++++++++-----
 2 files changed, 49 insertions(+), 10 deletions(-)

diff --git a/exec.c b/exec.c
index 5dc6bc7..7c2def0 100644
--- a/exec.c
+++ b/exec.c
@@ -1736,12 +1736,18 @@ void tlb_flush(CPUState *env, int flush_global)
         env->tlb_table[2][i].addr_read = -1;
         env->tlb_table[2][i].addr_write = -1;
         env->tlb_table[2][i].addr_code = -1;
-#if (NB_MMU_MODES == 4)
+#endif
+#if (NB_MMU_MODES >= 4)
         env->tlb_table[3][i].addr_read = -1;
         env->tlb_table[3][i].addr_write = -1;
         env->tlb_table[3][i].addr_code = -1;
 #endif
+#if (NB_MMU_MODES >= 5)
+        env->tlb_table[4][i].addr_read = -1;
+        env->tlb_table[4][i].addr_write = -1;
+        env->tlb_table[4][i].addr_code = -1;
 #endif
+
     }
 
     memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
@@ -1785,9 +1791,12 @@ void tlb_flush_page(CPUState *env, target_ulong addr)
     tlb_flush_entry(&env->tlb_table[1][i], addr);
 #if (NB_MMU_MODES >= 3)
     tlb_flush_entry(&env->tlb_table[2][i], addr);
-#if (NB_MMU_MODES == 4)
+#endif
+#if (NB_MMU_MODES >= 4)
     tlb_flush_entry(&env->tlb_table[3][i], addr);
 #endif
+#if (NB_MMU_MODES >= 5)
+    tlb_flush_entry(&env->tlb_table[4][i], addr);
 #endif
 
     tlb_flush_jmp_cache(env, addr);
@@ -1871,10 +1880,14 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
 #if (NB_MMU_MODES >= 3)
         for(i = 0; i < CPU_TLB_SIZE; i++)
             tlb_reset_dirty_range(&env->tlb_table[2][i], start1, length);
-#if (NB_MMU_MODES == 4)
+#endif
+#if (NB_MMU_MODES >= 4)
         for(i = 0; i < CPU_TLB_SIZE; i++)
             tlb_reset_dirty_range(&env->tlb_table[3][i], start1, length);
 #endif
+#if (NB_MMU_MODES >= 5)
+        for(i = 0; i < CPU_TLB_SIZE; i++)
+            tlb_reset_dirty_range(&env->tlb_table[4][i], start1, length);
 #endif
     }
 }
@@ -1920,10 +1933,14 @@ void cpu_tlb_update_dirty(CPUState *env)
 #if (NB_MMU_MODES >= 3)
     for(i = 0; i < CPU_TLB_SIZE; i++)
         tlb_update_dirty(&env->tlb_table[2][i]);
-#if (NB_MMU_MODES == 4)
+#endif
+#if (NB_MMU_MODES >= 4)
     for(i = 0; i < CPU_TLB_SIZE; i++)
         tlb_update_dirty(&env->tlb_table[3][i]);
 #endif
+#if (NB_MMU_MODES >= 5)
+    for(i = 0; i < CPU_TLB_SIZE; i++)
+        tlb_update_dirty(&env->tlb_table[4][i]);
 #endif
 }
 
@@ -1945,9 +1962,12 @@ static inline void tlb_set_dirty(CPUState *env, target_ulong vaddr)
     tlb_set_dirty1(&env->tlb_table[1][i], vaddr);
 #if (NB_MMU_MODES >= 3)
     tlb_set_dirty1(&env->tlb_table[2][i], vaddr);
-#if (NB_MMU_MODES == 4)
+#endif
+#if (NB_MMU_MODES >= 4)
     tlb_set_dirty1(&env->tlb_table[3][i], vaddr);
 #endif
+#if (NB_MMU_MODES >= 5)
+    tlb_set_dirty1(&env->tlb_table[4][i], vaddr);
 #endif
 }
 
diff --git a/softmmu_exec.h b/softmmu_exec.h
index 9cc4535..a43e621 100644
--- a/softmmu_exec.h
+++ b/softmmu_exec.h
@@ -60,6 +60,7 @@
 #include "softmmu_header.h"
 #undef ACCESS_TYPE
 #undef MEMSUFFIX
+#endif /* (NB_MMU_MODES >= 3) */
 
 #if (NB_MMU_MODES >= 4)
 
@@ -78,12 +79,30 @@
 #include "softmmu_header.h"
 #undef ACCESS_TYPE
 #undef MEMSUFFIX
+#endif /* (NB_MMU_MODES >= 4) */
 
-#if (NB_MMU_MODES > 4)
-#error "NB_MMU_MODES > 4 is not supported for now"
-#endif /* (NB_MMU_MODES > 4) */
-#endif /* (NB_MMU_MODES == 4) */
-#endif /* (NB_MMU_MODES >= 3) */
+#if (NB_MMU_MODES >= 5)
+
+#define ACCESS_TYPE 4
+#define MEMSUFFIX MMU_MODE4_SUFFIX
+#define DATA_SIZE 1
+#include "softmmu_header.h"
+
+#define DATA_SIZE 2
+#include "softmmu_header.h"
+
+#define DATA_SIZE 4
+#include "softmmu_header.h"
+
+#define DATA_SIZE 8
+#include "softmmu_header.h"
+#undef ACCESS_TYPE
+#undef MEMSUFFIX
+#endif /* (NB_MMU_MODES >= 5) */
+
+#if (NB_MMU_MODES > 5)
+#error "NB_MMU_MODES > 5 is not supported for now"
+#endif /* (NB_MMU_MODES > 5) */
 
 /* these access are slower, they must be as rare as possible */
 #define ACCESS_TYPE (NB_MMU_MODES)
-- 
1.6.2

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

* [Qemu-devel] [PATCH 05/19] Split cpu_mmu_index into cpu_mmu_index_data and cpu_mmu_index_code.
  2009-03-30 14:36       ` [Qemu-devel] [PATCH 04/19] Allow 5 mmu indexes Tristan Gingold
@ 2009-03-30 14:36         ` Tristan Gingold
  2009-03-30 14:36           ` [Qemu-devel] [PATCH 06/19] Bug fix alpha: stop translation if too long Tristan Gingold
  2009-04-15 14:30           ` [Qemu-devel] [PATCH 05/19] Split cpu_mmu_index into cpu_mmu_index_data and cpu_mmu_index_code Aurelien Jarno
  2009-04-07 21:48         ` [Qemu-devel] [PATCH 04/19] Allow 5 mmu indexes Aurelien Jarno
  1 sibling, 2 replies; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

This is required by alpha system emulation as PAL mode disable instruction
mmu but not data mmu.
This might also be required for other cpus that have a split I/D mmu enable.

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 exec-all.h               |    2 +-
 softmmu_header.h         |    4 ++--
 target-alpha/cpu.h       |   13 +++++++++++--
 target-alpha/op_helper.c |    4 ++--
 target-arm/cpu.h         |    3 ++-
 target-cris/cpu.h        |    3 ++-
 target-cris/translate.c  |    6 +++---
 target-i386/cpu.h        |    3 ++-
 target-m68k/cpu.h        |    3 ++-
 target-mips/cpu.h        |    3 ++-
 target-ppc/cpu.h         |    3 ++-
 target-sh4/cpu.h         |    3 ++-
 target-sparc/cpu.h       |    3 ++-
 target-sparc/translate.c |    2 +-
 14 files changed, 36 insertions(+), 19 deletions(-)

diff --git a/exec-all.h b/exec-all.h
index 143aca1..a661cb1 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -318,7 +318,7 @@ static inline target_ulong get_phys_addr_code(CPUState *env1, target_ulong addr)
     int mmu_idx, page_index, pd;
 
     page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
-    mmu_idx = cpu_mmu_index(env1);
+    mmu_idx = cpu_mmu_index_code(env1);
     if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code !=
                  (addr & TARGET_PAGE_MASK))) {
         ldub_code(addr);
diff --git a/softmmu_header.h b/softmmu_header.h
index a1b3808..f6f83da 100644
--- a/softmmu_header.h
+++ b/softmmu_header.h
@@ -46,12 +46,12 @@
 
 #elif ACCESS_TYPE == (NB_MMU_MODES)
 
-#define CPU_MMU_INDEX (cpu_mmu_index(env))
+#define CPU_MMU_INDEX (cpu_mmu_index_data(env))
 #define MMUSUFFIX _mmu
 
 #elif ACCESS_TYPE == (NB_MMU_MODES + 1)
 
-#define CPU_MMU_INDEX (cpu_mmu_index(env))
+#define CPU_MMU_INDEX (cpu_mmu_index_code(env))
 #define MMUSUFFIX _cmmu
 
 #else
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 582827e..3798157 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -331,16 +331,25 @@ struct CPUAlphaState {
 #define cpu_exec cpu_alpha_exec
 #define cpu_gen_code cpu_alpha_gen_code
 #define cpu_signal_handler cpu_alpha_signal_handler
+#define cpu_list alpha_cpu_list
 
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
 #define MMU_MODE1_SUFFIX _executive
 #define MMU_MODE2_SUFFIX _supervisor
 #define MMU_MODE3_SUFFIX _user
+#define MMU_MODE4_SUFFIX _pal
+#define MMU_KERNEL_IDX 0
 #define MMU_USER_IDX 3
-static inline int cpu_mmu_index (CPUState *env)
+#define MMU_PAL_IDX 4
+static inline int cpu_mmu_index_data (CPUState *env)
 {
-    return (env->ps >> 3) & 3;
+    return env->mmu_data_index;
+}
+
+static inline int cpu_mmu_index_code (CPUState *env)
+{
+    return env->mmu_code_index;
 }
 
 #if defined(CONFIG_USER_ONLY)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 7ad1b3d..433a0da 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1049,7 +1049,7 @@ uint64_t helper_ld_virt_to_phys (uint64_t virtaddr)
     int index, mmu_idx;
     void *retaddr;
 
-    mmu_idx = cpu_mmu_index(env);
+    mmu_idx = cpu_mmu_index_data(env);
     index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  redo:
     tlb_addr = env->tlb_table[mmu_idx][index].addr_read;
@@ -1071,7 +1071,7 @@ uint64_t helper_st_virt_to_phys (uint64_t virtaddr)
     int index, mmu_idx;
     void *retaddr;
 
-    mmu_idx = cpu_mmu_index(env);
+    mmu_idx = cpu_mmu_index_data(env);
     index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  redo:
     tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index f98655f..c0cfb8d 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -412,7 +412,8 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 #define MMU_MODE0_SUFFIX _kernel
 #define MMU_MODE1_SUFFIX _user
 #define MMU_USER_IDX 1
-static inline int cpu_mmu_index (CPUState *env)
+#define cpu_mmu_index_data cpu_mmu_index_code
+static inline int cpu_mmu_index_code (CPUState *env)
 {
     return (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR ? 1 : 0;
 }
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index e98a48d..807a55a 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -212,7 +212,8 @@ enum {
 #define MMU_MODE0_SUFFIX _kernel
 #define MMU_MODE1_SUFFIX _user
 #define MMU_USER_IDX 1
-static inline int cpu_mmu_index (CPUState *env)
+#define cpu_mmu_index_data cpu_mmu_index_code
+static inline int cpu_mmu_index_code (CPUState *env)
 {
 	return !!(env->pregs[PR_CCS] & U_FLAG);
 }
diff --git a/target-cris/translate.c b/target-cris/translate.c
index d5fcb9e..20699e9 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -1104,7 +1104,7 @@ static inline void cris_prepare_jmp (DisasContext *dc, unsigned int type)
 
 static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr)
 {
-	int mem_index = cpu_mmu_index(dc->env);
+	int mem_index = cpu_mmu_index_data(dc->env);
 
 	/* If we get a fault on a delayslot we must keep the jmp state in
 	   the cpu-state to be able to re-execute the jmp.  */
@@ -1117,7 +1117,7 @@ static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr)
 static void gen_load(DisasContext *dc, TCGv dst, TCGv addr, 
 		     unsigned int size, int sign)
 {
-	int mem_index = cpu_mmu_index(dc->env);
+	int mem_index = cpu_mmu_index_data(dc->env);
 
 	/* If we get a fault on a delayslot we must keep the jmp state in
 	   the cpu-state to be able to re-execute the jmp.  */
@@ -1147,7 +1147,7 @@ static void gen_load(DisasContext *dc, TCGv dst, TCGv addr,
 static void gen_store (DisasContext *dc, TCGv addr, TCGv val,
 		       unsigned int size)
 {
-	int mem_index = cpu_mmu_index(dc->env);
+	int mem_index = cpu_mmu_index_data(dc->env);
 
 	/* If we get a fault on a delayslot we must keep the jmp state in
 	   the cpu-state to be able to re-execute the jmp.  */
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 90bceab..f3ccb53 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -842,7 +842,8 @@ static inline int cpu_get_time_fast(void)
 #define MMU_MODE0_SUFFIX _kernel
 #define MMU_MODE1_SUFFIX _user
 #define MMU_USER_IDX 1
-static inline int cpu_mmu_index (CPUState *env)
+#define cpu_mmu_index_data cpu_mmu_index_code
+static inline int cpu_mmu_index_code (CPUState *env)
 {
     return (env->hflags & HF_CPL_MASK) == 3 ? 1 : 0;
 }
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index e2529eb..94af716 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -218,7 +218,8 @@ void register_m68k_insns (CPUM68KState *env);
 #define MMU_MODE0_SUFFIX _kernel
 #define MMU_MODE1_SUFFIX _user
 #define MMU_USER_IDX 1
-static inline int cpu_mmu_index (CPUState *env)
+#define cpu_mmu_index_data cpu_mmu_index_code
+static inline int cpu_mmu_index_code (CPUState *env)
 {
     return (env->sr & SR_S) == 0 ? 1 : 0;
 }
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index b415dc4..a793166 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -489,7 +489,8 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
 #define MMU_MODE1_SUFFIX _super
 #define MMU_MODE2_SUFFIX _user
 #define MMU_USER_IDX 2
-static inline int cpu_mmu_index (CPUState *env)
+#define cpu_mmu_index_data cpu_mmu_index_code
+static inline int cpu_mmu_index_code (CPUState *env)
 {
     return env->hflags & MIPS_HFLAG_KSU;
 }
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 87b3460..4d75ced 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -809,7 +809,8 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val);
 #define MMU_MODE1_SUFFIX _kernel
 #define MMU_MODE2_SUFFIX _hypv
 #define MMU_USER_IDX 0
-static inline int cpu_mmu_index (CPUState *env)
+#define cpu_mmu_index_data cpu_mmu_index_code
+static inline int cpu_mmu_index_code (CPUState *env)
 {
     return env->mmu_idx;
 }
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index aea7108..eaae3cf 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -181,7 +181,8 @@ void cpu_load_tlb(CPUSH4State * env);
 #define MMU_MODE0_SUFFIX _kernel
 #define MMU_MODE1_SUFFIX _user
 #define MMU_USER_IDX 1
-static inline int cpu_mmu_index (CPUState *env)
+#define cpu_mmu_index_data cpu_mmu_index_code
+static inline int cpu_mmu_index_code (CPUState *env)
 {
     return (env->sr & SR_MD) == 0 ? 1 : 0;
 }
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 8b84789..33cf4c3 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -456,7 +456,8 @@ int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
 #define MMU_KERNEL_IDX 1
 #define MMU_HYPV_IDX   2
 
-static inline int cpu_mmu_index(CPUState *env1)
+#define cpu_mmu_index_data cpu_mmu_index_code
+static inline int cpu_mmu_index_code(CPUState *env1)
 {
 #if defined(CONFIG_USER_ONLY)
     return MMU_USER_IDX;
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index d059408..017c375 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -4769,7 +4769,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
     dc->pc = pc_start;
     last_pc = dc->pc;
     dc->npc = (target_ulong) tb->cs_base;
-    dc->mem_idx = cpu_mmu_index(env);
+    dc->mem_idx = cpu_mmu_index_code(env);
     dc->def = env->def;
     if ((dc->def->features & CPU_FEATURE_FLOAT))
         dc->fpu_enabled = cpu_fpu_enabled(env);
-- 
1.6.2

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

* [Qemu-devel] [PATCH 06/19] Bug fix alpha: stop translation if too long
  2009-03-30 14:36         ` [Qemu-devel] [PATCH 05/19] Split cpu_mmu_index into cpu_mmu_index_data and cpu_mmu_index_code Tristan Gingold
@ 2009-03-30 14:36           ` Tristan Gingold
  2009-03-30 14:36             ` [Qemu-devel] [PATCH 07/19] Alpha bug: fix palcode mask for user pal calls Tristan Gingold
  2009-04-07 21:44             ` [Qemu-devel] [PATCH 06/19] Bug fix alpha: stop translation if too long Aurelien Jarno
  2009-04-15 14:30           ` [Qemu-devel] [PATCH 05/19] Split cpu_mmu_index into cpu_mmu_index_data and cpu_mmu_index_code Aurelien Jarno
  1 sibling, 2 replies; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 target-alpha/translate.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index e9463ae..dad1686 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2401,10 +2401,10 @@ static always_inline void gen_intermediate_code_internal (CPUState *env,
         ret = translate_one(ctxp, insn);
         if (ret != 0)
             break;
-        /* if we reach a page boundary or are single stepping, stop
-         * generation
-         */
+        /* if we reach a page boundary, or translation is too long
+           or are single stepping, stop generation.  */
         if (((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) ||
+            gen_opc_ptr >= gen_opc_end ||
             num_insns >= max_insns) {
             break;
         }
-- 
1.6.2

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

* [Qemu-devel] [PATCH 07/19] Alpha bug: fix palcode mask for user pal calls
  2009-03-30 14:36           ` [Qemu-devel] [PATCH 06/19] Bug fix alpha: stop translation if too long Tristan Gingold
@ 2009-03-30 14:36             ` Tristan Gingold
  2009-03-30 14:36               ` [Qemu-devel] [PATCH 08/19] Alpha: document more registers used by 21264 Tristan Gingold
  2009-04-07 22:31               ` [Qemu-devel] [PATCH 07/19] Alpha bug: fix palcode mask for user pal calls Aurelien Jarno
  2009-04-07 21:44             ` [Qemu-devel] [PATCH 06/19] Bug fix alpha: stop translation if too long Aurelien Jarno
  1 sibling, 2 replies; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

(Also 6 bits for unprivileged calls)

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 target-alpha/translate.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index dad1686..821f0d4 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -685,7 +685,7 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
         /* CALL_PAL */
         if (palcode >= 0x80 && palcode < 0xC0) {
             /* Unprivileged PAL call */
-            gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x1F) << 6), 0);
+            gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x3F) << 6), 0);
 #if !defined (CONFIG_USER_ONLY)
         } else if (palcode < 0x40) {
             /* Privileged PAL code */
-- 
1.6.2

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

* [Qemu-devel] [PATCH 08/19] Alpha: document more registers used by 21264
  2009-03-30 14:36             ` [Qemu-devel] [PATCH 07/19] Alpha bug: fix palcode mask for user pal calls Tristan Gingold
@ 2009-03-30 14:36               ` Tristan Gingold
  2009-03-30 14:36                 ` [Qemu-devel] [PATCH 09/19] Add square wave output support Tristan Gingold
  2009-04-07 22:32                 ` [Qemu-devel] [PATCH 08/19] Alpha: document more registers used by 21264 Aurelien Jarno
  2009-04-07 22:31               ` [Qemu-devel] [PATCH 07/19] Alpha bug: fix palcode mask for user pal calls Aurelien Jarno
  1 sibling, 2 replies; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 target-alpha/cpu.h |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 3798157..db53650 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -158,7 +158,7 @@ enum {
     IPR_ITB_PTE      = 0x01,            /* 21264 */
     IPR_ITB_IAP      = 0x02,
     IPR_ITB_IA       = 0x03,            /* 21264 */
-    IPR_ITB_IS       = 0x04,
+    IPR_ITB_IS       = 0x04,            /* 21264 */
     IPR_PMPC         = 0x05,
     IPR_EXC_ADDR     = 0x06,            /* 21264 */
     IPR_IVA_FORM     = 0x07,            /* 21264 */
@@ -221,7 +221,7 @@ enum {
     IPR_M_CTL        = 0x28,            /* 21264 */
 #define IPR_M_CTL_SPE_SHIFT 1
 #define IPR_M_CTL_SPE_MASK 7
-    IPR_DC_CTL       = 0x29,
+    IPR_DC_CTL       = 0x29,            /* 21264 */
     IPR_DC_STAT      = 0x2A,            /* 21264 */
     /* Cbox IPRs */
     IPR_C_DATA       = 0x2B,
-- 
1.6.2

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

* [Qemu-devel] [PATCH 09/19] Add square wave output support.
  2009-03-30 14:36               ` [Qemu-devel] [PATCH 08/19] Alpha: document more registers used by 21264 Tristan Gingold
@ 2009-03-30 14:36                 ` Tristan Gingold
  2009-03-30 14:36                   ` [Qemu-devel] [PATCH 10/19] Add ali1543 super IO pci device Tristan Gingold
  2009-04-07 22:29                   ` [Qemu-devel] [PATCH 09/19] Add square wave output support Aurelien Jarno
  2009-04-07 22:32                 ` [Qemu-devel] [PATCH 08/19] Alpha: document more registers used by 21264 Aurelien Jarno
  1 sibling, 2 replies; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

This is necessary for es40 as the sqw output is directly connected to the
core chipset.

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 hw/mc146818rtc.c |   39 +++++++++++++++++++++++++++++----------
 hw/pc.h          |    1 +
 2 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 5b08d72..f6bb21d 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -50,11 +50,12 @@
 
 #define REG_A_UIP 0x80
 
-#define REG_B_SET 0x80
-#define REG_B_PIE 0x40
-#define REG_B_AIE 0x20
-#define REG_B_UIE 0x10
-#define REG_B_DM  0x04
+#define REG_B_SET  0x80
+#define REG_B_PIE  0x40
+#define REG_B_AIE  0x20
+#define REG_B_UIE  0x10
+#define REG_B_SQWE 0x08
+#define REG_B_DM   0x04
 
 struct RTCState {
     uint8_t cmos_data[128];
@@ -62,6 +63,7 @@ struct RTCState {
     struct tm current_tm;
     int base_year;
     qemu_irq irq;
+    qemu_irq sqw_irq;
     int it_shift;
     /* periodic timer */
     QEMUTimer *periodic_timer;
@@ -95,16 +97,20 @@ static void rtc_timer_update(RTCState *s, int64_t current_time)
 {
     int period_code, period;
     int64_t cur_clock, next_irq_clock;
+    int enable_pie;
 
     period_code = s->cmos_data[RTC_REG_A] & 0x0f;
 #if defined TARGET_I386 || defined TARGET_X86_64
     /* disable periodic timer if hpet is in legacy mode, since interrupts are
      * disabled anyway.
      */
-    if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE) && !hpet_in_legacy_mode()) {
+    enable_pie = hpet_in_legacy_mode();
 #else
-    if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
+    enable_pie = 1;
 #endif
+    if (period_code != 0
+        && (((s->cmos_data[RTC_REG_B] & REG_B_PIE) && enable_pie)
+            || ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) {
         if (period_code <= 2)
             period_code += 7;
         /* period in 32 Khz cycles */
@@ -138,8 +144,15 @@ static void rtc_periodic_timer(void *opaque)
         return;
     }
 #endif
-    s->cmos_data[RTC_REG_C] |= 0xc0;
-    rtc_irq_raise(s->irq);
+    if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
+        s->cmos_data[RTC_REG_C] |= 0xc0;
+        rtc_irq_raise(s->irq);
+    }
+    if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) {
+        /* Not square wave at all but we don't want 2048Hz interrupts!
+           Must be seen as a pulse.  */
+        qemu_irq_raise(s->sqw_irq);
+    }
 }
 
 static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
@@ -527,13 +540,14 @@ static int rtc_load_td(QEMUFile *f, void *opaque, int version_id)
 }
 #endif
 
-RTCState *rtc_init(int base, qemu_irq irq, int base_year)
+RTCState *rtc_init_sqw(int base, qemu_irq irq, qemu_irq sqw_irq, int base_year)
 {
     RTCState *s;
 
     s = qemu_mallocz(sizeof(RTCState));
 
     s->irq = irq;
+    s->sqw_irq = sqw_irq;
     s->cmos_data[RTC_REG_A] = 0x26;
     s->cmos_data[RTC_REG_B] = 0x02;
     s->cmos_data[RTC_REG_C] = 0x00;
@@ -563,6 +577,11 @@ RTCState *rtc_init(int base, qemu_irq irq, int base_year)
     return s;
 }
 
+RTCState *rtc_init(int base, qemu_irq irq, int base_year)
+{
+    return rtc_init_sqw(base, irq, NULL, base_year);
+}
+
 /* Memory mapped interface */
 static uint32_t cmos_mm_readb (void *opaque, target_phys_addr_t addr)
 {
diff --git a/hw/pc.h b/hw/pc.h
index 5b378d4..7345f04 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -90,6 +90,7 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
 typedef struct RTCState RTCState;
 
 RTCState *rtc_init(int base, qemu_irq irq, int base_year);
+RTCState *rtc_init_sqw(int base, qemu_irq irq, qemu_irq sqw_irq, int base_year);
 RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
                       int base_year);
 void rtc_set_memory(RTCState *s, int addr, int val);
-- 
1.6.2

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

* [Qemu-devel] [PATCH 10/19] Add ali1543 super IO pci device.
  2009-03-30 14:36                 ` [Qemu-devel] [PATCH 09/19] Add square wave output support Tristan Gingold
@ 2009-03-30 14:36                   ` Tristan Gingold
  2009-03-30 14:36                     ` [Qemu-devel] [PATCH 11/19] Add 21272 chipset (memory and pci controller for alpha) Tristan Gingold
  2009-04-07 22:29                   ` [Qemu-devel] [PATCH 09/19] Add square wave output support Aurelien Jarno
  1 sibling, 1 reply; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

This is a very partial implementation just enough for es40 firmware.

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 hw/ali1543.c |  150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/pci.h     |    5 ++
 hw/pci_ids.h |    3 +
 3 files changed, 158 insertions(+), 0 deletions(-)
 create mode 100644 hw/ali1543.c

diff --git a/hw/ali1543.c b/hw/ali1543.c
new file mode 100644
index 0000000..c4b0572
--- /dev/null
+++ b/hw/ali1543.c
@@ -0,0 +1,150 @@
+/*
+ * QEMU Ali 1543c emulation
+ *
+ * Copyright (c) 2009 AdaCore
+ *
+ * Written by Tristan Gingold.
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+#include <time.h>
+#include <sys/time.h>
+#include "hw.h"
+#include "net.h"
+#include "sysemu.h"
+#include "devices.h"
+#include "boards.h"
+#include "pc.h"
+#include "isa.h"
+#include "qemu-char.h"
+#include "pci.h"
+
+/* Ali 1543 is a south-bridge super-IO.  It contains a DMA, a PIC, a PIT,
+  a ps/2 kbd interface, 2 IDE controller, 1 USB controller (OHCI), 1 FDC,
+  2 serials ports, 1 parallel port and a PMU.  */
+
+//#define DEBUG_CFG
+
+struct ALI1543State {
+    PCIDevice pci;
+
+    qemu_irq *irq; /* Upstream handler. */
+    PITState *pit;
+    qemu_irq *i8259;
+
+    /* Configuration.  */
+    enum cfg_state { CFG_SNOOP, CFG_51, CFG_EN } cfg_state;
+    unsigned char cfg_index;
+};
+
+static void ali_cfg_write(void *opaque, uint32_t addr, uint32_t val)
+{
+    ALI1543State *ali = opaque;
+
+    if ((addr & 1) == 0) {
+        switch (ali->cfg_state) {
+        case CFG_SNOOP:
+            if (val == 0x51)
+                ali->cfg_state = CFG_51;
+            else
+                qemu_log("ali1543-cfg: write %02x to cfg_port\n", val);
+            break;
+        case CFG_51:
+            if (val == 0x23)
+                ali->cfg_state = CFG_EN;
+            else {
+                qemu_log("ali1543-cfg: write %02x to cfg_port (51)\n", val);
+                ali->cfg_state = CFG_SNOOP;
+            }
+            break;
+        case CFG_EN:
+            ali->cfg_index = val;
+            break;
+        }
+    }
+    else {
+#ifdef DEBUG_CFG
+        qemu_log("ali1543-cfg: write %02x to cfg reg %02x (addr=%x)\n",
+                 val, ali->cfg_index, addr);
+#endif
+    }
+}
+
+static uint32_t ali_cfg_read(void *opaque, uint32_t addr)
+{
+    ALI1543State *ali = opaque;
+    uint32_t res;
+
+    if ((addr & 1) == 0) {
+        if (ali->cfg_state != CFG_EN) {
+            qemu_log("ali1543-cfg: read fromcfg_port\n");
+            res = 0;
+        }
+        else
+            res = ali->cfg_index;
+    }
+    else {
+        switch (ali->cfg_index) {
+        case 0x20:
+            res = 0x43;
+            break;
+        case 0x21:
+            res = 0x15;
+            break;
+        default:
+#ifdef DEBUG_CFG
+            qemu_log("ali1543-cfg: read from reg %02x\n", ali->cfg_index);
+#endif
+            res = 0;
+            break;
+        }
+    }
+    return res;
+}
+
+ALI1543State *ali1543_init (PCIBus *bus, int devfn, qemu_irq irq)
+{
+    ALI1543State *ali;
+    uint8_t *pci_conf;
+
+    ali = (ALI1543State*)pci_register_device(bus, "Ali1543",
+                                             sizeof(ALI1543State),
+                                             devfn, NULL, NULL);
+
+    pci_conf = ali->pci.config;
+
+    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_AL);
+    pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_AL_M1533);
+    pci_conf[0x08] = 0xc3; // Revision
+    pci_config_set_class(pci_conf, PCI_CLASS_BRIDGE_ISA);
+    pci_conf[0x2c] = 0; // Subsystem
+    pci_conf[0x2d] = 0;
+    pci_conf[0x2e] = 0;
+    pci_conf[0x2f] = 0;
+
+    register_ioport_read(0x370, 2, 1, ali_cfg_read, ali);
+    register_ioport_write(0x370, 2, 1, ali_cfg_write, ali);
+
+    ali->i8259 = i8259_init(irq);
+
+    /* serial_init already handles NULL CharDriverState but this code adds
+       a more useful label.  */
+    if (serial_hds[0] == NULL)
+        serial_hds[0] = qemu_chr_open("com1", "nul", NULL);
+    if (serial_hds[1] == NULL)
+        serial_hds[1] = qemu_chr_open("com2", "nul", NULL);
+
+    serial_init(0x3f8, ali->i8259[4], 115200, serial_hds[0]);
+    serial_init(0x2f8, ali->i8259[3], 115200, serial_hds[1]);
+    ali->pit = pit_init(0x40, ali->i8259[0]);
+    pcspk_init(ali->pit);
+    DMA_init(0);
+
+    return ali;
+}
+
+qemu_irq ali1543_get_irq(ALI1543State *c, int n)
+{
+    return c->i8259[n];
+}
diff --git a/hw/pci.h b/hw/pci.h
index 831f1b1..e4e0738 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -261,4 +261,9 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
 PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                             qemu_irq *pic, int devfn_min, int nirq);
 
+/* ali1543.c */
+typedef struct ALI1543State ALI1543State;
+ALI1543State *ali1543_init (PCIBus *bus, int devfn, qemu_irq irq);
+qemu_irq ali1543_get_irq(ALI1543State *c, int n);
+
 #endif
diff --git a/hw/pci_ids.h b/hw/pci_ids.h
index 427fcd5..4119ead 100644
--- a/hw/pci_ids.h
+++ b/hw/pci_ids.h
@@ -70,6 +70,9 @@
 #define PCI_VENDOR_ID_CMD                0x1095
 #define PCI_DEVICE_ID_CMD_646            0x0646
 
+#define PCI_VENDOR_ID_AL                 0x10b9
+#define PCI_DEVICE_ID_AL_M1533           0x1533
+
 #define PCI_VENDOR_ID_REALTEK            0x10ec
 #define PCI_DEVICE_ID_REALTEK_8139       0x8139
 
-- 
1.6.2

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

* [Qemu-devel] [PATCH 11/19] Add 21272 chipset (memory and pci controller for alpha)
  2009-03-30 14:36                   ` [Qemu-devel] [PATCH 10/19] Add ali1543 super IO pci device Tristan Gingold
@ 2009-03-30 14:36                     ` Tristan Gingold
  2009-03-30 14:36                       ` [Qemu-devel] [PATCH 12/19] Add target-alpha/machine.c and hw/es40.c for es40 machine emulation Tristan Gingold
  0 siblings, 1 reply; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 hw/21272.c |  869 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/pci.h   |    8 +
 2 files changed, 877 insertions(+), 0 deletions(-)
 create mode 100644 hw/21272.c

diff --git a/hw/21272.c b/hw/21272.c
new file mode 100644
index 0000000..a54dd59
--- /dev/null
+++ b/hw/21272.c
@@ -0,0 +1,869 @@
+/*
+ * Qemu 21272 (Tsunami/Typhoon) chipset emulation.
+ *
+ * Copyright (c) 2009 AdaCore
+ *
+ * Written by Tristan Gingold.
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ */
+#include "hw.h"
+#include "devices.h"
+#include "pci.h"
+
+//#define DEBUG_CCHIP
+//#define DEBUG_PCHIP
+//#define DEBUG_DCHIP
+//#define DEBUG_PCICFG
+
+typedef struct PchipState PchipState;
+struct PchipState {
+    /* IntAck handler.  */
+    int (*iack_handler)(void *);
+    void *iack_handler_param;
+
+    PCIBus *pci;
+
+    /* Pchip id.  */
+    int num;
+
+    /* Used to reconstruct 64bits accesses.  Low long word first.  */
+    uint32_t data;
+
+    uint32_t wsba[3];
+    uint64_t wsba3;
+    uint32_t wsm[3];
+    uint32_t wsm3;
+    uint64_t tba[3];
+    uint64_t tba3;
+    uint32_t perrmask;
+    uint32_t plat;
+    /* pctl */
+    unsigned char ptevrfy;
+    unsigned char mwin;
+    unsigned char hole;
+    unsigned char chaindis;
+};
+
+struct TyphoonState {
+    qemu_irq *irqs;
+    qemu_irq *intim_irq;
+    CPUState *cpu[4];
+
+    /* Used to reconstruct 64bits accesses.  Low long word first.  */
+    uint32_t data;
+
+    unsigned char misc_rev;
+    unsigned char misc_abw;
+    unsigned char misc_abt;
+
+    int b_irq[4];
+
+    uint64_t dim[4];
+    uint64_t dir[4];
+    uint64_t drir;
+    uint64_t aar[4];
+
+    /* dchip */
+    uint64_t csc;
+    uint64_t str;
+
+    PchipState pchip[2];
+};
+
+static void illegal_write (void *opaque,
+                            target_phys_addr_t addr, uint32_t value)
+{
+    qemu_log("illegal_write at addr="TARGET_FMT_lx"\n", addr);
+}
+
+static uint32_t illegal_read (void *opaque, target_phys_addr_t addr)
+{
+    qemu_log("illegal_read at addr="TARGET_FMT_lx"\n", addr);
+    return 0;
+}
+
+static uint32_t typhoon_cchip_readl (void *opaque, target_phys_addr_t addr)
+{
+    TyphoonState *s = opaque;
+    uint64_t val;
+    int reg;
+
+    /* Handle 64-bits accesses;  */
+    if (addr & 0x04)
+        return s->data;
+
+    reg = addr >> 6;
+    switch (reg) {
+    case 0x00: /* CSC */
+        val = s->csc;
+        break;
+    case 0x02: /* MISC */
+        val = ((uint64_t)s->misc_rev << 32)
+            | ((uint64_t)s->misc_abt << 20)
+            | ((uint64_t)s->misc_abw << 16)
+            | ((s->b_irq[0] & 4) << 2)
+            | ((s->b_irq[1] & 4) << 3)
+            | ((s->b_irq[2] & 4) << 4)
+            | ((s->b_irq[3] & 4) << 5)
+            | ((s->b_irq[0] & 8) << 5)
+            | ((s->b_irq[1] & 8) << 6)
+            | ((s->b_irq[2] & 8) << 7)
+            | ((s->b_irq[3] & 8) << 8);
+        break;
+    case 0x04:
+    case 0x05:
+    case 0x06:
+    case 0x07:
+        val = s->aar[reg - 4];
+        break;
+    case 0x08:
+    case 0x09:
+    case 0x18:
+    case 0x19:
+        val = s->dim[(reg & 1) | ((reg & 0x10) >> 3)];
+        break;
+    case 0x0a:
+    case 0x0b:
+    case 0x1a:
+    case 0x1b:
+        val = s->dir[(reg & 1) | ((reg & 0x10) >> 3)];
+        break;
+    case 0x0c:
+        val = s->drir;
+        break;
+    default:
+        qemu_log("21272: unhandled cchip read  reg=%x\n", reg);
+        val = 0;
+        break;
+    }
+
+#ifdef DEBUG_CCHIP
+    fprintf(stderr,"typhoon cchip read  reg=%x, val=%016"PRIx64"\n", reg, val);
+#endif
+    s->data = val >> 32;
+    return (uint32_t)val;
+}
+
+static void typhoon_cchip_writel (void *opaque,
+                                  target_phys_addr_t addr, uint32_t value)
+{
+    TyphoonState *s = opaque;
+    int reg;
+    uint64_t val;
+
+#if 0
+    fprintf(stderr,"typhoon write addr="TARGET_FMT_lx", val=%08x\n",
+            addr, value);
+#endif
+
+    /* Handle 64-bits accesses.  LSB first.  */
+    if (!(addr & 0x04)) {
+        s->data = value;
+        return;
+    }
+    else
+        val = ((uint64_t)value << 32) | s->data;
+
+    reg = addr >> 6;
+
+#ifdef DEBUG_CCHIP
+    fprintf(stderr,"typhoon cchip write reg=%x, val=%016"PRIx64"\n", reg, val);
+#endif
+
+    switch (reg) {
+    case 0x00: /* CSC */
+        s->csc = (s->csc & 0xffffU) | (val & 0x0777777fff3f0000ULL);
+        break;
+    case 0x02: /* MISC */
+        if (val & (1 << 24)) {
+            /* ACL: arbitration clear.  */
+            s->misc_abt = 0;
+            s->misc_abw = 0;
+        }
+        if (val & (0xf << 12)) {
+            int i;
+            for (i = 0; i < 4 && s->cpu[i]; i++)
+                if ((val & (0x1000 << i))) {
+                    s->b_irq[i] &= ~(1 << 3);
+                    cpu_alpha_update_irq(s->cpu[i], s->b_irq[i]);
+                }
+        }
+        if ((val & (0xf << 16)) && s->misc_abw == 0) {
+            /* ABW: arbitration won.  */
+            s->misc_abw = (val >> 16) & 0x0f;
+        }
+        if ((val & (0x0f << 20)) && s->misc_abt == 0) {
+            /* ABT: arbitration try.  */
+            s->misc_abt = (val >> 20) & 0x0f;
+        }
+        if (val & (1ULL << 28)) {
+            /* NXM - not handled.  */
+        }
+        if (val & (0x0fULL << 40)) {
+            /* DEVUP - not handled.  */
+        }
+        if (val & (0x0f << 4)) {
+            /* ITINTR */
+            int i;
+            for (i = 0; i < 4 && s->cpu[i]; i++)
+                if ((val & (0x10 << i))) {
+                    s->b_irq[i] &= ~(1 << 2);
+                    cpu_alpha_update_irq(s->cpu[i], s->b_irq[i]);
+                }
+        }
+        if (val & ~((0xfULL << 40) | (0xffULL << 32) | (1 << 28) | (1ULL << 24)
+                    | (0x0f << 12) | (0xf << 16)
+                    | (0x0f << 20) | (0x0f << 4))) {
+            qemu_log("21272: unhandled value %016"PRIx64" written in MISC\n",
+                     val);
+        }
+        break;
+    case 0x08:
+    case 0x09:
+    case 0x18:
+    case 0x19:
+        s->dim[(reg & 1) | ((reg & 0x10) >> 3)] = val;
+        break;
+    default:
+        qemu_log("21272: unhandled cchip write reg %x (%016"PRIx64")\n",
+                 reg, val);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc *typhoon_cchip_read[] = {
+    &illegal_read,
+    &illegal_read,
+    &typhoon_cchip_readl,
+};
+
+static CPUWriteMemoryFunc *typhoon_cchip_write[] = {
+    &illegal_write,
+    &illegal_write,
+    &typhoon_cchip_writel,
+};
+
+static uint32_t typhoon_dchip_readl (void *opaque, target_phys_addr_t addr)
+{
+    TyphoonState *s = opaque;
+    uint64_t val;
+    int reg;
+
+    /* Handle 64-bits accesses;  */
+    if (addr & 0x04)
+        return s->data;
+
+    reg = addr >> 6;
+    switch (reg) {
+    case 0x20: /* DSC */
+        val = (s->csc & 0x3f) | ((s->csc >> (14 - 6)) & 0x40);
+        val = (val << 8) | val;
+        val = (val << 16) | val;
+        val = (val << 32) | val;
+        break;
+    case 0x21: /* STR */
+        val = s->str;
+        break;
+    case 0x22: /* DREV */
+        val = 0x01 * 0x0101010101010101ULL;
+        break;
+    case 0x23: /* DSC2 */
+        val = 0;
+    default:
+        qemu_log("21272: unhandled dchip read  reg=%x\n", reg);
+        val = 0;
+        break;
+    }
+
+#ifdef DEBUG_DCHIP
+    fprintf(stderr,"typhoon dchip read  reg=%x, val=%016"PRIx64"\n", reg, val);
+#endif
+    s->data = val >> 32;
+    return (uint32_t)val;
+}
+
+static void typhoon_dchip_writel (void *opaque,
+                                  target_phys_addr_t addr, uint32_t value)
+{
+    TyphoonState *s = opaque;
+    int reg;
+    uint64_t val;
+
+#if 0
+    fprintf(stderr,"typhoon write addr="TARGET_FMT_lx", val=%08x\n",
+            addr, value);
+#endif
+
+    /* Handle 64-bits accesses.  LSB first.  */
+    if (!(addr & 0x04)) {
+        s->data = value;
+        return;
+    }
+    else
+        val = ((uint64_t)value << 32) | s->data;
+
+    reg = addr >> 6;
+
+#ifdef DEBUG_DCHIP
+    fprintf(stderr,"typhoon dchip write reg=%x, val=%016"PRIx64"\n", reg, val);
+#endif
+
+    switch (reg) {
+    default:
+        qemu_log("21272: unhandled dchip write reg %x (%016"PRIx64")\n",
+                 reg, val);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc *typhoon_dchip_read[] = {
+    &illegal_read,
+    &illegal_read,
+    &typhoon_dchip_readl,
+};
+
+static CPUWriteMemoryFunc *typhoon_dchip_write[] = {
+    &illegal_write,
+    &illegal_write,
+    &typhoon_dchip_writel,
+};
+
+static uint32_t typhoon_pchip_readl (void *opaque, target_phys_addr_t addr)
+{
+    PchipState *s = opaque;
+    uint64_t val;
+    int reg;
+
+    /* Handle 64-bits accesses;  */
+    if (addr & 0x04)
+        return s->data;
+
+    reg = addr >> 6;
+    switch (reg) {
+    case 0x00:
+    case 0x01:
+    case 0x02:
+        val = s->wsba[reg];
+        break;
+    case 0x03:
+        val = s->wsba3;
+        break;
+    case 0x04:
+    case 0x05:
+    case 0x06:
+        val = s->wsm[reg - 4];
+        break;
+    case 0x07:
+        val = s->wsm3;
+        break;
+    case 0x08:
+    case 0x09:
+    case 0x0a:
+        val = s->tba[reg - 0x8];
+        break;
+    case 0x0b:
+        val = s->tba3;
+        break;
+    case 0x0c: /* pctl  */
+        val = (((uint64_t)(s->num & 3)) << 46)
+            | (((uint64_t)s->ptevrfy) << 44)
+            | (1ULL << 40) /* PCLKX */
+            | (1 << 24) /* Rev */
+            | (s->mwin << 6)
+            | (s->hole << 5)
+            | (s->chaindis << 3);
+        break;
+    case 0x0d: /* plat */
+        val = s->plat;
+        break;
+    case 0x0f: /* PERROR */
+        val = 0;  /* Not emulated.  */
+        break;
+    case 0x10: /* PERRMASK */
+        val = s->perrmask;
+        break;
+    case 0x20: /* WO. */
+        val = 0;
+        break;
+    default:
+        qemu_log("21272: unhandled pchip read  reg=%x\n", reg);
+        val = 0;
+        break;
+    }
+
+#ifdef DEBUG_PCHIP
+    fprintf(stderr,"typhoon pchip%d read  reg=%x, val=%016"PRIx64"\n",
+            s->num, reg, val);
+#endif
+    s->data = val >> 32;
+    return (uint32_t)val;
+}
+
+static void typhoon_pchip_writel (void *opaque,
+                                  target_phys_addr_t addr, uint32_t value)
+{
+    PchipState *s = opaque;
+    int reg;
+    uint64_t val;
+
+    /* Handle 64-bits accesses.  LSB first.  */
+    if (!(addr & 0x04)) {
+        s->data = value;
+        return;
+    }
+    else
+        val = ((uint64_t)value << 32) | s->data;
+
+    reg = addr >> 6;
+
+#ifdef DEBUG_PCHIP
+    fprintf(stderr,"typhoon pchip%d write reg=%x, val=%016"PRIx64"\n",
+            s->num, reg, val);
+#endif
+
+    switch (reg) {
+    case 0:
+    case 1:
+    case 2:
+        s->wsba[reg] = val & 0xfff00003;
+        if (val & 1)
+            qemu_log("21272: enabling wsba%d!\n", reg); /* Not yet emulated */
+        break;
+    case 3:
+        s->wsba3 = val & 0xffffff80fff00003ULL;
+        if (val & 1)
+            qemu_log("21272: enabling wsba3!\n"); /* Not yet emulated */
+        break;
+    case 0x4:
+    case 0x5:
+    case 0x6:
+        s->wsm[reg - 4] = val & 0xfff00000;
+        break;
+    case 0x7:
+        s->wsm3 = val & 0xfff00000;
+        break;
+    case 0x8:
+    case 0x9:
+    case 0xa:
+        s->tba[reg - 0x8] = val & 0x7fffffc00;
+        break;
+    case 0xb:
+        s->tba3 = val & 0x7fffffc00;
+        break;
+    case 0x0c: /* pctl  */
+        s->ptevrfy = (val >> 44) & 1;
+        s->mwin = (val >> 6) & 1;
+        s->hole = (val >> 5) & 1;
+        s->chaindis = (val >> 3) & 1;
+        if (val & ((1ULL << 43) | (1ULL << 42) | (3ULL << 36) | (0x0fULL << 32)
+                   | (0x0f << 20) | (1 << 19) | (0x3f << 8)
+                   | (1 << 2) | (1 << 1)))
+            qemu_log("21272: pchip pctl: unhandled value %016"PRIx64"\n",
+                     val);
+        break;
+    case 0x0d: /* plat */
+        s->plat = val & 0xff00;
+        break;
+    case 0x0f: /* PERROR */
+        break; /* Not emulated.  */
+    case 0x10: /* PERRMASK */
+        s->perrmask = val & 0xfff;
+        break;
+    case 0x13: /* tlbia */
+        /* FIXME: todo */
+        break;
+    case 0x20: /* SPRST */
+        /* Software pci-reset.  FIXME: disable bus?  */
+        break;
+    default:
+        qemu_log("21272: unhandled pchip write reg=%x (%016"PRIx64")\n",
+                 reg, val);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc *typhoon_pchip_read[] = {
+    &illegal_read,
+    &illegal_read,
+    &typhoon_pchip_readl,
+};
+
+static CPUWriteMemoryFunc *typhoon_pchip_write[] = {
+    &illegal_write,
+    &illegal_write,
+    &typhoon_pchip_writel,
+};
+
+
+static void pchip_pci_io_writeb (void *opaque, target_phys_addr_t addr,
+                                uint32_t value)
+{
+    cpu_outb(NULL, addr, value);
+}
+
+static uint32_t pchip_pci_io_readb (void *opaque, target_phys_addr_t addr)
+{
+    return cpu_inb(NULL, addr);
+}
+
+static void pchip_pci_io_writew (void *opaque, target_phys_addr_t addr,
+                                uint32_t value)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+    value = bswap16(value);
+#endif
+    cpu_outw(NULL, addr, value);
+}
+
+static uint32_t pchip_pci_io_readw (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t ret;
+
+    ret = cpu_inw(NULL, addr);
+#ifdef TARGET_WORDS_BIGENDIAN
+    ret = bswap16(ret);
+#endif
+    return ret;
+}
+
+static void pchip_pci_io_writel (void *opaque, target_phys_addr_t addr,
+                                uint32_t value)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+    value = bswap32(value);
+#endif
+    cpu_outl(NULL, addr, value);
+}
+
+static uint32_t pchip_pci_io_readl (void *opaque, target_phys_addr_t addr)
+{
+    uint32_t ret;
+
+    ret = cpu_inl(NULL, addr);
+#ifdef TARGET_WORDS_BIGENDIAN
+    ret = bswap32(ret);
+#endif
+    return ret;
+}
+
+static CPUWriteMemoryFunc *pchip_pci_io_write[] = {
+    &pchip_pci_io_writeb,
+    &pchip_pci_io_writew,
+    &pchip_pci_io_writel,
+};
+
+static CPUReadMemoryFunc *pchip_pci_io_read[] = {
+    &pchip_pci_io_readb,
+    &pchip_pci_io_readw,
+    &pchip_pci_io_readl,
+};
+
+static void pchip_pci_cfg_writex (void *opaque, target_phys_addr_t addr,
+                                  uint32_t value, int sz)
+{
+    uint32_t a = addr & 0xffffffU;
+    PchipState *s = opaque;
+
+#ifdef DEBUG_PCICFG
+    fprintf(stderr, "pci_cfg write: addr=%06x, sz=%d %u:%u:%02x, val=%08x\n",
+            a, sz,
+            (a >> 11) & 0x1f, (a >> 8) & 0x7, a & 0xff, value);
+#endif
+
+    pci_data_write(s->pci, a, value, 1 << sz);
+}
+
+static void pchip_pci_cfg_writel (void *opaque, target_phys_addr_t addr,
+                                uint32_t value)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+    value = bswap32(value);
+#endif
+    pchip_pci_cfg_writex(opaque, addr, value, 2);
+}
+
+static void pchip_pci_cfg_writew (void *opaque, target_phys_addr_t addr,
+                                uint32_t value)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+    value = bswap16(value);
+#endif
+    pchip_pci_cfg_writex(opaque, addr, value, 1);
+}
+
+static void pchip_pci_cfg_writeb (void *opaque, target_phys_addr_t addr,
+                                uint32_t value)
+{
+    pchip_pci_cfg_writex(opaque, addr, value, 0);
+}
+
+static uint32_t pchip_pci_cfg_readx (void *opaque, target_phys_addr_t addr,
+                                     int sz)
+{
+    uint32_t a = addr & 0xffffffU;
+    PchipState *s = opaque;
+    uint32_t val;
+
+    if (s->num == 0)
+        val = pci_data_read(s->pci, a, 1 << sz);
+    else {
+        switch (sz) {
+        case 0:
+            val = 0xff;
+            break;
+        case 1:
+            val = 0xffff;
+            break;
+        default:
+        case 2:
+            val = 0xffffffff;
+            break;
+        }
+    }
+
+#ifdef DEBUG_PCICFG
+    fprintf(stderr, "pci_cfg  read: addr=%06x, sz=%d %u:%u:%02x, val=%08x\n",
+            a, sz,
+            (a >> 11) & 0x1f, (a >> 8) & 0x7, a & 0xff,
+            val);
+#endif
+
+    return val;
+}
+
+static uint32_t pchip_pci_cfg_readb (void *opaque, target_phys_addr_t addr)
+{
+    return pchip_pci_cfg_readx(opaque, addr, 0);
+}
+
+static uint32_t pchip_pci_cfg_readw (void *opaque, target_phys_addr_t addr)
+{
+    return pchip_pci_cfg_readx(opaque, addr, 1);
+}
+
+static uint32_t pchip_pci_cfg_readl (void *opaque, target_phys_addr_t addr)
+{
+    return pchip_pci_cfg_readx(opaque, addr, 2);
+}
+
+static CPUWriteMemoryFunc *pchip_pci_cfg_write[] = {
+    &pchip_pci_cfg_writeb,
+    &pchip_pci_cfg_writew,
+    &pchip_pci_cfg_writel,
+};
+
+static CPUReadMemoryFunc *pchip_pci_cfg_read[] = {
+    &pchip_pci_cfg_readb,
+    &pchip_pci_cfg_readw,
+    &pchip_pci_cfg_readl,
+};
+
+static void pchip_pci_iack_writex (void *opaque,
+                            target_phys_addr_t addr, uint32_t value)
+{
+    qemu_log("21272: pci iack addr=%08x, val=%08x\n", (uint32_t)addr, value);
+}
+
+static uint32_t pchip_pci_iack_readx (void *opaque, target_phys_addr_t addr)
+{
+    PchipState *s = opaque;
+    uint32_t res;
+
+    /* Ideally we should have a PCIBus interface.  */
+    res = (*s->iack_handler)(s->iack_handler_param);
+    //fprintf(stderr, "21272 iack: addr=%016"PRIx64", res=%d\n", addr, res);
+    return res;
+}
+
+static CPUWriteMemoryFunc *pchip_pci_iack_write[] = {
+    &pchip_pci_iack_writex,
+    &pchip_pci_iack_writex,
+    &pchip_pci_iack_writex,
+};
+
+static CPUReadMemoryFunc *pchip_pci_iack_read[] = {
+    &pchip_pci_iack_readx,
+    &pchip_pci_iack_readx,
+    &pchip_pci_iack_readx,
+};
+
+static void typhoon_reset (void *opaque)
+{
+    TyphoonState *s = opaque;
+
+    s->misc_rev = 8;
+    s->misc_abw = 0;
+}
+
+static void cchip_set_irq(void *opaque, int irq, int level)
+{
+    TyphoonState *s = opaque;
+    uint64_t mask;
+    int i;
+
+#if 0
+    qemu_log("cchip_set_irq: irq=%d level=%d\n", irq, level);
+#endif
+    mask = 1ULL << irq;
+    if (level)
+        s->drir |= mask;
+    else
+        s->drir &= ~mask;
+
+    for (i = 0; i < 4 && s->cpu[i]; i++) {
+        int old = s->b_irq[i];
+        s->dir[i] = s->drir & s->dim[i];
+        if (s->dir[i] >> 58)
+            s->b_irq[i] |= (1 << 0);
+        else
+            s->b_irq[i] &= ~(1 << 0);
+
+        if (s->dir[i] << 8)
+            s->b_irq[i] |= (1 << 1);
+        else
+            s->b_irq[i] &= ~(1 << 1);
+
+#if 0
+        qemu_log("cchip_set_irq: cpu[%d]: drir=%016"PRIx64" dim=%016"PRIx64" "
+                 " dir=%016"PRIx64" birq=%02x\n",
+                 i, s->drir, s->dim[i], s->dir[i], s->b_irq[i]);
+#endif
+        if (s->b_irq[i] != old)
+            cpu_alpha_update_irq(s->cpu[i], s->b_irq[i]);
+    }
+}
+
+static void intim_set_irq(void *opaque, int irq, int level)
+{
+    int i;
+    TyphoonState *s = opaque;
+    unsigned char old;
+
+#if 0
+    {
+        static int cnt;
+        cnt++;
+        if ((cnt % 1024) == 1023)
+            fprintf(stderr, "Clock!\n");
+    }
+#endif
+
+    if (0 && (s->b_irq[0] & 0x04))
+        fprintf(stderr, "!!Interrupt missed\n");
+
+    for (i = 0; i < 4 && s->cpu[i]; i++) {
+        old = s->b_irq[i];
+        if (!(old & (1 << 2))) {
+            s->b_irq[i] |= (1 << 2);
+            cpu_alpha_update_irq(s->cpu[i], s->b_irq[i]);
+        }
+    }
+}
+
+
+static int typhoon_map_irq(PCIDevice *pci_dev, int irq_num)
+{
+    return irq_num;
+}
+
+static void typhoon_set_irq(qemu_irq *pic, int irq_num, int level)
+{
+    /* Never called (yet).  */
+    fprintf(stderr, "typhoon_set_irq: irq_num=%d, level=%d\n", irq_num, level);
+    exit(4);
+}
+
+TyphoonState *typhoon_21272_init (uint64_t *arr, qemu_irq **irqs,
+                                  qemu_irq *intim_irq, void *cpu0)
+{
+    TyphoonState *s;
+    int cchip;
+    int dchip;
+    int pchip;
+    int pci_io;
+    int pci_cfg;
+    int pci_iack;
+    int i;
+
+    s = qemu_mallocz(sizeof(TyphoonState));
+
+    /* Cchip registers.  */
+    cchip = cpu_register_io_memory(0, typhoon_cchip_read,
+                                   typhoon_cchip_write, s);
+    cpu_register_physical_memory(0x801a0000000ULL, 0x0002000, cchip);
+
+    /* Dchip registers.  */
+    dchip = cpu_register_io_memory(0, typhoon_dchip_read,
+                                   typhoon_dchip_write, s);
+    cpu_register_physical_memory(0x801b0000000ULL, 0x0002000, dchip);
+
+    /* Pchip0 registers.  */
+    pchip = cpu_register_io_memory(0, typhoon_pchip_read,
+                                   typhoon_pchip_write, &s->pchip[0]);
+    cpu_register_physical_memory(0x80180000000ULL, 0x0002000, pchip);
+
+    /* Pchip1 registers.  */
+    pchip = cpu_register_io_memory(0, typhoon_pchip_read,
+                                    typhoon_pchip_write, &s->pchip[1]);
+    cpu_register_physical_memory(0x80380000000ULL, 0x0002000, pchip);
+
+    /* Pchip0 PCI I/O  */
+    pci_io = cpu_register_io_memory(0, pchip_pci_io_read,
+                                    pchip_pci_io_write, &s->pchip[0]);
+    cpu_register_physical_memory(0x801fc000000ULL, 0x0010000, pci_io);
+
+    /* Pchip0 PCI cfg  */
+    pci_cfg = cpu_register_io_memory(0, pchip_pci_cfg_read,
+                                    pchip_pci_cfg_write, &s->pchip[0]);
+    cpu_register_physical_memory(0x801fe000000ULL, 0x0010000, pci_cfg);
+
+    /* Pchip0 PCI IntAck  */
+    pci_iack = cpu_register_io_memory(0, pchip_pci_iack_read,
+                                      pchip_pci_iack_write, &s->pchip[0]);
+    cpu_register_physical_memory(0x801f8000000ULL, 0x002000, pci_iack);
+
+    /* Pchip0 PCI cfg  */
+    pci_cfg = cpu_register_io_memory(0, pchip_pci_cfg_read,
+                                    pchip_pci_cfg_write, &s->pchip[1]);
+    cpu_register_physical_memory(0x803fe000000ULL, 0x0010000, pci_cfg);
+
+    s->pchip[0].pci = pci_register_bus(typhoon_set_irq,
+                                       typhoon_map_irq,
+                                       (void *)&s->pchip[0], 0, 64);
+
+    pci_mem_base = 0x80000000000ULL;
+    isa_mem_base = 0x80000000000ULL;
+
+    typhoon_reset(s);
+
+    /* P1 chip present, 8 dchips, 2 memory buses.  */
+    s->csc = (1 << 14) | (3 << 0);
+
+    /* Configure cchip array address.  */
+    for (i = 0; i < 4; i++)
+        s->aar[i] = arr[i];
+
+    s->cpu[0] = cpu0;
+    s->irqs = qemu_allocate_irqs(cchip_set_irq, s, 64);
+    *irqs = s->irqs;
+
+    s->intim_irq = qemu_allocate_irqs(intim_set_irq, s, 1);
+    *intim_irq = s->intim_irq[0];
+
+    qemu_register_reset(&typhoon_reset, s);
+
+    return s;
+}
+
+void typhoon_set_iack_handler(TyphoonState *c, int num,
+                              int (*handler)(void *), void *param)
+{
+    c->pchip[num].iack_handler = handler;
+    c->pchip[num].iack_handler_param = param;
+}
+
+PCIBus *typhoon_get_pci_bus(TyphoonState *c, int num)
+{
+    return c->pchip[num].pci;
+}
diff --git a/hw/pci.h b/hw/pci.h
index e4e0738..4f2496f 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -261,6 +261,14 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
 PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                             qemu_irq *pic, int devfn_min, int nirq);
 
+/* 21272.c */
+typedef struct TyphoonState TyphoonState;
+TyphoonState *typhoon_21272_init (uint64_t *arr, qemu_irq **irqs,
+                                  qemu_irq *intim_irq, void *cpu0);
+void typhoon_set_iack_handler(TyphoonState *c, int num,
+                              int (*handler)(void *), void *param);
+PCIBus *typhoon_get_pci_bus(TyphoonState *c, int num);
+
 /* ali1543.c */
 typedef struct ALI1543State ALI1543State;
 ALI1543State *ali1543_init (PCIBus *bus, int devfn, qemu_irq irq);
-- 
1.6.2

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

* [Qemu-devel] [PATCH 12/19] Add target-alpha/machine.c and hw/es40.c for es40 machine emulation.
  2009-03-30 14:36                     ` [Qemu-devel] [PATCH 11/19] Add 21272 chipset (memory and pci controller for alpha) Tristan Gingold
@ 2009-03-30 14:36                       ` Tristan Gingold
  2009-03-30 14:36                         ` [Qemu-devel] [PATCH 13/19] Move softmmu_helper.h from exec.h to op_helper.c on alpha Tristan Gingold
  0 siblings, 1 reply; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 30610 bytes --]

The machine emulation is not yet complete, in particular vm save and load is
not yet implemented.

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 Makefile.target        |    4 +
 hw/boards.h            |    4 +
 hw/es40.c              |  922 ++++++++++++++++++++++++++++++++++++++++++++++++
 target-alpha/machine.c |   22 ++
 4 files changed, 952 insertions(+), 0 deletions(-)
 create mode 100644 hw/es40.c
 create mode 100644 target-alpha/machine.c

diff --git a/Makefile.target b/Makefile.target
index f862d90..68937fe 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -683,6 +683,10 @@ ifeq ($(TARGET_BASE_ARCH), m68k)
 OBJS+= an5206.o mcf5206.o ptimer.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
 OBJS+= m68k-semi.o dummy_m68k.o
 endif
+ifeq ($(TARGET_BASE_ARCH), alpha)
+OBJS+= es40.o 21272.o serial.o i8259.o mc146818rtc.o i8254.o pcspk.o dma.o
+OBJS+= ali1543.o
+endif
 ifdef CONFIG_GDBSTUB
 OBJS+=gdbstub.o gdbstub-xml.o
 endif
diff --git a/hw/boards.h b/hw/boards.h
index 1e18ba6..48c9821 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -127,4 +127,8 @@ extern QEMUMachine musicpal_machine;
 /* tosa.c */
 extern QEMUMachine tosapda_machine;
 
+/* es40.c */
+extern QEMUMachine es40_machine;
+extern QEMUMachine es40_rombuild_machine;
+
 #endif
diff --git a/hw/es40.c b/hw/es40.c
new file mode 100644
index 0000000..9d04326
--- /dev/null
+++ b/hw/es40.c
@@ -0,0 +1,922 @@
+/*
+ * QEMU ES-40 System Emulator
+ *
+ * Copyright (c) 2009 AdaCore
+ *
+ * Written by Tristan Gingold.
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ *
+ */
+#include <time.h>
+#include <sys/time.h>
+#include "hw.h"
+#include "net.h"
+#include "sysemu.h"
+#include "devices.h"
+#include "boards.h"
+#include "pc.h"
+#include "isa.h"
+#include "pci.h"
+
+/* Building the firmware for es40:
+
+   The main part of the firmware is called SRM.  You can get an original
+   image from HP web site:
+
+   ftp://ftp.hp.com/pub/alphaserver/firmware/current_platforms/v7.3_release/ES40_series/ES40/es40.zip
+
+   Extract the archive and copy cl67srmrom.exe into a directory.
+
+   Then start Qemu using es40-rombuild machine:
+
+   $ qemu-system-alpha -M es40-rombuild -boot n -L .
+
+   This builds the rom, writes es40.rom file and exits.  Now you have it.
+*/
+
+//#define DEBUG_TIGBUS
+
+/* For Rombuild.  */
+#define ROMBUILD_BIOS_FILENAME "cl67srmrom.exe"
+#define LFU_HDR_SIZE 0x240
+#define LFU_START_ADDR 0x900000
+#define LFU_LOAD_ADDR  0x900000
+#define LFU_MEM_SIZE   0x1000000
+#define LFU_RAM_OFFSET 0x400000
+
+#define SRM_SIZE 0x200000
+
+/* For es40.  */
+#define BIOS_FILENAME "es40.rom"
+
+static ram_addr_t ram_offset;
+
+static void illegal_write (void *opaque,
+                            target_phys_addr_t addr, uint32_t value)
+{
+    qemu_log("illegal_write at addr="TARGET_FMT_lx"\n", addr);
+}
+
+static uint32_t illegal_read (void *opaque, target_phys_addr_t addr)
+{
+    qemu_log("illegal_read at addr="TARGET_FMT_lx"\n", addr);
+    return 0;
+}
+
+typedef struct TigBusState TigBusState;
+struct TigBusState {
+    /* See 264dptrm.pdf.  */
+    unsigned char halt_a;
+    unsigned char halt_b;
+};
+
+static uint32_t tigbus_readl (void *opaque, target_phys_addr_t addr)
+{
+    TigBusState *s = opaque;
+    uint32_t ret;
+    int reg = addr >> 6;
+
+    /* TIGbus registers are mostly only 8 bits.  */
+    if (addr & 0x04)
+        return 0;
+
+    switch (reg) {
+    case 0x17:
+        ret = s->halt_b;
+        break;
+    case 0x12: /* Power fault detected.  */
+        ret = 0;
+        break;
+    case 0x04:
+        ret = 0;
+        break;
+    default:
+        qemu_log("tigbus: unhandled read reg=%02x\n", reg);
+        ret = 0;
+        break;
+    }
+
+#ifdef DEBUG_TIGBUS
+    fprintf(stderr,"tigbus read  reg=%02x, val=%08x\n", reg, ret);
+#endif
+    return ret;
+}
+
+static void tigbus_writel (void *opaque,
+                            target_phys_addr_t addr, uint32_t value)
+{
+    TigBusState *s = opaque;
+    int reg = addr >> 6;
+
+    if (addr & 0x04)
+        return;
+
+#ifdef DEBUG_TIGBUS
+    fprintf(stderr,"tigbus write reg=%02x, val=%08x\n", reg, value);
+#endif
+
+    switch (reg) {
+    case 0x17:
+        s->halt_b = value & 0x0f;
+        break;
+    case 0x12: /* Power fault detected.  */
+        break;
+    default:
+        qemu_log("tigbus: unhandled write to reg=0x%02x (%08x)\n",
+                 reg, value);
+        break;
+    }
+}
+
+static CPUReadMemoryFunc *tigbus_read[] = {
+    &illegal_read,
+    &illegal_read,
+    &tigbus_readl,
+};
+
+static CPUWriteMemoryFunc *tigbus_write[] = {
+    &illegal_write,
+    &illegal_write,
+    &tigbus_writel,
+};
+
+/* Dual Port Ram.
+
+0 0 SROM EV6 BIST status 1=good  0=bad
+1 1 SROM Bit[7]=Master Bits[0,1]=CPU_ID
+2 2 SROM Test STR status 1=good  0=bad
+3 3 SROM Test CSC status 1=good  0=bad
+4 4 SROM Test Pchip 0 PCTL status 1=good, 0=bad
+5 5 SROM Test Pchip 1  PCTL status 1=good, 0=bad
+6 6 SROM Test DIMx status 1=good  0=bad
+7 7 SROM Test TIG bus status
+8 8 SROM Dual-Port RAM test DD= started
+9 9 SROM Status of DPR test 1=good  0=bad
+A A SROM Status of CPU speed function  FF=good, 0=bad
+B B SROM Lower byte of CPU speed in MHz
+C C SROM Upper byte of CPU speed in MHz
+D:F - - Reserved
+10:15 SROM Power On Time Stamp for CPU 0—written as BCD
+ Byte 10 = Hours (0-23)
+ Byte 11 = Minutes (0-59)
+ Byte 12 = Seconds (0-59)
+ Byte 13 = Day of Month (1-31)
+ Byte 14 = Month (1-12)
+ Byte 15 = Year (0-99)
+16 SROM SROM Power On Error Indication for CPU is "alive."
+ For example; 0 = no error, 2 = Secondary time-out Error, 3 = Bcache Error
+17:1D Unused
+1E SROM Last "sync state" reached;  80=Finished GOOD
+1F SROM Size of Bcache in MB
+20:3F 20 Repeat  for CPU1 of CPU0    0-1F
+40:5F 20 Repeat  for CPU2 of CPU0    0-1F
+60:7F 20 Repeat  for CPU3 of CPU0    0-1F
+80 80 SROM Array 0 (AAR 0)  Configuration
+   Bits<7:4>
+ 4 = non split -  lower set only
+ 5 = split - lower set only
+ 9 = split -  upper set only
+ D = split - 8 DIMMs
+ F = Twice split -  8 DIMMs
+     Bits<3:0>
+ 0 = Configured -  Lowest array
+ 1 = Configured -  Next lowest array
+ 2 = Configured -  Second highest  array
+ 3 = Configured -  Highest array
+ 4 = Misconfigured -  Missing DIMM(s)
+ 8 = Miconfigured -  Illegal DIMM(s)
+ C = Misconfigured -  Incompatible  DIMM(s)
+81 81 SROM Array 0 (AAR 0)Size (x64 Mbytes)
+  0 = no good memory
+  1 =   64 Mbyte
+  2 = 128 Mbyte
+  4 = 256 Mbyte
+  8 = 512 Mbyte
+ 10 =     1 Gbyte
+ 20 =     2 Gbyte
+ 40 =     4 Gbyte
+ 80 =     8 Gbyte
+82 82 SROM Array 1 (AAR 1) Configuration
+83 83 SROM Array 1 (AAR 1) Size (x64 Mbytes)
+84 84 SROM Array 2  (AAR 2) Configuration
+85 85 SROM Array 2 (AAR  2) Size (x64 Mbytes)
+86 86 SROM Array 3  (AAR 3) Configuration
+87 87 SROM Array 3 (AAR 3) Size (x64 Mbytes)
+88:8B SROM Byte to define failed DIMMs for MMBs
+88 - MMB 0
+89 - MMB 1
+8A - MMB 2
+8B - MMB 3
+ Bit set indicates failure.
+ Bit definitions ( bit 0 = DIMM 1, bit 1 = DIMM2,
+ bit 2 = DIMM 3, bit 7 = DIMM 8)
+8C:8F 8C-8F SROM Byte to define misconfigured DIMMs for MMBs
+8C - MMB 0
+8D - MMB 1
+8E - MMB 2
+8F - MMB 3
+ Bit definitions ( bit 0 = DIMM 1, bit 1 = DIMM2,
+ bit 2 = DIMM 3, bit 7 = DIMM 8)
+90 90 RMC Power Supply/VTERM  present
+91 91 RMC Power Supply  PS_POK bits
+92 92 RMC AC input value from Power Supply
+93:96 93 RMC Temperature from CPU(x) in BCD
+97:99 97 RMC Temperature Zone(x) from 3 PCI temp sensors
+9A:9F 9A RMC Fan Status; Raw Fan speed value
+A0:A9 A0 RMC Failure registers used as part of the 680 machine
+ check logout frame.  See Appendix D.
+AA RMC Fan status (bit 0 = fan 1, bit 1 = fan 2,
+ 1- indicates good; 0 indicates fan failure
+AB RMC Status of RMC to read I2C bus of MMB0  DIMMs
+ Definition:
+   Bit 7 - DIMM 8   0=OK  1=Fail
+   Bit 6 - DIMM 7
+   Bit 5 - DIMM 6
+    ...
+   Bit 0 - DIMM 1
+AC RMC Status of RMC to read I2C bus of MMB1 DIMMs
+AD RMC Status of RMC to read I2C bus of MMB2 DIMMs
+AE RMC Status of RMC to read I2C bus of MMB3 DIMMs
+AF RMC Status of RMC to read MMB and CPU I2C buses
+ Definition:
+  Bit 7 - MMB3     0=OK  1=Fail
+  Bit 6 - MMB2
+  Bit 5 - MMB1
+  Bit 4 - MMB0
+  Bit 3 - CPU3
+  Bit 2 - CPU2
+  Bit 1 - CPU1
+  Bit 0 - CPU0
+B0 RMC Status of RMC to read CPB (PCI backplane) I2C EEROM 0=OK  1 = fail
+B1 RMC Status of RMC to read CSB (motherboard) I2C EEROM  0=OK  1 = fail
+B2 RMC Status of RMC to read SCSI backplane
+Definition:
+  Bit 0 - SCSI backplane 0
+  Bit 1 - SCSI backplane 1
+  Bit 4 - Power supply 0
+  Bit 5 - Power supply 1
+  Bit 6 - Power supply 2
+B3:B9 Unused Unused
+BA RMC I2C done, BA =  finished
+BB RMC RMC Power on Error indicates error during power-up (1=Flash Corrupted)
+BC RMC RMC flash update error status
+BD RMC Copy of PS input Value.  See Appendix D.
+BE RMC Copy of the byte from the I/O expanders on the
+ SPC loaded by the RMC on fatal errors.  See Appendix D.
+BF RMC Reason for system failure.  See Appendix D.
+C0:D8 Unused
+D9 RMC Baud rate
+DA TIG Indicates TIG finished loading its code (0xAA indicates done)
+DB:E3 RMC Fan/Temp info from PS1
+E4:EC RMC Fan/Temp info from PS2
+ED:F5 RMC Fan/Temp info from PS3
+F6:F8 Unused Unused
+F9 Firmware Buffer Size (0-0xFF) or 1 to 256 bytes
+FA:FB FA Firmware Command address qualifier
+FA = lower byte, FB = upper byte
+FC FC RMC Command status associated with the RMC
+ response to a request from the firmware
+  0 = successful completion
+80 = unsuccessful completion
+81 = invalid command code
+82 = invalid command qualifier
+FD FD RMC Command ID associated with the RMC
+  response to a request from the firmware
+FE FE Firmware Command Code associated with a “command”
+sent to the RMC
+  1 = update I2C EEROM
+  2 = update baud rate
+  3 = display to OCP
+F0 = update RMC flash
+FF FF Firmware Command ID associated with a “command” sent to the RMC
+100:1FF 100 RMC Copy of EEROM on MMB0 J1 DIMM 1,
+ initially read on I2C bus by RMC when 5
+ volts supply turned on. Written by Compaq
+ Analyze after error diagnosed to particular FRU
+200:2FF 200 RMC Copy of EEROM on MMB0 J2 DIMM 2
+300:3FF 300 RMC Copy of EEROM on MMB0 J3 DIMM 3
+400:4FF 400 RMC Copy of EEROM on MMB0 J4 DIMM 4
+500:5FF 500 RMC Copy of EEROM on MMB0 J5 DIMM 5
+600:7FF 600 RMC Copy of EEROM on MMB0 J6 DIMM 6
+700:7FF 700 RMC Copy of EEROM on MMB0 J7 DIMM 7
+800:8FF 800 RMC Copy of EEROM on MMB0 J8 DIMM 8
+900:9FF 900 RMC Copy of EEROM on MMB1 J1 DIMM 1
+A00:AFF A00 RMC Copy of EEROM on MMB1 J2 DIMM 2
+B00:BFF B00 RMC Copy of EEROM on MMB1 J3 DIMM 3
+C00:CFF C00 RMC Copy of EEROM on MMB1 J4 DIMM 4
+D00:DFF D00 RMC Copy of EEROM on MMB1 J5 DIMM 5
+E00:EFF E00 RMC Copy of EEROM on MMB1 J6 DIMM 6
+F00:FFF F00 RMC Copy of EEROM on MMB1 J7 DIMM 7
+1000:10FF 1000 RMC Copy of EEROM on MMB1 J8 DIMM 8
+1100:11FF 1100 RMC Copy of EEROM on MMB2 J1 DIMM 1
+1200:12FF 1200 RMC Copy of EEROM on MMB2 J2 DIMM 2
+1300:13FF 1300 RMC Copy of EEROM on MMB2 J3 DIMM 3
+1400:14FF 1400 RMC Copy of EEROM on MMB2 J4 DIMM 4
+1500:15FF 1500 RMC Copy of EEROM on MMB2 J5 DIMM 5
+1600:16FF 1600 RMC Copy of EEROM on MMB2 J6 DIMM 6
+1700:17FF 1700 RMC Copy of EEROM on MMB2 J7 DIMM 7
+1800:18FF 1800 RMC Copy of EEROM on MMB2 J8 DIMM 8
+1900:19FF 1900 RMC Copy of EEROM on MMB3 J1 DIMM 1
+1A00:1AFF 1A00 RMC Copy of EEROM on MMB3 J2 DIMM 2
+1B00:1BFF 1B00 RMC Copy of EEROM on MMB3 J3 DIMM 3
+1C00:1CFF 1C00 RMC Copy of EEROM on MMB3 J4 DIMM 4
+1D00:1DFF 1D00 RMC Copy of EEROM on MMB3 J5 DIMM 5
+1E00:1EFF 1E00 RMC Copy of EEROM on MMB3 J6 DIMM 6
+1F00:1FFF 1F00 RMC Copy of EEROM on MMB3 J7 DIMM 7
+2000:20FF 2000 RMC Copy of EEROM on MMB3 J8 DIMM 8
+2100:21FF 2100 RMC Copy of EEROM from CPU0
+2200:22FF 2200 RMC Copy of EEROM from CPU1
+2300:23FF 2300 RMC Copy of EEROM from CPU2
+2400:24FF 2400 RMC Copy of EEROM from CPU3
+2500:25FF 2500 RMC Copy of MMB 0  J5 FRU EEROM
+2600:26FF 2600 RMC Copy of MMB 1  J7 FRU EEROM
+2700:27FF 2700 RMC Copy of MMB 2  J6 FRU EEROM
+2800:28FF 2800 RMC Copy of MMB 3  J8 FRU EEROM
+2900:29FF 2900 RMC Copy of EEROM on CPB (PCI backplane)
+2A00:2AFF 2A00 RMC Copy of EEROM on CSB (motherboard)
+2B00:2BFF 2B00 RMC Last EV6 Correctable Error-ASCII
+ character string that indicates correctable
+ error occurred, type, FRU, and so on.  Backed
+ up in CSB (motherboard) EEROM. Written by Compaq Analyze
+2C00:2CFF 2C00 RMC Last Redundant Failure-ASCII
+ character string that indicates redundant
+ failure occurred, type, FRU, and so on.
+ Backed up in system CSB (motherboard) EEROM. Written by Compaq Analyze
+2D00:2DFF 2D00 RMC Last System Failure-ASCII character
+ string that indicates system failure occurred, type, FRU, and so on. Backed
+ up in CSB (motherboard) EEROM. Written by Compaq Analyze.
+2E00:2FFF 2E00 RMC Uncorrectable machine logout frame (512 bytes)
+3000:3008 SROM SROM Version  (ASCII string)
+3009:300B RMC Rev Level of RMC first byte is letter Rev
+ [x/t/v] second 2 bytes are major/minor.
+ This is the rev level of the RMC on-chip code.
+300C:300E RMC Rev Level of RMC first byte is letter Rev
+ [x/t/v] second 2 bytes are major/minor.
+ This is the rev level of the RMC flash code.
+300F:3010 300F RMC Revision Field of the DPR Structure
+3011:30FF Unused Unused
+3100:31FF RMC Copy of PS0 EEROM (first 256 bytes)
+3200:32FF RMC Copy of PS1  EEROM (first 256 bytes)
+3300:33FF RMC Copy of PS2  EEROM (first 256 bytes)
+3400 SROM Size of Bcache in MB
+3401 SROM Flash SROM is valid flag; 8 = valid, 0 = invalid
+3402 SROM System's errors determined by SROM
+3403:340F SROM/SRM Reserved for future SROM/SRM communication
+3410:3417 SROM/SRM Jump to address for CPU0
+3418 SROM/SRM Waiting to jump to flag for CPU0
+3419 SROM Shadow of value written to EV6 DC_CTL register.
+341A:341E SROM Shadow of most recent writes to EV6 CBOX 'Write-many' chain.
+341F SROM/SRM Reserved for future SROM/SRM communication
+3420:342F SROM/SRM Repeat  for CPU1 of CPU0    3410-341F
+3430:343F SROM/SRM Repeat  for CPU2 of CPU0    3410-341F
+3440:344F SROM/SRM Repeat  for CPU3 of CPU0    3410-341F
+3450:349F SROM/RMC Reserved for SROM mini-console via
+ RMC communication area. Future design.
+34A0:34A7 SROM Array 0 to DIMM ID translation
+ Bits<7:5>
+ 0 = Exists, No Error
+ 1 = Expected Missing
+ 2 = Error - Missing  DIMM(s)
+ 4 = Error - Illegal DIMM(s)
+ 6 = Error - Incompatible DIMM(s)
+ Bits<4:0>
+ Bits <2:0> = DIMM + 1 (1-8)
+ Bits <4:3> = MMB (0-3)
+34A8:34AF SROM Repeat for Array 1 of Array 0
+34A0:34A7
+34B0:34B7 SROM Repeat for Array 2 of Array 0
+34A0:34A7
+34B8:34CF SROM Repeat for Array 3 of Array 0
+34A0:34A7
+34C0:34FF 34C0 SROM Used as scratch area for SROM
+3500:35FF Firmware Used as the dedicated buffer in which
+ SRM writes OCP or FRU EEROM data.
+ Firmware will write this data, RMC will only read this data.
+3600:36FF 3600 SRM Reserved
+3700:37FF SRM Reserved
+3800:3AFF RMC RMC scratch space
+3B00:3BFF RMC First SCSI backplane EEROM
+3C00:3CFF RMC Second SCSI backplane EEROM
+3D00:3DFF RMC PS0 second 256 bytes
+3E00:3EFF RMC PS1 second 256 bytes
+3F00:3FFF RMC PS2 second 256 bytes
+*/
+
+struct DPRamState {
+    unsigned char mem[0x4000];
+    uint32_t set_vec[0x4000 >> 5];
+};
+typedef struct DPRamState DPRamState;
+
+static uint32_t tigbus_dpram_readl (void *opaque, target_phys_addr_t addr)
+{
+    DPRamState *dpr = opaque;
+    int reg = addr >> 6;
+
+    /* Discard upper long word.  */
+    if (addr & 0x4)
+        return 0;
+
+#if 0
+    if (!(dpr->set_vec[reg >> 5] &(1 << (reg & 0x1f))))
+        fprintf(stderr,"tigbus dpram: reading uninitialized 0x%04x\n", reg);
+#endif
+
+    return dpr->mem[reg];
+}
+
+static void tigbus_dpram_writel (void *opaque,
+                               target_phys_addr_t addr, uint32_t value)
+{
+    DPRamState *dpr = opaque;
+    int reg = addr >> 6;
+
+    /* Discard upper long word.  */
+    if (addr & 0x4)
+        return;
+
+#if 0
+    fprintf(stderr, "tigbus dpram write %02x at %08x (%04x)\n",
+            value, (unsigned int) addr, reg);
+#endif
+
+    dpr->mem[reg] = value;
+    dpr->set_vec[reg >> 5] |= (1 << (reg & 0x1f));
+    if (reg == 0xff) {
+        const char *cmd;
+        dpr->mem[0xfc] = 0;
+        dpr->mem[0xfd] = dpr->mem[0xff];
+        switch (dpr->mem[0xfe]) {
+        case 0x01:
+            cmd = "eeprom update";
+            break;
+        case 0x02:
+            cmd = "baud rate update";
+            break;
+        case 0x03:
+        {
+            char buf[17];
+            memcpy(buf, &dpr->mem[0x3500], 16);
+            buf[16] = 0;
+            fprintf(stderr,"OCP message: [%s]\n", buf);
+#if 0
+            if (strncmp (buf, "create powerup  ", 16) == 0) {
+                loglevel = CPU_LOG_TB_IN_ASM | CPU_LOG_EXEC | CPU_LOG_TB_CPU;
+            }
+#endif
+            if (1)
+              cmd = NULL;
+            else
+              cmd = "OCP display";
+            break;
+        }
+        case 0xf0:
+            cmd = "update RMC flash";
+            break;
+        default:
+            cmd = NULL;
+            fprintf(stderr,"tigbus dpram: cmd unknown 0x%02x\n",
+                    dpr->mem[0xfe]);
+            dpr->mem[0xfc] = 0x81;
+            break;
+        }
+        if (cmd) {
+            fprintf(stderr,
+                    "tigbus dpram: cmd %02x, id=%02x: %s, addr=%04x len=%d\n",
+                    dpr->mem[0xfe], dpr->mem[0xff],
+                    cmd, (dpr->mem[0xfb] << 8) | dpr->mem[0xfa],
+                    dpr->mem[0xf9] + 1);
+        }
+    }
+}
+
+static CPUReadMemoryFunc *tigbus_dpram_read[] = {
+    &illegal_read,
+    &illegal_read,
+    &tigbus_dpram_readl,
+};
+
+static CPUWriteMemoryFunc *tigbus_dpram_write[] = {
+    &illegal_write,
+    &illegal_write,
+    &tigbus_dpram_writel,
+};
+
+static void dpr_set(DPRamState *dpr, int reg, unsigned char val)
+{
+    dpr->mem[reg] = val;
+    dpr->set_vec[reg >> 5] |= (1 << (reg & 0x1f));
+}
+
+static void tigbus_reset (void *opaque)
+{
+    /* TigBusState *s = opaque; */
+}
+
+static void tigbus_init (uint64_t arr[])
+{
+    TigBusState *s;
+    int mem;
+    int dpram_io;
+    DPRamState *dpram;
+    int i;
+
+    s = qemu_mallocz(sizeof(TigBusState));
+    mem = cpu_register_io_memory(0, tigbus_read, tigbus_write, s);
+    cpu_register_physical_memory(0x80130000000ULL, 0x0002000, mem);
+
+    dpram = qemu_mallocz(sizeof(DPRamState));
+    dpram_io = cpu_register_io_memory(0, tigbus_dpram_read,
+                                      tigbus_dpram_write, dpram);
+    cpu_register_physical_memory(0x80110000000ULL, 0x0100000, dpram_io);
+
+    /* Initialize dpram.  */
+#define S(r,v) dpr_set(dpram,r,v)
+    S(0x00, 1); /* BIST OK */
+    S(0x01, 0x80); /* CPU 0 is master */
+    S(0x02, 1); /* STR ok */
+    S(0x03, 1); /* CSC ok */
+    S(0x04, 1); /* Pchip0 ok */
+    S(0x05, 1); /* Pchip1 ok */
+    S(0x06, 1); /* DIMx ok */
+    S(0x07, 1); /* TIG ok */
+    S(0x08, 0xdd); /* DPRam ok */
+    S(0x09, 0x1); /* DPRDDam ok */
+    S(0x0a, 0xff); /* cpu speed ok */
+    S(0x0b, 600 % 256);
+    S(0x0c, 600 / 256);
+    /* Unused.  */
+    S(0x0d, 0);
+    S(0x0e, 0);
+    S(0x0f, 0);
+    /* Power On time stamp.  Use RTC ?  */
+    S(0x10, 0x12);
+    S(0x11, 0x30);
+    S(0x12, 0x25);
+    S(0x13, 0x15);
+    S(0x14, 0x02);
+    S(0x15, 0x05);
+    S(0x16, 0x0); /* Power On indicator.  */
+    /* Unused.  */
+    S(0x17, 0);
+    S(0x18, 0);
+    S(0x19, 0);
+    S(0x1a, 0);
+    S(0x1b, 0);
+    S(0x1c, 0);
+    S(0x1d, 0);
+    S(0x1e, 0x80); /* Finished good */
+    S(0x1f, 0x8); /* Bcache size */
+
+    for (i = 0x20; i < 0x80; i++)
+        S(i, 0);    /* For other cpus.  */
+
+    /* Array configuration */
+    for (i = 0x0; i < 0x4; i++) {
+        S(0x80 + 2 * i, arr[i] ? 0xf0 | i : 4);
+        if (arr[i]) {
+            int msb = ((arr[i] >> 12) & 0x0f) - 1;
+            if (msb < 2)
+                msb = 2;
+            S(0x80 + 2 * i + 1, 1 << (msb - 2));
+        }
+        else
+            S(0x80 + 2 * i + 1, 0);
+    }
+    for (i = 0x88; i < 0x90; i++)
+        S(i, 0);
+    S(0x90, 0xff); /* PSU */
+    S(0x91, 0x00); /* PSU */
+    S(0x92, 0x07); /* AC */
+    S(0x93, 0x30); /* CPU 0 */
+    S(0x94, 0x00); /* CPU 1 */
+    S(0x95, 0x00); /* CPU 2 */
+    S(0x96, 0x00); /* CPU 3 */
+    S(0x97, 0x22); /* Pci 0 */
+    S(0x98, 0x22); /* Pci 1 */
+    S(0x99, 0x22); /* Pci 2 */
+    S(0x9a, 0x90); /* fan speed */
+    S(0x9b, 0x90); /* fan speed */
+    S(0x9c, 0x90); /* fan speed */
+    S(0x9d, 0x90); /* fan speed */
+    S(0x9e, 0x90); /* fan speed */
+    S(0x9f, 0x90); /* fan speed */
+    for (i = 0xa0; i < 0xaa; i++)
+        S(i, 0); /* 680 logout frame */
+    S(0xaa, 0); /* Fan status */
+    S(0xab, 0); /* MMB0 dimm i2c */
+    S(0xac, 0); /* MMB1 dimm i2c */
+    S(0xad, 0); /* MMB2 dimm i2c */
+    S(0xae, 0); /* MMB3 dimm i2c */
+    S(0xaf, 0); /* MMB & cpu i2c */
+    S(0xb0, 0); /* cpb i2c */
+    S(0xb1, 0); /* csb i2c */
+    S(0xb2, 0); /* scsi and ps i2c */
+    for (i = 0xb3; i < 0xba; i++)
+        S(i, 0); /* usued */
+    S(0xba, 0xba); /* i2c done */
+    S(0xbb, 0x0); /* rmc flash ok */
+    S(0xbc, 0x0); /* rmc flash ok */
+
+    S(0xbd, 0x7); /* PS val */
+    S(0xbe, 0x0); /* SPC fault */
+    S(0xbf, 0x0); /* system fault */
+
+    for (i = 0xc0; i <= 0xd8; i++)
+        S(i, 0); /* usued */
+
+    S(0xd9, 2); /* RMC baud rate.  */
+    S(0xda, 0xaa); /* TIG loaded.  */
+    for (i = 0; i < 3; i++) {
+        S(0xdb + i * 9, 0xf4 + i); /* PS id */
+        S(0xdc + i * 9, 0x45);
+        S(0xdd + i * 9, 0x51);
+        S(0xde + i * 9, 0x37);
+        S(0xdf + i * 9, 0x90); /* Fan speed */
+        S(0xe0 + i * 9, 0xd6);
+        S(0xe1 + i * 9, 0x49);
+        S(0xe2 + i * 9, 0x4b);
+        S(0xe3 + i * 9, 0x0);
+    }
+    S(0xf6, 0); /* unused.  */
+    S(0xf7, 0); /* unused.  */
+    S(0xf8, 0); /* unused.  */
+    S(0xf9, 0); /* buffer size.  */
+    S(0xfa, 0); /* cmd addr.  */
+    S(0xfb, 0); /* cmd addr.  */
+    S(0xfc, 0); /* command status.  */
+    S(0xfd, 1); /* command id.  */
+    S(0xff, 1); /* command id.  */
+
+    for (i = 0x2900; i < 0x2a00; i++)
+        S(i, 0);    /* PCI backplane FRU.  */
+    for (i = 0x2a00; i < 0x2b00; i++)
+        S(i, 0);    /* motherboard FRU.  */
+    for (i = 0x2b00; i < 0x2c00; i++)
+        S(i, 0);    /* last correctable error.  */
+    for (i = 0x2c00; i < 0x2d00; i++)
+        S(i, 0);    /* last redundant error.  */
+    for (i = 0x2d00; i < 0x2e00; i++)
+        S(i, 0);    /* last system failure.  */
+
+    S(0x3000, 'V'); /* SROM version  */
+    S(0x3001, '2');
+    S(0x3002, '.');
+    S(0x3003, '2');
+    S(0x3004, '2');
+    S(0x3005, 'G');
+    S(0x3006, 0);
+    S(0x3007, 0);
+    S(0x3008, 0);
+    S(0x3009, 'V'); /* RMC rom version */
+    S(0x300a, '1');
+    S(0x300b, '0');
+    S(0x300c, 'V'); /* RMC flash version */
+    S(0x300d, '1');
+    S(0x300e, '0');
+    S(0x300f, '1'); /* RMC revision field */
+    S(0x3010, '0');
+    for (i = 0x3011; i <= 0x30ff; i++)
+        S(i, 0);    /* unsued */
+
+    S(0x3400, 8); /* Size of Bcache */
+    S(0x3401, 8); /* Flash rom valid */
+    S(0x3402, 0); /* system errors */
+    for (i = 0x3403; i < 0x3410; i++)
+        S(i, 0);    /* Reserved.  */
+    for (i = 0x3410; i < 0x3420; i++)
+        S(i, 0);    /* Jump to address.  */
+    for (i = 0x3420; i <= 0x349f; i++)
+        S(i, 0);    /* cpu 1-3 */
+    /* Array map.  */
+    for (i = 0; i < 0x20; i++) {
+        if (arr[i / 8])
+            S(0x34a0 + i, (((i >> 0) & 1) | (((i >> 1) & 1) << 3)
+                           | (((i >> 2) & 1) << 2) | (((i >> 3) & 1) << 1)
+                           | (((i >> 4) & 1) << 4)));
+        else
+            S(0x34a0 + i, 0x20);
+    }
+#undef S
+
+    tigbus_reset(s);
+    qemu_register_reset(&tigbus_reset, s);
+}
+
+struct srm_patch {
+  uint64_t addr;
+  uint32_t old_insn;
+  uint32_t new_insn;
+};
+
+static const struct srm_patch srm_patches[] = {
+  { 0x142a0, 0x259f11e2, 0x259f0000 }, /* ldah s3, 0x11e2 */
+  { 0x142a4, 0x218ca300, 0x218c0001 }, /* lda s3,-23808(s3) */
+  { 0x14260, 0x259f00e5, 0x259f0000 }, /* ldah s3,229 */
+  { 0x14264, 0x218ce1c0, 0x218c0001 }, /* lda s3,-7744(s3) */
+
+#if 1
+  /* Disable memory testing.  */
+  { 0x8bb88, 0xe4200004, 0xc3e00004 }, /* beq t0,0x8bb9c -- aa */
+  { 0x8bbc0, 0xe400001b, 0xc3e0001b }, /* beq v0,0x8bc30 -- 55 */
+  { 0x8bc48, 0xe4a0001b, 0xc3e0001b }, /* beq t4,0x8bcb8 -- 00 */
+#endif
+  { 0, 0, 0}
+};
+
+void alpha_21264_srm_write(CPUState *env)
+{
+    int fd;
+    int i;
+    uint32_t insn;
+    static const char rom_file[] = BIOS_FILENAME;
+
+    env->a21264.pal_reloc_val = 1;
+    env->a21264.pal_reloc_mask = 0;
+    env->a21264.pal_reloc_offset = 0;
+
+    /* Apply patch list.  */
+    for (i = 0; srm_patches[i].addr; i++) {
+        insn = ldl_phys(srm_patches[i].addr);
+        if (insn != srm_patches[i].old_insn)
+            fprintf(stderr, "SRM patch mismatch at %"PRIx64": insn=%x\n",
+                    srm_patches[i].addr, insn);
+        else
+            stl_phys(srm_patches[i].addr, srm_patches[i].new_insn);
+    }
+
+    /* Save SRM.  */
+    fd = open(rom_file, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0644);
+    if (fd < 0) {
+      save_error:
+        fprintf(stderr,"qemu: can't open %s\n", rom_file);
+        exit(1);
+    }
+    if (write(fd, phys_ram_base + ram_offset, SRM_SIZE) != SRM_SIZE)
+        goto save_error;
+    close(fd);
+    printf ("Bios written to %s\nExit\n", rom_file);
+    exit (0);
+}
+
+static void es40_rombuild_init(ram_addr_t ram_size, int vga_ram_size,
+                               const char *boot_device,
+                               const char *kernel_filename,
+                               const char *kernel_cmdline,
+                               const char *initrd_filename,
+                               const char *cpu_model)
+{
+    CPUState *env;
+    int bios_size;
+    int srm_ram_size;
+    int fd;
+    char buf[1024];
+
+    if (!cpu_model)
+        cpu_model = "21264";
+
+    printf("Initializing CPU\n");
+    env = cpu_init(cpu_model);
+    if (!env) {
+        fprintf(stderr, "Unable to find Alpha CPU definition\n");
+        exit(1);
+    }
+
+    /* BIOS load */
+    if (bios_name == NULL)
+        bios_name = ROMBUILD_BIOS_FILENAME;
+    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
+    fd = open(buf, O_RDONLY | O_BINARY);
+    if (fd < 0) {
+      load_error:
+        fprintf(stderr,"qemu: can't open %s\n", buf);
+        exit(1);
+    }
+    bios_size = lseek(fd, 0, SEEK_END);
+    if (bios_size <= 0)
+        goto load_error;
+    bios_size -= LFU_HDR_SIZE;
+    srm_ram_size = TARGET_PAGE_ALIGN(bios_size);
+    ram_offset = qemu_ram_alloc(LFU_MEM_SIZE);
+    lseek(fd, LFU_HDR_SIZE, SEEK_SET);
+    if (read(fd, phys_ram_base + ram_offset + LFU_LOAD_ADDR, bios_size)
+        != bios_size)
+        goto load_error;
+    close(fd);
+    memcpy(phys_ram_base + ram_offset + LFU_LOAD_ADDR + LFU_RAM_OFFSET,
+           phys_ram_base + ram_offset + LFU_LOAD_ADDR,
+           bios_size);
+    printf ("SRM loaded\n");
+
+    cpu_register_physical_memory(0, LFU_MEM_SIZE, ram_offset);
+
+    env->pc = LFU_START_ADDR;
+    env->a21264.pal_reloc_val = LFU_LOAD_ADDR;
+    env->a21264.pal_reloc_mask = ~(uint64_t)0xfffffU;
+    env->a21264.pal_reloc_offset = LFU_RAM_OFFSET;
+}
+
+static void es40_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    env->pc = 0x8000;
+}
+
+static void configure_mem_array(ram_addr_t ram_size, uint64_t *aar)
+{
+    int msb;
+    uint32_t base;
+    int i;
+    uint32_t size;
+
+    for (i = 0; i < 4; i++)
+        aar[i] = 0;
+
+    /* Configure cchip array address.  */
+    size = ram_size >> 24;
+    base = 0;
+    for (i = 0; i < 4; i++) {
+        msb = ffs(size);
+        if (msb == 0)
+            break;
+        msb--;
+        if (msb > 8)
+            msb = 8;
+        aar[i] = (((uint64_t)base) << 24)
+            | ((msb + 1) << 12) | (1 << 2) | (1 << 0);
+        base += 1 << msb;
+        size -= 1 << msb;
+        printf ("es40: arr[%d]=%016"PRIx64": %4uMB at %5uMB\n",
+                i, aar[i], 16 << msb, base << 4);
+    }
+}
+
+static void es40_init(ram_addr_t ram_size, int vga_ram_size,
+                      const char *boot_device,
+                      const char *kernel_filename, const char *kernel_cmdline,
+                      const char *initrd_filename, const char *cpu_model)
+{
+    CPUState *env;
+    char buf[1024];
+    qemu_irq *cchip_irqs;
+    qemu_irq tim_irq;
+    TyphoonState *typhoon;
+    ALI1543State *ali;
+    PCIBus *hose0;
+    uint64_t arr[4];
+
+    if (!cpu_model)
+        cpu_model = "21264";
+
+    env = cpu_init(cpu_model);
+    if (!env) {
+        fprintf(stderr, "Unable to find Alpha CPU definition\n");
+        exit(1);
+    }
+    qemu_register_reset(es40_cpu_reset, env);
+
+    /* Allocate RAM.  */
+    ram_offset = qemu_ram_alloc(ram_size);
+    cpu_register_physical_memory(0, ram_size, ram_offset);
+
+    /* SRM load */
+    if (bios_name == NULL)
+        bios_name = BIOS_FILENAME;
+    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
+    if (load_image(buf, phys_ram_base + ram_offset) != SRM_SIZE) {
+        fprintf(stderr,"qemu: can't read %s - (or bad size)\n", buf);
+        exit(1);
+    }
+
+    configure_mem_array(ram_size, arr);
+    typhoon = typhoon_21272_init(arr, &cchip_irqs, &tim_irq, env);
+    tigbus_init(arr);
+
+    hose0 = typhoon_get_pci_bus(typhoon, 0);
+
+    ali = ali1543_init(hose0, PCI_DEVFN(7,0), cchip_irqs[55]);
+
+    typhoon_set_iack_handler(typhoon, 0,
+                             (int (*)(void *))pic_read_irq, isa_pic);
+
+    rtc_init_sqw(0x70, ali1543_get_irq(ali, 8), tim_irq, 1980);
+
+    es40_cpu_reset(env);
+}
+
+
+QEMUMachine es40_rombuild_machine = {
+    .name = "es40-rombuild",
+    .desc = "Alpha es40 rom builder",
+    .init = es40_rombuild_init,
+    .ram_require = 16 << 20
+};
+
+QEMUMachine es40_machine = {
+    .name = "es40",
+    .desc = "Alpha es40",
+    .init = es40_init,
+    .ram_require = 64 << 20
+};
diff --git a/target-alpha/machine.c b/target-alpha/machine.c
new file mode 100644
index 0000000..ed42af9
--- /dev/null
+++ b/target-alpha/machine.c
@@ -0,0 +1,22 @@
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "qemu-timer.h"
+
+#include "exec-all.h"
+
+void register_machines(void)
+{
+    qemu_register_machine(&es40_machine);
+    qemu_register_machine(&es40_rombuild_machine);
+}
+
+void cpu_save(QEMUFile *f, void *opaque)
+{
+    /* FIXME: todo  */
+    abort();
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+    return -EINVAL;
+}
-- 
1.6.2

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

* [Qemu-devel] [PATCH 13/19] Move softmmu_helper.h from exec.h to op_helper.c on alpha.
  2009-03-30 14:36                       ` [Qemu-devel] [PATCH 12/19] Add target-alpha/machine.c and hw/es40.c for es40 machine emulation Tristan Gingold
@ 2009-03-30 14:36                         ` Tristan Gingold
  2009-03-30 14:36                           ` [Qemu-devel] [PATCH 14/19] alpha ld helpers now directly return the value Tristan Gingold
  0 siblings, 1 reply; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

There is no real needs to inline these functions everywhere and this
simplify debugging.

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 target-alpha/exec.h      |    4 ----
 target-alpha/op_helper.c |    4 ++++
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/target-alpha/exec.h b/target-alpha/exec.h
index 9ea7030..0ce82c8 100644
--- a/target-alpha/exec.h
+++ b/target-alpha/exec.h
@@ -36,10 +36,6 @@ register struct CPUAlphaState *env asm(AREG0);
 #include "cpu.h"
 #include "exec-all.h"
 
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif /* !defined(CONFIG_USER_ONLY) */
-
 static always_inline void env_to_regs(void)
 {
 }
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 433a0da..4b6ada7 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -23,6 +23,10 @@
 #include "softfloat.h"
 #include "helper.h"
 
+#if !defined(CONFIG_USER_ONLY)
+#include "softmmu_exec.h"
+#endif /* !defined(CONFIG_USER_ONLY) */
+
 void helper_tb_flush (void)
 {
     tb_flush(env);
-- 
1.6.2

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

* [Qemu-devel] [PATCH 14/19] alpha ld helpers now directly return the value.
  2009-03-30 14:36                         ` [Qemu-devel] [PATCH 13/19] Move softmmu_helper.h from exec.h to op_helper.c on alpha Tristan Gingold
@ 2009-03-30 14:36                           ` Tristan Gingold
  2009-03-30 14:36                             ` [Qemu-devel] [PATCH 15/19] Add alpha_cpu_list Tristan Gingold
  0 siblings, 1 reply; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

Remove _kernel helpers as they can be directly generated.
Replace ld/st_raw with _phys (bug fix).
Change argument name for st helpers (t0/t1 -> val/addr).

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 target-alpha/helper.h    |   22 +++++++---------
 target-alpha/op_helper.c |   62 ++++++++++++++++++++-------------------------
 target-alpha/translate.c |   32 ++++++++++++------------
 3 files changed, 54 insertions(+), 62 deletions(-)

diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 4c4855d..7c7278f 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -116,18 +116,16 @@ DEF_HELPER_0(restore_mode, void)
 
 DEF_HELPER_1(ld_virt_to_phys, i64, i64)
 DEF_HELPER_1(st_virt_to_phys, i64, i64)
-DEF_HELPER_2(ldl_raw, void, i64, i64)
-DEF_HELPER_2(ldq_raw, void, i64, i64)
-DEF_HELPER_2(ldl_l_raw, void, i64, i64)
-DEF_HELPER_2(ldq_l_raw, void, i64, i64)
-DEF_HELPER_2(ldl_kernel, void, i64, i64)
-DEF_HELPER_2(ldq_kernel, void, i64, i64)
-DEF_HELPER_2(ldl_data, void, i64, i64)
-DEF_HELPER_2(ldq_data, void, i64, i64)
-DEF_HELPER_2(stl_raw, void, i64, i64)
-DEF_HELPER_2(stq_raw, void, i64, i64)
-DEF_HELPER_2(stl_c_raw, i64, i64, i64)
-DEF_HELPER_2(stq_c_raw, i64, i64, i64)
+DEF_HELPER_1(ldl_phys, i64, i64)
+DEF_HELPER_1(ldq_phys, i64, i64)
+DEF_HELPER_1(ldl_l_phys, i64, i64)
+DEF_HELPER_1(ldq_l_phys, i64, i64)
+DEF_HELPER_1(ldl_data, i64, i64)
+DEF_HELPER_1(ldq_data, i64, i64)
+DEF_HELPER_2(stl_phys, void, i64, i64)
+DEF_HELPER_2(stq_phys, void, i64, i64)
+DEF_HELPER_2(stl_c_phys, i64, i64, i64)
+DEF_HELPER_2(stq_c_phys, i64, i64, i64)
 #endif
 
 #include "def-helper.h"
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 4b6ada7..9e9289f 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1091,64 +1091,58 @@ uint64_t helper_st_virt_to_phys (uint64_t virtaddr)
     return physaddr;
 }
 
-void helper_ldl_raw(uint64_t t0, uint64_t t1)
+uint64_t helper_ldl_phys(uint64_t addr)
 {
-    ldl_raw(t1, t0);
+    return ldl_phys(addr);
 }
 
-void helper_ldq_raw(uint64_t t0, uint64_t t1)
+uint64_t helper_ldq_phys(uint64_t addr)
 {
-    ldq_raw(t1, t0);
+    return ldq_phys(addr);
 }
 
-void helper_ldl_l_raw(uint64_t t0, uint64_t t1)
+uint64_t helper_ldl_l_phys(uint64_t addr)
 {
-    env->lock = t1;
-    ldl_raw(t1, t0);
+    env->lock = addr;
+    return ldl_phys(addr);
 }
 
-void helper_ldq_l_raw(uint64_t t0, uint64_t t1)
+uint64_t helper_ldq_l_phys(uint64_t addr)
 {
-    env->lock = t1;
-    ldl_raw(t1, t0);
+    env->lock = addr;
+    return ldl_raw(addr);
 }
 
-void helper_ldl_kernel(uint64_t t0, uint64_t t1)
+uint64_t helper_ldl_data(uint64_t addr)
 {
-    ldl_kernel(t1, t0);
+    /* FIXME: ldl_data won't work in case of fault  */
+    cpu_abort(env, "ldl_data not implemented\n");
+    return ldl_data(addr);
 }
 
-void helper_ldq_kernel(uint64_t t0, uint64_t t1)
+uint64_t helper_ldq_data(uint64_t addr)
 {
-    ldq_kernel(t1, t0);
+    /* FIXME: ldq_data won't work in case of fault  */
+    cpu_abort(env, "ldq_data not implemented\n");
+    return ldq_data(addr);
 }
 
-void helper_ldl_data(uint64_t t0, uint64_t t1)
+void helper_stl_phys(uint64_t val, uint64_t addr)
 {
-    ldl_data(t1, t0);
+    stl_phys(addr, val);
 }
 
-void helper_ldq_data(uint64_t t0, uint64_t t1)
+void helper_stq_phys(uint64_t val, uint64_t addr)
 {
-    ldq_data(t1, t0);
+    stq_phys(addr, val);
 }
 
-void helper_stl_raw(uint64_t t0, uint64_t t1)
-{
-    stl_raw(t1, t0);
-}
-
-void helper_stq_raw(uint64_t t0, uint64_t t1)
-{
-    stq_raw(t1, t0);
-}
-
-uint64_t helper_stl_c_raw(uint64_t t0, uint64_t t1)
+uint64_t helper_stl_c_phys(uint64_t val, uint64_t addr)
 {
     uint64_t ret;
 
-    if (t1 == env->lock) {
-        stl_raw(t1, t0);
+    if (addr == env->lock) {
+        stl_phys(addr, val);
         ret = 0;
     } else
         ret = 1;
@@ -1158,12 +1152,12 @@ uint64_t helper_stl_c_raw(uint64_t t0, uint64_t t1)
     return ret;
 }
 
-uint64_t helper_stq_c_raw(uint64_t t0, uint64_t t1)
+uint64_t helper_stq_c_phys(uint64_t val, uint64_t addr)
 {
     uint64_t ret;
 
-    if (t1 == env->lock) {
-        stq_raw(t1, t0);
+    if (addr == env->lock) {
+        stq_phys(addr, val);
         ret = 0;
     } else
         ret = 1;
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 821f0d4..41f24a5 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1794,19 +1794,19 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
             switch ((insn >> 12) & 0xF) {
             case 0x0:
                 /* Longword physical access (hw_ldl/p) */
-                gen_helper_ldl_raw(cpu_ir[ra], addr);
+                gen_helper_ldl_phys(cpu_ir[ra], addr);
                 break;
             case 0x1:
                 /* Quadword physical access (hw_ldq/p) */
-                gen_helper_ldq_raw(cpu_ir[ra], addr);
+                gen_helper_ldq_phys(cpu_ir[ra], addr);
                 break;
             case 0x2:
                 /* Longword physical access with lock (hw_ldl_l/p) */
-                gen_helper_ldl_l_raw(cpu_ir[ra], addr);
+                gen_helper_ldl_l_phys(cpu_ir[ra], addr);
                 break;
             case 0x3:
                 /* Quadword physical access with lock (hw_ldq_l/p) */
-                gen_helper_ldq_l_raw(cpu_ir[ra], addr);
+                gen_helper_ldq_l_phys(cpu_ir[ra], addr);
                 break;
             case 0x4:
                 /* Longword virtual PTE fetch (hw_ldl/v) */
@@ -1825,12 +1825,12 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
             case 0x8:
                 /* Longword virtual access (hw_ldl) */
                 gen_helper_st_virt_to_phys(addr, addr);
-                gen_helper_ldl_raw(cpu_ir[ra], addr);
+                gen_helper_ldl_phys(cpu_ir[ra], addr);
                 break;
             case 0x9:
                 /* Quadword virtual access (hw_ldq) */
                 gen_helper_st_virt_to_phys(addr, addr);
-                gen_helper_ldq_raw(cpu_ir[ra], addr);
+                gen_helper_ldq_phys(cpu_ir[ra], addr);
                 break;
             case 0xA:
                 /* Longword virtual access with protection check (hw_ldl/w) */
@@ -1844,14 +1844,14 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
                 /* Longword virtual access with alt access mode (hw_ldl/a)*/
                 gen_helper_set_alt_mode();
                 gen_helper_st_virt_to_phys(addr, addr);
-                gen_helper_ldl_raw(cpu_ir[ra], addr);
+                gen_helper_ldl_phys(cpu_ir[ra], addr);
                 gen_helper_restore_mode();
                 break;
             case 0xD:
                 /* Quadword virtual access with alt access mode (hw_ldq/a) */
                 gen_helper_set_alt_mode();
                 gen_helper_st_virt_to_phys(addr, addr);
-                gen_helper_ldq_raw(cpu_ir[ra], addr);
+                gen_helper_ldq_phys(cpu_ir[ra], addr);
                 gen_helper_restore_mode();
                 break;
             case 0xE:
@@ -2123,29 +2123,29 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
             switch ((insn >> 12) & 0xF) {
             case 0x0:
                 /* Longword physical access */
-                gen_helper_stl_raw(val, addr);
+                gen_helper_stl_phys(val, addr);
                 break;
             case 0x1:
                 /* Quadword physical access */
-                gen_helper_stq_raw(val, addr);
+                gen_helper_stq_phys(val, addr);
                 break;
             case 0x2:
                 /* Longword physical access with lock */
-                gen_helper_stl_c_raw(val, val, addr);
+                gen_helper_stl_c_phys(val, val, addr);
                 break;
             case 0x3:
                 /* Quadword physical access with lock */
-                gen_helper_stq_c_raw(val, val, addr);
+                gen_helper_stq_c_phys(val, val, addr);
                 break;
             case 0x4:
                 /* Longword virtual access */
                 gen_helper_st_virt_to_phys(addr, addr);
-                gen_helper_stl_raw(val, addr);
+                gen_helper_stl_phys(val, addr);
                 break;
             case 0x5:
                 /* Quadword virtual access */
                 gen_helper_st_virt_to_phys(addr, addr);
-                gen_helper_stq_raw(val, addr);
+                gen_helper_stq_phys(val, addr);
                 break;
             case 0x6:
                 /* Invalid */
@@ -2169,14 +2169,14 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
                 /* Longword virtual access with alternate access mode */
                 gen_helper_set_alt_mode();
                 gen_helper_st_virt_to_phys(addr, addr);
-                gen_helper_stl_raw(val, addr);
+                gen_helper_stl_phys(val, addr);
                 gen_helper_restore_mode();
                 break;
             case 0xD:
                 /* Quadword virtual access with alternate access mode */
                 gen_helper_set_alt_mode();
                 gen_helper_st_virt_to_phys(addr, addr);
-                gen_helper_stl_raw(val, addr);
+                gen_helper_stl_phys(val, addr);
                 gen_helper_restore_mode();
                 break;
             case 0xE:
-- 
1.6.2

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

* [Qemu-devel] [PATCH 15/19] Add alpha_cpu_list.
  2009-03-30 14:36                           ` [Qemu-devel] [PATCH 14/19] alpha ld helpers now directly return the value Tristan Gingold
@ 2009-03-30 14:36                             ` Tristan Gingold
  2009-03-30 14:36                               ` [Qemu-devel] [PATCH 16/19] Alpha: lower parent irq when irq is lowered Tristan Gingold
  0 siblings, 1 reply; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

Add alpha_cpu_list and use cpu_model to select the model in cpu_alpha_init.
Set implver and amask from the model.

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 target-alpha/cpu.h       |    1 +
 target-alpha/translate.c |   40 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index db53650..c27e89f 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -436,6 +436,7 @@ enum {
 
 CPUAlphaState * cpu_alpha_init (const char *cpu_model);
 int cpu_alpha_exec(CPUAlphaState *s);
+void alpha_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...));
 /* you can call this signal handler from your SIGBUS and SIGSEGV
    signal handlers to inform the virtual CPU of exceptions. non zero
    is returned if the signal was handled by the virtual CPU.  */
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 41f24a5..dab8d78 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2459,17 +2459,53 @@ void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
     gen_intermediate_code_internal(env, tb, 1);
 }
 
+struct alpha_def {
+    const char *name;
+    uint32_t implver;
+    uint32_t amask;
+};
+
+static const struct alpha_def alpha_defs[] = {
+#ifdef CONFIG_USER_ONLY
+    { "21064", IMPLVER_2106x, 0 },
+    { "21164", IMPLVER_21164, 0 },
+#endif
+    { "21264", IMPLVER_21264, (AMASK_PREFETCH | AMASK_TRAP | AMASK_BWX
+                               | AMASK_FIX) },
+};
+
+void alpha_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(alpha_defs); i++)
+        (*cpu_fprintf)(f, "%s\n", alpha_defs[i].name);
+}
+
 CPUAlphaState * cpu_alpha_init (const char *cpu_model)
 {
     CPUAlphaState *env;
     uint64_t hwpcb;
+    const struct alpha_def *cpu = alpha_defs;
+
+    if (cpu_model != NULL) {
+        int i;
 
+        for (i = 0; i < ARRAY_SIZE(alpha_defs); i++)
+            if (strcmp (alpha_defs[i].name, cpu_model) == 0) {
+                cpu = &alpha_defs[i];
+                break;
+            }
+        if (cpu == NULL)
+            return NULL;
+    }
     env = qemu_mallocz(sizeof(CPUAlphaState));
     cpu_exec_init(env);
     alpha_translate_init();
     tlb_flush(env, 1);
-    /* XXX: should not be hardcoded */
-    env->implver = IMPLVER_2106x;
+
+    env->implver = cpu->implver;
+    env->amask = cpu->amask;
     env->ps = 0x1F00;
 #if defined (CONFIG_USER_ONLY)
     env->ps |= 1 << 3;
-- 
1.6.2

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

* [Qemu-devel] [PATCH 16/19] Alpha: lower parent irq when irq is lowered.
  2009-03-30 14:36                             ` [Qemu-devel] [PATCH 15/19] Add alpha_cpu_list Tristan Gingold
@ 2009-03-30 14:36                               ` Tristan Gingold
  2009-03-30 14:36                                 ` [Qemu-devel] [PATCH 17/19] Move linux-user pal emulation to linux-user/ Tristan Gingold
  2009-04-15 14:42                                 ` [Qemu-devel] [PATCH 16/19] Alpha: lower parent irq when irq is lowered Aurelien Jarno
  0 siblings, 2 replies; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 hw/i8259.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/i8259.c b/hw/i8259.c
index f813525..adabd2b 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -169,7 +169,7 @@ void pic_update_irq(PicState2 *s)
     }
 
 /* all targets should do this rather than acking the IRQ in the cpu */
-#if defined(TARGET_MIPS) || defined(TARGET_PPC)
+#if defined(TARGET_MIPS) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
     else {
         qemu_irq_lower(s->parent_irq);
     }
-- 
1.6.2

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

* [Qemu-devel] [PATCH 17/19] Move linux-user pal emulation to linux-user/
  2009-03-30 14:36                               ` [Qemu-devel] [PATCH 16/19] Alpha: lower parent irq when irq is lowered Tristan Gingold
@ 2009-03-30 14:36                                 ` Tristan Gingold
  2009-03-30 14:36                                   ` [Qemu-devel] [PATCH 18/19] Correctly decode hw_ld/hw_st opcodes for all alpha implementations Tristan Gingold
  2009-04-15 14:42                                 ` [Qemu-devel] [PATCH 16/19] Alpha: lower parent irq when irq is lowered Aurelien Jarno
  1 sibling, 1 reply; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

Move pal emulation for user emulation from alpha_palcode.c to linux-user/mai
Add generic exception names.
Fix offset for PAL calls.

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 Makefile.target          |    5 +--
 hw/alpha_palcode.c       |   44 ---------------------
 linux-user/main.c        |   96 +++++++++++++++++++++++++---------------------
 target-alpha/cpu.h       |   39 +++++++++++++++---
 target-alpha/helper.c    |    4 +-
 target-alpha/translate.c |    1 -
 6 files changed, 87 insertions(+), 102 deletions(-)

diff --git a/Makefile.target b/Makefile.target
index 68937fe..de6f7eb 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -157,10 +157,6 @@ ifeq ($(TARGET_BASE_ARCH), arm)
 LIBOBJS+= neon_helper.o iwmmxt_helper.o
 endif
 
-ifeq ($(TARGET_BASE_ARCH), alpha)
-LIBOBJS+= alpha_palcode.o
-endif
-
 ifeq ($(TARGET_BASE_ARCH), cris)
 LIBOBJS+= cris-dis.o
 
@@ -686,6 +682,7 @@ endif
 ifeq ($(TARGET_BASE_ARCH), alpha)
 OBJS+= es40.o 21272.o serial.o i8259.o mc146818rtc.o i8254.o pcspk.o dma.o
 OBJS+= ali1543.o
+#OBJS+= alpha_palcode.o # Not currently used until pal is virtualized
 endif
 ifdef CONFIG_GDBSTUB
 OBJS+=gdbstub.o gdbstub-xml.o
diff --git a/hw/alpha_palcode.c b/hw/alpha_palcode.c
index bfffb5d..189033c 100644
--- a/hw/alpha_palcode.c
+++ b/hw/alpha_palcode.c
@@ -26,7 +26,6 @@
 #include "cpu.h"
 #include "exec-all.h"
 
-#if !defined (CONFIG_USER_ONLY)
 /* Shared handlers */
 static void pal_reset (CPUState *env);
 /* Console handlers */
@@ -1051,46 +1050,3 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
     return ret;
 }
 #endif
-
-#else /* !defined (CONFIG_USER_ONLY) */
-void pal_init (CPUState *env)
-{
-}
-
-void call_pal (CPUState *env, int palcode)
-{
-    target_long ret;
-
-    qemu_log("%s: palcode %02x\n", __func__, palcode);
-    switch (palcode) {
-    case 0x83:
-        /* CALLSYS */
-        qemu_log("CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]);
-        ret = do_syscall(env, env->ir[IR_V0], env->ir[IR_A0], env->ir[IR_A1],
-                         env->ir[IR_A2], env->ir[IR_A3], env->ir[IR_A4],
-                         env->ir[IR_A5]);
-        if (ret >= 0) {
-            env->ir[IR_A3] = 0;
-            env->ir[IR_V0] = ret;
-        } else {
-            env->ir[IR_A3] = 1;
-            env->ir[IR_V0] = -ret;
-        }
-        break;
-    case 0x9E:
-        /* RDUNIQUE */
-        env->ir[IR_V0] = env->unique;
-        qemu_log("RDUNIQUE: " TARGET_FMT_lx "\n", env->unique);
-        break;
-    case 0x9F:
-        /* WRUNIQUE */
-        env->unique = env->ir[IR_A0];
-        qemu_log("WRUNIQUE: " TARGET_FMT_lx "\n", env->unique);
-        break;
-    default:
-        qemu_log("%s: unhandled palcode %02x\n",
-                    __func__, palcode);
-        exit(1);
-    }
-}
-#endif
diff --git a/linux-user/main.c b/linux-user/main.c
index feb3036..5a1e98b 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2110,6 +2110,43 @@ void cpu_loop(CPUM68KState *env)
 #endif /* TARGET_M68K */
 
 #ifdef TARGET_ALPHA
+static void call_pal (CPUState *env, int palcode)
+{
+    target_long ret;
+
+    qemu_log("%s: palcode %02x\n", __func__, palcode);
+    switch (palcode) {
+    case 0x83:
+        /* CALLSYS */
+        qemu_log("CALLSYS n " TARGET_FMT_ld "\n", env->ir[0]);
+        ret = do_syscall(env, env->ir[IR_V0], env->ir[IR_A0], env->ir[IR_A1],
+                         env->ir[IR_A2], env->ir[IR_A3], env->ir[IR_A4],
+                         env->ir[IR_A5]);
+        if (ret >= 0) {
+            env->ir[IR_A3] = 0;
+            env->ir[IR_V0] = ret;
+        } else {
+            env->ir[IR_A3] = 1;
+            env->ir[IR_V0] = -ret;
+        }
+        break;
+    case 0x9E:
+        /* RDUNIQUE */
+        env->ir[IR_V0] = env->user.unique;
+        qemu_log("RDUNIQUE: " TARGET_FMT_lx "\n", env->user.unique);
+        break;
+    case 0x9F:
+        /* WRUNIQUE */
+        env->user.unique = env->ir[IR_A0];
+        qemu_log("WRUNIQUE: " TARGET_FMT_lx "\n", env->user.unique);
+        break;
+    default:
+        qemu_log("%s: unhandled palcode %02x\n",
+                    __func__, palcode);
+        exit(1);
+    }
+}
+
 void cpu_loop (CPUState *env)
 {
     int trapnr;
@@ -2119,61 +2156,29 @@ void cpu_loop (CPUState *env)
         trapnr = cpu_alpha_exec (env);
 
         switch (trapnr) {
-        case EXCP_RESET:
-            fprintf(stderr, "Reset requested. Exit\n");
-            exit(1);
-            break;
-        case EXCP_MCHK:
-            fprintf(stderr, "Machine check exception. Exit\n");
-            exit(1);
-            break;
-        case EXCP_ARITH:
+        case EXCP_GEN_ARITH:
             fprintf(stderr, "Arithmetic trap.\n");
             exit(1);
             break;
-        case EXCP_HW_INTERRUPT:
-            fprintf(stderr, "External interrupt. Exit\n");
-            exit(1);
-            break;
-        case EXCP_DFAULT:
-            fprintf(stderr, "MMU data fault\n");
+        case EXCP_GEN_INTERRUPT:
+            fprintf(stderr, "Hardware interruption\n");
             exit(1);
             break;
-        case EXCP_DTB_MISS_PAL:
-            fprintf(stderr, "MMU data TLB miss in PALcode\n");
-            exit(1);
-            break;
-        case EXCP_ITB_MISS:
-            fprintf(stderr, "MMU instruction TLB miss\n");
-            exit(1);
-            break;
-        case EXCP_ITB_ACV:
-            fprintf(stderr, "MMU instruction access violation\n");
-            exit(1);
-            break;
-        case EXCP_DTB_MISS_NATIVE:
-            fprintf(stderr, "MMU data TLB miss\n");
-            exit(1);
-            break;
-        case EXCP_UNALIGN:
-            fprintf(stderr, "Unaligned access\n");
-            exit(1);
-            break;
-        case EXCP_OPCDEC:
+        case EXCP_GEN_OPCDEC:
             fprintf(stderr, "Invalid instruction\n");
             exit(1);
             break;
-        case EXCP_FEN:
-            fprintf(stderr, "Floating-point not allowed\n");
+        case EXCP_USER_ITB_MISS:
+            fprintf(stderr, "MMU instruction TLB miss\n");
             exit(1);
             break;
-        case EXCP_CALL_PAL ... (EXCP_CALL_PALP - 1):
-            call_pal(env, (trapnr >> 6) | 0x80);
-            break;
-        case EXCP_CALL_PALP ... (EXCP_CALL_PALE - 1):
+        case EXCP_CALL_PALP ... (EXCP_CALL_PAL - 1):
             fprintf(stderr, "Privileged call to PALcode\n");
             exit(1);
             break;
+        case EXCP_CALL_PAL ... (EXCP_CALL_PALE - 1):
+            call_pal(env, ((trapnr - EXCP_CALL_PAL) >> 6) | 0x80);
+            break;
         case EXCP_DEBUG:
             {
                 int sig;
@@ -2409,6 +2414,9 @@ int main(int argc, char **argv, char **envp)
 #else
         cpu_model = "750";
 #endif
+#elif defined(TARGET_ALPHA)
+        cpu_model = "21264";
+
 #else
         cpu_model = "any";
 #endif
@@ -2665,10 +2673,10 @@ int main(int argc, char **argv, char **envp)
         for(i = 0; i < 28; i++) {
             env->ir[i] = ((abi_ulong *)regs)[i];
         }
-        env->ipr[IPR_USP] = regs->usp;
+        env->user.usp = regs->usp;
         env->ir[30] = regs->usp;
         env->pc = regs->pc;
-        env->unique = regs->unique;
+        env->user.unique = regs->unique;
     }
 #elif defined(TARGET_CRIS)
     {
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index c27e89f..7cd6395 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -291,7 +291,11 @@ struct pal_handler_t {
     void (*call_pal)(CPUAlphaState *env, uint32_t palcode);
 };
 
+#if !defined(CONFIG_USER_ONLY)
 #define NB_MMU_MODES 4
+#else
+#define NB_MMU_MODES 2
+#endif
 
 struct CPUAlphaState {
     uint64_t ir[31];
@@ -318,6 +322,12 @@ struct CPUAlphaState {
     CPU_COMMON
 
     uint32_t hflags;
+#if defined(CONFIG_USER_ONLY)
+    struct {
+        uint64_t usp;
+        uint64_t unique;
+    } user;
+#endif
 
     int error_code;
 
@@ -342,6 +352,8 @@ struct CPUAlphaState {
 #define MMU_KERNEL_IDX 0
 #define MMU_USER_IDX 3
 #define MMU_PAL_IDX 4
+
+#if !defined(CONFIG_USER_ONLY)
 static inline int cpu_mmu_index_data (CPUState *env)
 {
     return env->mmu_data_index;
@@ -351,8 +363,13 @@ static inline int cpu_mmu_index_code (CPUState *env)
 {
     return env->mmu_code_index;
 }
+#else
+#define cpu_mmu_index_data cpu_mmu_index_code
+static inline int cpu_mmu_index_code (CPUState *env)
+{
+    return 0;
+}
 
-#if defined(CONFIG_USER_ONLY)
 static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
 {
     if (newsp)
@@ -384,9 +401,20 @@ enum {
     EXCP_UNALIGN          = 0x11E0,
     EXCP_OPCDEC           = 0x13E0,
     EXCP_FEN              = 0x17E0,
-    EXCP_CALL_PAL         = 0x2000,
-    EXCP_CALL_PALP        = 0x3000,
-    EXCP_CALL_PALE        = 0x4000,
+
+    /* Generic exception - to be mapped to processor.  */
+    EXCP_GEN_OPCDEC             = 1,
+    EXCP_GEN_ARITH              = 2,
+    EXCP_GEN_INTERRUPT          = 3,
+    EXCP_GEN_LAST               = 3,
+
+    /* User linux exception.  */
+    EXCP_USER_DFAULT            = 0x0100,
+    EXCP_USER_ITB_MISS          = 0x0101,
+
+    EXCP_CALL_PALP        = 0x2000,
+    EXCP_CALL_PAL         = 0x3000,
+    EXCP_CALL_PALE        = 0x4000, /* End of Pal */
     /* Pseudo exception for console */
     EXCP_CONSOLE_DISPATCH = 0x4001,
     EXCP_CONSOLE_FIXUP    = 0x4002,
@@ -448,11 +476,8 @@ void do_interrupt (CPUState *env);
 
 int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp);
 int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp);
-void pal_init (CPUState *env);
 #if !defined (CONFIG_USER_ONLY)
 void call_pal (CPUState *env);
-#else
-void call_pal (CPUState *env, int palcode);
 #endif
 
 static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index fc68a7e..4046463 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -31,9 +31,9 @@ int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
                                 int mmu_idx, int is_softmmu)
 {
     if (rw == 2)
-        env->exception_index = EXCP_ITB_MISS;
+        env->exception_index = EXCP_USER_ITB_MISS;
     else
-        env->exception_index = EXCP_DFAULT;
+        env->exception_index = EXCP_USER_DFAULT;
     env->ipr[IPR_EXC_ADDR] = address;
 
     return 1;
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index dab8d78..061cf5f 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2510,7 +2510,6 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
 #if defined (CONFIG_USER_ONLY)
     env->ps |= 1 << 3;
 #endif
-    pal_init(env);
     /* Initialize IPR */
     hwpcb = env->ipr[IPR_PCBB];
     env->ipr[IPR_ASN] = 0;
-- 
1.6.2

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

* [Qemu-devel] [PATCH 18/19] Correctly decode hw_ld/hw_st opcodes for all alpha implementations.
  2009-03-30 14:36                                 ` [Qemu-devel] [PATCH 17/19] Move linux-user pal emulation to linux-user/ Tristan Gingold
@ 2009-03-30 14:36                                   ` Tristan Gingold
  2009-03-30 14:36                                     ` [Qemu-devel] [PATCH 19/19] Add full emulation for 21264 Tristan Gingold
  2009-04-07 21:52                                     ` [Qemu-devel] [PATCH 18/19] Correctly decode hw_ld/hw_st opcodes for all alpha implementations Aurelien Jarno
  0 siblings, 2 replies; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

Allow privilegied pal_code only in kernel mode.

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 target-alpha/translate.c |   30 +++++++++++++++++++++++-------
 1 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 061cf5f..6938b5d 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -52,6 +52,7 @@ struct DisasContext {
     int pal_mode;
 #endif
     uint32_t amask;
+    uint32_t implver;
 };
 
 /* global register indexes */
@@ -103,6 +104,20 @@ static void alpha_translate_init(void)
     done_init = 1;
 }
 
+static inline int get_mxcr_iprn(DisasContext *ctx, uint32_t insn)
+{
+    switch (ctx->implver) {
+    case IMPLVER_2106x:
+        return insn & 0xff;
+    case IMPLVER_21164:
+        return insn & 0xffff;
+    case IMPLVER_21264:
+        return (insn >> 8) & 0xff;
+    default:
+        abort();
+    }
+}
+
 static always_inline void gen_excp (DisasContext *ctx,
                                     int exception, int error_code)
 {
@@ -689,7 +704,7 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
 #if !defined (CONFIG_USER_ONLY)
         } else if (palcode < 0x40) {
             /* Privileged PAL code */
-            if (ctx->mem_idx & 1)
+            if (ctx->mem_idx != MMU_KERNEL_IDX)
                 goto invalid_opc;
             else
                 gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x3F) << 6), 0);
@@ -1748,7 +1763,7 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
         if (!ctx->pal_mode)
             goto invalid_opc;
         if (ra != 31) {
-            TCGv tmp = tcg_const_i32(insn & 0xFF);
+            TCGv tmp = tcg_const_i32(get_mxcr_iprn(ctx, insn));
             gen_helper_mfpr(cpu_ir[ra], tmp, cpu_ir[ra]);
             tcg_temp_free(tmp);
         }
@@ -2063,9 +2078,9 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
         if (!ctx->pal_mode)
             goto invalid_opc;
         else {
-            TCGv tmp1 = tcg_const_i32(insn & 0xFF);
-            if (ra != 31)
-                gen_helper_mtpr(tmp1, cpu_ir[ra]);
+            TCGv tmp1 = tcg_const_i32(get_mxcr_iprn(ctx, insn));
+            if (rb != 31)
+                gen_helper_mtpr(tmp1, cpu_ir[rb]);
             else {
                 TCGv tmp2 = tcg_const_i64(0);
                 gen_helper_mtpr(tmp1, tmp2);
@@ -2089,7 +2104,7 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
         } else {
             TCGv tmp;
 
-            if (ra != 31) {
+            if (rb != 31) {
                 tmp = tcg_temp_new();
                 tcg_gen_addi_i64(tmp, cpu_ir[rb], (((int64_t)insn << 51) >> 51));
             } else
@@ -2097,7 +2112,7 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
             gen_helper_hw_ret(tmp);
             tcg_temp_free(tmp);
         }
-        ret = 2;
+        ret = 3;
         break;
 #endif
     case 0x1F:
@@ -2352,6 +2367,7 @@ static always_inline void gen_intermediate_code_internal (CPUState *env,
     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
     ctx.pc = pc_start;
     ctx.amask = env->amask;
+    ctx.implver = env->implver;
 #if defined (CONFIG_USER_ONLY)
     ctx.mem_idx = 0;
 #else
-- 
1.6.2

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

* [Qemu-devel] [PATCH 19/19] Add full emulation for 21264.
  2009-03-30 14:36                                   ` [Qemu-devel] [PATCH 18/19] Correctly decode hw_ld/hw_st opcodes for all alpha implementations Tristan Gingold
@ 2009-03-30 14:36                                     ` Tristan Gingold
  2009-04-07 21:52                                     ` [Qemu-devel] [PATCH 18/19] Correctly decode hw_ld/hw_st opcodes for all alpha implementations Aurelien Jarno
  1 sibling, 0 replies; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 14:36 UTC (permalink / raw)
  To: qemu-devel

This is still work in progress but complete enough to run the firmware.

Remove old and incomplete code for pal virtualization.

Signed-off-by: Tristan Gingold <gingold@adacore.com>
---
 cpu-exec.c               |    1 +
 hw/alpha_palcode.c       |   37 ++-
 target-alpha/cpu.h       |  286 +++++++++++------
 target-alpha/helper.c    |  798 +++++++++++++++++++++++++++++-----------------
 target-alpha/helper.h    |    6 +-
 target-alpha/op_helper.c |  199 ++++++++-----
 target-alpha/translate.c |  153 +++++----
 7 files changed, 944 insertions(+), 536 deletions(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index cf7c1fb..674d521 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -486,6 +486,7 @@ int cpu_exec(CPUState *env1)
                     }
 #elif defined(TARGET_ALPHA)
                     if (interrupt_request & CPU_INTERRUPT_HARD) {
+                        env->exception_index = EXCP_GEN_INTERRUPT;
                         do_interrupt(env);
                         next_tb = 0;
                     }
diff --git a/hw/alpha_palcode.c b/hw/alpha_palcode.c
index 189033c..c778319 100644
--- a/hw/alpha_palcode.c
+++ b/hw/alpha_palcode.c
@@ -22,10 +22,39 @@
 #include <stdlib.h>
 #include <stdio.h>
 
-#include "qemu.h"
 #include "cpu.h"
 #include "exec-all.h"
 
+typedef struct pal_handler_t pal_handler_t;
+struct pal_handler_t {
+    /* Reset */
+    void (*reset)(CPUAlphaState *env);
+    /* Uncorrectable hardware error */
+    void (*machine_check)(CPUAlphaState *env);
+    /* Arithmetic exception */
+    void (*arithmetic)(CPUAlphaState *env);
+    /* Interrupt / correctable hardware error */
+    void (*interrupt)(CPUAlphaState *env);
+    /* Data fault */
+    void (*dfault)(CPUAlphaState *env);
+    /* DTB miss pal */
+    void (*dtb_miss_pal)(CPUAlphaState *env);
+    /* DTB miss native */
+    void (*dtb_miss_native)(CPUAlphaState *env);
+    /* Unaligned access */
+    void (*unalign)(CPUAlphaState *env);
+    /* ITB miss */
+    void (*itb_miss)(CPUAlphaState *env);
+    /* Instruction stream access violation */
+    void (*itb_acv)(CPUAlphaState *env);
+    /* Reserved or privileged opcode */
+    void (*opcdec)(CPUAlphaState *env);
+    /* Floating point exception */
+    void (*fen)(CPUAlphaState *env);
+    /* Call pal instruction */
+    void (*call_pal)(CPUAlphaState *env, uint32_t palcode);
+};
+
 /* Shared handlers */
 static void pal_reset (CPUState *env);
 /* Console handlers */
@@ -88,7 +117,7 @@ static void do_swappal (CPUState *env, uint64_t palid)
     case 0 ... 2:
         pal_handler = &pal_handlers[palid];
         env->pal_handler = pal_handler;
-        env->ipr[IPR_PAL_BASE] = -1ULL;
+        env->pal_base = -1ULL;
         (*pal_handler->reset)(env);
         break;
     case 3 ... 255:
@@ -98,8 +127,8 @@ static void do_swappal (CPUState *env, uint64_t palid)
     default:
         /* We were given the entry point address */
         env->pal_handler = NULL;
-        env->ipr[IPR_PAL_BASE] = palid;
-        env->pc = env->ipr[IPR_PAL_BASE];
+        env->pal_base = palid;
+        env->pc = env->pal_base;
         cpu_loop_exit();
     }
 }
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 7cd6395..712de88 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -140,6 +140,23 @@ enum {
     FP_ROUND_DYNAMIC = 0x3,
 };
 
+/* How palcode is interpreted.  */
+enum pal_emul {
+    /* No pal emulation (user linux).  */
+    PAL_NONE,
+
+    /* As a real-cpu palcode.  */
+    PAL_21264
+#if 0
+    PAL_21064,
+    PAL_21164,
+    /* Palcode virtualization (TODO).  */
+    PAL_CONSOLE,
+    PAL_OPENVMS,
+    PAL_UNIX
+#endif
+};
+
 /* Internal processor registers */
 /* XXX: TOFIX: most of those registers are implementation dependant */
 enum {
@@ -170,7 +187,7 @@ enum {
     IPR_IER_CM       = 0x0B,            /* 21264: = CM | IER */
     IPR_SIRR         = 0x0C,            /* 21264 */
 #define IPR_SIRR_SHIFT 14
-#define IPR_SIRR_MASK 0x7fff
+#define IPR_SIRR_MASK (0x7fffULL << IPR_SIRR_SHIFT)
     IPR_ISUM         = 0x0D,            /* 21264 */
     IPR_HW_INT_CLR   = 0x0E,            /* 21264 */
     IPR_EXC_SUM      = 0x0F,
@@ -178,7 +195,7 @@ enum {
     IPR_I_CTL        = 0x11,
 #define IPR_I_CTL_CHIP_ID_SHIFT 24      /* 21264 */
 #define IPR_I_CTL_BIST_FAIL (1 << 23)   /* 21264 */
-#define IPR_I_CTL_IC_EN_SHIFT 2         /* 21264 */
+#define IPR_I_CTL_IC_EN_SHIFT 1         /* 21264 */
 #define IPR_I_CTL_SDE1_SHIFT 7          /* 21264 */
 #define IPR_I_CTL_HWE_SHIFT 12          /* 21264 */
 #define IPR_I_CTL_VA_48_SHIFT 15        /* 21264 */
@@ -212,8 +229,8 @@ enum {
 #define IPR_DTB_ALTMODE_MASK 3
     IPR_DTB_IAP      = 0xA2,
     IPR_DTB_IA       = 0xA3,            /* 21264 */
-    IPR_DTB_IS0      = 0x24,
-    IPR_DTB_IS1      = 0xA4,
+    IPR_DTB_IS0      = 0x24,            /* 21264 */
+    IPR_DTB_IS1      = 0xA4,            /* 21264 */
     IPR_DTB_ASN0     = 0x25,            /* 21264 */
     IPR_DTB_ASN1     = 0xA5,            /* 21264 */
 #define IPR_DTB_ASN_SHIFT 56
@@ -225,74 +242,44 @@ enum {
     IPR_DC_STAT      = 0x2A,            /* 21264 */
     /* Cbox IPRs */
     IPR_C_DATA       = 0x2B,
-    IPR_C_SHIFT      = 0x2C,
-
-    IPR_ASN,
-    IPR_ASTEN,
-    IPR_ASTSR,
-    IPR_DATFX,
-    IPR_ESP,
-    IPR_FEN,
-    IPR_IPIR,
-    IPR_IPL,
-    IPR_KSP,
-    IPR_MCES,
-    IPR_PERFMON,
-    IPR_PCBB,
-    IPR_PRBR,
-    IPR_PTBR,
-    IPR_SCBB,
-    IPR_SISR,
-    IPR_SSP,
-    IPR_SYSPTBR,
-    IPR_TBCHK,
-    IPR_TBIA,
-    IPR_TBIAP,
-    IPR_TBIS,
-    IPR_TBISD,
-    IPR_TBISI,
-    IPR_USP,
-    IPR_VIRBND,
-    IPR_VPTB,
-    IPR_WHAMI,
-    IPR_ALT_MODE,
-    IPR_LAST,
+    IPR_C_SHIFT      = 0x2C
 };
 
 typedef struct CPUAlphaState CPUAlphaState;
 
-typedef struct pal_handler_t pal_handler_t;
-struct pal_handler_t {
-    /* Reset */
-    void (*reset)(CPUAlphaState *env);
-    /* Uncorrectable hardware error */
-    void (*machine_check)(CPUAlphaState *env);
-    /* Arithmetic exception */
-    void (*arithmetic)(CPUAlphaState *env);
-    /* Interrupt / correctable hardware error */
-    void (*interrupt)(CPUAlphaState *env);
-    /* Data fault */
-    void (*dfault)(CPUAlphaState *env);
-    /* DTB miss pal */
-    void (*dtb_miss_pal)(CPUAlphaState *env);
-    /* DTB miss native */
-    void (*dtb_miss_native)(CPUAlphaState *env);
-    /* Unaligned access */
-    void (*unalign)(CPUAlphaState *env);
-    /* ITB miss */
-    void (*itb_miss)(CPUAlphaState *env);
-    /* Instruction stream access violation */
-    void (*itb_acv)(CPUAlphaState *env);
-    /* Reserved or privileged opcode */
-    void (*opcdec)(CPUAlphaState *env);
-    /* Floating point exception */
-    void (*fen)(CPUAlphaState *env);
-    /* Call pal instruction */
-    void (*call_pal)(CPUAlphaState *env, uint32_t palcode);
+struct alpha_pte {
+    uint32_t pa;
+    uint16_t fl;
+    uint8_t asn;
+};
+
+#define MAX_NBR_TLB_21264 128
+struct alpha_21264_tlb {
+    short int in_use;
+    short int next;
+    unsigned char spe;
+    struct alpha_21264_tlbe {
+        int64_t va;
+        struct alpha_pte pte;
+    } entries[MAX_NBR_TLB_21264];
 };
 
+#define ALPHA_PTE_V   (1 << 0)
+#define ALPHA_PTE_FOR (1 << 1)
+#define ALPHA_PTE_FOW (1 << 2)
+#define ALPHA_PTE_ASM (1 << 4)
+#define ALPHA_PTE_GH_SHIFT 5
+#define ALPHA_PTE_KRE (1 << 8)
+#define ALPHA_PTE_ERE (1 << 9)
+#define ALPHA_PTE_SRE (1 << 10)
+#define ALPHA_PTE_URE (1 << 11)
+#define ALPHA_PTE_KWE (1 << 12)
+#define ALPHA_PTE_EWE (1 << 13)
+#define ALPHA_PTE_SWE (1 << 14)
+#define ALPHA_PTE_UWE (1 << 15)
+
 #if !defined(CONFIG_USER_ONLY)
-#define NB_MMU_MODES 4
+#define NB_MMU_MODES 5
 #else
 #define NB_MMU_MODES 2
 #endif
@@ -304,29 +291,99 @@ struct CPUAlphaState {
     uint64_t fpcr;
     uint64_t pc;
     uint64_t lock;
-    uint32_t pcc[2];
-    uint64_t ipr[IPR_LAST];
-    uint64_t ps;
-    uint64_t unique;
-    int saved_mode; /* Used for HW_LD / HW_ST */
-    int intr_flag; /* For RC and RS */
-
-#if TARGET_LONG_BITS > HOST_LONG_BITS
-    /* temporary fixed-point registers
-     * used to emulate 64 bits target on 32 bits hosts
-     */
-    target_ulong t0, t1;
-#endif
 
     /* Those resources are used only in Qemu core */
     CPU_COMMON
 
-    uint32_t hflags;
+    unsigned char intr_flag; /* For RC and RS */
+    unsigned char fen; /* FPU enable */
+    unsigned char pal_mode;
+    enum pal_emul pal_emul;
+    unsigned char mmu_data_index; /* 0-3 */
+    unsigned char mmu_code_index; /* 0-4 (pal).  */
+
+    /* Common.  */
+    uint64_t pal_base;
+    uint64_t exc_addr;
+
 #if defined(CONFIG_USER_ONLY)
     struct {
         uint64_t usp;
         uint64_t unique;
     } user;
+#else
+    union {
+        struct {
+            /* Trick to emulate an Icache during early pal decompression.  */
+            uint64_t pal_reloc_mask;
+            uint64_t pal_reloc_val;
+            uint64_t pal_reloc_offset;
+
+            /* Shadow registers for pal mode.  */
+            uint64_t shadow_r4;
+            uint64_t shadow_r5;
+            uint64_t shadow_r6;
+            uint64_t shadow_r7;
+            uint64_t shadow_r20;
+            uint64_t shadow_r21;
+            uint64_t shadow_r22;
+            uint64_t shadow_r23;
+
+            /* CC */
+            uint32_t cc_counter;
+            uint64_t cc_load_ticks;
+
+            /* CC_CTL */
+            uint64_t cc_offset; /* Only the 32 MSB are set.  */
+            unsigned char cc_ena;
+
+            /* I_CTL  */
+            uint64_t i_vptb;
+            unsigned char iva_48;
+            unsigned char hwe;
+            unsigned char sde1;
+            unsigned char chip_id;
+            unsigned char ic_en;
+            unsigned char call_pal_r23;
+
+            /* IER + CM  */
+            unsigned char cm;
+            uint64_t ier;
+
+            uint64_t isum;
+            uint64_t ipend; /* fake. */
+
+            /* VA_CTL */
+            uint64_t d_vptb;
+            unsigned char dva_48;
+
+            /* PCTX.  */
+            unsigned char asn;
+            unsigned char astrr;
+            unsigned char aster;
+            unsigned char fpe;
+            unsigned char ppce;
+
+            unsigned char altmode;
+
+            /* SIRR */
+            uint32_t sirr;
+
+            uint64_t mm_stat;
+            uint64_t iva_form;
+
+            uint64_t va_form;
+            uint64_t va;
+
+            uint64_t itb_tag;
+            uint64_t itb_pte;
+            uint64_t dtb_tag;
+            uint64_t dtb_pte;
+            unsigned char dtb_asn;
+
+            struct alpha_21264_tlb itlb, dtlb;
+        } a21264;
+    };
 #endif
 
     int error_code;
@@ -334,7 +391,6 @@ struct CPUAlphaState {
     uint32_t features;
     uint32_t amask;
     int implver;
-    pal_handler_t *pal_handler;
 };
 
 #define cpu_init cpu_alpha_init
@@ -389,18 +445,33 @@ enum {
 };
 
 enum {
-    EXCP_RESET            = 0x0000,
-    EXCP_MCHK             = 0x0020,
-    EXCP_ARITH            = 0x0060,
-    EXCP_HW_INTERRUPT     = 0x00E0,
-    EXCP_DFAULT           = 0x01E0,
-    EXCP_DTB_MISS_PAL     = 0x09E0,
-    EXCP_ITB_MISS         = 0x03E0,
-    EXCP_ITB_ACV          = 0x07E0,
-    EXCP_DTB_MISS_NATIVE  = 0x08E0,
-    EXCP_UNALIGN          = 0x11E0,
-    EXCP_OPCDEC           = 0x13E0,
-    EXCP_FEN              = 0x17E0,
+    EXCP_21064_RESET            = 0x0000,
+    EXCP_21064_MCHK             = 0x0020,
+    EXCP_21064_ARITH            = 0x0060,
+    EXCP_21064_HW_INTERRUPT     = 0x00E0,
+    EXCP_21064_DFAULT           = 0x01E0,
+    EXCP_21064_DTB_MISS_PAL     = 0x09E0,
+    EXCP_21064_ITB_MISS         = 0x03E0,
+    EXCP_21064_ITB_ACV          = 0x07E0,
+    EXCP_21064_DTB_MISS_NATIVE  = 0x08E0,
+    EXCP_21064_UNALIGN          = 0x11E0,
+    EXCP_21064_OPCDEC           = 0x13E0,
+    EXCP_21064_FEN              = 0x17E0,
+
+    EXCP_21264_DTBM_DOUBLE_3    = 0x0100,
+    EXCP_21264_DTBM_DOUBLE_4    = 0x0180,
+    EXCP_21264_FEN              = 0x0200,
+    EXCP_21264_UNALIGN          = 0x0280,
+    EXCP_21264_DTBM_SINGLE      = 0x0300,
+    EXCP_21264_DFAULT           = 0x0380,
+    EXCP_21264_OPCDEC           = 0x0400,
+    EXCP_21264_IACV             = 0x0480,
+    EXCP_21264_MCHK             = 0x0500,
+    EXCP_21264_ITB_MISS         = 0x0580,
+    EXCP_21264_ARITH            = 0x0600,
+    EXCP_21264_INTERRUPT        = 0x0680,
+    EXCP_21264_MT_FPCR          = 0x0700,
+    EXCP_21264_RESET            = 0x0780,
 
     /* Generic exception - to be mapped to processor.  */
     EXCP_GEN_OPCDEC             = 1,
@@ -474,11 +545,21 @@ int cpu_alpha_handle_mmu_fault (CPUState *env, uint64_t address, int rw,
                                 int mmu_idx, int is_softmmu);
 void do_interrupt (CPUState *env);
 
-int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp);
-int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp);
-#if !defined (CONFIG_USER_ONLY)
-void call_pal (CPUState *env);
-#endif
+uint64_t cpu_alpha_mfpr_21264 (CPUState *env, int iprn);
+void cpu_alpha_mtpr_21264 (CPUState *env, int iprn, uint64_t val);
+void init_cpu_21264(CPUState *env);
+void swap_shadow_21264(CPUState *env);
+struct alpha_pte cpu_alpha_mmu_v2p_21264(CPUState *env, int64_t address,
+                                         int rwx);
+void cpu_alpha_mmu_dfault_21264(CPUState *env, int64_t address, int opc);
+int cpu_alpha_mmu_fault_21264 (CPUState *env, int64_t address, int rwx,
+                               int mmu_idx, void *retaddr);
+
+void cpu_alpha_mmu_fault_pal(CPUState *env, int64_t address);
+
+void alpha_21264_srm_write(CPUState *env);
+
+void cpu_alpha_update_irq (CPUState *env, int irqs);
 
 static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
 {
@@ -490,7 +571,16 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
 {
     *pc = env->pc;
     *cs_base = 0;
-    *flags = env->ps;
+    *flags = (env->mmu_code_index << 2) | env->mmu_data_index;
 }
 
+/* Flags for virt_to_phys helper. */
+#define ALPHA_HW_MMUIDX_MASK 3
+#define ALPHA_HW_V (1 << 2)
+#define ALPHA_HW_W (1 << 3)
+#define ALPHA_HW_E (1 << 4)
+#define ALPHA_HW_A (1 << 8)
+#define ALPHA_HW_L (1 << 9)
+#define ALPHA_HW_Q (1 << 10)
+
 #endif /* !defined (__CPU_ALPHA_H__) */
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 4046463..8e1b317 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -23,6 +23,7 @@
 #include <stdio.h>
 
 #include "cpu.h"
+#include "sysemu.h"
 #include "exec-all.h"
 
 #if defined(CONFIG_USER_ONLY)
@@ -34,7 +35,7 @@ int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
         env->exception_index = EXCP_USER_ITB_MISS;
     else
         env->exception_index = EXCP_USER_DFAULT;
-    env->ipr[IPR_EXC_ADDR] = address;
+    env->exc_addr = address;
 
     return 1;
 }
@@ -56,354 +57,568 @@ target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
     return -1;
 }
 
-int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
-                                int mmu_idx, int is_softmmu)
+#define GH_MASK(gh) (~((1ULL << (13 + gh)) - 1))
+#define TB_PTE_GET_GH(v) (((v) >> 5) & 3)
+#define TB_PTE_GET_RE(v) (((v) >> 8) & 0x0f)
+#define TB_PTE_GET_WE(v) (((v) >> 12) & 0x0f)
+#define TB_PTE_GET_ASM(v) (((v) >> 4) & 1)
+#define TB_PTE_GET_FO(v) (((v) >> 1) & 2)
+#define IPR_CM_GET_CM(v) (((v) >> 3) & 3)
+
+static uint64_t va_form (int64_t va, uint64_t vptb, int form)
+{
+    va = (va >> 13) << 3;
+    switch (form) {
+    case 0: /* VA_48 = 0, VA_FORM_32 = 0 */
+        return              (vptb & 0xfffffffe00000000ULL)
+            |                 (va & 0x00000001fffffff8ULL);
+    case 1: /* VA_48 = 1, VA_FORM_32 = 0 */
+        return              (vptb & 0xfffff80000000000ULL)
+            | (((va << 26) >> 26) & 0x000007fffffffff8ULL);
+    case 2: /* VA_48 = 0, VA_FORM_32 = 1 */
+        return              (vptb & 0xffffffffc0000000ULL)
+            |                 (va & 0x00000000003ffff8ULL);
+    default:
+        abort();
+    }
+}
+
+struct alpha_pte cpu_alpha_mmu_v2p_21264(CPUState *env, int64_t address,
+                                         int rwx)
 {
-    uint32_t opc;
+    struct alpha_21264_tlb *tlb;
+    struct alpha_pte pte;
+    int i;
+    int va_sh;
 
-    if (rw == 2) {
+    if (rwx == 2) {
         /* Instruction translation buffer miss */
-        env->exception_index = EXCP_ITB_MISS;
+        tlb = &env->a21264.itlb;
+        va_sh = env->a21264.iva_48 ? 64 - 48 : 64 - 43;
     } else {
-        if (env->ipr[IPR_EXC_ADDR] & 1)
-            env->exception_index = EXCP_DTB_MISS_PAL;
+        /* Data translation buffer miss */
+        tlb = &env->a21264.dtlb;
+        va_sh = env->a21264.dva_48 ? 64 - 48 : 64 - 43;
+    }
+
+    /* Check sign extension. */
+    if (((address << va_sh) >> va_sh) != address)
+        return ((struct alpha_pte){0, 0, 1});
+
+#if 0
+    fprintf(stderr, "mmu_fault_21264: addr=%016llx, rwx=%d\n", address, rwx);
+#endif
+
+    /* Super page.  */
+    if ((tlb->spe & 4) && ((address >> 46) & 3) == 2) {
+        pte.pa = (address & 0x000008ffffffe000ULL) >> 13;
+        pte.fl = ALPHA_PTE_KRE | ALPHA_PTE_KWE | ALPHA_PTE_V;
+        pte.asn = 0;
+        return pte;
+    }
+    if ((tlb->spe & 2) && ((address >> 41) & 0x7f) == 0x7e) {
+        pte.pa = (((address << 23) >> 23) & 0x000008ffffffe000ULL) >> 13;
+        pte.fl = ALPHA_PTE_KRE | ALPHA_PTE_KWE | ALPHA_PTE_V;
+        pte.asn = 0;
+        return pte;
+    }
+    if ((tlb->spe & 1) && ((address >> 30) & 0x3ffff) == 0x3fffe) {
+        pte.pa = (address & 0x000000003fffe000ULL) >> 13;
+        pte.fl = ALPHA_PTE_KRE | ALPHA_PTE_KWE | ALPHA_PTE_V;
+        pte.asn = 0;
+        return pte;
+    }
+
+    /* Search in TLB.  */
+    for (i = 0; i < MAX_NBR_TLB_21264; i++) {
+        struct alpha_21264_tlbe *tlbe = &tlb->entries[i];
+        int pg_sh;
+
+        if (!(tlbe->pte.fl & ALPHA_PTE_V))
+            continue;
+
+        pg_sh = 13 + 3 * TB_PTE_GET_GH(tlbe->pte.fl);
+        if ((tlbe->va >> pg_sh) == (address >> pg_sh)
+            && ((tlbe->pte.asn == env->a21264.asn)
+                || (tlbe->pte.fl & ALPHA_PTE_ASM)))
+            return tlbe->pte;
+    }
+
+    return ((struct alpha_pte){0, 0, 0});
+}
+
+void cpu_alpha_mmu_fault_pal(CPUState *env, int64_t address)
+{
+    target_ulong phys_addr = address & TARGET_PAGE_MASK;
+
+    if ((address & env->a21264.pal_reloc_mask)
+        == env->a21264.pal_reloc_val)
+        phys_addr += env->a21264.pal_reloc_offset;
+
+    tlb_set_page_exec(env, address & TARGET_PAGE_MASK, phys_addr,
+                      PAGE_EXEC, MMU_PAL_IDX, 1);
+}
+
+void cpu_alpha_mmu_dfault_21264(CPUState *env, int64_t address, int opc)
+{
+    env->a21264.mm_stat = (opc << 4) | ((opc & 0x04) != 0 ? 1 : 0);
+
+    env->a21264.va = address;
+    env->a21264.va_form =
+        va_form(address, env->a21264.d_vptb, env->a21264.dva_48);
+}
+
+int cpu_alpha_mmu_fault_21264(CPUState *env, int64_t address, int rwx,
+                              int mmu_idx, void *retaddr)
+{
+    struct alpha_pte pte;
+    int rights;
+
+    pte = cpu_alpha_mmu_v2p_21264(env, address, rwx);
+
+    rights = (pte.fl >> env->a21264.cm);
+    if ((pte.fl & ALPHA_PTE_V)
+        && (rights & (rwx == 1 ? ALPHA_PTE_KWE : ALPHA_PTE_KRE))
+        && (rwx == 2 || !((pte.fl >> rwx) & ALPHA_PTE_FOR))) {
+        uint64_t mask;
+        uint64_t pa;
+
+        mask = ((1ULL << (3 * TB_PTE_GET_GH(pte.fl))) - 1) << 13;
+        pa = ((((uint64_t)pte.pa) << 13) & ~mask) | (address & mask);
+        tlb_set_page_exec
+            (env, address & TARGET_PAGE_MASK, pa,
+             (rwx == 2) ? PAGE_READ | PAGE_EXEC
+             : ((rights & ALPHA_PTE_KWE ? PAGE_WRITE : 0)
+                | (rights & ALPHA_PTE_KRE ? PAGE_READ : 0)),
+             mmu_idx, 1);
+        return 0;
+    }
+
+    /* Not found.  */
+    if (rwx == 2) {
+        env->exception_index =
+            (pte.fl == 0 && pte.asn == 0) ? EXCP_21264_ITB_MISS
+            : EXCP_21264_IACV;
+
+        env->a21264.iva_form =
+            va_form(address, env->a21264.i_vptb, env->a21264.iva_48);
+        if (retaddr)
+            abort();
+    } else {
+        TranslationBlock *tb;
+        unsigned long pc;
+        uint64_t phys_pc;
+        uint32_t insn;
+
+        if (pte.fl == 0 && pte.asn == 0)
+            env->exception_index = EXCP_21264_DTBM_SINGLE;
         else
-            env->exception_index = EXCP_DTB_MISS_NATIVE;
-        opc = (ldl_code(env->pc) >> 21) << 4;
-        if (rw) {
-            opc |= 0x9;
-        } else {
-            opc |= 0x4;
+            env->exception_index = EXCP_21264_DFAULT;
+
+        /* In order to correctly set mm_stat and find the right exception,
+           we must find which instruction created the fault.  */
+
+        /* This code can only be called from a tb (but the debugger!).
+           FIXME: remove the abort() when the code is correct.  */
+        if (!likely(retaddr))
+            abort();
+
+        /* now we have a real cpu fault */
+        pc = (unsigned long)retaddr;
+        tb = tb_find_pc(pc);
+        if (!likely(tb)) {
+            /* Not from translated code!!  Not possible.  */
+            abort();
         }
-        env->ipr[IPR_MM_STAT] = opc;
+
+        /* the PC is inside the translated code. It means that we
+           have a virtual CPU fault */
+        cpu_restore_state(tb, env, pc, NULL);
+
+        /* Extract physical pc address.  */
+        /* FIXME: justify why page_addr[1] is not needed.  */
+        phys_pc = tb->page_addr[0] + (env->pc & ~TARGET_PAGE_MASK);
+
+        /* Extract instruction.  */
+        insn = ldl_phys(phys_pc);
+
+        cpu_alpha_mmu_dfault_21264(env, address, insn >> 26);
     }
 
     return 1;
 }
 
-int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp)
+static void insert_itlb_21264(CPUState *env, int64_t va, uint64_t pte)
+{
+    struct alpha_21264_tlb *tlb = &env->a21264.itlb;
+    struct alpha_21264_tlbe *e = &tlb->entries[tlb->next];
+
+    /* Should an already matching entry be discarded ?  Not sure.  */
+    e->va = ((va & TARGET_PAGE_MASK) << 16) >> 16;
+    e->pte.pa = pte >> 13;
+    e->pte.fl = (pte & 0x1fff) | ALPHA_PTE_V;
+    e->pte.asn = env->a21264.asn;
+
+    tlb->next = (tlb->next + 1) % MAX_NBR_TLB_21264;
+}
+
+static void insert_dtlb_21264(CPUState *env, int64_t va, uint64_t pte)
+{
+    struct alpha_21264_tlb *tlb = &env->a21264.dtlb;
+    struct alpha_21264_tlbe *e = &tlb->entries[tlb->next];
+
+    /* Should an already matching entry be discarded ?  Not sure.  */
+    e->va = ((va & TARGET_PAGE_MASK) << 16) >> 16;
+    e->pte.pa = pte >> 32;
+    e->pte.asn = env->a21264.asn;
+    e->pte.fl = pte | ALPHA_PTE_V;
+    tlb->next = (tlb->next + 1) % MAX_NBR_TLB_21264;
+}
+
+static void flush_tlb_21264(CPUState *env, struct alpha_21264_tlb *tlb)
 {
-    uint64_t hwpcb;
-    int ret = 0;
+    int i;
+
+    for (i = 0; i < MAX_NBR_TLB_21264; i++) {
+        struct alpha_21264_tlbe *e = &tlb->entries[i];
+        if (!(e->pte.fl & ALPHA_PTE_ASM)
+            && e->pte.asn == env->a21264.asn)
+            e->pte.fl = 0;
+    }
+}
+
+static void flush_tlb_21264_page(CPUState *env, struct alpha_21264_tlb *tlb,
+                                 uint64_t addr)
+{
+    int i;
+
+    for (i = 0; i < MAX_NBR_TLB_21264; i++) {
+        struct alpha_21264_tlbe *e = &tlb->entries[i];
+        if (!(e->pte.fl & ALPHA_PTE_ASM)
+            && e->pte.asn == env->a21264.asn
+            && e->va == addr)
+            e->pte.fl = 0;
+    }
+}
 
-    hwpcb = env->ipr[IPR_PCBB];
+uint64_t cpu_alpha_mfpr_21264 (CPUState *env, int iprn)
+{
     switch (iprn) {
-    case IPR_ASN:
-        if (env->features & FEATURE_ASN)
-            *valp = env->ipr[IPR_ASN];
-        else
-            *valp = 0;
-        break;
-    case IPR_ASTEN:
-        *valp = ((int64_t)(env->ipr[IPR_ASTEN] << 60)) >> 60;
-        break;
-    case IPR_ASTSR:
-        *valp = ((int64_t)(env->ipr[IPR_ASTSR] << 60)) >> 60;
-        break;
-    case IPR_DATFX:
-        /* Write only */
-        ret = -1;
+    case IPR_PAL_BASE:
+        return env->pal_base;
+    case IPR_I_CTL:
+        return env->a21264.i_vptb
+            | (env->a21264.chip_id << IPR_I_CTL_CHIP_ID_SHIFT)
+            | (env->a21264.iva_48 << IPR_I_CTL_VA_48_SHIFT)
+            | (env->a21264.hwe << IPR_I_CTL_HWE_SHIFT)
+            | (env->a21264.sde1 << IPR_I_CTL_SDE1_SHIFT)
+            | (env->a21264.ic_en << IPR_I_CTL_IC_EN_SHIFT)
+            | (env->a21264.call_pal_r23 << IPR_I_CTL_CALL_PAL_R23_SHIFT)
+            | (env->a21264.itlb.spe << IPR_I_CTL_SPE_SHIFT);
+    case IPR_IVA_FORM:
+        return env->a21264.iva_form;
+    case IPR_VA:
+        return env->a21264.va;
+    case IPR_EXC_ADDR:
+        return env->exc_addr;
+    case IPR_I_STAT:   /* Not emulated  */
+    case IPR_DC_STAT:  /* Not emulated  */
+        return 0;
+    case IPR_C_DATA:
+    case IPR_C_SHIFT:
+        return 0;
+    case IPR_PCTX ... IPR_PCTX_ALL:
+        return (((uint64_t)env->a21264.asn) << IPR_PCTX_ASN_SHIFT)
+            | (((uint64_t)env->a21264.astrr) << IPR_PCTX_ASTRR_SHIFT)
+            | (((uint64_t)env->a21264.aster) << IPR_PCTX_ASTER_SHIFT)
+            | (((uint64_t)env->a21264.fpe) << IPR_PCTX_FPE_SHIFT)
+            | (((uint64_t)env->a21264.ppce) << IPR_PCTX_PPCE_SHIFT);
+    case IPR_IER_CM:
+    case IPR_CM:
+    case IPR_IER:
+        return (((uint64_t)env->a21264.cm) << IPR_CM_SHIFT)
+            | env->a21264.ier;
+    case IPR_ISUM:
+        return env->a21264.isum;
+    case IPR_SIRR:
+        return env->a21264.sirr;
+    case IPR_MM_STAT:
+        return env->a21264.mm_stat;
+    case IPR_VA_FORM:
+        return env->a21264.va_form;
+    case IPR_EXC_SUM:
+        return 0; /* FIXME.  */
+    default:
+        cpu_abort(env, "cpu_alpha_mfpr_21264: ipr 0x%x not handled\n", iprn);
+    }
+}
+
+void cpu_alpha_mtpr_21264 (CPUState *env, int iprn, uint64_t val)
+{
+#if 0
+    qemu_log("cpu_alpha_mtpr_21264: ipr=0x%02x, val="TARGET_FMT_lx"\n",
+             iprn, val);
+#endif
+    switch (iprn) {
+    case IPR_CC:
+        env->a21264.cc_offset = (val >> 32) << 32;
+        break;
+    case IPR_CC_CTL:
+        env->a21264.cc_ena = (val >> IPR_CC_CTL_ENA_SHIFT) & 1;
+        env->a21264.cc_counter = val & IPR_CC_CTL_COUNTER_MASK;
+        env->a21264.cc_load_ticks = cpu_get_ticks();
+        break;
+    case IPR_ITB_TAG:
+        env->a21264.itb_tag = val & 0x0000ffffffffe000ULL;
+        break;
+    case IPR_DTB_TAG0:
+        env->a21264.dtb_tag = val & 0x0000ffffffffe000ULL;
+        break;
+    case IPR_DTB_TAG1:
+    case IPR_DTB_ASN1:
+    case IPR_DTB_PTE1:
+        break; /* DTAG */
+    case IPR_ITB_PTE:
+        env->a21264.itb_pte = val & 0x00000fffffffef70ULL;
+        insert_itlb_21264(env, env->a21264.itb_tag, env->a21264.itb_pte);
+        break;
+    case IPR_DTB_PTE0:
+        env->a21264.dtb_pte = val &= 0x7fffffff0000ffe6ULL;
+        insert_dtlb_21264(env, env->a21264.dtb_tag, env->a21264.dtb_pte);
+        break;
+    case IPR_DTB_ASN0:
+        env->a21264.dtb_asn = (val >> IPR_DTB_ASN_SHIFT) & 0xff;
+        break;
+    case IPR_PAL_BASE:
+        env->pal_base = val & 0x00000fffffff8000ULL;
+        break;
+    case IPR_I_CTL:
+    {
+        unsigned char old_sde1 = env->a21264.sde1;
+        env->a21264.i_vptb =
+          ((((int64_t)val) << 16) >> 16) & 0xffffffffc0000000ULL;
+        env->a21264.hwe = (val >> IPR_I_CTL_HWE_SHIFT) & 1;
+        env->a21264.sde1 = (val >> IPR_I_CTL_SDE1_SHIFT) & 1;
+        env->a21264.iva_48 = (val >> IPR_I_CTL_VA_48_SHIFT) & 3;
+        env->a21264.itlb.spe = (val >> IPR_I_CTL_SPE_SHIFT) & 7;
+        env->a21264.call_pal_r23 = (val >> IPR_I_CTL_CALL_PAL_R23_SHIFT) & 1;
+        if (env->pal_mode && old_sde1 != env->a21264.sde1)
+            swap_shadow_21264(env);
         break;
-    case IPR_ESP:
-        if (env->features & FEATURE_SPS)
-            *valp = env->ipr[IPR_ESP];
-        else
-            *valp = ldq_raw(hwpcb + 8);
-        break;
-    case IPR_FEN:
-        *valp = ((int64_t)(env->ipr[IPR_FEN] << 63)) >> 63;
-        break;
-    case IPR_IPIR:
-        /* Write-only */
-        ret = -1;
-        break;
-    case IPR_IPL:
-        *valp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59;
-        break;
-    case IPR_KSP:
-        if (!(env->ipr[IPR_EXC_ADDR] & 1)) {
-            ret = -1;
-        } else {
-            if (env->features & FEATURE_SPS)
-                *valp = env->ipr[IPR_KSP];
-            else
-                *valp = ldq_raw(hwpcb + 0);
+    }
+    case IPR_VA_CTL:
+        env->a21264.d_vptb = val & 0xffffffffc0000000ULL;
+        env->a21264.dva_48 = (val >> IPR_VA_CTL_VA_48_SHIFT) & 3;
+        /* env->a21264.b_endian = val & 1; */
+        if (val & 1)
+            cpu_abort (env, "mtpr va_ctl: b_endian not yet handled\n");
+        break;
+    case IPR_IER_CM:
+    case IPR_CM:
+    case IPR_IER:
+        if (iprn & 2) {
+            env->a21264.ier = val & IPR_IER_MASK;
+            env->a21264.isum = env->a21264.ipend & env->a21264.ier;
+        }
+        if (iprn & 1) {
+            env->a21264.cm = (val & IPR_CM_MASK) >> IPR_CM_SHIFT;
+            env->mmu_data_index = env->a21264.cm;
         }
         break;
-    case IPR_MCES:
-        *valp = ((int64_t)(env->ipr[IPR_MCES] << 59)) >> 59;
+    case IPR_IC_FLUSH:
+    case IPR_IC_FLUSH_ASM:
+        // tb_flush(env);
         break;
-    case IPR_PERFMON:
-        /* Implementation specific */
-        *valp = 0;
+    case IPR_ITB_IA:
+        tlb_flush(env, 1);
+        flush_tlb_21264(env, &env->a21264.itlb);
         break;
-    case IPR_PCBB:
-        *valp = ((int64_t)env->ipr[IPR_PCBB] << 16) >> 16;
+    case IPR_ITB_IS:
+        val &= TARGET_PAGE_MASK;
+        tlb_flush_page(env, val);
+        flush_tlb_21264_page(env, &env->a21264.itlb, val);
         break;
-    case IPR_PRBR:
-        *valp = env->ipr[IPR_PRBR];
+    case IPR_DTB_IA:
+        tlb_flush(env, 1);
+        flush_tlb_21264(env, &env->a21264.dtlb);
         break;
-    case IPR_PTBR:
-        *valp = env->ipr[IPR_PTBR];
+    case IPR_DTB_IS0:
+        val &= TARGET_PAGE_MASK;
+        tlb_flush_page(env, val);
+        flush_tlb_21264_page(env, &env->a21264.dtlb, val);
         break;
-    case IPR_SCBB:
-        *valp = (int64_t)((int32_t)env->ipr[IPR_SCBB]);
+    case IPR_DTB_IS1:
         break;
-    case IPR_SIRR:
-        /* Write-only */
-        ret = -1;
-        break;
-    case IPR_SISR:
-        *valp = (int64_t)((int16_t)env->ipr[IPR_SISR]);
-    case IPR_SSP:
-        if (env->features & FEATURE_SPS)
-            *valp = env->ipr[IPR_SSP];
-        else
-            *valp = ldq_raw(hwpcb + 16);
+    case IPR_I_STAT:   /* Not emulated  */
+    case IPR_DC_STAT:  /* Not emulated  */
         break;
-    case IPR_SYSPTBR:
-        if (env->features & FEATURE_VIRBND)
-            *valp = env->ipr[IPR_SYSPTBR];
-        else
-            ret = -1;
-        break;
-    case IPR_TBCHK:
-        if ((env->features & FEATURE_TBCHK)) {
-            /* XXX: TODO */
-            *valp = 0;
-            ret = -1;
-        } else {
-            ret = -1;
-        }
+    case IPR_MM_STAT:  /* RO */
         break;
-    case IPR_TBIA:
-        /* Write-only */
-        ret = -1;
+    case IPR_PCTX ... IPR_PCTX_ALL:
+        if (iprn & IPR_PCTX_ASN) {
+            env->a21264.asn = (val >> IPR_PCTX_ASN_SHIFT) & 0xff;
+            tlb_flush(env, 1);
+            tb_flush(env);
+        }
+        if (iprn & IPR_PCTX_ASTRR) {
+            env->a21264.astrr = (val >> IPR_PCTX_ASTRR_SHIFT) & 0xf;
+            if (env->a21264.astrr)
+                cpu_abort(env, "set pctx.astrr unhandled");
+        }
+        if (iprn & IPR_PCTX_ASTER) {
+            env->a21264.aster = (val >> IPR_PCTX_ASTER_SHIFT) & 0xf;
+            if (env->a21264.aster)
+                cpu_abort(env, "set pctx.aster unhandled");
+        }
+        if (iprn & IPR_PCTX_FPE) {
+            env->a21264.fpe = (val >> IPR_PCTX_FPE_SHIFT) & 1;
+            if (!env->a21264.fpe)
+                cpu_abort(env, "set pctx.fpe unhandled");
+        }
+        if (iprn & IPR_PCTX_PPCE)
+            env->a21264.ppce = (val >> IPR_PCTX_PPCE_SHIFT) & 1;
         break;
-    case IPR_TBIAP:
-        /* Write-only */
-        ret = -1;
+    case IPR_M_CTL:
+        env->a21264.dtlb.spe =
+            (val >> IPR_M_CTL_SPE_SHIFT) & IPR_M_CTL_SPE_MASK;
         break;
-    case IPR_TBIS:
-        /* Write-only */
-        ret = -1;
+    case IPR_SIRR:
+        env->a21264.sirr = val & IPR_SIRR_MASK;
+        env->a21264.ipend = ((env->a21264.ipend & ~IPR_SIRR_MASK)
+                             | env->a21264.sirr);
+        env->a21264.isum = env->a21264.ipend & env->a21264.ier;
         break;
-    case IPR_TBISD:
-        /* Write-only */
-        ret = -1;
+    case IPR_HW_INT_CLR:
         break;
-    case IPR_TBISI:
-        /* Write-only */
-        ret = -1;
+    case IPR_DTB_ALTMODE0:
+        env->a21264.altmode = val & IPR_DTB_ALTMODE_MASK;
         break;
-    case IPR_USP:
-        if (env->features & FEATURE_SPS)
-            *valp = env->ipr[IPR_USP];
-        else
-            *valp = ldq_raw(hwpcb + 24);
+    case IPR_PCTR_CTL:
+        /* Not emulated.  */
         break;
-    case IPR_VIRBND:
-        if (env->features & FEATURE_VIRBND)
-            *valp = env->ipr[IPR_VIRBND];
-        else
-            ret = -1;
+    case IPR_C_DATA:
+    case IPR_C_SHIFT:
         break;
-    case IPR_VPTB:
-        *valp = env->ipr[IPR_VPTB];
+    case IPR_DC_CTL:
+        /* Unhandled: f_bad_decc, f_bad_tpar, f_hit.  */
+        if (val & 0x34)
+            cpu_abort(env, "cpu_alpha_mtpr_21264 dc_ctl: bad value %08x\n",
+                      (unsigned)val);
         break;
-    case IPR_WHAMI:
-        *valp = env->ipr[IPR_WHAMI];
+    case 0x2d:  /* Not documented (M_FIX)  */
+        /* Hack: save srm.  */
+        if (env->a21264.pal_reloc_val)
+            alpha_21264_srm_write(env);
         break;
     default:
-        /* Invalid */
-        ret = -1;
-        break;
+        cpu_abort(env, "cpu_alpha_mtpr_21264: ipr 0x%x not handled\n", iprn);
     }
+}
 
-    return ret;
+void init_cpu_21264(CPUState *env)
+{
+    env->pal_base = 0;
+    env->a21264.chip_id = 0x21;
+    env->a21264.ic_en = 3;
+    env->pal_emul = PAL_21264;
+    memset (&env->a21264.itlb, 0, sizeof (env->a21264.itlb));
+    memset (&env->a21264.dtlb, 0, sizeof (env->a21264.dtlb));
 }
 
-int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp)
+void swap_shadow_21264(CPUState *env)
 {
-    uint64_t hwpcb, tmp64;
-    uint8_t tmp8;
-    int ret = 0;
+#define swap(a, b) do { uint64_t t = a; a = b; b = t; } while (0)
+    swap(env->a21264.shadow_r4, env->ir[4]);
+    swap(env->a21264.shadow_r5, env->ir[5]);
+    swap(env->a21264.shadow_r6, env->ir[6]);
+    swap(env->a21264.shadow_r7, env->ir[7]);
+    swap(env->a21264.shadow_r20, env->ir[20]);
+    swap(env->a21264.shadow_r21, env->ir[21]);
+    swap(env->a21264.shadow_r22, env->ir[22]);
+    swap(env->a21264.shadow_r23, env->ir[23]);
+#undef swap
+}
 
-    hwpcb = env->ipr[IPR_PCBB];
-    switch (iprn) {
-    case IPR_ASN:
-        /* Read-only */
-        ret = -1;
-        break;
-    case IPR_ASTEN:
-        tmp8 = ((int8_t)(env->ipr[IPR_ASTEN] << 4)) >> 4;
-        *oldvalp = tmp8;
-        tmp8 &= val & 0xF;
-        tmp8 |= (val >> 4) & 0xF;
-        env->ipr[IPR_ASTEN] &= ~0xF;
-        env->ipr[IPR_ASTEN] |= tmp8;
-        ret = 1;
-        break;
-    case IPR_ASTSR:
-        tmp8 = ((int8_t)(env->ipr[IPR_ASTSR] << 4)) >> 4;
-        *oldvalp = tmp8;
-        tmp8 &= val & 0xF;
-        tmp8 |= (val >> 4) & 0xF;
-        env->ipr[IPR_ASTSR] &= ~0xF;
-        env->ipr[IPR_ASTSR] |= tmp8;
-        ret = 1;
-    case IPR_DATFX:
-        env->ipr[IPR_DATFX] &= ~0x1;
-        env->ipr[IPR_DATFX] |= val & 1;
-        tmp64 = ldq_raw(hwpcb + 56);
-        tmp64 &= ~0x8000000000000000ULL;
-        tmp64 |= (val & 1) << 63;
-        stq_raw(hwpcb + 56, tmp64);
-        break;
-    case IPR_ESP:
-        if (env->features & FEATURE_SPS)
-            env->ipr[IPR_ESP] = val;
-        else
-            stq_raw(hwpcb + 8, val);
-        break;
-    case IPR_FEN:
-        env->ipr[IPR_FEN] = val & 1;
-        tmp64 = ldq_raw(hwpcb + 56);
-        tmp64 &= ~1;
-        tmp64 |= val & 1;
-        stq_raw(hwpcb + 56, tmp64);
-        break;
-    case IPR_IPIR:
-        /* XXX: TODO: Send IRQ to CPU #ir[16] */
-        break;
-    case IPR_IPL:
-        *oldvalp = ((int64_t)(env->ipr[IPR_IPL] << 59)) >> 59;
-        env->ipr[IPR_IPL] &= ~0x1F;
-        env->ipr[IPR_IPL] |= val & 0x1F;
-        /* XXX: may issue an interrupt or ASR _now_ */
-        ret = 1;
-        break;
-    case IPR_KSP:
-        if (!(env->ipr[IPR_EXC_ADDR] & 1)) {
-            ret = -1;
-        } else {
-            if (env->features & FEATURE_SPS)
-                env->ipr[IPR_KSP] = val;
-            else
-                stq_raw(hwpcb + 0, val);
-        }
-        break;
-    case IPR_MCES:
-        env->ipr[IPR_MCES] &= ~((val & 0x7) | 0x18);
-        env->ipr[IPR_MCES] |= val & 0x18;
-        break;
-    case IPR_PERFMON:
-        /* Implementation specific */
-        *oldvalp = 0;
-        ret = 1;
-        break;
-    case IPR_PCBB:
-        /* Read-only */
-        ret = -1;
-        break;
-    case IPR_PRBR:
-        env->ipr[IPR_PRBR] = val;
-        break;
-    case IPR_PTBR:
-        /* Read-only */
-        ret = -1;
-        break;
-    case IPR_SCBB:
-        env->ipr[IPR_SCBB] = (uint32_t)val;
-        break;
-    case IPR_SIRR:
-        if (val & 0xF) {
-            env->ipr[IPR_SISR] |= 1 << (val & 0xF);
-            /* XXX: request a software interrupt _now_ */
-        }
-        break;
-    case IPR_SISR:
-        /* Read-only */
-        ret = -1;
-        break;
-    case IPR_SSP:
-        if (env->features & FEATURE_SPS)
-            env->ipr[IPR_SSP] = val;
-        else
-            stq_raw(hwpcb + 16, val);
-        break;
-    case IPR_SYSPTBR:
-        if (env->features & FEATURE_VIRBND)
-            env->ipr[IPR_SYSPTBR] = val;
-        else
-            ret = -1;
-    case IPR_TBCHK:
-        /* Read-only */
-        ret = -1;
-        break;
-    case IPR_TBIA:
-        tlb_flush(env, 1);
-        break;
-    case IPR_TBIAP:
-        tlb_flush(env, 1);
-        break;
-    case IPR_TBIS:
-        tlb_flush_page(env, val);
-        break;
-    case IPR_TBISD:
-        tlb_flush_page(env, val);
-        break;
-    case IPR_TBISI:
-        tlb_flush_page(env, val);
-        break;
-    case IPR_USP:
-        if (env->features & FEATURE_SPS)
-            env->ipr[IPR_USP] = val;
-        else
-            stq_raw(hwpcb + 24, val);
-        break;
-    case IPR_VIRBND:
-        if (env->features & FEATURE_VIRBND)
-            env->ipr[IPR_VIRBND] = val;
-        else
-            ret = -1;
-        break;
-    case IPR_VPTB:
-        env->ipr[IPR_VPTB] = val;
-        break;
-    case IPR_WHAMI:
-        /* Read-only */
-        ret = -1;
+void cpu_alpha_update_irq (CPUState *env, int irqs)
+{
+    switch (env->pal_emul) {
+    case PAL_21264:
+        env->a21264.ipend &= ~(0x3fULL << 33);
+        env->a21264.ipend |= ((uint64_t)irqs) << 33;
+        env->a21264.isum = env->a21264.ipend & env->a21264.ier;
+        if (env->a21264.isum && !env->pal_mode)
+            cpu_interrupt(env, CPU_INTERRUPT_HARD);
         break;
     default:
-        /* Invalid */
-        ret = -1;
+        abort();
         break;
     }
-
-    return ret;
 }
 
 void do_interrupt (CPUState *env)
 {
     int excp;
 
-    env->ipr[IPR_EXC_ADDR] = env->pc | 1;
+    if (env->pal_mode && env->exception_index == EXCP_GEN_INTERRUPT) {
+        /* Can this happen ?  Maybe if the basic block finishes with a
+           palcall.  */
+        cpu_abort(env, "do_interrupt: pal_mode=1\n");
+    }
+
+    env->exc_addr = env->pc | env->pal_mode;
     excp = env->exception_index;
     env->exception_index = 0;
     env->error_code = 0;
-    /* XXX: disable interrupts and memory mapping */
-    if (env->ipr[IPR_PAL_BASE] != -1ULL) {
+    env->pal_mode = 1;
+    env->mmu_code_index = MMU_PAL_IDX;
+
+    /* Generic exception translation.  */
+    if (excp <= EXCP_GEN_LAST) {
+        switch (env->pal_emul) {
+        case PAL_21264:
+            switch (excp) {
+            case EXCP_GEN_OPCDEC:    excp = EXCP_21264_OPCDEC; break;
+            case EXCP_GEN_ARITH:     excp = EXCP_21264_ARITH; break;
+            case EXCP_GEN_INTERRUPT: excp = EXCP_21264_INTERRUPT; break;
+            default:
+                abort();
+            }
+            break;
+        case PAL_NONE:
+            cpu_abort(env, "do_interrupt: pal emul not supported\n");
+        }
+    }
+
+    switch (env->pal_emul) {
+    case PAL_21264:
+        if (env->a21264.sde1 && !(env->exc_addr & 1))
+            swap_shadow_21264(env);
+        if ((excp & EXCP_CALL_PALP) && env->a21264.call_pal_r23)
+            env->ir[23] = env->pc;
+        if (excp == EXCP_21264_INTERRUPT)
+          cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+        break;
+    default:
+        break;
+    }
+
+
+    /* We use native PALcode */
+    env->pc = env->pal_base + excp;
+
+#if 0
+    if (env->pal_base != -1ULL) {
         /* We use native PALcode */
-        env->pc = env->ipr[IPR_PAL_BASE] + excp;
+        env->pc = env->pal_base + excp;
     } else {
         /* We use emulated PALcode */
         call_pal(env);
         /* Emulate REI */
-        env->pc = env->ipr[IPR_EXC_ADDR] & ~7;
-        env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
+        env->pc = env->exc_addr & ~3ULL;
+        /* env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1; */
         /* XXX: re-enable interrupts and memory mapping */
     }
+#endif
 }
 #endif
 
@@ -419,8 +634,8 @@ void cpu_dump_state (CPUState *env, FILE *f,
     };
     int i;
 
-    cpu_fprintf(f, "     PC  " TARGET_FMT_lx "      PS  " TARGET_FMT_lx "\n",
-                env->pc, env->ps);
+    cpu_fprintf(f, "     PC  " TARGET_FMT_lx "      pal=%d\n",
+                env->pc, env->pal_mode);
     for (i = 0; i < 31; i++) {
         cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i,
                     linux_reg_names[i], env->ir[i]);
@@ -434,5 +649,6 @@ void cpu_dump_state (CPUState *env, FILE *f,
         if ((i % 3) == 2)
             cpu_fprintf(f, "\n");
     }
-    cpu_fprintf(f, "\nlock     " TARGET_FMT_lx "\n", env->lock);
+    cpu_fprintf(f, "\n");
+    /* cpu_fprintf(f, "\nlock     " TARGET_FMT_lx "\n", env->lock); */
 }
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 7c7278f..eaab3d0 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -111,11 +111,9 @@ DEF_HELPER_0(hw_rei, void)
 DEF_HELPER_1(hw_ret, void, i64)
 DEF_HELPER_2(mfpr, i64, int, i64)
 DEF_HELPER_2(mtpr, void, int, i64)
-DEF_HELPER_0(set_alt_mode, void)
-DEF_HELPER_0(restore_mode, void)
 
-DEF_HELPER_1(ld_virt_to_phys, i64, i64)
-DEF_HELPER_1(st_virt_to_phys, i64, i64)
+DEF_HELPER_2(21264_hw_ldq, i64, i64, i32)
+DEF_HELPER_2(21264_hw_ldl, i64, i64, i32)
 DEF_HELPER_1(ldl_phys, i64, i64)
 DEF_HELPER_1(ldq_phys, i64, i64)
 DEF_HELPER_1(ldl_l_phys, i64, i64)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 9e9289f..37d7be0 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -27,6 +27,8 @@
 #include "softmmu_exec.h"
 #endif /* !defined(CONFIG_USER_ONLY) */
 
+extern uint64_t cpu_get_ticks(void);
+
 void helper_tb_flush (void)
 {
     tb_flush(env);
@@ -58,8 +60,22 @@ uint64_t helper_amask (uint64_t arg)
 
 uint64_t helper_load_pcc (void)
 {
-    /* XXX: TODO */
+#ifdef CONFIG_USER_ONLY
+    /* FIXME */
     return 0;
+#else
+    uint32_t res;
+
+    switch (env->pal_emul) {
+    case PAL_21264:
+        res = env->a21264.cc_counter;
+        if (env->a21264.cc_ena)
+            res += (cpu_get_ticks() - env->a21264.cc_load_ticks) >> 3;
+        return res | env->a21264.cc_offset;
+    default:
+        cpu_abort(env,"load_ppc: bad pal emul\n");
+    }
+#endif
 }
 
 uint64_t helper_load_implver (void)
@@ -145,7 +161,7 @@ uint64_t helper_addqv (uint64_t op1, uint64_t op2)
     uint64_t tmp = op1;
     op1 += op2;
     if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) {
-        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
+        helper_excp(EXCP_GEN_ARITH, EXCP_ARITH_OVERFLOW);
     }
     return op1;
 }
@@ -155,7 +171,7 @@ uint64_t helper_addlv (uint64_t op1, uint64_t op2)
     uint64_t tmp = op1;
     op1 = (uint32_t)(op1 + op2);
     if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) {
-        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
+        helper_excp(EXCP_GEN_ARITH, EXCP_ARITH_OVERFLOW);
     }
     return op1;
 }
@@ -165,7 +181,7 @@ uint64_t helper_subqv (uint64_t op1, uint64_t op2)
     uint64_t tmp = op1;
     op1 -= op2;
     if (unlikely(((~tmp) ^ op1 ^ (-1ULL)) & ((~tmp) ^ op2) & (1ULL << 63))) {
-        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
+        helper_excp(EXCP_GEN_ARITH, EXCP_ARITH_OVERFLOW);
     }
     return op1;
 }
@@ -175,7 +191,7 @@ uint64_t helper_sublv (uint64_t op1, uint64_t op2)
     uint64_t tmp = op1;
     op1 = (uint32_t)(op1 - op2);
     if (unlikely(((~tmp) ^ op1 ^ (-1UL)) & ((~tmp) ^ op2) & (1UL << 31))) {
-        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
+        helper_excp(EXCP_GEN_ARITH, EXCP_ARITH_OVERFLOW);
     }
     return op1;
 }
@@ -185,7 +201,7 @@ uint64_t helper_mullv (uint64_t op1, uint64_t op2)
     int64_t res = (int64_t)op1 * (int64_t)op2;
 
     if (unlikely((int32_t)res != res)) {
-        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
+        helper_excp(EXCP_GEN_ARITH, EXCP_ARITH_OVERFLOW);
     }
     return (int64_t)((int32_t)res);
 }
@@ -197,7 +213,7 @@ uint64_t helper_mulqv (uint64_t op1, uint64_t op2)
     muls64(&tl, &th, op1, op2);
     /* If th != 0 && th != -1, then we had an overflow */
     if (unlikely((th + 1) > 1)) {
-        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
+        helper_excp(EXCP_GEN_ARITH, EXCP_ARITH_OVERFLOW);
     }
     return tl;
 }
@@ -390,7 +406,7 @@ static always_inline float32 f_to_float32 (uint64_t a)
 
     if (unlikely(!exp && mant_sig)) {
         /* Reserved operands / Dirty zero */
-        helper_excp(EXCP_OPCDEC, 0);
+        helper_excp(EXCP_GEN_OPCDEC, 0);
     }
 
     if (exp < 3) {
@@ -517,7 +533,7 @@ static always_inline float64 g_to_float64 (uint64_t a)
 
     if (!exp && mant_sig) {
         /* Reserved operands / Dirty zero */
-        helper_excp(EXCP_OPCDEC, 0);
+        helper_excp(EXCP_GEN_OPCDEC, 0);
     }
 
     if (exp < 3) {
@@ -972,7 +988,7 @@ static always_inline uint64_t __helper_cvtql (uint64_t a, int s, int v)
     r |= ((uint64_t)(a & 0x7FFFFFFF)) << 29;
 
     if (v && (int64_t)((int32_t)r) != (int64_t)r) {
-        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
+        helper_excp(EXCP_GEN_ARITH, EXCP_ARITH_OVERFLOW);
     }
     if (s) {
         /* TODO */
@@ -999,96 +1015,137 @@ uint64_t helper_cvtqlsv (uint64_t a)
 #if !defined (CONFIG_USER_ONLY)
 void helper_hw_rei (void)
 {
-    env->pc = env->ipr[IPR_EXC_ADDR] & ~3;
-    env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
+#if 0
+    /* FIXME: For 21064/21164 only ?  */
+    env->pc = env->any.ipr[IPR_EXC_ADDR] & ~3;
+    env->any.ipr[IPR_EXC_ADDR] = env->any.ipr[IPR_EXC_ADDR] & 1;
     /* XXX: re-enable interrupts and memory mapping */
+#else
+    cpu_abort(env, "hw_rei not implemented\n");
+#endif
 }
 
 void helper_hw_ret (uint64_t a)
 {
-    env->pc = a & ~3;
-    env->ipr[IPR_EXC_ADDR] = a & 1;
-    /* XXX: re-enable interrupts and memory mapping */
+    switch (env->pal_emul) {
+    case PAL_21264:
+        if (!(a & 1) && env->a21264.isum) {
+#if 0
+            qemu_log("pal mode ret interrupt ier=%016llx, isum=%016llx ir=%x\n",
+                     env->a21264.ier, env->a21264.isum,
+                     env->interrupt_request);
+#endif
+            /* Very fast interrupt delivery!  */
+            env->exc_addr = a;
+            env->pc = env->pal_base + EXCP_21264_INTERRUPT;
+            env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+            break;
+        }
+        env->pc = a & ~3;
+        if (env->pal_mode != (a & 1)) {
+            env->pal_mode = a & 1;
+            if (!env->pal_mode)
+                env->mmu_code_index = env->mmu_data_index;
+            else
+                env->mmu_code_index = MMU_PAL_IDX;
+            if (env->a21264.sde1 && !(a & 1))
+                swap_shadow_21264(env);
+        }
+        break;
+    case PAL_NONE:
+        cpu_abort(env, "hw_ret: not supported by pal emulation\n");
+    }
 }
 
 uint64_t helper_mfpr (int iprn, uint64_t val)
 {
-    uint64_t tmp;
-
-    if (cpu_alpha_mfpr(env, iprn, &tmp) == 0)
-        val = tmp;
-
+    switch (env->pal_emul) {
+    case PAL_21264:
+      return cpu_alpha_mfpr_21264(env, iprn);
+      break;
+    case PAL_NONE:
+        cpu_abort(env, "hw_mfpr: not supported by pal emulation\n");
+    }
     return val;
 }
 
 void helper_mtpr (int iprn, uint64_t val)
 {
-    cpu_alpha_mtpr(env, iprn, val, NULL);
-}
-
-void helper_set_alt_mode (void)
-{
-    env->saved_mode = env->ps & 0xC;
-    env->ps = (env->ps & ~0xC) | (env->ipr[IPR_ALT_MODE] & 0xC);
-}
-
-void helper_restore_mode (void)
-{
-    env->ps = (env->ps & ~0xC) | env->saved_mode;
+    switch (env->pal_emul) {
+    case PAL_21264:
+      cpu_alpha_mtpr_21264(env, iprn, val);
+      return;
+    case PAL_NONE:
+        cpu_abort(env, "hw_mtpr: not supported by pal emulation\n");
+    }
 }
-
 #endif
 
 /*****************************************************************************/
 /* Softmmu support */
 #if !defined (CONFIG_USER_ONLY)
 
-/* XXX: the two following helpers are pure hacks.
- *      Hopefully, we emulate the PALcode, then we should never see
- *      HW_LD / HW_ST instructions.
- */
-uint64_t helper_ld_virt_to_phys (uint64_t virtaddr)
+static uint64_t hw_ld_virt2phys (uint64_t virtaddr, uint32_t v2p_flags)
+{
+    int mmu_idx;
+    struct alpha_pte pte;
+
+    mmu_idx = v2p_flags & ALPHA_HW_MMUIDX_MASK;
+    pte = cpu_alpha_mmu_v2p_21264(env, virtaddr, 0);
+    if (!(pte.fl & ALPHA_PTE_V)) {
+        if (v2p_flags & ALPHA_HW_V) {
+            /* Virtual pte access.  */
+            env->exception_index = env->a21264.iva_48 ?
+                EXCP_21264_DTBM_DOUBLE_4 : EXCP_21264_DTBM_DOUBLE_3;
+        } else
+            env->exception_index = EXCP_21264_DTBM_SINGLE;
+        cpu_alpha_mmu_dfault_21264(env, virtaddr, 0x03);
+        cpu_loop_exit();
+    }
+    if ((v2p_flags & ALPHA_HW_W)
+        && (!((pte.fl >> mmu_idx) & ALPHA_PTE_KRE)
+            || (pte.fl & ALPHA_PTE_FOR))) {
+        env->exception_index = EXCP_21264_DFAULT;
+        cpu_alpha_mmu_dfault_21264(env, virtaddr, 0x03);
+        cpu_loop_exit();
+    }
+    return (((uint64_t)pte.pa) << 13) | (virtaddr & ~TARGET_PAGE_MASK);
+}
+
+uint64_t helper_21264_hw_ldq (uint64_t virtaddr, uint32_t v2p_flags)
 {
     uint64_t tlb_addr, physaddr;
     int index, mmu_idx;
-    void *retaddr;
 
-    mmu_idx = cpu_mmu_index_data(env);
+    mmu_idx = v2p_flags & ALPHA_HW_MMUIDX_MASK;
     index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- redo:
     tlb_addr = env->tlb_table[mmu_idx][index].addr_read;
     if ((virtaddr & TARGET_PAGE_MASK) ==
         (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
         physaddr = virtaddr + env->tlb_table[mmu_idx][index].addend;
+        return ldq_raw((uint8_t *)physaddr);
     } else {
-        /* the page is not in the TLB : fill it */
-        retaddr = GETPC();
-        tlb_fill(virtaddr, 0, mmu_idx, retaddr);
-        goto redo;
+        physaddr = hw_ld_virt2phys(virtaddr, v2p_flags);
+        return ldq_phys(physaddr);
     }
-    return physaddr;
 }
 
-uint64_t helper_st_virt_to_phys (uint64_t virtaddr)
+uint64_t helper_21264_hw_ldl (uint64_t virtaddr, uint32_t v2p_flags)
 {
     uint64_t tlb_addr, physaddr;
     int index, mmu_idx;
-    void *retaddr;
 
-    mmu_idx = cpu_mmu_index_data(env);
+    mmu_idx = v2p_flags & ALPHA_HW_MMUIDX_MASK;
     index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- redo:
-    tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
+    tlb_addr = env->tlb_table[mmu_idx][index].addr_read;
     if ((virtaddr & TARGET_PAGE_MASK) ==
         (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
         physaddr = virtaddr + env->tlb_table[mmu_idx][index].addend;
+        return ldl_raw((uint8_t *)physaddr);
     } else {
-        /* the page is not in the TLB : fill it */
-        retaddr = GETPC();
-        tlb_fill(virtaddr, 1, mmu_idx, retaddr);
-        goto redo;
+        physaddr = hw_ld_virt2phys(virtaddr, v2p_flags);
+        return ldl_phys(physaddr);
     }
-    return physaddr;
 }
 
 uint64_t helper_ldl_phys(uint64_t addr)
@@ -1185,31 +1242,29 @@ uint64_t helper_stq_c_phys(uint64_t val, uint64_t addr)
    NULL, it means that the function was called in C code (i.e. not
    from generated code or from helper.c) */
 /* XXX: fix it to restore all registers */
-void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
+void tlb_fill (target_ulong addr, int rwx, int mmu_idx, void *retaddr)
 {
-    TranslationBlock *tb;
     CPUState *saved_env;
-    unsigned long pc;
     int ret;
 
     /* XXX: hack to restore env in all cases, even if not called from
        generated code */
     saved_env = env;
     env = cpu_single_env;
-    ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
-    if (!likely(ret == 0)) {
-        if (likely(retaddr)) {
-            /* now we have a real cpu fault */
-            pc = (unsigned long)retaddr;
-            tb = tb_find_pc(pc);
-            if (likely(tb)) {
-                /* the PC is inside the translated code. It means that we have
-                   a virtual CPU fault */
-                cpu_restore_state(tb, env, pc, NULL);
-            }
+
+    if (rwx == 2 && mmu_idx == MMU_PAL_IDX)
+        cpu_alpha_mmu_fault_pal(env, addr);
+    else {
+        switch (env->pal_emul) {
+        case PAL_21264:
+            ret = cpu_alpha_mmu_fault_21264(env, addr, rwx, mmu_idx, retaddr);
+            if (!likely(ret == 0))
+                /* Exception index and error code are already set */
+                cpu_loop_exit();
+            break;
+        case PAL_NONE:
+            cpu_abort(env, "tlb_fill: not supported by pal emulation\n");
         }
-        /* Exception index and error code are already set */
-        cpu_loop_exit();
     }
     env = saved_env;
 }
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 6938b5d..99527f5 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -47,6 +47,7 @@
 typedef struct DisasContext DisasContext;
 struct DisasContext {
     uint64_t pc;
+    CPUAlphaState *env;
     int mem_idx;
 #if !defined (CONFIG_USER_ONLY)
     int pal_mode;
@@ -106,7 +107,7 @@ static void alpha_translate_init(void)
 
 static inline int get_mxcr_iprn(DisasContext *ctx, uint32_t insn)
 {
-    switch (ctx->implver) {
+    switch (ctx->env->implver) {
     case IMPLVER_2106x:
         return insn & 0xff;
     case IMPLVER_21164:
@@ -118,6 +119,43 @@ static inline int get_mxcr_iprn(DisasContext *ctx, uint32_t insn)
     }
 }
 
+#if !defined (CONFIG_USER_ONLY)
+static inline void gen_hw_ld(DisasContext *ctx, int ra, TCGv addr,
+                              int hw_flags)
+{
+    TCGv_i32 flags = tcg_temp_new_i32();
+
+    tcg_gen_movi_i64(cpu_pc, ctx->pc - 4);
+    tcg_gen_movi_i32(flags, ctx->mem_idx | hw_flags);
+    switch (ctx->env->pal_emul) {
+    case PAL_21264:
+        if (hw_flags & ALPHA_HW_L)
+            gen_helper_21264_hw_ldl(cpu_ir[ra], addr, flags);
+        else if (hw_flags & ALPHA_HW_Q)
+            gen_helper_21264_hw_ldq(cpu_ir[ra], addr, flags);
+        else
+            abort();
+        break;
+    default:
+        cpu_abort(ctx->env, "gen_hw_ld: pal emul %d not supported\n",
+                  ctx->env->pal_emul);
+    }
+    tcg_temp_free_i32(flags);
+}
+
+static inline void gen_hw_st(DisasContext *ctx, int ra, TCGv addr,
+                              int hw_flags)
+{
+    TCGv_i32 flags = tcg_temp_new_i32();
+
+    tcg_gen_movi_i64(cpu_pc, ctx->pc - 4);
+    tcg_gen_movi_i32(flags, ctx->mem_idx | hw_flags);
+    cpu_abort(ctx->env, "gen_hw_st: pal emul %d not supported\n",
+              ctx->env->pal_emul);
+    tcg_temp_free_i32(flags);
+}
+#endif /* CONFIG_USER_ONLY */
+
 static always_inline void gen_excp (DisasContext *ctx,
                                     int exception, int error_code)
 {
@@ -133,7 +171,7 @@ static always_inline void gen_excp (DisasContext *ctx,
 
 static always_inline void gen_invalid (DisasContext *ctx)
 {
-    gen_excp(ctx, EXCP_OPCDEC, 0);
+    gen_excp(ctx, EXCP_GEN_OPCDEC, 0);
 }
 
 static always_inline void gen_qemu_ldf (TCGv t0, TCGv t1, int flags)
@@ -1806,6 +1844,8 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
                 tcg_gen_addi_i64(addr, cpu_ir[rb], disp12);
             else
                 tcg_gen_movi_i64(addr, disp12);
+            /* Data alignment check is disabled for hw_ld */
+            tcg_gen_andi_i64(addr, addr, ((insn >> 12) & 1) ? ~0x7 : ~0x3);
             switch ((insn >> 12) & 0xF) {
             case 0x0:
                 /* Longword physical access (hw_ldl/p) */
@@ -1825,11 +1865,11 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
                 break;
             case 0x4:
                 /* Longword virtual PTE fetch (hw_ldl/v) */
-                tcg_gen_qemu_ld32s(cpu_ir[ra], addr, 0);
+                gen_hw_ld(ctx, ra, addr, ALPHA_HW_V | ALPHA_HW_L);
                 break;
             case 0x5:
                 /* Quadword virtual PTE fetch (hw_ldq/v) */
-                tcg_gen_qemu_ld64(cpu_ir[ra], addr, 0);
+                gen_hw_ld(ctx, ra, addr, ALPHA_HW_V | ALPHA_HW_Q);
                 break;
             case 0x6:
                 /* Incpu_ir[ra]id */
@@ -1839,51 +1879,37 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
                 goto invalid_opc;
             case 0x8:
                 /* Longword virtual access (hw_ldl) */
-                gen_helper_st_virt_to_phys(addr, addr);
-                gen_helper_ldl_phys(cpu_ir[ra], addr);
+                gen_hw_ld(ctx, ra, addr, ALPHA_HW_L);
                 break;
             case 0x9:
                 /* Quadword virtual access (hw_ldq) */
-                gen_helper_st_virt_to_phys(addr, addr);
-                gen_helper_ldq_phys(cpu_ir[ra], addr);
+                gen_hw_ld(ctx, ra, addr, ALPHA_HW_Q);
                 break;
             case 0xA:
                 /* Longword virtual access with protection check (hw_ldl/w) */
-                tcg_gen_qemu_ld32s(cpu_ir[ra], addr, 0);
+                gen_hw_ld(ctx, ra, addr, ALPHA_HW_W | ALPHA_HW_L);
                 break;
             case 0xB:
                 /* Quadword virtual access with protection check (hw_ldq/w) */
-                tcg_gen_qemu_ld64(cpu_ir[ra], addr, 0);
+                gen_hw_ld(ctx, ra, addr, ALPHA_HW_W | ALPHA_HW_Q);
                 break;
             case 0xC:
                 /* Longword virtual access with alt access mode (hw_ldl/a)*/
-                gen_helper_set_alt_mode();
-                gen_helper_st_virt_to_phys(addr, addr);
-                gen_helper_ldl_phys(cpu_ir[ra], addr);
-                gen_helper_restore_mode();
+                gen_hw_ld(ctx, ra, addr, ALPHA_HW_A | ALPHA_HW_L);
                 break;
             case 0xD:
                 /* Quadword virtual access with alt access mode (hw_ldq/a) */
-                gen_helper_set_alt_mode();
-                gen_helper_st_virt_to_phys(addr, addr);
-                gen_helper_ldq_phys(cpu_ir[ra], addr);
-                gen_helper_restore_mode();
+                gen_hw_ld(ctx, ra, addr, ALPHA_HW_A | ALPHA_HW_Q);
                 break;
             case 0xE:
                 /* Longword virtual access with alternate access mode and
-                 * protection checks (hw_ldl/wa)
-                 */
-                gen_helper_set_alt_mode();
-                gen_helper_ldl_data(cpu_ir[ra], addr);
-                gen_helper_restore_mode();
+                 * protection checks (hw_ldl/wa) */
+                gen_hw_ld(ctx, ra, addr, ALPHA_HW_A | ALPHA_HW_W | ALPHA_HW_L);
                 break;
             case 0xF:
                 /* Quadword virtual access with alternate access mode and
-                 * protection checks (hw_ldq/wa)
-                 */
-                gen_helper_set_alt_mode();
-                gen_helper_ldq_data(cpu_ir[ra], addr);
-                gen_helper_restore_mode();
+                 * protection checks (hw_ldq/wa) */
+                gen_hw_ld(ctx, ra, addr, ALPHA_HW_A | ALPHA_HW_W | ALPHA_HW_Q);
                 break;
             }
             tcg_temp_free(addr);
@@ -2135,6 +2161,7 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
                 val = tcg_temp_new();
                 tcg_gen_movi_i64(val, 0);
             }
+            LOG_DISAS("pal1f acc=%d\n", (insn >> 12) & 0xf);
             switch ((insn >> 12) & 0xF) {
             case 0x0:
                 /* Longword physical access */
@@ -2154,13 +2181,11 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
                 break;
             case 0x4:
                 /* Longword virtual access */
-                gen_helper_st_virt_to_phys(addr, addr);
-                gen_helper_stl_phys(val, addr);
+                gen_hw_st(ctx, addr, val, ALPHA_HW_L);
                 break;
             case 0x5:
                 /* Quadword virtual access */
-                gen_helper_st_virt_to_phys(addr, addr);
-                gen_helper_stq_phys(val, addr);
+                gen_hw_st(ctx, addr, val, ALPHA_HW_Q);
                 break;
             case 0x6:
                 /* Invalid */
@@ -2182,17 +2207,11 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
                 goto invalid_opc;
             case 0xC:
                 /* Longword virtual access with alternate access mode */
-                gen_helper_set_alt_mode();
-                gen_helper_st_virt_to_phys(addr, addr);
-                gen_helper_stl_phys(val, addr);
-                gen_helper_restore_mode();
+                gen_hw_st(ctx, addr, val, ALPHA_HW_A | ALPHA_HW_L);
                 break;
             case 0xD:
                 /* Quadword virtual access with alternate access mode */
-                gen_helper_set_alt_mode();
-                gen_helper_st_virt_to_phys(addr, addr);
-                gen_helper_stl_phys(val, addr);
-                gen_helper_restore_mode();
+                gen_hw_st(ctx, addr, val, ALPHA_HW_A | ALPHA_HW_Q);
                 break;
             case 0xE:
                 /* Invalid */
@@ -2367,12 +2386,20 @@ static always_inline void gen_intermediate_code_internal (CPUState *env,
     gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
     ctx.pc = pc_start;
     ctx.amask = env->amask;
-    ctx.implver = env->implver;
+    ctx.env = env;
 #if defined (CONFIG_USER_ONLY)
     ctx.mem_idx = 0;
 #else
-    ctx.mem_idx = ((env->ps >> 3) & 3);
-    ctx.pal_mode = env->ipr[IPR_EXC_ADDR] & 1;
+    ctx.mem_idx = env->mmu_data_index;
+    ctx.pal_mode = env->pal_mode;
+    switch (env->pal_emul) {
+    case PAL_21264:
+        if (env->a21264.hwe && env->a21264.cm == 0)
+            ctx.pal_mode = 1;
+        break;
+    default:
+        break;
+    }
 #endif
     num_insns = 0;
     max_insns = tb->cflags & CF_COUNT_MASK;
@@ -2428,7 +2455,7 @@ static always_inline void gen_intermediate_code_internal (CPUState *env,
         if (env->singlestep_enabled) {
             gen_excp(&ctx, EXCP_DEBUG, 0);
             break;
-	}
+        }
 
 #if defined (DO_SINGLE_STEP)
         break;
@@ -2501,7 +2528,6 @@ void alpha_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
 CPUAlphaState * cpu_alpha_init (const char *cpu_model)
 {
     CPUAlphaState *env;
-    uint64_t hwpcb;
     const struct alpha_def *cpu = alpha_defs;
 
     if (cpu_model != NULL) {
@@ -2520,31 +2546,24 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
     alpha_translate_init();
     tlb_flush(env, 1);
 
+    env->pal_emul = PAL_NONE;
     env->implver = cpu->implver;
     env->amask = cpu->amask;
-    env->ps = 0x1F00;
-#if defined (CONFIG_USER_ONLY)
-    env->ps |= 1 << 3;
-#endif
-    /* Initialize IPR */
-    hwpcb = env->ipr[IPR_PCBB];
-    env->ipr[IPR_ASN] = 0;
-    env->ipr[IPR_ASTEN] = 0;
-    env->ipr[IPR_ASTSR] = 0;
-    env->ipr[IPR_DATFX] = 0;
-    /* XXX: fix this */
-    //    env->ipr[IPR_ESP] = ldq_raw(hwpcb + 8);
-    //    env->ipr[IPR_KSP] = ldq_raw(hwpcb + 0);
-    //    env->ipr[IPR_SSP] = ldq_raw(hwpcb + 16);
-    //    env->ipr[IPR_USP] = ldq_raw(hwpcb + 24);
-    env->ipr[IPR_FEN] = 0;
-    env->ipr[IPR_IPL] = 31;
-    env->ipr[IPR_MCES] = 0;
-    env->ipr[IPR_PERFMON] = 0; /* Implementation specific */
-    //    env->ipr[IPR_PTBR] = ldq_raw(hwpcb + 32);
-    env->ipr[IPR_SISR] = 0;
-    env->ipr[IPR_VIRBND] = -1ULL;
 
+#ifndef CONFIG_USER_ONLY
+    env->pal_mode = 1;
+    env->mmu_code_index = 4;
+    env->mmu_data_index = 0;
+
+    switch (env->implver) {
+    case IMPLVER_21264:
+        init_cpu_21264(env);
+        break;
+    default:
+        abort();
+        break;
+    }
+#endif
     return env;
 }
 
-- 
1.6.2

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

* Re: [Qemu-devel] [PATCH 0/20]: add alpha es40 system emulation (v4)
  2009-03-30 14:36 [Qemu-devel] [PATCH 0/20]: add alpha es40 system emulation (v4) Tristan Gingold
  2009-03-30 14:36 ` [Qemu-devel] [PATCH 01/19] Add support for multi-level phys map Tristan Gingold
@ 2009-03-30 15:46 ` Brian Wheeler
  2009-03-30 16:04   ` Tristan Gingold
  1 sibling, 1 reply; 36+ messages in thread
From: Brian Wheeler @ 2009-03-30 15:46 UTC (permalink / raw)
  To: qemu-devel

I get a fatal message on boot:

es40: arr[0]=0000000000004005:  128MB at   128MB
qemu: fatal: cpu_alpha_mtpr_21264: ipr 0x80 not handled


Putting an empty case in helper.c gets past that, but then fails on 0xf0
and 0x22.  Then it fails on pctx.astrr

Brian



On Mon, 2009-03-30 at 16:36 +0200, Tristan Gingold wrote:
> new version of alpha system emulation.
> 
> I have followed Paul Brook's advice and now patch 02 has only one code paths.
> For 32 bits address spaces the code looks equivalent to the current one.
> For address spaces lager than 32 bits, only the size of level may have
> changed.
> 
> I have also fixed the comment (thanks to Aurelien) in path 05.
> 
> Two new bugs in alpha tcg code have been fixed (see pathes 07 and 08)
> 
> Some bugs have also been fixed in system emulation code.  I am making
> progress...  With some additionnal patches, I can now run AlphaBIOS.
> 
> Comments and reviews are welcome,
> Tristan.
> 
> 

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

* Re: [Qemu-devel] [PATCH 0/20]: add alpha es40 system emulation (v4)
  2009-03-30 15:46 ` [Qemu-devel] [PATCH 0/20]: add alpha es40 system emulation (v4) Brian Wheeler
@ 2009-03-30 16:04   ` Tristan Gingold
  2009-03-30 16:43     ` Brian Wheeler
  0 siblings, 1 reply; 36+ messages in thread
From: Tristan Gingold @ 2009-03-30 16:04 UTC (permalink / raw)
  To: qemu-devel


On Mar 30, 2009, at 5:46 PM, Brian Wheeler wrote:

> I get a fatal message on boot:
>
> es40: arr[0]=0000000000004005:  128MB at   128MB
> qemu: fatal: cpu_alpha_mtpr_21264: ipr 0x80 not handled
>
>
> Putting an empty case in helper.c gets past that, but then fails on  
> 0xf0
> and 0x22.  Then it fails on pctx.astrr

Looks like garbage is executed.  Can you send to me /tmp/qemu.log when  
run with -d in_asm,cpu,exec ?

Thanks,
Tristan.

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

* Re: [Qemu-devel] [PATCH 0/20]: add alpha es40 system emulation (v4)
  2009-03-30 16:04   ` Tristan Gingold
@ 2009-03-30 16:43     ` Brian Wheeler
  0 siblings, 0 replies; 36+ messages in thread
From: Brian Wheeler @ 2009-03-30 16:43 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 564 bytes --]

On Mon, 2009-03-30 at 18:04 +0200, Tristan Gingold wrote:
> On Mar 30, 2009, at 5:46 PM, Brian Wheeler wrote:
> 
> > I get a fatal message on boot:
> >
> > es40: arr[0]=0000000000004005:  128MB at   128MB
> > qemu: fatal: cpu_alpha_mtpr_21264: ipr 0x80 not handled
> >
> >
> > Putting an empty case in helper.c gets past that, but then fails on  
> > 0xf0
> > and 0x22.  Then it fails on pctx.astrr
> 
> Looks like garbage is executed.  Can you send to me /tmp/qemu.log when  
> run with -d in_asm,cpu,exec ?
> 
> Thanks,
> Tristan.
> 
> 
> 

Its attached.

Brian

[-- Attachment #2: qemu.log --]
[-- Type: text/x-log, Size: 7688 bytes --]

pc 0000000000008000 mem_idx 0
opcode 47ff0410 2
opc 11 ra 31 rb 31 rc 16 disp16 0410
pc 0000000000008004 mem_idx 0
opcode c3402e1e 4
opc 30 ra 26 rb 0 rc 30 disp16 2e1e
     PC  0000000000008000      pal=1
IR00 v0  0000000000000000 IR01 t0  0000000000000000 IR02 t1  0000000000000000 
IR03 t2  0000000000000000 IR04 t3  0000000000000000 IR05 t4  0000000000000000 
IR06 t5  0000000000000000 IR07 t6  0000000000000000 IR08 t7  0000000000000000 
IR09 s0  0000000000000000 IR10 s1  0000000000000000 IR11 s2  0000000000000000 
IR12 s3  0000000000000000 IR13 s4  0000000000000000 IR14 s5  0000000000000000 
IR15 fp  0000000000000000 IR16 a0  0000000000000000 IR17 a1  0000000000000000 
IR18 a2  0000000000000000 IR19 a3  0000000000000000 IR20 a4  0000000000000000 
IR21 a5  0000000000000000 IR22 t8  0000000000000000 IR23 t9  0000000000000000 
IR24 t10 0000000000000000 IR25 t11 0000000000000000 IR26 ra  0000000000000000 
IR27 t12 0000000000000000 IR28 at  0000000000000000 IR29 gp  0000000000000000 
IR30 sp  0000000000000000 
FIR00    0000000000000000 FIR01    0000000000000000 FIR02    0000000000000000 
FIR03    0000000000000000 FIR04    0000000000000000 FIR05    0000000000000000 
FIR06    0000000000000000 FIR07    0000000000000000 FIR08    0000000000000000 
FIR09    0000000000000000 FIR10    0000000000000000 FIR11    0000000000000000 
FIR12    0000000000000000 FIR13    0000000000000000 FIR14    0000000000000000 
FIR15    0000000000000000 FIR16    0000000000000000 FIR17    0000000000000000 
FIR18    0000000000000000 FIR19    0000000000000000 FIR20    0000000000000000 
FIR21    0000000000000000 FIR22    0000000000000000 FIR23    0000000000000000 
FIR24    0000000000000000 FIR25    0000000000000000 FIR26    0000000000000000 
FIR27    0000000000000000 FIR28    0000000000000000 FIR29    0000000000000000 
FIR30    0000000000000000 
IN: 
0x0000000000008000:  clr	a0
0x0000000000008004:  br	ra,0x13880

pc 0000000000013880 mem_idx 0
opcode 44000400 6
opc 11 ra 0 rb 0 rc 0 disp16 0400
pc 0000000000013884 mem_idx 0
opcode 47ff041f 8
opc 11 ra 31 rb 31 rc 31 disp16 041f
pc 0000000000013888 mem_idx 0
opcode 47ff041f 10
opc 11 ra 31 rb 31 rc 31 disp16 041f
pc 000000000001388c mem_idx 0
opcode 47ff041f 12
opc 11 ra 31 rb 31 rc 31 disp16 041f
pc 0000000000013890 mem_idx 0
opcode 77ff0310 14
opc 1d ra 31 rb 31 rc 16 disp16 0310
     PC  0000000000013880      pal=1
IR00 v0  0000000000000000 IR01 t0  0000000000000000 IR02 t1  0000000000000000 
IR03 t2  0000000000000000 IR04 t3  0000000000000000 IR05 t4  0000000000000000 
IR06 t5  0000000000000000 IR07 t6  0000000000000000 IR08 t7  0000000000000000 
IR09 s0  0000000000000000 IR10 s1  0000000000000000 IR11 s2  0000000000000000 
IR12 s3  0000000000000000 IR13 s4  0000000000000000 IR14 s5  0000000000000000 
IR15 fp  0000000000000000 IR16 a0  0000000000000000 IR17 a1  0000000000000000 
IR18 a2  0000000000000000 IR19 a3  0000000000000000 IR20 a4  0000000000000000 
IR21 a5  0000000000000000 IR22 t8  0000000000000000 IR23 t9  0000000000000000 
IR24 t10 0000000000000000 IR25 t11 0000000000000000 IR26 ra  0000000000008008 
IR27 t12 0000000000000000 IR28 at  0000000000000000 IR29 gp  0000000000000000 
IR30 sp  0000000000000000 
FIR00    0000000000000000 FIR01    0000000000000000 FIR02    0000000000000000 
FIR03    0000000000000000 FIR04    0000000000000000 FIR05    0000000000000000 
FIR06    0000000000000000 FIR07    0000000000000000 FIR08    0000000000000000 
FIR09    0000000000000000 FIR10    0000000000000000 FIR11    0000000000000000 
FIR12    0000000000000000 FIR13    0000000000000000 FIR14    0000000000000000 
FIR15    0000000000000000 FIR16    0000000000000000 FIR17    0000000000000000 
FIR18    0000000000000000 FIR19    0000000000000000 FIR20    0000000000000000 
FIR21    0000000000000000 FIR22    0000000000000000 FIR23    0000000000000000 
FIR24    0000000000000000 FIR25    0000000000000000 FIR26    0000000000000000 
FIR27    0000000000000000 FIR28    0000000000000000 FIR29    0000000000000000 
FIR30    0000000000000000 
IN: 
0x0000000000013880:  mov	v0,v0
0x0000000000013884:  nop	
0x0000000000013888:  nop	
0x000000000001388c:  nop	
0x0000000000013890:  pal1d	0x3ff0310

pc 0000000000013894 mem_idx 0
opcode 77ffa380 16
opc 1d ra 31 rb 31 rc 0 disp16 ffffa380
     PC  0000000000013894      pal=1
IR00 v0  0000000000000000 IR01 t0  0000000000000000 IR02 t1  0000000000000000 
IR03 t2  0000000000000000 IR04 t3  0000000000000000 IR05 t4  0000000000000000 
IR06 t5  0000000000000000 IR07 t6  0000000000000000 IR08 t7  0000000000000000 
IR09 s0  0000000000000000 IR10 s1  0000000000000000 IR11 s2  0000000000000000 
IR12 s3  0000000000000000 IR13 s4  0000000000000000 IR14 s5  0000000000000000 
IR15 fp  0000000000000000 IR16 a0  0000000000000000 IR17 a1  0000000000000000 
IR18 a2  0000000000000000 IR19 a3  0000000000000000 IR20 a4  0000000000000000 
IR21 a5  0000000000000000 IR22 t8  0000000000000000 IR23 t9  0000000000000000 
IR24 t10 0000000000000000 IR25 t11 0000000000000000 IR26 ra  0000000000008008 
IR27 t12 0000000000000000 IR28 at  0000000000000000 IR29 gp  0000000000000000 
IR30 sp  0000000000000000 
FIR00    0000000000000000 FIR01    0000000000000000 FIR02    0000000000000000 
FIR03    0000000000000000 FIR04    0000000000000000 FIR05    0000000000000000 
FIR06    0000000000000000 FIR07    0000000000000000 FIR08    0000000000000000 
FIR09    0000000000000000 FIR10    0000000000000000 FIR11    0000000000000000 
FIR12    0000000000000000 FIR13    0000000000000000 FIR14    0000000000000000 
FIR15    0000000000000000 FIR16    0000000000000000 FIR17    0000000000000000 
FIR18    0000000000000000 FIR19    0000000000000000 FIR20    0000000000000000 
FIR21    0000000000000000 FIR22    0000000000000000 FIR23    0000000000000000 
FIR24    0000000000000000 FIR25    0000000000000000 FIR26    0000000000000000 
FIR27    0000000000000000 FIR28    0000000000000000 FIR29    0000000000000000 
FIR30    0000000000000000 
IN: 
0x0000000000013894:  pal1d	0x3ffa380

qemu: fatal: cpu_alpha_mtpr_21264: ipr 0x80 not handled

     PC  0000000000013894      pal=1
IR00 v0  0000000000000000 IR01 t0  0000000000000000 IR02 t1  0000000000000000 
IR03 t2  0000000000000000 IR04 t3  0000000000000000 IR05 t4  0000000000000000 
IR06 t5  0000000000000000 IR07 t6  0000000000000000 IR08 t7  0000000000000000 
IR09 s0  0000000000000000 IR10 s1  0000000000000000 IR11 s2  0000000000000000 
IR12 s3  0000000000000000 IR13 s4  0000000000000000 IR14 s5  0000000000000000 
IR15 fp  0000000000000000 IR16 a0  0000000000000000 IR17 a1  0000000000000000 
IR18 a2  0000000000000000 IR19 a3  0000000000000000 IR20 a4  0000000000000000 
IR21 a5  0000000000000000 IR22 t8  0000000000000000 IR23 t9  0000000000000000 
IR24 t10 0000000000000000 IR25 t11 0000000000000000 IR26 ra  0000000000008008 
IR27 t12 0000000000000000 IR28 at  0000000000000000 IR29 gp  0000000000000000 
IR30 sp  0000000000000000 
FIR00    0000000000000000 FIR01    0000000000000000 FIR02    0000000000000000 
FIR03    0000000000000000 FIR04    0000000000000000 FIR05    0000000000000000 
FIR06    0000000000000000 FIR07    0000000000000000 FIR08    0000000000000000 
FIR09    0000000000000000 FIR10    0000000000000000 FIR11    0000000000000000 
FIR12    0000000000000000 FIR13    0000000000000000 FIR14    0000000000000000 
FIR15    0000000000000000 FIR16    0000000000000000 FIR17    0000000000000000 
FIR18    0000000000000000 FIR19    0000000000000000 FIR20    0000000000000000 
FIR21    0000000000000000 FIR22    0000000000000000 FIR23    0000000000000000 
FIR24    0000000000000000 FIR25    0000000000000000 FIR26    0000000000000000 
FIR27    0000000000000000 FIR28    0000000000000000 FIR29    0000000000000000 
FIR30    0000000000000000 

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

* Re: [Qemu-devel] [PATCH 06/19] Bug fix alpha: stop translation if too long
  2009-03-30 14:36           ` [Qemu-devel] [PATCH 06/19] Bug fix alpha: stop translation if too long Tristan Gingold
  2009-03-30 14:36             ` [Qemu-devel] [PATCH 07/19] Alpha bug: fix palcode mask for user pal calls Tristan Gingold
@ 2009-04-07 21:44             ` Aurelien Jarno
  1 sibling, 0 replies; 36+ messages in thread
From: Aurelien Jarno @ 2009-04-07 21:44 UTC (permalink / raw)
  To: Tristan Gingold; +Cc: qemu-devel

On Mon, Mar 30, 2009 at 04:36:21PM +0200, Tristan Gingold wrote:
> Signed-off-by: Tristan Gingold <gingold@adacore.com>
> ---
>  target-alpha/translate.c |    6 +++---
>  1 files changed, 3 insertions(+), 3 deletions(-)

I have applied a slightly different patch to split the tests into
different if for better readability. Thanks.

> diff --git a/target-alpha/translate.c b/target-alpha/translate.c
> index e9463ae..dad1686 100644
> --- a/target-alpha/translate.c
> +++ b/target-alpha/translate.c
> @@ -2401,10 +2401,10 @@ static always_inline void gen_intermediate_code_internal (CPUState *env,
>          ret = translate_one(ctxp, insn);
>          if (ret != 0)
>              break;
> -        /* if we reach a page boundary or are single stepping, stop
> -         * generation
> -         */
> +        /* if we reach a page boundary, or translation is too long
> +           or are single stepping, stop generation.  */
>          if (((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) ||
> +            gen_opc_ptr >= gen_opc_end ||
>              num_insns >= max_insns) {
>              break;
>          }
> -- 
> 1.6.2
> 
> 
> 
> 

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 03/19] Alpha: set target page size to 13 bits.
  2009-03-30 14:36     ` [Qemu-devel] [PATCH 03/19] Alpha: set target page size to 13 bits Tristan Gingold
  2009-03-30 14:36       ` [Qemu-devel] [PATCH 04/19] Allow 5 mmu indexes Tristan Gingold
@ 2009-04-07 21:47       ` Aurelien Jarno
  1 sibling, 0 replies; 36+ messages in thread
From: Aurelien Jarno @ 2009-04-07 21:47 UTC (permalink / raw)
  To: Tristan Gingold; +Cc: qemu-devel

On Mon, Mar 30, 2009 at 04:36:18PM +0200, Tristan Gingold wrote:
> (As defined by the alpha arch ref).
> 
> Signed-off-by: Tristan Gingold <gingold@adacore.com>

Thanks, applied.

> ---
>  target-alpha/cpu.h |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
> index a9f1c0f..582827e 100644
> --- a/target-alpha/cpu.h
> +++ b/target-alpha/cpu.h
> @@ -40,7 +40,7 @@
>  #define ICACHE_LINE_SIZE 32
>  #define DCACHE_LINE_SIZE 32
>  
> -#define TARGET_PAGE_BITS 12
> +#define TARGET_PAGE_BITS 13
>  
>  #define VA_BITS 43
>  
> -- 
> 1.6.2
> 
> 
> 
> 

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 04/19] Allow 5 mmu indexes.
  2009-03-30 14:36       ` [Qemu-devel] [PATCH 04/19] Allow 5 mmu indexes Tristan Gingold
  2009-03-30 14:36         ` [Qemu-devel] [PATCH 05/19] Split cpu_mmu_index into cpu_mmu_index_data and cpu_mmu_index_code Tristan Gingold
@ 2009-04-07 21:48         ` Aurelien Jarno
  1 sibling, 0 replies; 36+ messages in thread
From: Aurelien Jarno @ 2009-04-07 21:48 UTC (permalink / raw)
  To: Tristan Gingold; +Cc: qemu-devel

On Mon, Mar 30, 2009 at 04:36:19PM +0200, Tristan Gingold wrote:
> This is necessary for alpha because it has 4 protection levels and pal mode.
> 
> Signed-off-by: Tristan Gingold <gingold@adacore.com>

Thanks, applied.

> ---
>  exec.c         |   30 +++++++++++++++++++++++++-----
>  softmmu_exec.h |   29 ++++++++++++++++++++++++-----
>  2 files changed, 49 insertions(+), 10 deletions(-)
> 
> diff --git a/exec.c b/exec.c
> index 5dc6bc7..7c2def0 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -1736,12 +1736,18 @@ void tlb_flush(CPUState *env, int flush_global)
>          env->tlb_table[2][i].addr_read = -1;
>          env->tlb_table[2][i].addr_write = -1;
>          env->tlb_table[2][i].addr_code = -1;
> -#if (NB_MMU_MODES == 4)
> +#endif
> +#if (NB_MMU_MODES >= 4)
>          env->tlb_table[3][i].addr_read = -1;
>          env->tlb_table[3][i].addr_write = -1;
>          env->tlb_table[3][i].addr_code = -1;
>  #endif
> +#if (NB_MMU_MODES >= 5)
> +        env->tlb_table[4][i].addr_read = -1;
> +        env->tlb_table[4][i].addr_write = -1;
> +        env->tlb_table[4][i].addr_code = -1;
>  #endif
> +
>      }
>  
>      memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
> @@ -1785,9 +1791,12 @@ void tlb_flush_page(CPUState *env, target_ulong addr)
>      tlb_flush_entry(&env->tlb_table[1][i], addr);
>  #if (NB_MMU_MODES >= 3)
>      tlb_flush_entry(&env->tlb_table[2][i], addr);
> -#if (NB_MMU_MODES == 4)
> +#endif
> +#if (NB_MMU_MODES >= 4)
>      tlb_flush_entry(&env->tlb_table[3][i], addr);
>  #endif
> +#if (NB_MMU_MODES >= 5)
> +    tlb_flush_entry(&env->tlb_table[4][i], addr);
>  #endif
>  
>      tlb_flush_jmp_cache(env, addr);
> @@ -1871,10 +1880,14 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
>  #if (NB_MMU_MODES >= 3)
>          for(i = 0; i < CPU_TLB_SIZE; i++)
>              tlb_reset_dirty_range(&env->tlb_table[2][i], start1, length);
> -#if (NB_MMU_MODES == 4)
> +#endif
> +#if (NB_MMU_MODES >= 4)
>          for(i = 0; i < CPU_TLB_SIZE; i++)
>              tlb_reset_dirty_range(&env->tlb_table[3][i], start1, length);
>  #endif
> +#if (NB_MMU_MODES >= 5)
> +        for(i = 0; i < CPU_TLB_SIZE; i++)
> +            tlb_reset_dirty_range(&env->tlb_table[4][i], start1, length);
>  #endif
>      }
>  }
> @@ -1920,10 +1933,14 @@ void cpu_tlb_update_dirty(CPUState *env)
>  #if (NB_MMU_MODES >= 3)
>      for(i = 0; i < CPU_TLB_SIZE; i++)
>          tlb_update_dirty(&env->tlb_table[2][i]);
> -#if (NB_MMU_MODES == 4)
> +#endif
> +#if (NB_MMU_MODES >= 4)
>      for(i = 0; i < CPU_TLB_SIZE; i++)
>          tlb_update_dirty(&env->tlb_table[3][i]);
>  #endif
> +#if (NB_MMU_MODES >= 5)
> +    for(i = 0; i < CPU_TLB_SIZE; i++)
> +        tlb_update_dirty(&env->tlb_table[4][i]);
>  #endif
>  }
>  
> @@ -1945,9 +1962,12 @@ static inline void tlb_set_dirty(CPUState *env, target_ulong vaddr)
>      tlb_set_dirty1(&env->tlb_table[1][i], vaddr);
>  #if (NB_MMU_MODES >= 3)
>      tlb_set_dirty1(&env->tlb_table[2][i], vaddr);
> -#if (NB_MMU_MODES == 4)
> +#endif
> +#if (NB_MMU_MODES >= 4)
>      tlb_set_dirty1(&env->tlb_table[3][i], vaddr);
>  #endif
> +#if (NB_MMU_MODES >= 5)
> +    tlb_set_dirty1(&env->tlb_table[4][i], vaddr);
>  #endif
>  }
>  
> diff --git a/softmmu_exec.h b/softmmu_exec.h
> index 9cc4535..a43e621 100644
> --- a/softmmu_exec.h
> +++ b/softmmu_exec.h
> @@ -60,6 +60,7 @@
>  #include "softmmu_header.h"
>  #undef ACCESS_TYPE
>  #undef MEMSUFFIX
> +#endif /* (NB_MMU_MODES >= 3) */
>  
>  #if (NB_MMU_MODES >= 4)
>  
> @@ -78,12 +79,30 @@
>  #include "softmmu_header.h"
>  #undef ACCESS_TYPE
>  #undef MEMSUFFIX
> +#endif /* (NB_MMU_MODES >= 4) */
>  
> -#if (NB_MMU_MODES > 4)
> -#error "NB_MMU_MODES > 4 is not supported for now"
> -#endif /* (NB_MMU_MODES > 4) */
> -#endif /* (NB_MMU_MODES == 4) */
> -#endif /* (NB_MMU_MODES >= 3) */
> +#if (NB_MMU_MODES >= 5)
> +
> +#define ACCESS_TYPE 4
> +#define MEMSUFFIX MMU_MODE4_SUFFIX
> +#define DATA_SIZE 1
> +#include "softmmu_header.h"
> +
> +#define DATA_SIZE 2
> +#include "softmmu_header.h"
> +
> +#define DATA_SIZE 4
> +#include "softmmu_header.h"
> +
> +#define DATA_SIZE 8
> +#include "softmmu_header.h"
> +#undef ACCESS_TYPE
> +#undef MEMSUFFIX
> +#endif /* (NB_MMU_MODES >= 5) */
> +
> +#if (NB_MMU_MODES > 5)
> +#error "NB_MMU_MODES > 5 is not supported for now"
> +#endif /* (NB_MMU_MODES > 5) */
>  
>  /* these access are slower, they must be as rare as possible */
>  #define ACCESS_TYPE (NB_MMU_MODES)
> -- 
> 1.6.2
> 
> 
> 
> 

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 18/19] Correctly decode hw_ld/hw_st opcodes for all alpha implementations.
  2009-03-30 14:36                                   ` [Qemu-devel] [PATCH 18/19] Correctly decode hw_ld/hw_st opcodes for all alpha implementations Tristan Gingold
  2009-03-30 14:36                                     ` [Qemu-devel] [PATCH 19/19] Add full emulation for 21264 Tristan Gingold
@ 2009-04-07 21:52                                     ` Aurelien Jarno
  2009-04-08 12:26                                       ` Tristan Gingold
  1 sibling, 1 reply; 36+ messages in thread
From: Aurelien Jarno @ 2009-04-07 21:52 UTC (permalink / raw)
  To: qemu-devel

On Mon, Mar 30, 2009 at 04:36:33PM +0200, Tristan Gingold wrote:
> Allow privilegied pal_code only in kernel mode.
> 
> Signed-off-by: Tristan Gingold <gingold@adacore.com>
> ---
>  target-alpha/translate.c |   30 +++++++++++++++++++++++-------
>  1 files changed, 23 insertions(+), 7 deletions(-)
> 
> diff --git a/target-alpha/translate.c b/target-alpha/translate.c
> index 061cf5f..6938b5d 100644
> --- a/target-alpha/translate.c
> +++ b/target-alpha/translate.c
> @@ -52,6 +52,7 @@ struct DisasContext {
>      int pal_mode;
>  #endif
>      uint32_t amask;
> +    uint32_t implver;
>  };
>  
>  /* global register indexes */
> @@ -103,6 +104,20 @@ static void alpha_translate_init(void)
>      done_init = 1;
>  }
>  
> +static inline int get_mxcr_iprn(DisasContext *ctx, uint32_t insn)
> +{
> +    switch (ctx->implver) {
> +    case IMPLVER_2106x:
> +        return insn & 0xff;
> +    case IMPLVER_21164:
> +        return insn & 0xffff;
> +    case IMPLVER_21264:
> +        return (insn >> 8) & 0xff;
> +    default:
> +        abort();
> +    }
> +}
> +
>  static always_inline void gen_excp (DisasContext *ctx,
>                                      int exception, int error_code)
>  {
> @@ -689,7 +704,7 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
>  #if !defined (CONFIG_USER_ONLY)
>          } else if (palcode < 0x40) {
>              /* Privileged PAL code */
> -            if (ctx->mem_idx & 1)
> +            if (ctx->mem_idx != MMU_KERNEL_IDX)
>                  goto invalid_opc;
>              else
>                  gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x3F) << 6), 0);
> @@ -1748,7 +1763,7 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
>          if (!ctx->pal_mode)
>              goto invalid_opc;
>          if (ra != 31) {
> -            TCGv tmp = tcg_const_i32(insn & 0xFF);
> +            TCGv tmp = tcg_const_i32(get_mxcr_iprn(ctx, insn));
>              gen_helper_mfpr(cpu_ir[ra], tmp, cpu_ir[ra]);
>              tcg_temp_free(tmp);
>          }
> @@ -2063,9 +2078,9 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
>          if (!ctx->pal_mode)
>              goto invalid_opc;
>          else {
> -            TCGv tmp1 = tcg_const_i32(insn & 0xFF);
> -            if (ra != 31)
> -                gen_helper_mtpr(tmp1, cpu_ir[ra]);
> +            TCGv tmp1 = tcg_const_i32(get_mxcr_iprn(ctx, insn));
> +            if (rb != 31)
> +                gen_helper_mtpr(tmp1, cpu_ir[rb]);
>              else {
>                  TCGv tmp2 = tcg_const_i64(0);
>                  gen_helper_mtpr(tmp1, tmp2);
> @@ -2089,7 +2104,7 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
>          } else {
>              TCGv tmp;
>  
> -            if (ra != 31) {
> +            if (rb != 31) {
>                  tmp = tcg_temp_new();
>                  tcg_gen_addi_i64(tmp, cpu_ir[rb], (((int64_t)insn << 51) >> 51));
>              } else
> @@ -2097,7 +2112,7 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
>              gen_helper_hw_ret(tmp);
>              tcg_temp_free(tmp);
>          }
> -        ret = 2;
> +        ret = 3;
>          break;
>  #endif
>      case 0x1F:
> @@ -2352,6 +2367,7 @@ static always_inline void gen_intermediate_code_internal (CPUState *env,
>      gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
>      ctx.pc = pc_start;
>      ctx.amask = env->amask;
> +    ctx.implver = env->implver;
>  #if defined (CONFIG_USER_ONLY)
>      ctx.mem_idx = 0;
>  #else

implver is defined once at init time, and I don't expect it to change
once qemu has been started. Therefore I think there is no need to copy
env->implver into ctx.implver, env->implver can be accessed directly,
even from translate.c

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 09/19] Add square wave output support.
  2009-03-30 14:36                 ` [Qemu-devel] [PATCH 09/19] Add square wave output support Tristan Gingold
  2009-03-30 14:36                   ` [Qemu-devel] [PATCH 10/19] Add ali1543 super IO pci device Tristan Gingold
@ 2009-04-07 22:29                   ` Aurelien Jarno
  1 sibling, 0 replies; 36+ messages in thread
From: Aurelien Jarno @ 2009-04-07 22:29 UTC (permalink / raw)
  To: Tristan Gingold; +Cc: qemu-devel

On Mon, Mar 30, 2009 at 04:36:24PM +0200, Tristan Gingold wrote:
> This is necessary for es40 as the sqw output is directly connected to the
> core chipset.
> 
> Signed-off-by: Tristan Gingold <gingold@adacore.com>

Thanks, applied.

> ---
>  hw/mc146818rtc.c |   39 +++++++++++++++++++++++++++++----------
>  hw/pc.h          |    1 +
>  2 files changed, 30 insertions(+), 10 deletions(-)
> 
> diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
> index 5b08d72..f6bb21d 100644
> --- a/hw/mc146818rtc.c
> +++ b/hw/mc146818rtc.c
> @@ -50,11 +50,12 @@
>  
>  #define REG_A_UIP 0x80
>  
> -#define REG_B_SET 0x80
> -#define REG_B_PIE 0x40
> -#define REG_B_AIE 0x20
> -#define REG_B_UIE 0x10
> -#define REG_B_DM  0x04
> +#define REG_B_SET  0x80
> +#define REG_B_PIE  0x40
> +#define REG_B_AIE  0x20
> +#define REG_B_UIE  0x10
> +#define REG_B_SQWE 0x08
> +#define REG_B_DM   0x04
>  
>  struct RTCState {
>      uint8_t cmos_data[128];
> @@ -62,6 +63,7 @@ struct RTCState {
>      struct tm current_tm;
>      int base_year;
>      qemu_irq irq;
> +    qemu_irq sqw_irq;
>      int it_shift;
>      /* periodic timer */
>      QEMUTimer *periodic_timer;
> @@ -95,16 +97,20 @@ static void rtc_timer_update(RTCState *s, int64_t current_time)
>  {
>      int period_code, period;
>      int64_t cur_clock, next_irq_clock;
> +    int enable_pie;
>  
>      period_code = s->cmos_data[RTC_REG_A] & 0x0f;
>  #if defined TARGET_I386 || defined TARGET_X86_64
>      /* disable periodic timer if hpet is in legacy mode, since interrupts are
>       * disabled anyway.
>       */
> -    if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE) && !hpet_in_legacy_mode()) {
> +    enable_pie = hpet_in_legacy_mode();
>  #else
> -    if (period_code != 0 && (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
> +    enable_pie = 1;
>  #endif
> +    if (period_code != 0
> +        && (((s->cmos_data[RTC_REG_B] & REG_B_PIE) && enable_pie)
> +            || ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) {
>          if (period_code <= 2)
>              period_code += 7;
>          /* period in 32 Khz cycles */
> @@ -138,8 +144,15 @@ static void rtc_periodic_timer(void *opaque)
>          return;
>      }
>  #endif
> -    s->cmos_data[RTC_REG_C] |= 0xc0;
> -    rtc_irq_raise(s->irq);
> +    if (s->cmos_data[RTC_REG_B] & REG_B_PIE) {
> +        s->cmos_data[RTC_REG_C] |= 0xc0;
> +        rtc_irq_raise(s->irq);
> +    }
> +    if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) {
> +        /* Not square wave at all but we don't want 2048Hz interrupts!
> +           Must be seen as a pulse.  */
> +        qemu_irq_raise(s->sqw_irq);
> +    }
>  }
>  
>  static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
> @@ -527,13 +540,14 @@ static int rtc_load_td(QEMUFile *f, void *opaque, int version_id)
>  }
>  #endif
>  
> -RTCState *rtc_init(int base, qemu_irq irq, int base_year)
> +RTCState *rtc_init_sqw(int base, qemu_irq irq, qemu_irq sqw_irq, int base_year)
>  {
>      RTCState *s;
>  
>      s = qemu_mallocz(sizeof(RTCState));
>  
>      s->irq = irq;
> +    s->sqw_irq = sqw_irq;
>      s->cmos_data[RTC_REG_A] = 0x26;
>      s->cmos_data[RTC_REG_B] = 0x02;
>      s->cmos_data[RTC_REG_C] = 0x00;
> @@ -563,6 +577,11 @@ RTCState *rtc_init(int base, qemu_irq irq, int base_year)
>      return s;
>  }
>  
> +RTCState *rtc_init(int base, qemu_irq irq, int base_year)
> +{
> +    return rtc_init_sqw(base, irq, NULL, base_year);
> +}
> +
>  /* Memory mapped interface */
>  static uint32_t cmos_mm_readb (void *opaque, target_phys_addr_t addr)
>  {
> diff --git a/hw/pc.h b/hw/pc.h
> index 5b378d4..7345f04 100644
> --- a/hw/pc.h
> +++ b/hw/pc.h
> @@ -90,6 +90,7 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
>  typedef struct RTCState RTCState;
>  
>  RTCState *rtc_init(int base, qemu_irq irq, int base_year);
> +RTCState *rtc_init_sqw(int base, qemu_irq irq, qemu_irq sqw_irq, int base_year);
>  RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq,
>                        int base_year);
>  void rtc_set_memory(RTCState *s, int addr, int val);
> -- 
> 1.6.2
> 
> 
> 
> 

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 07/19] Alpha bug: fix palcode mask for user pal calls
  2009-03-30 14:36             ` [Qemu-devel] [PATCH 07/19] Alpha bug: fix palcode mask for user pal calls Tristan Gingold
  2009-03-30 14:36               ` [Qemu-devel] [PATCH 08/19] Alpha: document more registers used by 21264 Tristan Gingold
@ 2009-04-07 22:31               ` Aurelien Jarno
  1 sibling, 0 replies; 36+ messages in thread
From: Aurelien Jarno @ 2009-04-07 22:31 UTC (permalink / raw)
  To: Tristan Gingold; +Cc: qemu-devel

On Mon, Mar 30, 2009 at 04:36:22PM +0200, Tristan Gingold wrote:
> (Also 6 bits for unprivileged calls)
> 
> Signed-off-by: Tristan Gingold <gingold@adacore.com>

Thanks, applied.

> ---
>  target-alpha/translate.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/target-alpha/translate.c b/target-alpha/translate.c
> index dad1686..821f0d4 100644
> --- a/target-alpha/translate.c
> +++ b/target-alpha/translate.c
> @@ -685,7 +685,7 @@ static always_inline int translate_one (DisasContext *ctx, uint32_t insn)
>          /* CALL_PAL */
>          if (palcode >= 0x80 && palcode < 0xC0) {
>              /* Unprivileged PAL call */
> -            gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x1F) << 6), 0);
> +            gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x3F) << 6), 0);
>  #if !defined (CONFIG_USER_ONLY)
>          } else if (palcode < 0x40) {
>              /* Privileged PAL code */
> -- 
> 1.6.2
> 
> 
> 
> 

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 08/19] Alpha: document more registers used by 21264
  2009-03-30 14:36               ` [Qemu-devel] [PATCH 08/19] Alpha: document more registers used by 21264 Tristan Gingold
  2009-03-30 14:36                 ` [Qemu-devel] [PATCH 09/19] Add square wave output support Tristan Gingold
@ 2009-04-07 22:32                 ` Aurelien Jarno
  1 sibling, 0 replies; 36+ messages in thread
From: Aurelien Jarno @ 2009-04-07 22:32 UTC (permalink / raw)
  To: Tristan Gingold; +Cc: qemu-devel

On Mon, Mar 30, 2009 at 04:36:23PM +0200, Tristan Gingold wrote:
> Signed-off-by: Tristan Gingold <gingold@adacore.com>
> ---
>  target-alpha/cpu.h |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)

Thanks, applied.

> diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
> index 3798157..db53650 100644
> --- a/target-alpha/cpu.h
> +++ b/target-alpha/cpu.h
> @@ -158,7 +158,7 @@ enum {
>      IPR_ITB_PTE      = 0x01,            /* 21264 */
>      IPR_ITB_IAP      = 0x02,
>      IPR_ITB_IA       = 0x03,            /* 21264 */
> -    IPR_ITB_IS       = 0x04,
> +    IPR_ITB_IS       = 0x04,            /* 21264 */
>      IPR_PMPC         = 0x05,
>      IPR_EXC_ADDR     = 0x06,            /* 21264 */
>      IPR_IVA_FORM     = 0x07,            /* 21264 */
> @@ -221,7 +221,7 @@ enum {
>      IPR_M_CTL        = 0x28,            /* 21264 */
>  #define IPR_M_CTL_SPE_SHIFT 1
>  #define IPR_M_CTL_SPE_MASK 7
> -    IPR_DC_CTL       = 0x29,
> +    IPR_DC_CTL       = 0x29,            /* 21264 */
>      IPR_DC_STAT      = 0x2A,            /* 21264 */
>      /* Cbox IPRs */
>      IPR_C_DATA       = 0x2B,
> -- 
> 1.6.2
> 
> 
> 
> 

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 18/19] Correctly decode hw_ld/hw_st opcodes for all alpha implementations.
  2009-04-07 21:52                                     ` [Qemu-devel] [PATCH 18/19] Correctly decode hw_ld/hw_st opcodes for all alpha implementations Aurelien Jarno
@ 2009-04-08 12:26                                       ` Tristan Gingold
  0 siblings, 0 replies; 36+ messages in thread
From: Tristan Gingold @ 2009-04-08 12:26 UTC (permalink / raw)
  To: Aurelien Jarno; +Cc: qemu-devel


On Apr 7, 2009, at 11:52 PM, Aurelien Jarno wrote:

> implver is defined once at init time, and I don't expect it to change
> once qemu has been started. Therefore I think there is no need to copy
> env->implver into ctx.implver, env->implver can be accessed directly,
> even from translate.c

Yes, I definitely agree with you.  I have already slightly changes  
this patch also to avoid to use
an helper for implver instruction.

To be submitted very soon.

Thank you,
Tristan.

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

* Re: [Qemu-devel] [PATCH 05/19] Split cpu_mmu_index into cpu_mmu_index_data and cpu_mmu_index_code.
  2009-03-30 14:36         ` [Qemu-devel] [PATCH 05/19] Split cpu_mmu_index into cpu_mmu_index_data and cpu_mmu_index_code Tristan Gingold
  2009-03-30 14:36           ` [Qemu-devel] [PATCH 06/19] Bug fix alpha: stop translation if too long Tristan Gingold
@ 2009-04-15 14:30           ` Aurelien Jarno
  2009-04-21 12:10             ` Tristan Gingold
  1 sibling, 1 reply; 36+ messages in thread
From: Aurelien Jarno @ 2009-04-15 14:30 UTC (permalink / raw)
  To: Tristan Gingold; +Cc: qemu-devel

On Mon, Mar 30, 2009 at 04:36:20PM +0200, Tristan Gingold wrote:
> This is required by alpha system emulation as PAL mode disable instruction
> mmu but not data mmu.
> This might also be required for other cpus that have a split I/D mmu enable.
> 
> Signed-off-by: Tristan Gingold <gingold@adacore.com>
> ---
>  exec-all.h               |    2 +-
>  softmmu_header.h         |    4 ++--
>  target-alpha/cpu.h       |   13 +++++++++++--
>  target-alpha/op_helper.c |    4 ++--
>  target-arm/cpu.h         |    3 ++-
>  target-cris/cpu.h        |    3 ++-
>  target-cris/translate.c  |    6 +++---
>  target-i386/cpu.h        |    3 ++-
>  target-m68k/cpu.h        |    3 ++-
>  target-mips/cpu.h        |    3 ++-
>  target-ppc/cpu.h         |    3 ++-
>  target-sh4/cpu.h         |    3 ++-
>  target-sparc/cpu.h       |    3 ++-
>  target-sparc/translate.c |    2 +-
>  14 files changed, 36 insertions(+), 19 deletions(-)
> 
> diff --git a/exec-all.h b/exec-all.h
> index 143aca1..a661cb1 100644
> --- a/exec-all.h
> +++ b/exec-all.h
> @@ -318,7 +318,7 @@ static inline target_ulong get_phys_addr_code(CPUState *env1, target_ulong addr)
>      int mmu_idx, page_index, pd;
>  
>      page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
> -    mmu_idx = cpu_mmu_index(env1);
> +    mmu_idx = cpu_mmu_index_code(env1);
>      if (unlikely(env1->tlb_table[mmu_idx][page_index].addr_code !=
>                   (addr & TARGET_PAGE_MASK))) {
>          ldub_code(addr);
> diff --git a/softmmu_header.h b/softmmu_header.h
> index a1b3808..f6f83da 100644
> --- a/softmmu_header.h
> +++ b/softmmu_header.h
> @@ -46,12 +46,12 @@
>  
>  #elif ACCESS_TYPE == (NB_MMU_MODES)
>  
> -#define CPU_MMU_INDEX (cpu_mmu_index(env))
> +#define CPU_MMU_INDEX (cpu_mmu_index_data(env))
>  #define MMUSUFFIX _mmu
>  
>  #elif ACCESS_TYPE == (NB_MMU_MODES + 1)
>  
> -#define CPU_MMU_INDEX (cpu_mmu_index(env))
> +#define CPU_MMU_INDEX (cpu_mmu_index_code(env))
>  #define MMUSUFFIX _cmmu
>  
>  #else
> diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
> index 582827e..3798157 100644
> --- a/target-alpha/cpu.h
> +++ b/target-alpha/cpu.h
> @@ -331,16 +331,25 @@ struct CPUAlphaState {
>  #define cpu_exec cpu_alpha_exec
>  #define cpu_gen_code cpu_alpha_gen_code
>  #define cpu_signal_handler cpu_alpha_signal_handler
> +#define cpu_list alpha_cpu_list
>  
>  /* MMU modes definitions */
>  #define MMU_MODE0_SUFFIX _kernel
>  #define MMU_MODE1_SUFFIX _executive
>  #define MMU_MODE2_SUFFIX _supervisor
>  #define MMU_MODE3_SUFFIX _user
> +#define MMU_MODE4_SUFFIX _pal
> +#define MMU_KERNEL_IDX 0
>  #define MMU_USER_IDX 3
> -static inline int cpu_mmu_index (CPUState *env)
> +#define MMU_PAL_IDX 4
> +static inline int cpu_mmu_index_data (CPUState *env)
>  {
> -    return (env->ps >> 3) & 3;
> +    return env->mmu_data_index;
> +}
> +
> +static inline int cpu_mmu_index_code (CPUState *env)
> +{
> +    return env->mmu_code_index;
>  }

>From where env->mmu_data_index and env->mmu_code_index come from? After
applying this patch, I get:

  CC    main.o
In file included from /home/aurel32/git/qemu/linux-user/qemu.h:8,
                 from /home/aurel32/git/qemu/linux-user/main.c:30:
/home/aurel32/git/qemu/target-alpha/cpu.h: In function 'cpu_mmu_index_data':
/home/aurel32/git/qemu/target-alpha/cpu.h:347: error: 'struct CPUAlphaState' has no member named 'mmu_data_index'
/home/aurel32/git/qemu/target-alpha/cpu.h: In function 'cpu_mmu_index_code':
/home/aurel32/git/qemu/target-alpha/cpu.h:352: error: 'struct CPUAlphaState' has no member named 'mmu_code_index'
/home/aurel32/git/qemu/linux-user/main.c: In function 'main':
/home/aurel32/git/qemu/linux-user/main.c:2359: warning: implicit declaration of function 'alpha_cpu_list'
make: *** [main.o] Error 1

>  #if defined(CONFIG_USER_ONLY)
> diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
> index 7ad1b3d..433a0da 100644
> --- a/target-alpha/op_helper.c
> +++ b/target-alpha/op_helper.c
> @@ -1049,7 +1049,7 @@ uint64_t helper_ld_virt_to_phys (uint64_t virtaddr)
>      int index, mmu_idx;
>      void *retaddr;
>  
> -    mmu_idx = cpu_mmu_index(env);
> +    mmu_idx = cpu_mmu_index_data(env);
>      index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
>   redo:
>      tlb_addr = env->tlb_table[mmu_idx][index].addr_read;
> @@ -1071,7 +1071,7 @@ uint64_t helper_st_virt_to_phys (uint64_t virtaddr)
>      int index, mmu_idx;
>      void *retaddr;
>  
> -    mmu_idx = cpu_mmu_index(env);
> +    mmu_idx = cpu_mmu_index_data(env);
>      index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
>   redo:
>      tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
> diff --git a/target-arm/cpu.h b/target-arm/cpu.h
> index f98655f..c0cfb8d 100644
> --- a/target-arm/cpu.h
> +++ b/target-arm/cpu.h
> @@ -412,7 +412,8 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
>  #define MMU_MODE0_SUFFIX _kernel
>  #define MMU_MODE1_SUFFIX _user
>  #define MMU_USER_IDX 1
> -static inline int cpu_mmu_index (CPUState *env)
> +#define cpu_mmu_index_data cpu_mmu_index_code
> +static inline int cpu_mmu_index_code (CPUState *env)
>  {
>      return (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR ? 1 : 0;
>  }
> diff --git a/target-cris/cpu.h b/target-cris/cpu.h
> index e98a48d..807a55a 100644
> --- a/target-cris/cpu.h
> +++ b/target-cris/cpu.h
> @@ -212,7 +212,8 @@ enum {
>  #define MMU_MODE0_SUFFIX _kernel
>  #define MMU_MODE1_SUFFIX _user
>  #define MMU_USER_IDX 1
> -static inline int cpu_mmu_index (CPUState *env)
> +#define cpu_mmu_index_data cpu_mmu_index_code
> +static inline int cpu_mmu_index_code (CPUState *env)
>  {
>  	return !!(env->pregs[PR_CCS] & U_FLAG);
>  }
> diff --git a/target-cris/translate.c b/target-cris/translate.c
> index d5fcb9e..20699e9 100644
> --- a/target-cris/translate.c
> +++ b/target-cris/translate.c
> @@ -1104,7 +1104,7 @@ static inline void cris_prepare_jmp (DisasContext *dc, unsigned int type)
>  
>  static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr)
>  {
> -	int mem_index = cpu_mmu_index(dc->env);
> +	int mem_index = cpu_mmu_index_data(dc->env);
>  
>  	/* If we get a fault on a delayslot we must keep the jmp state in
>  	   the cpu-state to be able to re-execute the jmp.  */
> @@ -1117,7 +1117,7 @@ static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr)
>  static void gen_load(DisasContext *dc, TCGv dst, TCGv addr, 
>  		     unsigned int size, int sign)
>  {
> -	int mem_index = cpu_mmu_index(dc->env);
> +	int mem_index = cpu_mmu_index_data(dc->env);
>  
>  	/* If we get a fault on a delayslot we must keep the jmp state in
>  	   the cpu-state to be able to re-execute the jmp.  */
> @@ -1147,7 +1147,7 @@ static void gen_load(DisasContext *dc, TCGv dst, TCGv addr,
>  static void gen_store (DisasContext *dc, TCGv addr, TCGv val,
>  		       unsigned int size)
>  {
> -	int mem_index = cpu_mmu_index(dc->env);
> +	int mem_index = cpu_mmu_index_data(dc->env);
>  
>  	/* If we get a fault on a delayslot we must keep the jmp state in
>  	   the cpu-state to be able to re-execute the jmp.  */
> diff --git a/target-i386/cpu.h b/target-i386/cpu.h
> index 90bceab..f3ccb53 100644
> --- a/target-i386/cpu.h
> +++ b/target-i386/cpu.h
> @@ -842,7 +842,8 @@ static inline int cpu_get_time_fast(void)
>  #define MMU_MODE0_SUFFIX _kernel
>  #define MMU_MODE1_SUFFIX _user
>  #define MMU_USER_IDX 1
> -static inline int cpu_mmu_index (CPUState *env)
> +#define cpu_mmu_index_data cpu_mmu_index_code
> +static inline int cpu_mmu_index_code (CPUState *env)
>  {
>      return (env->hflags & HF_CPL_MASK) == 3 ? 1 : 0;
>  }
> diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
> index e2529eb..94af716 100644
> --- a/target-m68k/cpu.h
> +++ b/target-m68k/cpu.h
> @@ -218,7 +218,8 @@ void register_m68k_insns (CPUM68KState *env);
>  #define MMU_MODE0_SUFFIX _kernel
>  #define MMU_MODE1_SUFFIX _user
>  #define MMU_USER_IDX 1
> -static inline int cpu_mmu_index (CPUState *env)
> +#define cpu_mmu_index_data cpu_mmu_index_code
> +static inline int cpu_mmu_index_code (CPUState *env)
>  {
>      return (env->sr & SR_S) == 0 ? 1 : 0;
>  }
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index b415dc4..a793166 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -489,7 +489,8 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
>  #define MMU_MODE1_SUFFIX _super
>  #define MMU_MODE2_SUFFIX _user
>  #define MMU_USER_IDX 2
> -static inline int cpu_mmu_index (CPUState *env)
> +#define cpu_mmu_index_data cpu_mmu_index_code
> +static inline int cpu_mmu_index_code (CPUState *env)
>  {
>      return env->hflags & MIPS_HFLAG_KSU;
>  }
> diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
> index 87b3460..4d75ced 100644
> --- a/target-ppc/cpu.h
> +++ b/target-ppc/cpu.h
> @@ -809,7 +809,8 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val);
>  #define MMU_MODE1_SUFFIX _kernel
>  #define MMU_MODE2_SUFFIX _hypv
>  #define MMU_USER_IDX 0
> -static inline int cpu_mmu_index (CPUState *env)
> +#define cpu_mmu_index_data cpu_mmu_index_code
> +static inline int cpu_mmu_index_code (CPUState *env)
>  {
>      return env->mmu_idx;
>  }
> diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
> index aea7108..eaae3cf 100644
> --- a/target-sh4/cpu.h
> +++ b/target-sh4/cpu.h
> @@ -181,7 +181,8 @@ void cpu_load_tlb(CPUSH4State * env);
>  #define MMU_MODE0_SUFFIX _kernel
>  #define MMU_MODE1_SUFFIX _user
>  #define MMU_USER_IDX 1
> -static inline int cpu_mmu_index (CPUState *env)
> +#define cpu_mmu_index_data cpu_mmu_index_code
> +static inline int cpu_mmu_index_code (CPUState *env)
>  {
>      return (env->sr & SR_MD) == 0 ? 1 : 0;
>  }
> diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
> index 8b84789..33cf4c3 100644
> --- a/target-sparc/cpu.h
> +++ b/target-sparc/cpu.h
> @@ -456,7 +456,8 @@ int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
>  #define MMU_KERNEL_IDX 1
>  #define MMU_HYPV_IDX   2
>  
> -static inline int cpu_mmu_index(CPUState *env1)
> +#define cpu_mmu_index_data cpu_mmu_index_code
> +static inline int cpu_mmu_index_code(CPUState *env1)
>  {
>  #if defined(CONFIG_USER_ONLY)
>      return MMU_USER_IDX;
> diff --git a/target-sparc/translate.c b/target-sparc/translate.c
> index d059408..017c375 100644
> --- a/target-sparc/translate.c
> +++ b/target-sparc/translate.c
> @@ -4769,7 +4769,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
>      dc->pc = pc_start;
>      last_pc = dc->pc;
>      dc->npc = (target_ulong) tb->cs_base;
> -    dc->mem_idx = cpu_mmu_index(env);
> +    dc->mem_idx = cpu_mmu_index_code(env);
>      dc->def = env->def;
>      if ((dc->def->features & CPU_FEATURE_FLOAT))
>          dc->fpu_enabled = cpu_fpu_enabled(env);
> -- 
> 1.6.2
> 
> 
> 
> 

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 16/19] Alpha: lower parent irq when irq is lowered.
  2009-03-30 14:36                               ` [Qemu-devel] [PATCH 16/19] Alpha: lower parent irq when irq is lowered Tristan Gingold
  2009-03-30 14:36                                 ` [Qemu-devel] [PATCH 17/19] Move linux-user pal emulation to linux-user/ Tristan Gingold
@ 2009-04-15 14:42                                 ` Aurelien Jarno
  1 sibling, 0 replies; 36+ messages in thread
From: Aurelien Jarno @ 2009-04-15 14:42 UTC (permalink / raw)
  To: Tristan Gingold; +Cc: qemu-devel

On Mon, Mar 30, 2009 at 04:36:31PM +0200, Tristan Gingold wrote:
> Signed-off-by: Tristan Gingold <gingold@adacore.com>
> ---
>  hw/i8259.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)

Thanks, applied.

> diff --git a/hw/i8259.c b/hw/i8259.c
> index f813525..adabd2b 100644
> --- a/hw/i8259.c
> +++ b/hw/i8259.c
> @@ -169,7 +169,7 @@ void pic_update_irq(PicState2 *s)
>      }
>  
>  /* all targets should do this rather than acking the IRQ in the cpu */
> -#if defined(TARGET_MIPS) || defined(TARGET_PPC)
> +#if defined(TARGET_MIPS) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
>      else {
>          qemu_irq_lower(s->parent_irq);
>      }
> -- 
> 1.6.2
> 
> 
> 
> 

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 01/19] Add support for multi-level phys map.
  2009-03-30 14:36 ` [Qemu-devel] [PATCH 01/19] Add support for multi-level phys map Tristan Gingold
  2009-03-30 14:36   ` [Qemu-devel] [PATCH 02/19] Increase Alpha physical address size to 44 bits Tristan Gingold
@ 2009-04-15 16:23   ` Aurelien Jarno
  2009-04-21 12:11     ` Tristan Gingold
  1 sibling, 1 reply; 36+ messages in thread
From: Aurelien Jarno @ 2009-04-15 16:23 UTC (permalink / raw)
  To: qemu-devel

On Mon, Mar 30, 2009 at 04:36:16PM +0200, Tristan Gingold wrote:
> As Alpha physical addresses are 44 bits, l1_phys_map can't be anymore 2 levels.
> Use a more generic multi-level approach and explain why we don't need to
> extend l1_map.
> 
> Signed-off-by: Tristan Gingold <gingold@adacore.com>
> ---
>  exec.c |   50 ++++++++++++++++++++++++++------------------------
>  1 files changed, 26 insertions(+), 24 deletions(-)
> 
> diff --git a/exec.c b/exec.c
> index df22c79..4b2ebc2 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -147,15 +147,14 @@ typedef struct PhysPageDesc {
>  } PhysPageDesc;
>  
>  #define L2_BITS 10
> -#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
> -/* XXX: this is a temporary hack for alpha target.
> - *      In the future, this is to be replaced by a multi-level table
> - *      to actually be able to handle the complete 64 bits address space.
> - */
> -#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
> +
> +#define L1_BITS_ ((TARGET_PHYS_ADDR_SPACE_BITS - TARGET_PAGE_BITS) % L2_BITS)
> +#if L1_BITS_ < 4 /* avoid ridiculous small l1 */
> +#define L1_BITS (L1_BITS_ + L2_BITS)
>  #else
> -#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
> +#define L1_BITS L1_BITS_
>  #endif
> +#define L1_SHIFT (TARGET_PHYS_ADDR_SPACE_BITS - TARGET_PAGE_BITS - L1_BITS)
>  
>  #define L1_SIZE (1 << L1_BITS)
>  #define L2_SIZE (1 << L2_BITS)
> @@ -165,7 +164,9 @@ unsigned long qemu_host_page_bits;
>  unsigned long qemu_host_page_size;
>  unsigned long qemu_host_page_mask;
>  
> -/* XXX: for system emulation, it could just be an array */
> +/* XXX: for system emulation, it could just be an array.  As this is currently
> +   a two level map this limits the size of RAM memory that can contains
> +   target code.  In practice this is large enough (>= 4GB) */
>  static PageDesc *l1_map[L1_SIZE];
>  static PhysPageDesc **l1_phys_map;
>  
> @@ -338,25 +339,26 @@ static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc)
>  {
>      void **lp, **p;
>      PhysPageDesc *pd;
> +    int i;
>  
> +    /* Level 1.  */
>      p = (void **)l1_phys_map;
> -#if TARGET_PHYS_ADDR_SPACE_BITS > 32
> +    lp = p + ((index >> L1_SHIFT) & (L1_SIZE - 1));
>  
> -#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS)
> -#error unsupported TARGET_PHYS_ADDR_SPACE_BITS
> -#endif
> -    lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1));
> -    p = *lp;
> -    if (!p) {
> -        /* allocate if not found */
> -        if (!alloc)
> -            return NULL;
> -        p = qemu_vmalloc(sizeof(void *) * L1_SIZE);
> -        memset(p, 0, sizeof(void *) * L1_SIZE);
> -        *lp = p;
> +    /* Level 2..n-1 */
> +    for (i = (L1_SHIFT / L2_BITS) - 1; i > 0; i--) {
> +        p = *lp;
> +        if (!p) {
> +            /* allocate if not found */
> +            if (!alloc)
> +                return NULL;
> +            p = qemu_vmalloc(sizeof(void *) * L2_SIZE);
> +            memset(p, 0, sizeof(void *) * L2_SIZE);
> +            *lp = p;
> +        }
> +        lp = p + ((index >> (i * L2_BITS)) & (L2_SIZE - 1));
>      }
> -#endif
> -    lp = p + ((index >> L2_BITS) & (L1_SIZE - 1));
> +
>      pd = *lp;
>      if (!pd) {
>          int i;

While this part of the patch looks ok, it seems that some other parts of
exec.c needs to be modified to accommodate the new multi-level map. Is
some parts of the patch missing?

Also I think that we should remove L2_* into LN_* to show it is actually
a multilevel map.

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PATCH 05/19] Split cpu_mmu_index into cpu_mmu_index_data and cpu_mmu_index_code.
  2009-04-15 14:30           ` [Qemu-devel] [PATCH 05/19] Split cpu_mmu_index into cpu_mmu_index_data and cpu_mmu_index_code Aurelien Jarno
@ 2009-04-21 12:10             ` Tristan Gingold
  0 siblings, 0 replies; 36+ messages in thread
From: Tristan Gingold @ 2009-04-21 12:10 UTC (permalink / raw)
  To: Aurelien Jarno; +Cc: qemu-devel


On Apr 15, 2009, at 4:30 PM, Aurelien Jarno wrote:

> On Mon, Mar 30, 2009 at 04:36:20PM +0200, Tristan Gingold wrote:
>> This is required by alpha system emulation as PAL mode disable  
>> instruction
>> mmu but not data mmu.
>> This might also be required for other cpus that have a split I/D  
>> mmu enable.

[...]

>> +#define MMU_PAL_IDX 4
>> +static inline int cpu_mmu_index_data (CPUState *env)
>> {
>> -    return (env->ps >> 3) & 3;
>> +    return env->mmu_data_index;
>> +}
>> +
>> +static inline int cpu_mmu_index_code (CPUState *env)
>> +{
>> +    return env->mmu_code_index;
>> }
>
> From where env->mmu_data_index and env->mmu_code_index come from?  
> After
> applying this patch, I get:

Yes, the dependancy is wrong.  I will fix it.

Tristan.

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

* Re: [Qemu-devel] [PATCH 01/19] Add support for multi-level phys map.
  2009-04-15 16:23   ` [Qemu-devel] [PATCH 01/19] Add support for multi-level phys map Aurelien Jarno
@ 2009-04-21 12:11     ` Tristan Gingold
  0 siblings, 0 replies; 36+ messages in thread
From: Tristan Gingold @ 2009-04-21 12:11 UTC (permalink / raw)
  To: qemu-devel


On Apr 15, 2009, at 6:23 PM, Aurelien Jarno wrote:

> On Mon, Mar 30, 2009 at 04:36:16PM +0200, Tristan Gingold wrote:
>> As Alpha physical addresses are 44 bits, l1_phys_map can't be  
>> anymore 2 levels.
>> Use a more generic multi-level approach and explain why we don't  
>> need to
>> extend l1_map.

[...]

> While this part of the patch looks ok, it seems that some other  
> parts of
> exec.c needs to be modified to accommodate the new multi-level map. Is
> some parts of the patch missing?

No, I think it is complete.  Can you point out which part seems to be  
modified ?

> Also I think that we should remove L2_* into LN_* to show it is  
> actually
> a multilevel map.

Yes, good idea.

Tristan.

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

end of thread, other threads:[~2009-04-21 12:11 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-03-30 14:36 [Qemu-devel] [PATCH 0/20]: add alpha es40 system emulation (v4) Tristan Gingold
2009-03-30 14:36 ` [Qemu-devel] [PATCH 01/19] Add support for multi-level phys map Tristan Gingold
2009-03-30 14:36   ` [Qemu-devel] [PATCH 02/19] Increase Alpha physical address size to 44 bits Tristan Gingold
2009-03-30 14:36     ` [Qemu-devel] [PATCH 03/19] Alpha: set target page size to 13 bits Tristan Gingold
2009-03-30 14:36       ` [Qemu-devel] [PATCH 04/19] Allow 5 mmu indexes Tristan Gingold
2009-03-30 14:36         ` [Qemu-devel] [PATCH 05/19] Split cpu_mmu_index into cpu_mmu_index_data and cpu_mmu_index_code Tristan Gingold
2009-03-30 14:36           ` [Qemu-devel] [PATCH 06/19] Bug fix alpha: stop translation if too long Tristan Gingold
2009-03-30 14:36             ` [Qemu-devel] [PATCH 07/19] Alpha bug: fix palcode mask for user pal calls Tristan Gingold
2009-03-30 14:36               ` [Qemu-devel] [PATCH 08/19] Alpha: document more registers used by 21264 Tristan Gingold
2009-03-30 14:36                 ` [Qemu-devel] [PATCH 09/19] Add square wave output support Tristan Gingold
2009-03-30 14:36                   ` [Qemu-devel] [PATCH 10/19] Add ali1543 super IO pci device Tristan Gingold
2009-03-30 14:36                     ` [Qemu-devel] [PATCH 11/19] Add 21272 chipset (memory and pci controller for alpha) Tristan Gingold
2009-03-30 14:36                       ` [Qemu-devel] [PATCH 12/19] Add target-alpha/machine.c and hw/es40.c for es40 machine emulation Tristan Gingold
2009-03-30 14:36                         ` [Qemu-devel] [PATCH 13/19] Move softmmu_helper.h from exec.h to op_helper.c on alpha Tristan Gingold
2009-03-30 14:36                           ` [Qemu-devel] [PATCH 14/19] alpha ld helpers now directly return the value Tristan Gingold
2009-03-30 14:36                             ` [Qemu-devel] [PATCH 15/19] Add alpha_cpu_list Tristan Gingold
2009-03-30 14:36                               ` [Qemu-devel] [PATCH 16/19] Alpha: lower parent irq when irq is lowered Tristan Gingold
2009-03-30 14:36                                 ` [Qemu-devel] [PATCH 17/19] Move linux-user pal emulation to linux-user/ Tristan Gingold
2009-03-30 14:36                                   ` [Qemu-devel] [PATCH 18/19] Correctly decode hw_ld/hw_st opcodes for all alpha implementations Tristan Gingold
2009-03-30 14:36                                     ` [Qemu-devel] [PATCH 19/19] Add full emulation for 21264 Tristan Gingold
2009-04-07 21:52                                     ` [Qemu-devel] [PATCH 18/19] Correctly decode hw_ld/hw_st opcodes for all alpha implementations Aurelien Jarno
2009-04-08 12:26                                       ` Tristan Gingold
2009-04-15 14:42                                 ` [Qemu-devel] [PATCH 16/19] Alpha: lower parent irq when irq is lowered Aurelien Jarno
2009-04-07 22:29                   ` [Qemu-devel] [PATCH 09/19] Add square wave output support Aurelien Jarno
2009-04-07 22:32                 ` [Qemu-devel] [PATCH 08/19] Alpha: document more registers used by 21264 Aurelien Jarno
2009-04-07 22:31               ` [Qemu-devel] [PATCH 07/19] Alpha bug: fix palcode mask for user pal calls Aurelien Jarno
2009-04-07 21:44             ` [Qemu-devel] [PATCH 06/19] Bug fix alpha: stop translation if too long Aurelien Jarno
2009-04-15 14:30           ` [Qemu-devel] [PATCH 05/19] Split cpu_mmu_index into cpu_mmu_index_data and cpu_mmu_index_code Aurelien Jarno
2009-04-21 12:10             ` Tristan Gingold
2009-04-07 21:48         ` [Qemu-devel] [PATCH 04/19] Allow 5 mmu indexes Aurelien Jarno
2009-04-07 21:47       ` [Qemu-devel] [PATCH 03/19] Alpha: set target page size to 13 bits Aurelien Jarno
2009-04-15 16:23   ` [Qemu-devel] [PATCH 01/19] Add support for multi-level phys map Aurelien Jarno
2009-04-21 12:11     ` Tristan Gingold
2009-03-30 15:46 ` [Qemu-devel] [PATCH 0/20]: add alpha es40 system emulation (v4) Brian Wheeler
2009-03-30 16:04   ` Tristan Gingold
2009-03-30 16:43     ` Brian Wheeler

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