* [Qemu-devel] [PATCH 01/24] Export the unassigned_mem read/write functions.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 02/24] target-alpha: Disassemble EV6 PALcode instructions Richard Henderson
` (23 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
cpu-common.h | 7 +++++++
exec.c | 12 ++++++------
2 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/cpu-common.h b/cpu-common.h
index 96c02ae..e17020b 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -45,6 +45,13 @@ static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
cpu_register_physical_memory_offset(start_addr, size, phys_offset, 0);
}
+extern CPUReadMemoryFunc unassigned_mem_readb;
+extern CPUReadMemoryFunc unassigned_mem_readw;
+extern CPUReadMemoryFunc unassigned_mem_readl;
+extern CPUWriteMemoryFunc unassigned_mem_writeb;
+extern CPUWriteMemoryFunc unassigned_mem_writew;
+extern CPUWriteMemoryFunc unassigned_mem_writel;
+
ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr);
ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
ram_addr_t size, void *host);
diff --git a/exec.c b/exec.c
index b1ee52a..994d51b 100644
--- a/exec.c
+++ b/exec.c
@@ -3090,7 +3090,7 @@ ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
return ram_addr;
}
-static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
+uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
{
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
@@ -3101,7 +3101,7 @@ static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
return 0;
}
-static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr)
+uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr)
{
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
@@ -3112,7 +3112,7 @@ static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr)
return 0;
}
-static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr)
+uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr)
{
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
@@ -3123,7 +3123,7 @@ static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr)
return 0;
}
-static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
@@ -3133,7 +3133,7 @@ static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_
#endif
}
-static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
{
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
@@ -3143,7 +3143,7 @@ static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_
#endif
}
-static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 02/24] target-alpha: Disassemble EV6 PALcode instructions.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 01/24] Export the unassigned_mem read/write functions Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 03/24] pci: Export pci_to_cpu_addr Richard Henderson
` (22 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
The QEMU emulation PALcode will use EV6 PALcode insns regardless
of the "real" cpu instruction set being emulated.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
alpha-dis.c | 4 ----
dis-asm.h | 3 +++
disas.c | 2 +-
3 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/alpha-dis.c b/alpha-dis.c
index 8a2411e..ae331b3 100644
--- a/alpha-dis.c
+++ b/alpha-dis.c
@@ -238,10 +238,6 @@ extern const unsigned alpha_num_operands;
#define AXP_REG_SP 30
#define AXP_REG_ZERO 31
-#define bfd_mach_alpha_ev4 0x10
-#define bfd_mach_alpha_ev5 0x20
-#define bfd_mach_alpha_ev6 0x30
-
enum bfd_reloc_code_real {
BFD_RELOC_23_PCREL_S2,
BFD_RELOC_ALPHA_HINT
diff --git a/dis-asm.h b/dis-asm.h
index 296537a..5b07d7f 100644
--- a/dis-asm.h
+++ b/dis-asm.h
@@ -184,6 +184,9 @@ enum bfd_architecture
#define bfd_mach_sh5 0x50
bfd_arch_alpha, /* Dec Alpha */
#define bfd_mach_alpha 1
+#define bfd_mach_alpha_ev4 0x10
+#define bfd_mach_alpha_ev5 0x20
+#define bfd_mach_alpha_ev6 0x30
bfd_arch_arm, /* Advanced Risc Machines ARM */
#define bfd_mach_arm_unknown 0
#define bfd_mach_arm_2 1
diff --git a/disas.c b/disas.c
index 223606c..d208c52 100644
--- a/disas.c
+++ b/disas.c
@@ -205,7 +205,7 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
disasm_info.mach = bfd_mach_sh4;
print_insn = print_insn_sh;
#elif defined(TARGET_ALPHA)
- disasm_info.mach = bfd_mach_alpha;
+ disasm_info.mach = bfd_mach_alpha_ev6;
print_insn = print_insn_alpha;
#elif defined(TARGET_CRIS)
if (flags != 32) {
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 03/24] pci: Export pci_to_cpu_addr.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 01/24] Export the unassigned_mem read/write functions Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 02/24] target-alpha: Disassemble EV6 PALcode instructions Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 04/24] target-alpha: Remove partial support for palcode emulation Richard Henderson
` (21 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
This is, more or less, the read accessor to pci_bus_set_mem_base
as a write accessor. It will be needed for implementing sparse
memory spaces for Alpha.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
hw/pci.c | 3 +--
hw/pci.h | 1 +
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/hw/pci.c b/hw/pci.c
index 6b577e1..8c7f52a 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -793,8 +793,7 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
return pci_dev;
}
-static target_phys_addr_t pci_to_cpu_addr(PCIBus *bus,
- target_phys_addr_t addr)
+target_phys_addr_t pci_to_cpu_addr(PCIBus *bus, target_phys_addr_t addr)
{
return addr + bus->mem_base;
}
diff --git a/hw/pci.h b/hw/pci.h
index 52ee8c9..cb0f738 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -242,6 +242,7 @@ void pci_device_reset(PCIDevice *dev);
void pci_bus_reset(PCIBus *bus);
void pci_bus_set_mem_base(PCIBus *bus, target_phys_addr_t base);
+target_phys_addr_t pci_to_cpu_addr(PCIBus *bus, target_phys_addr_t addr);
PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
const char *default_devaddr);
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 04/24] target-alpha: Remove partial support for palcode emulation.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (2 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 03/24] pci: Export pci_to_cpu_addr Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 05/24] target-alpha: Tidy exception constants Richard Henderson
` (20 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
This code does not work, and will be replaced by a bios image.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
Makefile.target | 2 +-
hw/alpha_palcode.c | 1048 ----------------------------------------------
target-alpha/cpu.h | 35 --
target-alpha/helper.c | 2 +-
target-alpha/translate.c | 2 -
5 files changed, 2 insertions(+), 1087 deletions(-)
delete mode 100644 hw/alpha_palcode.c
diff --git a/Makefile.target b/Makefile.target
index d5761b7..5ea7ce1 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -362,7 +362,7 @@ obj-m68k-y += m68k-semi.o dummy_m68k.o
obj-s390x-y = s390-virtio-bus.o s390-virtio.o
-obj-alpha-y = alpha_palcode.o
+obj-alpha-y =
main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
diff --git a/hw/alpha_palcode.c b/hw/alpha_palcode.c
deleted file mode 100644
index 033b542..0000000
--- a/hw/alpha_palcode.c
+++ /dev/null
@@ -1,1048 +0,0 @@
-/*
- * Alpha emulation - PALcode emulation for qemu.
- *
- * Copyright (c) 2007 Jocelyn Mayer
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "cpu.h"
-#include "exec-all.h"
-
-/* Shared handlers */
-static void pal_reset (CPUState *env);
-/* Console handlers */
-static void pal_console_call (CPUState *env, uint32_t palcode);
-/* OpenVMS handlers */
-static void pal_openvms_call (CPUState *env, uint32_t palcode);
-/* UNIX / Linux handlers */
-static void pal_unix_call (CPUState *env, uint32_t palcode);
-
-pal_handler_t pal_handlers[] = {
- /* Console handler */
- {
- .reset = &pal_reset,
- .call_pal = &pal_console_call,
- },
- /* OpenVMS handler */
- {
- .reset = &pal_reset,
- .call_pal = &pal_openvms_call,
- },
- /* UNIX / Linux handler */
- {
- .reset = &pal_reset,
- .call_pal = &pal_unix_call,
- },
-};
-
-#if 0
-/* One must explicitly check that the TB is valid and the FOE bit is reset */
-static void update_itb (void)
-{
- /* This writes into a temp register, not the actual one */
- mtpr(TB_TAG);
- mtpr(TB_CTL);
- /* This commits the TB update */
- mtpr(ITB_PTE);
-}
-
-static void update_dtb (void);
-{
- mtpr(TB_CTL);
- /* This write into a temp register, not the actual one */
- mtpr(TB_TAG);
- /* This commits the TB update */
- mtpr(DTB_PTE);
-}
-#endif
-
-static void pal_reset (CPUState *env)
-{
-}
-
-static void do_swappal (CPUState *env, uint64_t palid)
-{
- pal_handler_t *pal_handler;
-
- switch (palid) {
- case 0 ... 2:
- pal_handler = &pal_handlers[palid];
- env->pal_handler = pal_handler;
- env->ipr[IPR_PAL_BASE] = -1ULL;
- (*pal_handler->reset)(env);
- break;
- case 3 ... 255:
- /* Unknown identifier */
- env->ir[0] = 1;
- return;
- 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];
- cpu_loop_exit();
- }
-}
-
-static void pal_console_call (CPUState *env, uint32_t palcode)
-{
- uint64_t palid;
-
- if (palcode < 0x00000080) {
- /* Privileged palcodes */
- if (!(env->ps >> 3)) {
- /* TODO: generate privilege exception */
- }
- }
- switch (palcode) {
- case 0x00000000:
- /* HALT */
- /* REQUIRED */
- break;
- case 0x00000001:
- /* CFLUSH */
- break;
- case 0x00000002:
- /* DRAINA */
- /* REQUIRED */
- /* Implemented as no-op */
- break;
- case 0x00000009:
- /* CSERVE */
- /* REQUIRED */
- break;
- case 0x0000000A:
- /* SWPPAL */
- /* REQUIRED */
- palid = env->ir[16];
- do_swappal(env, palid);
- break;
- case 0x00000080:
- /* BPT */
- /* REQUIRED */
- break;
- case 0x00000081:
- /* BUGCHK */
- /* REQUIRED */
- break;
- case 0x00000086:
- /* IMB */
- /* REQUIRED */
- /* Implemented as no-op */
- break;
- case 0x0000009E:
- /* RDUNIQUE */
- /* REQUIRED */
- break;
- case 0x0000009F:
- /* WRUNIQUE */
- /* REQUIRED */
- break;
- case 0x000000AA:
- /* GENTRAP */
- /* REQUIRED */
- break;
- default:
- break;
- }
-}
-
-static void pal_openvms_call (CPUState *env, uint32_t palcode)
-{
- uint64_t palid, val, oldval;
-
- if (palcode < 0x00000080) {
- /* Privileged palcodes */
- if (!(env->ps >> 3)) {
- /* TODO: generate privilege exception */
- }
- }
- switch (palcode) {
- case 0x00000000:
- /* HALT */
- /* REQUIRED */
- break;
- case 0x00000001:
- /* CFLUSH */
- break;
- case 0x00000002:
- /* DRAINA */
- /* REQUIRED */
- /* Implemented as no-op */
- break;
- case 0x00000003:
- /* LDQP */
- break;
- case 0x00000004:
- /* STQP */
- break;
- case 0x00000005:
- /* SWPCTX */
- break;
- case 0x00000006:
- /* MFPR_ASN */
- if (cpu_alpha_mfpr(env, IPR_ASN, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x00000007:
- /* MTPR_ASTEN */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_ASTEN, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x00000008:
- /* MTPR_ASTSR */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_ASTSR, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x00000009:
- /* CSERVE */
- /* REQUIRED */
- break;
- case 0x0000000A:
- /* SWPPAL */
- /* REQUIRED */
- palid = env->ir[16];
- do_swappal(env, palid);
- break;
- case 0x0000000B:
- /* MFPR_FEN */
- if (cpu_alpha_mfpr(env, IPR_FEN, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x0000000C:
- /* MTPR_FEN */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_FEN, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x0000000D:
- /* MTPR_IPIR */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_IPIR, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x0000000E:
- /* MFPR_IPL */
- if (cpu_alpha_mfpr(env, IPR_IPL, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x0000000F:
- /* MTPR_IPL */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_IPL, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x00000010:
- /* MFPR_MCES */
- if (cpu_alpha_mfpr(env, IPR_MCES, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x00000011:
- /* MTPR_MCES */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_MCES, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x00000012:
- /* MFPR_PCBB */
- if (cpu_alpha_mfpr(env, IPR_PCBB, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x00000013:
- /* MFPR_PRBR */
- if (cpu_alpha_mfpr(env, IPR_PRBR, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x00000014:
- /* MTPR_PRBR */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_PRBR, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x00000015:
- /* MFPR_PTBR */
- if (cpu_alpha_mfpr(env, IPR_PTBR, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x00000016:
- /* MFPR_SCBB */
- if (cpu_alpha_mfpr(env, IPR_SCBB, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x00000017:
- /* MTPR_SCBB */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_SCBB, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x00000018:
- /* MTPR_SIRR */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_SIRR, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x00000019:
- /* MFPR_SISR */
- if (cpu_alpha_mfpr(env, IPR_SISR, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x0000001A:
- /* MFPR_TBCHK */
- if (cpu_alpha_mfpr(env, IPR_TBCHK, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x0000001B:
- /* MTPR_TBIA */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_TBIA, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x0000001C:
- /* MTPR_TBIAP */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_TBIAP, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x0000001D:
- /* MTPR_TBIS */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_TBIS, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x0000001E:
- /* MFPR_ESP */
- if (cpu_alpha_mfpr(env, IPR_ESP, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x0000001F:
- /* MTPR_ESP */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_ESP, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x00000020:
- /* MFPR_SSP */
- if (cpu_alpha_mfpr(env, IPR_SSP, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x00000021:
- /* MTPR_SSP */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_SSP, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x00000022:
- /* MFPR_USP */
- if (cpu_alpha_mfpr(env, IPR_USP, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x00000023:
- /* MTPR_USP */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_USP, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x00000024:
- /* MTPR_TBISD */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_TBISD, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x00000025:
- /* MTPR_TBISI */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_TBISI, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x00000026:
- /* MFPR_ASTEN */
- if (cpu_alpha_mfpr(env, IPR_ASTEN, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x00000027:
- /* MFPR_ASTSR */
- if (cpu_alpha_mfpr(env, IPR_ASTSR, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x00000029:
- /* MFPR_VPTB */
- if (cpu_alpha_mfpr(env, IPR_VPTB, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x0000002A:
- /* MTPR_VPTB */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_VPTB, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x0000002B:
- /* MTPR_PERFMON */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x0000002E:
- /* MTPR_DATFX */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_DATFX, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x0000003E:
- /* WTINT */
- break;
- case 0x0000003F:
- /* MFPR_WHAMI */
- if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x00000080:
- /* BPT */
- /* REQUIRED */
- break;
- case 0x00000081:
- /* BUGCHK */
- /* REQUIRED */
- break;
- case 0x00000082:
- /* CHME */
- break;
- case 0x00000083:
- /* CHMK */
- break;
- case 0x00000084:
- /* CHMS */
- break;
- case 0x00000085:
- /* CHMU */
- break;
- case 0x00000086:
- /* IMB */
- /* REQUIRED */
- /* Implemented as no-op */
- break;
- case 0x00000087:
- /* INSQHIL */
- break;
- case 0x00000088:
- /* INSQTIL */
- break;
- case 0x00000089:
- /* INSQHIQ */
- break;
- case 0x0000008A:
- /* INSQTIQ */
- break;
- case 0x0000008B:
- /* INSQUEL */
- break;
- case 0x0000008C:
- /* INSQUEQ */
- break;
- case 0x0000008D:
- /* INSQUEL/D */
- break;
- case 0x0000008E:
- /* INSQUEQ/D */
- break;
- case 0x0000008F:
- /* PROBER */
- break;
- case 0x00000090:
- /* PROBEW */
- break;
- case 0x00000091:
- /* RD_PS */
- break;
- case 0x00000092:
- /* REI */
- break;
- case 0x00000093:
- /* REMQHIL */
- break;
- case 0x00000094:
- /* REMQTIL */
- break;
- case 0x00000095:
- /* REMQHIQ */
- break;
- case 0x00000096:
- /* REMQTIQ */
- break;
- case 0x00000097:
- /* REMQUEL */
- break;
- case 0x00000098:
- /* REMQUEQ */
- break;
- case 0x00000099:
- /* REMQUEL/D */
- break;
- case 0x0000009A:
- /* REMQUEQ/D */
- break;
- case 0x0000009B:
- /* SWASTEN */
- break;
- case 0x0000009C:
- /* WR_PS_SW */
- break;
- case 0x0000009D:
- /* RSCC */
- break;
- case 0x0000009E:
- /* READ_UNQ */
- /* REQUIRED */
- break;
- case 0x0000009F:
- /* WRITE_UNQ */
- /* REQUIRED */
- break;
- case 0x000000A0:
- /* AMOVRR */
- break;
- case 0x000000A1:
- /* AMOVRM */
- break;
- case 0x000000A2:
- /* INSQHILR */
- break;
- case 0x000000A3:
- /* INSQTILR */
- break;
- case 0x000000A4:
- /* INSQHIQR */
- break;
- case 0x000000A5:
- /* INSQTIQR */
- break;
- case 0x000000A6:
- /* REMQHILR */
- break;
- case 0x000000A7:
- /* REMQTILR */
- break;
- case 0x000000A8:
- /* REMQHIQR */
- break;
- case 0x000000A9:
- /* REMQTIQR */
- break;
- case 0x000000AA:
- /* GENTRAP */
- /* REQUIRED */
- break;
- case 0x000000AE:
- /* CLRFEN */
- break;
- default:
- break;
- }
-}
-
-static void pal_unix_call (CPUState *env, uint32_t palcode)
-{
- uint64_t palid, val, oldval;
-
- if (palcode < 0x00000080) {
- /* Privileged palcodes */
- if (!(env->ps >> 3)) {
- /* TODO: generate privilege exception */
- }
- }
- switch (palcode) {
- case 0x00000000:
- /* HALT */
- /* REQUIRED */
- break;
- case 0x00000001:
- /* CFLUSH */
- break;
- case 0x00000002:
- /* DRAINA */
- /* REQUIRED */
- /* Implemented as no-op */
- break;
- case 0x00000009:
- /* CSERVE */
- /* REQUIRED */
- break;
- case 0x0000000A:
- /* SWPPAL */
- /* REQUIRED */
- palid = env->ir[16];
- do_swappal(env, palid);
- break;
- case 0x0000000D:
- /* WRIPIR */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_IPIR, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x00000010:
- /* RDMCES */
- if (cpu_alpha_mfpr(env, IPR_MCES, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x00000011:
- /* WRMCES */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_MCES, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x0000002B:
- /* WRFEN */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x0000002D:
- /* WRVPTPTR */
- break;
- case 0x00000030:
- /* SWPCTX */
- break;
- case 0x00000031:
- /* WRVAL */
- break;
- case 0x00000032:
- /* RDVAL */
- break;
- case 0x00000033:
- /* TBI */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_TBIS, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x00000034:
- /* WRENT */
- break;
- case 0x00000035:
- /* SWPIPL */
- break;
- case 0x00000036:
- /* RDPS */
- break;
- case 0x00000037:
- /* WRKGP */
- break;
- case 0x00000038:
- /* WRUSP */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_USP, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x00000039:
- /* WRPERFMON */
- val = env->ir[16];
- if (cpu_alpha_mtpr(env, IPR_PERFMON, val, &oldval) == 1)
- env->ir[0] = val;
- break;
- case 0x0000003A:
- /* RDUSP */
- if (cpu_alpha_mfpr(env, IPR_USP, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x0000003C:
- /* WHAMI */
- if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x0000003D:
- /* RETSYS */
- break;
- case 0x0000003E:
- /* WTINT */
- break;
- case 0x0000003F:
- /* RTI */
- if (cpu_alpha_mfpr(env, IPR_WHAMI, &val) == 0)
- env->ir[0] = val;
- break;
- case 0x00000080:
- /* BPT */
- /* REQUIRED */
- break;
- case 0x00000081:
- /* BUGCHK */
- /* REQUIRED */
- break;
- case 0x00000083:
- /* CALLSYS */
- break;
- case 0x00000086:
- /* IMB */
- /* REQUIRED */
- /* Implemented as no-op */
- break;
- case 0x00000092:
- /* URTI */
- break;
- case 0x0000009E:
- /* RDUNIQUE */
- /* REQUIRED */
- break;
- case 0x0000009F:
- /* WRUNIQUE */
- /* REQUIRED */
- break;
- case 0x000000AA:
- /* GENTRAP */
- /* REQUIRED */
- break;
- case 0x000000AE:
- /* CLRFEN */
- break;
- default:
- break;
- }
-}
-
-void call_pal (CPUState *env)
-{
- pal_handler_t *pal_handler = env->pal_handler;
-
- switch (env->exception_index) {
- case EXCP_RESET:
- (*pal_handler->reset)(env);
- break;
- case EXCP_MCHK:
- (*pal_handler->machine_check)(env);
- break;
- case EXCP_ARITH:
- (*pal_handler->arithmetic)(env);
- break;
- case EXCP_INTERRUPT:
- (*pal_handler->interrupt)(env);
- break;
- case EXCP_DFAULT:
- (*pal_handler->dfault)(env);
- break;
- case EXCP_DTB_MISS_PAL:
- (*pal_handler->dtb_miss_pal)(env);
- break;
- case EXCP_DTB_MISS_NATIVE:
- (*pal_handler->dtb_miss_native)(env);
- break;
- case EXCP_UNALIGN:
- (*pal_handler->unalign)(env);
- break;
- case EXCP_ITB_MISS:
- (*pal_handler->itb_miss)(env);
- break;
- case EXCP_ITB_ACV:
- (*pal_handler->itb_acv)(env);
- break;
- case EXCP_OPCDEC:
- (*pal_handler->opcdec)(env);
- break;
- case EXCP_FEN:
- (*pal_handler->fen)(env);
- break;
- default:
- if (env->exception_index >= EXCP_CALL_PAL &&
- env->exception_index < EXCP_CALL_PALP) {
- /* Unprivileged PAL call */
- (*pal_handler->call_pal)
- (env, (env->exception_index - EXCP_CALL_PAL) >> 6);
- } else if (env->exception_index >= EXCP_CALL_PALP &&
- env->exception_index < EXCP_CALL_PALE) {
- /* Privileged PAL call */
- (*pal_handler->call_pal)
- (env, ((env->exception_index - EXCP_CALL_PALP) >> 6) + 0x80);
- } else {
- /* Should never happen */
- }
- break;
- }
- env->ipr[IPR_EXC_ADDR] &= ~1;
-}
-
-void pal_init (CPUState *env)
-{
- do_swappal(env, 0);
-}
-
-#if 0
-static uint64_t get_ptebase (CPUState *env, uint64_t vaddr)
-{
- uint64_t virbnd, ptbr;
-
- if ((env->features & FEATURE_VIRBND)) {
- cpu_alpha_mfpr(env, IPR_VIRBND, &virbnd);
- if (vaddr >= virbnd)
- cpu_alpha_mfpr(env, IPR_SYSPTBR, &ptbr);
- else
- cpu_alpha_mfpr(env, IPR_PTBR, &ptbr);
- } else {
- cpu_alpha_mfpr(env, IPR_PTBR, &ptbr);
- }
-
- return ptbr;
-}
-
-static int get_page_bits (CPUState *env)
-{
- /* XXX */
- return 13;
-}
-
-static int get_pte (uint64_t *pfnp, int *zbitsp, int *protp,
- uint64_t ptebase, int page_bits, uint64_t level,
- int mmu_idx, int rw)
-{
- uint64_t pteaddr, pte, pfn;
- uint8_t gh;
- int ure, uwe, kre, kwe, foE, foR, foW, v, ret, ar, is_user;
-
- /* XXX: TOFIX */
- is_user = mmu_idx == MMU_USER_IDX;
- pteaddr = (ptebase << page_bits) + (8 * level);
- pte = ldq_raw(pteaddr);
- /* Decode all interresting PTE fields */
- pfn = pte >> 32;
- uwe = (pte >> 13) & 1;
- kwe = (pte >> 12) & 1;
- ure = (pte >> 9) & 1;
- kre = (pte >> 8) & 1;
- gh = (pte >> 5) & 3;
- foE = (pte >> 3) & 1;
- foW = (pte >> 2) & 1;
- foR = (pte >> 1) & 1;
- v = pte & 1;
- ret = 0;
- if (!v)
- ret = 0x1;
- /* Check access rights */
- ar = 0;
- if (is_user) {
- if (ure)
- ar |= PAGE_READ;
- if (uwe)
- ar |= PAGE_WRITE;
- if (rw == 1 && !uwe)
- ret |= 0x2;
- if (rw != 1 && !ure)
- ret |= 0x2;
- } else {
- if (kre)
- ar |= PAGE_READ;
- if (kwe)
- ar |= PAGE_WRITE;
- if (rw == 1 && !kwe)
- ret |= 0x2;
- if (rw != 1 && !kre)
- ret |= 0x2;
- }
- if (rw == 0 && foR)
- ret |= 0x4;
- if (rw == 2 && foE)
- ret |= 0x8;
- if (rw == 1 && foW)
- ret |= 0xC;
- *pfnp = pfn;
- if (zbitsp != NULL)
- *zbitsp = page_bits + (3 * gh);
- if (protp != NULL)
- *protp = ar;
-
- return ret;
-}
-
-static int paddr_from_pte (uint64_t *paddr, int *zbitsp, int *prot,
- uint64_t ptebase, int page_bits,
- uint64_t vaddr, int mmu_idx, int rw)
-{
- uint64_t pfn, page_mask, lvl_mask, level1, level2, level3;
- int lvl_bits, ret;
-
- page_mask = (1ULL << page_bits) - 1ULL;
- lvl_bits = page_bits - 3;
- lvl_mask = (1ULL << lvl_bits) - 1ULL;
- level3 = (vaddr >> page_bits) & lvl_mask;
- level2 = (vaddr >> (page_bits + lvl_bits)) & lvl_mask;
- level1 = (vaddr >> (page_bits + (2 * lvl_bits))) & lvl_mask;
- /* Level 1 PTE */
- ret = get_pte(&pfn, NULL, NULL, ptebase, page_bits, level1, 0, 0);
- switch (ret) {
- case 3:
- /* Access violation */
- return 2;
- case 2:
- /* translation not valid */
- return 1;
- default:
- /* OK */
- break;
- }
- /* Level 2 PTE */
- ret = get_pte(&pfn, NULL, NULL, pfn, page_bits, level2, 0, 0);
- switch (ret) {
- case 3:
- /* Access violation */
- return 2;
- case 2:
- /* translation not valid */
- return 1;
- default:
- /* OK */
- break;
- }
- /* Level 3 PTE */
- ret = get_pte(&pfn, zbitsp, prot, pfn, page_bits, level3, mmu_idx, rw);
- if (ret & 0x1) {
- /* Translation not valid */
- ret = 1;
- } else if (ret & 2) {
- /* Access violation */
- ret = 2;
- } else {
- switch (ret & 0xC) {
- case 0:
- /* OK */
- ret = 0;
- break;
- case 0x4:
- /* Fault on read */
- ret = 3;
- break;
- case 0x8:
- /* Fault on execute */
- ret = 4;
- break;
- case 0xC:
- /* Fault on write */
- ret = 5;
- break;
- }
- }
- *paddr = (pfn << page_bits) | (vaddr & page_mask);
-
- return 0;
-}
-
-static int virtual_to_physical (CPUState *env, uint64_t *physp,
- int *zbitsp, int *protp,
- uint64_t virtual, int mmu_idx, int rw)
-{
- uint64_t sva, ptebase;
- int seg, page_bits, ret;
-
- sva = ((int64_t)(virtual << (64 - VA_BITS))) >> (64 - VA_BITS);
- if (sva != virtual)
- seg = -1;
- else
- seg = sva >> (VA_BITS - 2);
- virtual &= ~(0xFFFFFC0000000000ULL << (VA_BITS - 43));
- ptebase = get_ptebase(env, virtual);
- page_bits = get_page_bits(env);
- ret = 0;
- switch (seg) {
- case 0:
- /* seg1: 3 levels of PTE */
- ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
- virtual, mmu_idx, rw);
- break;
- case 1:
- /* seg1: 2 levels of PTE */
- ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
- virtual, mmu_idx, rw);
- break;
- case 2:
- /* kernel segment */
- if (mmu_idx != 0) {
- ret = 2;
- } else {
- *physp = virtual;
- }
- break;
- case 3:
- /* seg1: TB mapped */
- ret = paddr_from_pte(physp, zbitsp, protp, ptebase, page_bits,
- virtual, mmu_idx, rw);
- break;
- default:
- ret = 1;
- break;
- }
-
- return ret;
-}
-
-/* XXX: code provision */
-int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
- int mmu_idx, int is_softmmu)
-{
- uint64_t physical, page_size, end;
- int prot, zbits, ret;
-
- ret = virtual_to_physical(env, &physical, &zbits, &prot,
- address, mmu_idx, rw);
-
- switch (ret) {
- case 0:
- /* No fault */
- page_size = 1ULL << zbits;
- address &= ~(page_size - 1);
- /* FIXME: page_size should probably be passed to tlb_set_page,
- and this loop removed. */
- for (end = physical + page_size; physical < end; physical += 0x1000) {
- tlb_set_page(env, address, physical, prot, mmu_idx,
- TARGET_PAGE_SIZE);
- address += 0x1000;
- }
- ret = 0;
- break;
-#if 0
- case 1:
- env->exception_index = EXCP_DFAULT;
- env->ipr[IPR_EXC_ADDR] = address;
- ret = 1;
- break;
- case 2:
- env->exception_index = EXCP_ACCESS_VIOLATION;
- env->ipr[IPR_EXC_ADDR] = address;
- ret = 1;
- break;
- case 3:
- env->exception_index = EXCP_FAULT_ON_READ;
- env->ipr[IPR_EXC_ADDR] = address;
- ret = 1;
- break;
- case 4:
- env->exception_index = EXCP_FAULT_ON_EXECUTE;
- env->ipr[IPR_EXC_ADDR] = address;
- ret = 1;
- case 5:
- env->exception_index = EXCP_FAULT_ON_WRITE;
- env->ipr[IPR_EXC_ADDR] = address;
- ret = 1;
-#endif
- default:
- /* Should never happen */
- env->exception_index = EXCP_MCHK;
- env->ipr[IPR_EXC_ADDR] = address;
- ret = 1;
- break;
- }
-
- return ret;
-}
-#endif
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 686fb4a..0daa556 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -319,36 +319,6 @@ enum {
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);
-};
-
#define NB_MMU_MODES 4
struct CPUAlphaState {
@@ -393,7 +363,6 @@ struct CPUAlphaState {
uint32_t features;
uint32_t amask;
int implver;
- pal_handler_t *pal_handler;
};
#define cpu_init cpu_alpha_init
@@ -506,10 +475,6 @@ uint64_t cpu_alpha_load_fpcr (CPUState *env);
void cpu_alpha_store_fpcr (CPUState *env, uint64_t val);
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 pal_init (CPUState *env);
-void call_pal (CPUState *env);
-#endif
static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
target_ulong *cs_base, int *flags)
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 3ba4478..f7cf4ee 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -528,7 +528,7 @@ void do_interrupt (CPUState *env)
env->pc = env->ipr[IPR_PAL_BASE] + excp;
} else {
/* We use emulated PALcode */
- call_pal(env);
+ abort();
/* Emulate REI */
env->pc = env->ipr[IPR_EXC_ADDR] & ~7;
env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 96e922b..699c70d 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3330,8 +3330,6 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
env->ps |= 1 << 3;
cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
| FPCR_UNFD | FPCR_INED | FPCR_DNOD));
-#else
- pal_init(env);
#endif
env->lock_addr = -1;
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 05/24] target-alpha: Tidy exception constants.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (3 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 04/24] target-alpha: Remove partial support for palcode emulation Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 06/24] target-alpha: Rationalize internal processor registers Richard Henderson
` (19 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
There's no need to attempt to match EXCP_* values with PALcode entry
point offsets. Instead, compress all the values to make for more
efficient switch statements within QEMU.
We will be doing TLB fill within QEMU proper, not within the PALcode,
so all of the ITB/DTB miss, double fault, and access exceptions can
be compressed to EXCP_MMFAULT.
Compress all of the EXCP_CALL_PAL exceptions into one.
Use env->error_code to store the specific entry point.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
linux-user/main.c | 43 +++++++++++++------------------------------
target-alpha/cpu.h | 33 +++++++++++++--------------------
target-alpha/helper.c | 6 +-----
target-alpha/translate.c | 4 ++--
4 files changed, 29 insertions(+), 57 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index a1e37e4..5b25736 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2526,19 +2526,12 @@ void cpu_loop (CPUState *env)
fprintf(stderr, "Machine check exception. Exit\n");
exit(1);
break;
- case EXCP_ARITH:
- env->lock_addr = -1;
- info.si_signo = TARGET_SIGFPE;
- info.si_errno = 0;
- info.si_code = TARGET_FPE_FLTINV;
- info._sifields._sigfault._addr = env->pc;
- queue_signal(env, info.si_signo, &info);
- break;
- case EXCP_HW_INTERRUPT:
+ case EXCP_CLK_INTERRUPT:
+ case EXCP_DEV_INTERRUPT:
fprintf(stderr, "External interrupt. Exit\n");
exit(1);
break;
- case EXCP_DFAULT:
+ case EXCP_MMFAULT:
env->lock_addr = -1;
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
@@ -2547,22 +2540,6 @@ void cpu_loop (CPUState *env)
info._sifields._sigfault._addr = env->ipr[IPR_EXC_ADDR];
queue_signal(env, info.si_signo, &info);
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:
env->lock_addr = -1;
info.si_signo = TARGET_SIGBUS;
@@ -2580,12 +2557,20 @@ void cpu_loop (CPUState *env)
info._sifields._sigfault._addr = env->pc;
queue_signal(env, info.si_signo, &info);
break;
+ case EXCP_ARITH:
+ env->lock_addr = -1;
+ info.si_signo = TARGET_SIGFPE;
+ info.si_errno = 0;
+ info.si_code = TARGET_FPE_FLTINV;
+ info._sifields._sigfault._addr = env->pc;
+ queue_signal(env, info.si_signo, &info);
+ break;
case EXCP_FEN:
/* No-op. Linux simply re-enables the FPU. */
break;
- case EXCP_CALL_PAL ... (EXCP_CALL_PALP - 1):
+ case EXCP_CALL_PAL:
env->lock_addr = -1;
- switch ((trapnr >> 6) | 0x80) {
+ switch (env->error_code) {
case 0x80:
/* BPT */
info.si_signo = TARGET_SIGTRAP;
@@ -2676,8 +2661,6 @@ void cpu_loop (CPUState *env)
goto do_sigill;
}
break;
- case EXCP_CALL_PALP ... (EXCP_CALL_PALE - 1):
- goto do_sigill;
case EXCP_DEBUG:
info.si_signo = gdb_handlesig (env, TARGET_SIGTRAP);
if (info.si_signo) {
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 0daa556..f3e939b 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -391,26 +391,19 @@ 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_CALL_PAL = 0x2000,
- EXCP_CALL_PALP = 0x3000,
- EXCP_CALL_PALE = 0x4000,
- /* Pseudo exception for console */
- EXCP_CONSOLE_DISPATCH = 0x4001,
- EXCP_CONSOLE_FIXUP = 0x4002,
- EXCP_STL_C = 0x4003,
- EXCP_STQ_C = 0x4004,
+ EXCP_RESET,
+ EXCP_MCHK,
+ EXCP_CLK_INTERRUPT,
+ EXCP_DEV_INTERRUPT,
+ EXCP_MMFAULT,
+ EXCP_UNALIGN,
+ EXCP_OPCDEC,
+ EXCP_ARITH,
+ EXCP_FEN,
+ EXCP_CALL_PAL,
+ /* For Usermode emulation. */
+ EXCP_STL_C,
+ EXCP_STQ_C,
};
/* Arithmetic exception */
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index f7cf4ee..676c870 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -164,12 +164,8 @@ void cpu_alpha_store_fpcr (CPUState *env, uint64_t val)
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;
- else
- env->exception_index = EXCP_DFAULT;
+ env->exception_index = EXCP_MMFAULT;
env->ipr[IPR_EXC_ADDR] = address;
-
return 1;
}
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 699c70d..3a023a5 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1512,7 +1512,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
#endif
if (palcode >= 0x80 && palcode < 0xC0) {
/* Unprivileged PAL call */
- ret = gen_excp(ctx, EXCP_CALL_PAL + ((palcode & 0x3F) << 6), 0);
+ ret = gen_excp(ctx, EXCP_CALL_PAL, palcode & 0xBF);
break;
}
#ifndef CONFIG_USER_ONLY
@@ -1520,7 +1520,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
/* Privileged PAL code */
if (ctx->mem_idx & 1)
goto invalid_opc;
- ret = gen_excp(ctx, EXCP_CALL_PALP + ((palcode & 0x3F) << 6), 0);
+ ret = gen_excp(ctx, EXCP_CALL_PAL, palcode & 0x3F);
}
#endif
/* Invalid PAL call */
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 06/24] target-alpha: Rationalize internal processor registers.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (4 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 05/24] target-alpha: Tidy exception constants Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 07/24] target-alpha: Cleanup MMU modes Richard Henderson
` (18 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
Delete all the code that tried to emulate the real IPRs of some
unnamed CPU. Replace those with just 3 slots that we can use to
communicate trap information between the helper functions that
signal exceptions and the OS trap handler.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
linux-user/main.c | 6 +-
target-alpha/cpu.h | 147 ++------------------
target-alpha/helper.c | 348 +---------------------------------------------
target-alpha/helper.h | 2 -
target-alpha/op_helper.c | 17 +--
target-alpha/translate.c | 31 +----
6 files changed, 20 insertions(+), 531 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index 5b25736..503d7b8 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2535,9 +2535,9 @@ void cpu_loop (CPUState *env)
env->lock_addr = -1;
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
- info.si_code = (page_get_flags(env->ipr[IPR_EXC_ADDR]) & PAGE_VALID
+ info.si_code = (page_get_flags(env->trap_arg0) & PAGE_VALID
? TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR);
- info._sifields._sigfault._addr = env->ipr[IPR_EXC_ADDR];
+ info._sifields._sigfault._addr = env->trap_arg0;
queue_signal(env, info.si_signo, &info);
break;
case EXCP_UNALIGN:
@@ -2545,7 +2545,7 @@ void cpu_loop (CPUState *env)
info.si_signo = TARGET_SIGBUS;
info.si_errno = 0;
info.si_code = TARGET_BUS_ADRALN;
- info._sifields._sigfault._addr = env->ipr[IPR_EXC_ADDR];
+ info._sifields._sigfault._addr = env->trap_arg0;
queue_signal(env, info.si_signo, &info);
break;
case EXCP_OPCDEC:
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index f3e939b..e977705 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -192,141 +192,12 @@ enum {
#define SWCR_MASK (SWCR_TRAP_ENABLE_MASK | SWCR_MAP_MASK | SWCR_STATUS_MASK)
-/* Internal processor registers */
-/* XXX: TOFIX: most of those registers are implementation dependant */
-enum {
-#if defined(CONFIG_USER_ONLY)
- IPR_EXC_ADDR,
- IPR_EXC_SUM,
- IPR_EXC_MASK,
-#else
- /* Ebox IPRs */
- IPR_CC = 0xC0, /* 21264 */
- IPR_CC_CTL = 0xC1, /* 21264 */
-#define IPR_CC_CTL_ENA_SHIFT 32
-#define IPR_CC_CTL_COUNTER_MASK 0xfffffff0UL
- IPR_VA = 0xC2, /* 21264 */
- IPR_VA_CTL = 0xC4, /* 21264 */
-#define IPR_VA_CTL_VA_48_SHIFT 1
-#define IPR_VA_CTL_VPTB_SHIFT 30
- IPR_VA_FORM = 0xC3, /* 21264 */
- /* Ibox IPRs */
- IPR_ITB_TAG = 0x00, /* 21264 */
- IPR_ITB_PTE = 0x01, /* 21264 */
- IPR_ITB_IAP = 0x02,
- IPR_ITB_IA = 0x03, /* 21264 */
- IPR_ITB_IS = 0x04, /* 21264 */
- IPR_PMPC = 0x05,
- IPR_EXC_ADDR = 0x06, /* 21264 */
- IPR_IVA_FORM = 0x07, /* 21264 */
- IPR_CM = 0x09, /* 21264 */
-#define IPR_CM_SHIFT 3
-#define IPR_CM_MASK (3ULL << IPR_CM_SHIFT) /* 21264 */
- IPR_IER = 0x0A, /* 21264 */
-#define IPR_IER_MASK 0x0000007fffffe000ULL
- IPR_IER_CM = 0x0B, /* 21264: = CM | IER */
- IPR_SIRR = 0x0C, /* 21264 */
-#define IPR_SIRR_SHIFT 14
-#define IPR_SIRR_MASK 0x7fff
- IPR_ISUM = 0x0D, /* 21264 */
- IPR_HW_INT_CLR = 0x0E, /* 21264 */
- IPR_EXC_SUM = 0x0F,
- IPR_PAL_BASE = 0x10,
- 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_SDE1_SHIFT 7 /* 21264 */
-#define IPR_I_CTL_HWE_SHIFT 12 /* 21264 */
-#define IPR_I_CTL_VA_48_SHIFT 15 /* 21264 */
-#define IPR_I_CTL_SPE_SHIFT 3 /* 21264 */
-#define IPR_I_CTL_CALL_PAL_R23_SHIFT 20 /* 21264 */
- IPR_I_STAT = 0x16, /* 21264 */
- IPR_IC_FLUSH = 0x13, /* 21264 */
- IPR_IC_FLUSH_ASM = 0x12, /* 21264 */
- IPR_CLR_MAP = 0x15,
- IPR_SLEEP = 0x17,
- IPR_PCTX = 0x40,
- IPR_PCTX_ASN = 0x01, /* field */
-#define IPR_PCTX_ASN_SHIFT 39
- IPR_PCTX_ASTER = 0x02, /* field */
-#define IPR_PCTX_ASTER_SHIFT 5
- IPR_PCTX_ASTRR = 0x04, /* field */
-#define IPR_PCTX_ASTRR_SHIFT 9
- IPR_PCTX_PPCE = 0x08, /* field */
-#define IPR_PCTX_PPCE_SHIFT 1
- IPR_PCTX_FPE = 0x10, /* field */
-#define IPR_PCTX_FPE_SHIFT 2
- IPR_PCTX_ALL = 0x5f, /* all fields */
- IPR_PCTR_CTL = 0x14, /* 21264 */
- /* Mbox IPRs */
- IPR_DTB_TAG0 = 0x20, /* 21264 */
- IPR_DTB_TAG1 = 0xA0, /* 21264 */
- IPR_DTB_PTE0 = 0x21, /* 21264 */
- IPR_DTB_PTE1 = 0xA1, /* 21264 */
- IPR_DTB_ALTMODE = 0xA6,
- IPR_DTB_ALTMODE0 = 0x26, /* 21264 */
-#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_ASN0 = 0x25, /* 21264 */
- IPR_DTB_ASN1 = 0xA5, /* 21264 */
-#define IPR_DTB_ASN_SHIFT 56
- IPR_MM_STAT = 0x27, /* 21264 */
- IPR_M_CTL = 0x28, /* 21264 */
-#define IPR_M_CTL_SPE_SHIFT 1
-#define IPR_M_CTL_SPE_MASK 7
- IPR_DC_CTL = 0x29, /* 21264 */
- 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,
-#endif
- IPR_LAST,
-};
-
typedef struct CPUAlphaState CPUAlphaState;
-#define NB_MMU_MODES 4
-
struct CPUAlphaState {
uint64_t ir[31];
float64 fir[31];
uint64_t pc;
- uint64_t ipr[IPR_LAST];
- uint64_t ps;
uint64_t unique;
uint64_t lock_addr;
uint64_t lock_st_addr;
@@ -341,11 +212,18 @@ struct CPUAlphaState {
uint8_t fpcr_dnod;
uint8_t fpcr_undz;
- /* Used for HW_LD / HW_ST */
- uint8_t saved_mode;
- /* For RC and RS */
+ /* The Internal Processor Registers. Some of these we assume always
+ exist for use in user-mode. */
+ uint8_t ps;
uint8_t intr_flag;
+ /* These pass data from the exception logic in the translator and
+ helpers to the OS entry point. This is used for both system
+ emulation and user-mode. */
+ uint64_t trap_arg0;
+ uint64_t trap_arg1;
+ uint64_t trap_arg2;
+
#if TARGET_LONG_BITS > HOST_LONG_BITS
/* temporary fixed-point registers
* used to emulate 64 bits target on 32 bits hosts
@@ -356,8 +234,6 @@ struct CPUAlphaState {
/* Those resources are used only in Qemu core */
CPU_COMMON
- uint32_t hflags;
-
int error_code;
uint32_t features;
@@ -371,6 +247,7 @@ struct CPUAlphaState {
#define cpu_signal_handler cpu_alpha_signal_handler
/* MMU modes definitions */
+#define NB_MMU_MODES 4
#define MMU_MODE0_SUFFIX _kernel
#define MMU_MODE1_SUFFIX _executive
#define MMU_MODE2_SUFFIX _supervisor
@@ -466,8 +343,6 @@ void do_interrupt (CPUState *env);
uint64_t cpu_alpha_load_fpcr (CPUState *env);
void cpu_alpha_store_fpcr (CPUState *env, uint64_t val);
-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);
static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
target_ulong *cs_base, int *flags)
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 676c870..c5479fd 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -165,7 +165,7 @@ int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
int mmu_idx, int is_softmmu)
{
env->exception_index = EXCP_MMFAULT;
- env->ipr[IPR_EXC_ADDR] = address;
+ env->trap_arg0 = address;
return 1;
}
@@ -184,352 +184,12 @@ target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
int mmu_idx, int is_softmmu)
{
- uint32_t opc;
-
- if (rw == 2) {
- /* Instruction translation buffer miss */
- env->exception_index = EXCP_ITB_MISS;
- } else {
- if (env->ipr[IPR_EXC_ADDR] & 1)
- env->exception_index = EXCP_DTB_MISS_PAL;
- else
- env->exception_index = EXCP_DTB_MISS_NATIVE;
- opc = (ldl_code(env->pc) >> 21) << 4;
- if (rw) {
- opc |= 0x9;
- } else {
- opc |= 0x4;
- }
- env->ipr[IPR_MM_STAT] = opc;
- }
-
- return 1;
-}
-
-int cpu_alpha_mfpr (CPUState *env, int iprn, uint64_t *valp)
-{
- uint64_t hwpcb;
- int ret = 0;
-
- hwpcb = env->ipr[IPR_PCBB];
- 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;
- 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);
- }
- break;
- case IPR_MCES:
- *valp = ((int64_t)(env->ipr[IPR_MCES] << 59)) >> 59;
- break;
- case IPR_PERFMON:
- /* Implementation specific */
- *valp = 0;
- break;
- case IPR_PCBB:
- *valp = ((int64_t)env->ipr[IPR_PCBB] << 16) >> 16;
- break;
- case IPR_PRBR:
- *valp = env->ipr[IPR_PRBR];
- break;
- case IPR_PTBR:
- *valp = env->ipr[IPR_PTBR];
- break;
- case IPR_SCBB:
- *valp = (int64_t)((int32_t)env->ipr[IPR_SCBB]);
- 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);
- 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;
- }
- break;
- case IPR_TBIA:
- /* Write-only */
- ret = -1;
- break;
- case IPR_TBIAP:
- /* Write-only */
- ret = -1;
- break;
- case IPR_TBIS:
- /* Write-only */
- ret = -1;
- break;
- case IPR_TBISD:
- /* Write-only */
- ret = -1;
- break;
- case IPR_TBISI:
- /* Write-only */
- ret = -1;
- break;
- case IPR_USP:
- if (env->features & FEATURE_SPS)
- *valp = env->ipr[IPR_USP];
- else
- *valp = ldq_raw(hwpcb + 24);
- break;
- case IPR_VIRBND:
- if (env->features & FEATURE_VIRBND)
- *valp = env->ipr[IPR_VIRBND];
- else
- ret = -1;
- break;
- case IPR_VPTB:
- *valp = env->ipr[IPR_VPTB];
- break;
- case IPR_WHAMI:
- *valp = env->ipr[IPR_WHAMI];
- break;
- default:
- /* Invalid */
- ret = -1;
- break;
- }
-
- return ret;
-}
-
-int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp)
-{
- uint64_t hwpcb, tmp64;
- uint8_t tmp8;
- int ret = 0;
-
- 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;
- break;
- 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;
- break;
- default:
- /* Invalid */
- ret = -1;
- break;
- }
-
- return ret;
+ return 0;
}
void do_interrupt (CPUState *env)
{
- int excp;
-
- env->ipr[IPR_EXC_ADDR] = env->pc | 1;
- excp = env->exception_index;
- env->exception_index = -1;
- env->error_code = 0;
- /* XXX: disable interrupts and memory mapping */
- if (env->ipr[IPR_PAL_BASE] != -1ULL) {
- /* We use native PALcode */
- env->pc = env->ipr[IPR_PAL_BASE] + excp;
- } else {
- /* We use emulated PALcode */
- abort();
- /* Emulate REI */
- env->pc = env->ipr[IPR_EXC_ADDR] & ~7;
- env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
- /* XXX: re-enable interrupts and memory mapping */
- }
+ abort();
}
#endif
@@ -544,7 +204,7 @@ void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
};
int i;
- cpu_fprintf(f, " PC " TARGET_FMT_lx " PS " TARGET_FMT_lx "\n",
+ cpu_fprintf(f, " PC " TARGET_FMT_lx " PS %02x\n",
env->pc, env->ps);
for (i = 0; i < 31; i++) {
cpu_fprintf(f, "IR%02d %s " TARGET_FMT_lx " ", i,
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index ccf6a2a..7435c61 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -102,8 +102,6 @@ DEF_HELPER_1(ieee_input_s, i64, i64)
#if !defined (CONFIG_USER_ONLY)
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)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 6c2ae20..5b3f12d 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -373,7 +373,7 @@ void helper_fp_exc_raise(uint32_t exc, uint32_t regno)
if (exc) {
uint32_t hw_exc = 0;
- env->ipr[IPR_EXC_MASK] |= 1ull << regno;
+ env->trap_arg1 = 1ull << regno;
if (exc & float_flag_invalid) {
hw_exc |= EXC_M_INV;
@@ -1173,21 +1173,6 @@ void helper_hw_ret (uint64_t a)
/* XXX: re-enable interrupts and memory mapping */
}
-uint64_t helper_mfpr (int iprn, uint64_t val)
-{
- uint64_t tmp;
-
- if (cpu_alpha_mfpr(env, iprn, &tmp) == 0)
- val = tmp;
-
- 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;
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 3a023a5..e52fa0a 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3325,42 +3325,13 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
env->implver = implver;
env->amask = amask;
- env->ps = 0x1F00;
#if defined (CONFIG_USER_ONLY)
- env->ps |= 1 << 3;
+ env->ps = 1 << 3;
cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
| FPCR_UNFD | FPCR_INED | FPCR_DNOD));
#endif
env->lock_addr = -1;
- /* Initialize IPR */
-#if defined (CONFIG_USER_ONLY)
- env->ipr[IPR_EXC_ADDR] = 0;
- env->ipr[IPR_EXC_SUM] = 0;
- env->ipr[IPR_EXC_MASK] = 0;
-#else
- {
- // uint64_t hwpcb;
- // 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;
- }
-#endif
-
qemu_init_vcpu(env);
return env;
}
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 07/24] target-alpha: Cleanup MMU modes.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (5 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 06/24] target-alpha: Rationalize internal processor registers Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 08/24] target-alpha: Fixup translation of PALmode instructions Richard Henderson
` (17 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
Don't bother including executive and supervisor modes.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/cpu.h | 36 ++++++++++++++++++++++++++++--------
1 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index e977705..4737b83 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -192,6 +192,33 @@ enum {
#define SWCR_MASK (SWCR_TRAP_ENABLE_MASK | SWCR_MAP_MASK | SWCR_STATUS_MASK)
+/* MMU modes definitions */
+
+/* Alpha has 5 MMU modes: PALcode, kernel, executive, supervisor, and user.
+ The Unix PALcode only exposes the kernel and user modes; presumably
+ executive and supervisor are used by VMS.
+
+ PALcode itself uses physical mode for code and kernel mode for data;
+ there are PALmode instructions that can access data via physical mode
+ or via an os-installed "alternate mode", which is one of the 4 above.
+
+ QEMU does not currently properly distinguish between code/data when
+ looking up addresses. To avoid having to address this issue, our
+ emulated PALcode will cheat and use the KSEG mapping for its code+data
+ rather than physical addresses.
+
+ Moreover, we're only emulating Unix PALcode, and not attempting VMS.
+
+ All of which allows us to drop all but kernel and user modes.
+ Elide the unused MMU modes to save space. */
+
+#define NB_MMU_MODES 2
+
+#define MMU_MODE0_SUFFIX _kernel
+#define MMU_MODE1_SUFFIX _user
+#define MMU_KERNEL_IDX 0
+#define MMU_USER_IDX 1
+
typedef struct CPUAlphaState CPUAlphaState;
struct CPUAlphaState {
@@ -246,16 +273,9 @@ struct CPUAlphaState {
#define cpu_gen_code cpu_alpha_gen_code
#define cpu_signal_handler cpu_alpha_signal_handler
-/* MMU modes definitions */
-#define NB_MMU_MODES 4
-#define MMU_MODE0_SUFFIX _kernel
-#define MMU_MODE1_SUFFIX _executive
-#define MMU_MODE2_SUFFIX _supervisor
-#define MMU_MODE3_SUFFIX _user
-#define MMU_USER_IDX 3
static inline int cpu_mmu_index (CPUState *env)
{
- return (env->ps >> 3) & 3;
+ return (env->ps >> 3) & 1;
}
#include "cpu-all.h"
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 08/24] target-alpha: Fixup translation of PALmode instructions.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (6 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 07/24] target-alpha: Cleanup MMU modes Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 09/24] target-alpha: Add IPRs to be used by the emulation PALcode Richard Henderson
` (16 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
All of the "raw" memory accesses should be "phys" instead. Fix
some confusion about argument ordering of the store routines.
Fix the implementation of store-conditional.
Delete the "alt-mode" helpers. Because we only implement two
mmu modes, let /a imply user-mode unconditionally.
For the moment, stub out HW_MTPR and HW_MFPR.
Merge hw_rei with hw_ret.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/cpu.h | 4 +
target-alpha/helper.h | 27 +++-----
target-alpha/op_helper.c | 159 ++++++++++------------------------------------
target-alpha/translate.c | 130 ++++++++++----------------------------
4 files changed, 82 insertions(+), 238 deletions(-)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 4737b83..1c848bd 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -192,6 +192,8 @@ enum {
#define SWCR_MASK (SWCR_TRAP_ENABLE_MASK | SWCR_MAP_MASK | SWCR_STATUS_MASK)
+#define CPU_SAVE_VERSION 1
+
/* MMU modes definitions */
/* Alpha has 5 MMU modes: PALcode, kernel, executive, supervisor, and user.
@@ -243,6 +245,8 @@ struct CPUAlphaState {
exist for use in user-mode. */
uint8_t ps;
uint8_t intr_flag;
+ uint8_t fen;
+ uint8_t pal_mode;
/* These pass data from the exception logic in the translator and
helpers to the OS entry point. This is used for both system
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 7435c61..9ffc372 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -100,25 +100,16 @@ DEF_HELPER_1(ieee_input_cmp, i64, i64)
DEF_HELPER_1(ieee_input_s, i64, i64)
#if !defined (CONFIG_USER_ONLY)
-DEF_HELPER_0(hw_rei, void)
DEF_HELPER_1(hw_ret, void, 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(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_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 5b3f12d..bbf89fe 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1155,167 +1155,78 @@ uint64_t helper_cvtqg (uint64_t a)
/* PALcode support special instructions */
#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;
- env->intr_flag = 0;
- env->lock_addr = -1;
- /* XXX: re-enable interrupts and memory mapping */
-}
-
void helper_hw_ret (uint64_t a)
{
env->pc = a & ~3;
- env->ipr[IPR_EXC_ADDR] = a & 1;
+ env->pal_mode = a & 1;
env->intr_flag = 0;
env->lock_addr = -1;
- /* XXX: re-enable interrupts and memory mapping */
-}
-
-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;
}
-
#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)
-{
- uint64_t tlb_addr, physaddr;
- int index, mmu_idx;
- void *retaddr;
-
- mmu_idx = cpu_mmu_index(env);
- 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;
- } else {
- /* the page is not in the TLB : fill it */
- retaddr = GETPC();
- tlb_fill(virtaddr, 0, mmu_idx, retaddr);
- goto redo;
- }
- return physaddr;
-}
-
-uint64_t helper_st_virt_to_phys (uint64_t virtaddr)
-{
- uint64_t tlb_addr, physaddr;
- int index, mmu_idx;
- void *retaddr;
-
- mmu_idx = cpu_mmu_index(env);
- index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- redo:
- tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
- if ((virtaddr & TARGET_PAGE_MASK) ==
- (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
- physaddr = virtaddr + env->tlb_table[mmu_idx][index].addend;
- } else {
- /* the page is not in the TLB : fill it */
- retaddr = GETPC();
- tlb_fill(virtaddr, 1, mmu_idx, retaddr);
- goto redo;
- }
- return physaddr;
-}
-
-void helper_ldl_raw(uint64_t t0, uint64_t t1)
-{
- ldl_raw(t1, t0);
-}
-
-void helper_ldq_raw(uint64_t t0, uint64_t t1)
-{
- ldq_raw(t1, t0);
-}
-
-void helper_ldl_l_raw(uint64_t t0, uint64_t t1)
-{
- env->lock = t1;
- ldl_raw(t1, t0);
-}
-
-void helper_ldq_l_raw(uint64_t t0, uint64_t t1)
+uint64_t helper_ldl_phys(uint64_t p)
{
- env->lock = t1;
- ldl_raw(t1, t0);
+ return (int32_t)ldl_phys(p);
}
-void helper_ldl_kernel(uint64_t t0, uint64_t t1)
+uint64_t helper_ldq_phys(uint64_t p)
{
- ldl_kernel(t1, t0);
+ return ldq_phys(p);
}
-void helper_ldq_kernel(uint64_t t0, uint64_t t1)
+uint64_t helper_ldl_l_phys(uint64_t p)
{
- ldq_kernel(t1, t0);
+ env->lock_addr = p;
+ return env->lock_value = (int32_t)ldl_phys(p);
}
-void helper_ldl_data(uint64_t t0, uint64_t t1)
+uint64_t helper_ldq_l_phys(uint64_t p)
{
- ldl_data(t1, t0);
+ env->lock_addr = p;
+ return env->lock_value = ldl_phys(p);
}
-void helper_ldq_data(uint64_t t0, uint64_t t1)
+void helper_stl_phys(uint64_t p, uint64_t v)
{
- ldq_data(t1, t0);
+ stl_phys(p, v);
}
-void helper_stl_raw(uint64_t t0, uint64_t t1)
+void helper_stq_phys(uint64_t p, uint64_t v)
{
- stl_raw(t1, t0);
+ stq_phys(p, v);
}
-void helper_stq_raw(uint64_t t0, uint64_t t1)
+uint64_t helper_stl_c_phys(uint64_t p, uint64_t v)
{
- stq_raw(t1, t0);
-}
-
-uint64_t helper_stl_c_raw(uint64_t t0, uint64_t t1)
-{
- uint64_t ret;
+ uint64_t ret = 0;
- if (t1 == env->lock) {
- stl_raw(t1, t0);
- ret = 0;
- } else
- ret = 1;
-
- env->lock = 1;
+ if (p == env->lock_addr) {
+ int32_t old = ldl_phys(p);
+ if (old == (int32_t)env->lock_value) {
+ stl_phys(p, v);
+ ret = 1;
+ }
+ }
+ env->lock_addr = -1;
return ret;
}
-uint64_t helper_stq_c_raw(uint64_t t0, uint64_t t1)
+uint64_t helper_stq_c_phys(uint64_t p, uint64_t v)
{
- uint64_t ret;
-
- if (t1 == env->lock) {
- stq_raw(t1, t0);
- ret = 0;
- } else
- ret = 1;
+ uint64_t ret = 0;
- env->lock = 1;
+ if (p == env->lock_addr) {
+ uint64_t old = ldq_phys(p);
+ if (old == env->lock_value) {
+ stq_phys(p, v);
+ ret = 1;
+ }
+ }
+ env->lock_addr = -1;
return ret;
}
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index e52fa0a..d9b6a72 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -322,7 +322,7 @@ static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
#if defined(CONFIG_USER_ONLY)
addr = cpu_lock_st_addr;
#else
- addr = tcg_local_new();
+ addr = tcg_temp_local_new();
#endif
if (rb != 31) {
@@ -345,7 +345,7 @@ static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
lab_fail = gen_new_label();
lab_done = gen_new_label();
- tcg_gen_brcond(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
+ tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail);
val = tcg_temp_new();
if (quad) {
@@ -353,7 +353,7 @@ static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb,
} else {
tcg_gen_qemu_ld32s(val, addr, ctx->mem_idx);
}
- tcg_gen_brcond(TCG_COND_NE, val, cpu_lock_value, lab_fail);
+ tcg_gen_brcond_i64(TCG_COND_NE, val, cpu_lock_value, lab_fail);
if (quad) {
tcg_gen_qemu_st64(cpu_ir[ra], addr, ctx->mem_idx);
@@ -2576,11 +2576,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
#else
if (!ctx->pal_mode)
goto invalid_opc;
- if (ra != 31) {
- TCGv tmp = tcg_const_i32(insn & 0xFF);
- gen_helper_mfpr(cpu_ir[ra], tmp, cpu_ir[ra]);
- tcg_temp_free(tmp);
- }
+ tcg_abort();
break;
#endif
case 0x1A:
@@ -2612,27 +2608,26 @@ static ExitStatus 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) */
- tcg_gen_qemu_ld32s(cpu_ir[ra], addr, 0);
- break;
+ goto invalid_opc;
case 0x5:
/* Quadword virtual PTE fetch (hw_ldq/v) */
- tcg_gen_qemu_ld64(cpu_ir[ra], addr, 0);
+ goto invalid_opc;
break;
case 0x6:
/* Incpu_ir[ra]id */
@@ -2642,51 +2637,33 @@ static ExitStatus 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_raw(cpu_ir[ra], addr);
- break;
+ goto invalid_opc;
case 0x9:
/* Quadword virtual access (hw_ldq) */
- gen_helper_st_virt_to_phys(addr, addr);
- gen_helper_ldq_raw(cpu_ir[ra], addr);
- break;
+ goto invalid_opc;
case 0xA:
/* Longword virtual access with protection check (hw_ldl/w) */
- tcg_gen_qemu_ld32s(cpu_ir[ra], addr, 0);
+ tcg_gen_qemu_ld32s(cpu_ir[ra], addr, MMU_KERNEL_IDX);
break;
case 0xB:
/* Quadword virtual access with protection check (hw_ldq/w) */
- tcg_gen_qemu_ld64(cpu_ir[ra], addr, 0);
+ tcg_gen_qemu_ld64(cpu_ir[ra], addr, MMU_KERNEL_IDX);
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_raw(cpu_ir[ra], addr);
- gen_helper_restore_mode();
- break;
+ goto invalid_opc;
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_restore_mode();
- break;
+ goto invalid_opc;
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) */
+ tcg_gen_qemu_ld32s(cpu_ir[ra], addr, MMU_USER_IDX);
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) */
+ tcg_gen_qemu_ld64(cpu_ir[ra], addr, MMU_USER_IDX);
break;
}
tcg_temp_free(addr);
@@ -2875,18 +2852,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
#else
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]);
- else {
- TCGv tmp2 = tcg_const_i64(0);
- gen_helper_mtpr(tmp1, tmp2);
- tcg_temp_free(tmp2);
- }
- tcg_temp_free(tmp1);
- ret = EXIT_PC_STALE;
- }
+ abort();
break;
#endif
case 0x1E:
@@ -2896,21 +2862,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
#else
if (!ctx->pal_mode)
goto invalid_opc;
- if (rb == 31) {
- /* "Old" alpha */
- gen_helper_hw_rei();
- } else {
- TCGv tmp;
-
- if (ra != 31) {
- tmp = tcg_temp_new();
- tcg_gen_addi_i64(tmp, cpu_ir[rb], (((int64_t)insn << 51) >> 51));
- } else
- tmp = tcg_const_i64(((int64_t)insn << 51) >> 51);
- gen_helper_hw_ret(tmp);
- tcg_temp_free(tmp);
- }
- ret = EXIT_PC_UPDATED;
+ gen_helper_hw_ret(cpu_ir[rb]);
break;
#endif
case 0x1F:
@@ -2936,30 +2888,26 @@ static ExitStatus 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(addr, val);
break;
case 0x1:
/* Quadword physical access */
- gen_helper_stq_raw(val, addr);
+ gen_helper_stq_phys(addr, val);
break;
case 0x2:
/* Longword physical access with lock */
- gen_helper_stl_c_raw(val, val, addr);
+ gen_helper_stl_c_phys(val, addr, val);
break;
case 0x3:
/* Quadword physical access with lock */
- gen_helper_stq_c_raw(val, val, addr);
+ gen_helper_stq_c_phys(val, addr, val);
break;
case 0x4:
/* Longword virtual access */
- gen_helper_st_virt_to_phys(addr, addr);
- gen_helper_stl_raw(val, addr);
- break;
+ goto invalid_opc;
case 0x5:
/* Quadword virtual access */
- gen_helper_st_virt_to_phys(addr, addr);
- gen_helper_stq_raw(val, addr);
- break;
+ goto invalid_opc;
case 0x6:
/* Invalid */
goto invalid_opc;
@@ -2980,18 +2928,10 @@ static ExitStatus 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_raw(val, addr);
- gen_helper_restore_mode();
- break;
+ goto invalid_opc;
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_restore_mode();
- break;
+ goto invalid_opc;
case 0xE:
/* Invalid */
goto invalid_opc;
@@ -3156,12 +3096,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
ctx.env = env;
ctx.pc = pc_start;
ctx.amask = env->amask;
-#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;
-#endif
+ ctx.mem_idx = cpu_mmu_index(env);
/* ??? Every TB begins with unset rounding mode, to be initialized on
the first fp insn of the TB. Alternately we could define a proper
@@ -3329,8 +3264,11 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
env->ps = 1 << 3;
cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
| FPCR_UNFD | FPCR_INED | FPCR_DNOD));
+#else
+ env->pal_mode = 1;
#endif
env->lock_addr = -1;
+ env->fen = 1;
qemu_init_vcpu(env);
return env;
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 09/24] target-alpha: Add IPRs to be used by the emulation PALcode.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (7 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 08/24] target-alpha: Fixup translation of PALmode instructions Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 10/24] target-alpha: Tidy up arithmetic exceptions Richard Henderson
` (15 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
These aren't actually used yet, but we can at least access
them via the HW_MFPR and HW_MTPR instructions.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/cpu.h | 13 +++++++
target-alpha/translate.c | 87 ++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 98 insertions(+), 2 deletions(-)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 1c848bd..dec8b26 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -247,6 +247,7 @@ struct CPUAlphaState {
uint8_t intr_flag;
uint8_t fen;
uint8_t pal_mode;
+ uint32_t pcc_ofs;
/* These pass data from the exception logic in the translator and
helpers to the OS entry point. This is used for both system
@@ -255,6 +256,18 @@ struct CPUAlphaState {
uint64_t trap_arg1;
uint64_t trap_arg2;
+#if !defined(CONFIG_USER_ONLY)
+ /* The internal data required by our emulation of the Unix PALcode. */
+ uint64_t exc_addr;
+ uint64_t palbr;
+ uint64_t ptbr;
+ uint64_t vptptr;
+ uint64_t sysval;
+ uint64_t usp;
+ uint64_t shadow[8];
+ uint64_t scratch[24];
+#endif
+
#if TARGET_LONG_BITS > HOST_LONG_BITS
/* temporary fixed-point registers
* used to emulate 64 bits target on 32 bits hosts
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index d9b6a72..7c90ad9 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1464,6 +1464,89 @@ static void gen_rx(int ra, int set)
tcg_temp_free_i32(tmp);
}
+#ifndef CONFIG_USER_ONLY
+
+#define PR_BYTE 0x100000
+#define PR_LONG 0x200000
+
+static int cpu_pr_data(int pr)
+{
+ switch (pr) {
+ case 0: return offsetof(CPUAlphaState, ps) | PR_BYTE;
+ case 1: return offsetof(CPUAlphaState, fen) | PR_BYTE;
+ case 2: return offsetof(CPUAlphaState, pcc_ofs) | PR_LONG;
+ case 3: return offsetof(CPUAlphaState, trap_arg0);
+ case 4: return offsetof(CPUAlphaState, trap_arg1);
+ case 5: return offsetof(CPUAlphaState, trap_arg2);
+ case 6: return offsetof(CPUAlphaState, exc_addr);
+ case 7: return offsetof(CPUAlphaState, palbr);
+ case 8: return offsetof(CPUAlphaState, ptbr);
+ case 9: return offsetof(CPUAlphaState, vptptr);
+ case 10: return offsetof(CPUAlphaState, unique);
+ case 11: return offsetof(CPUAlphaState, sysval);
+ case 12: return offsetof(CPUAlphaState, usp);
+
+ case 32 ... 39:
+ return offsetof(CPUAlphaState, shadow[pr - 32]);
+ case 40 ... 63:
+ return offsetof(CPUAlphaState, scratch[pr - 40]);
+ }
+ return 0;
+}
+
+static void gen_mfpr(int ra, int regno)
+{
+ int data = cpu_pr_data(regno);
+
+ /* In our emulated PALcode, these processor registers have no
+ side effects from reading. */
+ if (ra == 31) {
+ return;
+ }
+
+ /* The basic registers are data only, and unknown registers
+ are read-zero, write-ignore. */
+ if (data == 0) {
+ tcg_gen_movi_i64(cpu_ir[ra], 0);
+ } else if (data & PR_BYTE) {
+ tcg_gen_ld8u_i64(cpu_ir[ra], cpu_env, data & ~PR_BYTE);
+ } else if (data & PR_LONG) {
+ tcg_gen_ld32s_i64(cpu_ir[ra], cpu_env, data & ~PR_LONG);
+ } else {
+ tcg_gen_ld_i64(cpu_ir[ra], cpu_env, data);
+ }
+}
+
+static void gen_mtpr(int rb, int regno)
+{
+ TCGv tmp;
+ int data;
+
+ if (rb == 31) {
+ tmp = tcg_const_i64(0);
+ } else {
+ tmp = cpu_ir[rb];
+ }
+
+ /* The basic registers are data only, and unknown registers
+ are read-zero, write-ignore. */
+ data = cpu_pr_data(regno);
+ if (data != 0) {
+ if (data & PR_BYTE) {
+ tcg_gen_st8_i64(tmp, cpu_env, data & ~PR_BYTE);
+ } else if (data & PR_LONG) {
+ tcg_gen_st32_i64(tmp, cpu_env, data & ~PR_LONG);
+ } else {
+ tcg_gen_st_i64(tmp, cpu_env, data);
+ }
+ }
+
+ if (rb == 31) {
+ tcg_temp_free(tmp);
+ }
+}
+#endif /* !USER_ONLY*/
+
static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
{
uint32_t palcode;
@@ -2576,7 +2659,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
#else
if (!ctx->pal_mode)
goto invalid_opc;
- tcg_abort();
+ gen_mfpr(ra, insn & 0xffff);
break;
#endif
case 0x1A:
@@ -2852,7 +2935,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
#else
if (!ctx->pal_mode)
goto invalid_opc;
- abort();
+ gen_mtpr(rb, insn & 0xffff);
break;
#endif
case 0x1E:
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 10/24] target-alpha: Tidy up arithmetic exceptions.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (8 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 09/24] target-alpha: Add IPRs to be used by the emulation PALcode Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 11/24] target-alpha: Merge HW_REI and HW_RET implementations Richard Henderson
` (14 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
Introduce and use arith_excp, filling in the trap_arg[01] IPRs.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/op_helper.c | 34 +++++++++++++++++++++-------------
1 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index bbf89fe..9c19c96 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -32,6 +32,15 @@ void QEMU_NORETURN helper_excp (int excp, int error)
cpu_loop_exit();
}
+static void QEMU_NORETURN arith_excp(int exc, uint64_t mask)
+{
+ env->exception_index = EXCP_ARITH;
+ env->error_code = 0;
+ env->trap_arg0 = exc;
+ env->trap_arg1 = mask;
+ cpu_loop_exit();
+}
+
uint64_t helper_load_pcc (void)
{
/* ??? This isn't a timer for which we have any rate info. */
@@ -53,7 +62,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, EXC_M_IOV);
+ arith_excp(EXC_M_IOV, 0);
}
return op1;
}
@@ -63,7 +72,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, EXC_M_IOV);
+ arith_excp(EXC_M_IOV, 0);
}
return op1;
}
@@ -73,7 +82,7 @@ uint64_t helper_subqv (uint64_t op1, uint64_t op2)
uint64_t res;
res = op1 - op2;
if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) {
- helper_excp(EXCP_ARITH, EXC_M_IOV);
+ arith_excp(EXC_M_IOV, 0);
}
return res;
}
@@ -83,7 +92,7 @@ uint64_t helper_sublv (uint64_t op1, uint64_t op2)
uint32_t res;
res = op1 - op2;
if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) {
- helper_excp(EXCP_ARITH, EXC_M_IOV);
+ arith_excp(EXC_M_IOV, 0);
}
return res;
}
@@ -93,7 +102,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, EXC_M_IOV);
+ arith_excp(EXC_M_IOV, 0);
}
return (int64_t)((int32_t)res);
}
@@ -105,7 +114,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, EXC_M_IOV);
+ arith_excp(EXC_M_IOV, 0);
}
return tl;
}
@@ -373,8 +382,6 @@ void helper_fp_exc_raise(uint32_t exc, uint32_t regno)
if (exc) {
uint32_t hw_exc = 0;
- env->trap_arg1 = 1ull << regno;
-
if (exc & float_flag_invalid) {
hw_exc |= EXC_M_INV;
}
@@ -390,7 +397,8 @@ void helper_fp_exc_raise(uint32_t exc, uint32_t regno)
if (exc & float_flag_inexact) {
hw_exc |= EXC_M_INE;
}
- helper_excp(EXCP_ARITH, hw_exc);
+
+ arith_excp(hw_exc, 1ull << regno);
}
}
@@ -420,7 +428,7 @@ uint64_t helper_ieee_input(uint64_t val)
if (env->fpcr_dnz) {
val &= 1ull << 63;
} else {
- helper_excp(EXCP_ARITH, EXC_M_UNF);
+ arith_excp(EXC_M_UNF, 0);
}
}
} else if (exp == 0x7ff) {
@@ -428,7 +436,7 @@ uint64_t helper_ieee_input(uint64_t val)
/* ??? I'm not sure these exception bit flags are correct. I do
know that the Linux kernel, at least, doesn't rely on them and
just emulates the insn to figure out what exception to use. */
- helper_excp(EXCP_ARITH, frac ? EXC_M_INV : EXC_M_FOV);
+ arith_excp(frac ? EXC_M_INV : EXC_M_FOV, 0);
}
return val;
}
@@ -445,12 +453,12 @@ uint64_t helper_ieee_input_cmp(uint64_t val)
if (env->fpcr_dnz) {
val &= 1ull << 63;
} else {
- helper_excp(EXCP_ARITH, EXC_M_UNF);
+ arith_excp(EXC_M_UNF, 0);
}
}
} else if (exp == 0x7ff && frac) {
/* NaN. */
- helper_excp(EXCP_ARITH, EXC_M_INV);
+ arith_excp(EXC_M_INV, 0);
}
return val;
}
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 11/24] target-alpha: Merge HW_REI and HW_RET implementations.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (9 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 10/24] target-alpha: Tidy up arithmetic exceptions Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 12/24] target-alpha: Implement do_interrupt for system mode Richard Henderson
` (13 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/translate.c | 16 +++++++++++++---
1 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 7c90ad9..c8ef31d 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2939,14 +2939,24 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
#endif
case 0x1E:
- /* HW_REI (PALcode) */
+ /* HW_RET (PALcode) */
#if defined (CONFIG_USER_ONLY)
goto invalid_opc;
#else
if (!ctx->pal_mode)
goto invalid_opc;
- gen_helper_hw_ret(cpu_ir[rb]);
- break;
+ if (rb == 31) {
+ /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
+ address from EXC_ADDR. This turns out to be useful for our
+ emulation PALcode, so continue to accept it. */
+ TCGv tmp = tcg_temp_new();
+ tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUState, exc_addr));
+ gen_helper_hw_ret(tmp);
+ tcg_temp_free(tmp);
+ } else {
+ gen_helper_hw_ret(cpu_ir[rb]);
+ }
+ return EXIT_PC_UPDATED;
#endif
case 0x1F:
/* HW_ST (PALcode) */
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 12/24] target-alpha: Implement do_interrupt for system mode.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (10 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 11/24] target-alpha: Merge HW_REI and HW_RET implementations Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 13/24] target-alpha: Swap shadow registers moving to/from PALmode Richard Henderson
` (12 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/helper.c | 115 ++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 105 insertions(+), 10 deletions(-)
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index c5479fd..d5923e0 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -160,7 +160,6 @@ void cpu_alpha_store_fpcr (CPUState *env, uint64_t val)
}
#if defined(CONFIG_USER_ONLY)
-
int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
int mmu_idx, int is_softmmu)
{
@@ -168,14 +167,7 @@ int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
env->trap_arg0 = address;
return 1;
}
-
-void do_interrupt (CPUState *env)
-{
- env->exception_index = -1;
-}
-
#else
-
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
{
return -1;
@@ -186,12 +178,115 @@ int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
{
return 0;
}
+#endif /* USER_ONLY */
void do_interrupt (CPUState *env)
{
- abort();
+ int i = env->exception_index;
+
+ if (qemu_loglevel_mask(CPU_LOG_INT)) {
+ static int count;
+ const char *name = "<unknown>";
+
+ switch (i) {
+ case EXCP_RESET:
+ name = "reset";
+ break;
+ case EXCP_MCHK:
+ name = "mchk";
+ break;
+ case EXCP_CLK_INTERRUPT:
+ name = "clk_interrupt";
+ break;
+ case EXCP_DEV_INTERRUPT:
+ name = "dev_interrupt";
+ break;
+ case EXCP_MMFAULT:
+ name = "mmfault";
+ break;
+ case EXCP_UNALIGN:
+ name = "unalign";
+ break;
+ case EXCP_OPCDEC:
+ name = "opcdec";
+ break;
+ case EXCP_ARITH:
+ name = "arith";
+ break;
+ case EXCP_FEN:
+ name = "fen";
+ break;
+ case EXCP_CALL_PAL:
+ name = "call_pal";
+ break;
+ case EXCP_STL_C:
+ name = "stl_c";
+ break;
+ case EXCP_STQ_C:
+ name = "stq_c";
+ break;
+ }
+ qemu_log("INT %6d: %s(%#x) pc=%016" PRIx64 " sp=%016" PRIx64 "\n",
+ ++count, name, env->error_code, env->pc, env->ir[IR_SP]);
+ }
+
+ env->exception_index = -1;
+
+#if !defined(CONFIG_USER_ONLY)
+ switch (i) {
+ case EXCP_RESET:
+ i = 0x0000;
+ break;
+ case EXCP_MCHK:
+ i = 0x0080;
+ break;
+ case EXCP_CLK_INTERRUPT:
+ i = 0x0100;
+ break;
+ case EXCP_DEV_INTERRUPT:
+ i = 0x0180;
+ break;
+ case EXCP_MMFAULT:
+ i = 0x0200;
+ break;
+ case EXCP_UNALIGN:
+ i = 0x0280;
+ break;
+ case EXCP_OPCDEC:
+ i = 0x0300;
+ break;
+ case EXCP_ARITH:
+ i = 0x0380;
+ break;
+ case EXCP_FEN:
+ i = 0x0400;
+ break;
+ case EXCP_CALL_PAL:
+ i = env->error_code;
+ /* There are 64 entry points for both privilaged and unprivlaged,
+ with bit 0x80 indicating unprivlaged. Each entry point gets
+ 64 bytes to do its job. */
+ if (i & 0x80) {
+ i = 0x2000 + (i - 0x80) * 64;
+ } else {
+ i = 0x1000 + i * 64;
+ }
+ break;
+ default:
+ cpu_abort(env, "Unhandled CPU exception");
+ }
+
+ /* Remember where the exception happened. Emulate real hardware in
+ that the low bit of the PC indicates PALmode. */
+ env->exc_addr = env->pc | env->pal_mode;
+
+ /* Continue execution at the PALcode entry point. */
+ env->pc = env->palbr + i;
+
+ /* Switch to PALmode. */
+ env->pal_mode = 1;
+#endif /* !USER_ONLY */
}
-#endif
void cpu_dump_state (CPUState *env, FILE *f, fprintf_function cpu_fprintf,
int flags)
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 13/24] target-alpha: Swap shadow registers moving to/from PALmode.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (11 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 12/24] target-alpha: Implement do_interrupt for system mode Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 14/24] target-alpha: Add various symbolic constants Richard Henderson
` (11 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/cpu.h | 1 +
target-alpha/helper.c | 37 ++++++++++++++++++++++++++++++++++++-
target-alpha/op_helper.c | 5 ++++-
3 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index dec8b26..f6549f9 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -380,6 +380,7 @@ void do_interrupt (CPUState *env);
uint64_t cpu_alpha_load_fpcr (CPUState *env);
void cpu_alpha_store_fpcr (CPUState *env, uint64_t val);
+extern void swap_shadow_regs(CPUState *env);
static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
target_ulong *cs_base, int *flags)
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index d5923e0..ce5f257 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -168,6 +168,38 @@ int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
return 1;
}
#else
+void swap_shadow_regs(CPUState *env)
+{
+ uint64_t i0, i1, i2, i3, i4, i5, i6, i7;
+
+ i0 = env->ir[8];
+ i1 = env->ir[9];
+ i2 = env->ir[10];
+ i3 = env->ir[11];
+ i4 = env->ir[12];
+ i5 = env->ir[13];
+ i6 = env->ir[14];
+ i7 = env->ir[25];
+
+ env->ir[8] = env->shadow[0];
+ env->ir[9] = env->shadow[1];
+ env->ir[10] = env->shadow[2];
+ env->ir[11] = env->shadow[3];
+ env->ir[12] = env->shadow[4];
+ env->ir[13] = env->shadow[5];
+ env->ir[14] = env->shadow[6];
+ env->ir[25] = env->shadow[7];
+
+ env->shadow[0] = i0;
+ env->shadow[1] = i1;
+ env->shadow[2] = i2;
+ env->shadow[3] = i3;
+ env->shadow[4] = i4;
+ env->shadow[5] = i5;
+ env->shadow[6] = i6;
+ env->shadow[7] = i7;
+}
+
target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
{
return -1;
@@ -284,7 +316,10 @@ void do_interrupt (CPUState *env)
env->pc = env->palbr + i;
/* Switch to PALmode. */
- env->pal_mode = 1;
+ if (!env->pal_mode) {
+ env->pal_mode = 1;
+ swap_shadow_regs(env);
+ }
#endif /* !USER_ONLY */
}
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 9c19c96..d502bca 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1166,9 +1166,12 @@ uint64_t helper_cvtqg (uint64_t a)
void helper_hw_ret (uint64_t a)
{
env->pc = a & ~3;
- env->pal_mode = a & 1;
env->intr_flag = 0;
env->lock_addr = -1;
+ if ((a & 1) == 0) {
+ env->pal_mode = 0;
+ swap_shadow_regs(env);
+ }
}
#endif
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 14/24] target-alpha: Add various symbolic constants.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (12 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 13/24] target-alpha: Swap shadow registers moving to/from PALmode Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 15/24] target-alpha: All ISA checks to use TB->FLAGS Richard Henderson
` (10 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
The EXC_M_* constants were being set for the EV6, not as set for
the Unix kernel entry point.
Use PS_USER_MODE instead of hard-coding access to the PS register.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/cpu.h | 56 +++++++++++++++++++++++++++++++++++----------
target-alpha/translate.c | 2 +-
2 files changed, 44 insertions(+), 14 deletions(-)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index f6549f9..d8f2514 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -290,11 +290,6 @@ struct CPUAlphaState {
#define cpu_gen_code cpu_alpha_gen_code
#define cpu_signal_handler cpu_alpha_signal_handler
-static inline int cpu_mmu_index (CPUState *env)
-{
- return (env->ps >> 3) & 1;
-}
-
#include "cpu-all.h"
enum {
@@ -320,14 +315,49 @@ enum {
EXCP_STQ_C,
};
-/* Arithmetic exception */
-#define EXC_M_IOV (1<<16) /* Integer Overflow */
-#define EXC_M_INE (1<<15) /* Inexact result */
-#define EXC_M_UNF (1<<14) /* Underflow */
-#define EXC_M_FOV (1<<13) /* Overflow */
-#define EXC_M_DZE (1<<12) /* Division by zero */
-#define EXC_M_INV (1<<11) /* Invalid operation */
-#define EXC_M_SWC (1<<10) /* Software completion */
+/* Hardware interrupt (entInt) constants. */
+enum {
+ INT_K_IP,
+ INT_K_CLK,
+ INT_K_MCHK,
+ INT_K_DEV,
+ INT_K_PERF,
+};
+
+/* Memory management (entMM) constants. */
+enum {
+ MM_K_TNV,
+ MM_K_ACV,
+ MM_K_FOR,
+ MM_K_FOE,
+ MM_K_FOW
+};
+
+/* Arithmetic exception (entArith) constants. */
+enum {
+ EXC_M_SWC = 1, /* Software completion */
+ EXC_M_INV = 2, /* Invalid operation */
+ EXC_M_DZE = 4, /* Division by zero */
+ EXC_M_FOV = 8, /* Overflow */
+ EXC_M_UNF = 16, /* Underflow */
+ EXC_M_INE = 32, /* Inexact result */
+ EXC_M_IOV = 64 /* Integer Overflow */
+};
+
+/* Processor status constants. */
+enum {
+ /* Low 3 bits are interrupt mask level. */
+ PS_INT_MASK = 7,
+
+ /* Bits 4 and 5 are the mmu mode. The VMS PALcode uses all 4 modes;
+ The Unix PALcode only uses bit 4. */
+ PS_USER_MODE = 8
+};
+
+static inline int cpu_mmu_index (CPUState *env)
+{
+ return (env->ps & PS_USER_MODE) != 0;
+}
enum {
IR_V0 = 0,
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index c8ef31d..2c622b9 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3354,7 +3354,7 @@ CPUAlphaState * cpu_alpha_init (const char *cpu_model)
env->amask = amask;
#if defined (CONFIG_USER_ONLY)
- env->ps = 1 << 3;
+ env->ps = PS_USER_MODE;
cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
| FPCR_UNFD | FPCR_INED | FPCR_DNOD));
#else
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 15/24] target-alpha: All ISA checks to use TB->FLAGS.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (13 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 14/24] target-alpha: Add various symbolic constants Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 16/24] target-alpha: Disable interrupts properly Richard Henderson
` (9 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
We had two different methods in use, both of which referenced ENV,
and neither of which indicated to the generic code when different
compilation modes are not compatible.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/cpu.h | 32 ++++-
target-alpha/translate.c | 396 ++++++++++++++++++++++++----------------------
2 files changed, 239 insertions(+), 189 deletions(-)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index d8f2514..d4edaf8 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -412,12 +412,40 @@ uint64_t cpu_alpha_load_fpcr (CPUState *env);
void cpu_alpha_store_fpcr (CPUState *env, uint64_t val);
extern void swap_shadow_regs(CPUState *env);
+/* Bits in TB->FLAGS that control how translation is processed. */
+enum {
+ TB_FLAGS_PAL_MODE = 1,
+ TB_FLAGS_FEN = 2,
+ TB_FLAGS_USER_MODE = 8,
+
+ TB_FLAGS_AMASK_SHIFT = 4,
+ TB_FLAGS_AMASK_BWX = AMASK_BWX << TB_FLAGS_AMASK_SHIFT,
+ TB_FLAGS_AMASK_FIX = AMASK_FIX << TB_FLAGS_AMASK_SHIFT,
+ TB_FLAGS_AMASK_CIX = AMASK_CIX << TB_FLAGS_AMASK_SHIFT,
+ TB_FLAGS_AMASK_MVI = AMASK_MVI << TB_FLAGS_AMASK_SHIFT,
+ TB_FLAGS_AMASK_TRAP = AMASK_TRAP << TB_FLAGS_AMASK_SHIFT,
+ TB_FLAGS_AMASK_PREFETCH = AMASK_PREFETCH << TB_FLAGS_AMASK_SHIFT,
+};
+
static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
- target_ulong *cs_base, int *flags)
+ target_ulong *cs_base, int *pflags)
{
+ int flags = 0;
+
*pc = env->pc;
*cs_base = 0;
- *flags = env->ps;
+
+ if (env->pal_mode) {
+ flags = TB_FLAGS_PAL_MODE;
+ } else {
+ flags = env->ps & PS_USER_MODE;
+ }
+ if (env->fen) {
+ flags |= TB_FLAGS_FEN;
+ }
+ flags |= env->amask << TB_FLAGS_AMASK_SHIFT;
+
+ *pflags = flags;
}
#if defined(CONFIG_USER_ONLY)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 2c622b9..47fb4fb 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -47,10 +47,6 @@ struct DisasContext {
CPUAlphaState *env;
uint64_t pc;
int mem_idx;
-#if !defined (CONFIG_USER_ONLY)
- int pal_mode;
-#endif
- uint32_t amask;
/* Current rounding mode for this TB. */
int tb_rm;
@@ -1649,20 +1645,22 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x0A:
/* LDBU */
- if (!(ctx->amask & AMASK_BWX))
- goto invalid_opc;
- gen_load_mem(ctx, &tcg_gen_qemu_ld8u, ra, rb, disp16, 0, 0);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_BWX) {
+ gen_load_mem(ctx, &tcg_gen_qemu_ld8u, ra, rb, disp16, 0, 0);
+ break;
+ }
+ goto invalid_opc;
case 0x0B:
/* LDQ_U */
gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 1);
break;
case 0x0C:
/* LDWU */
- if (!(ctx->amask & AMASK_BWX))
- goto invalid_opc;
- gen_load_mem(ctx, &tcg_gen_qemu_ld16u, ra, rb, disp16, 0, 0);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_BWX) {
+ gen_load_mem(ctx, &tcg_gen_qemu_ld16u, ra, rb, disp16, 0, 0);
+ break;
+ }
+ goto invalid_opc;
case 0x0D:
/* STW */
gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0);
@@ -2066,20 +2064,12 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
case 0x61:
/* AMASK */
if (likely(rc != 31)) {
- if (islit)
- tcg_gen_movi_i64(cpu_ir[rc], lit);
- else
- tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[rb]);
- switch (ctx->env->implver) {
- case IMPLVER_2106x:
- /* EV4, EV45, LCA, LCA45 & EV5 */
- break;
- case IMPLVER_21164:
- case IMPLVER_21264:
- case IMPLVER_21364:
- tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[rc],
- ~(uint64_t)ctx->amask);
- break;
+ uint64_t amask = ctx->tb->flags >> TB_FLAGS_AMASK_SHIFT;
+
+ if (islit) {
+ tcg_gen_movi_i64(cpu_ir[rc], lit & ~amask);
+ } else {
+ tcg_gen_andi_i64(cpu_ir[rc], cpu_ir[rb], ~amask);
}
}
break;
@@ -2293,8 +2283,9 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
switch (fpfn) { /* fn11 & 0x3F */
case 0x04:
/* ITOFS */
- if (!(ctx->amask & AMASK_FIX))
+ if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
goto invalid_opc;
+ }
if (likely(rc != 31)) {
if (ra != 31) {
TCGv_i32 tmp = tcg_temp_new_i32();
@@ -2307,20 +2298,23 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x0A:
/* SQRTF */
- if (!(ctx->amask & AMASK_FIX))
- goto invalid_opc;
- gen_fsqrtf(rb, rc);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
+ gen_fsqrtf(rb, rc);
+ break;
+ }
+ goto invalid_opc;
case 0x0B:
/* SQRTS */
- if (!(ctx->amask & AMASK_FIX))
- goto invalid_opc;
- gen_fsqrts(ctx, rb, rc, fn11);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
+ gen_fsqrts(ctx, rb, rc, fn11);
+ break;
+ }
+ goto invalid_opc;
case 0x14:
/* ITOFF */
- if (!(ctx->amask & AMASK_FIX))
+ if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
goto invalid_opc;
+ }
if (likely(rc != 31)) {
if (ra != 31) {
TCGv_i32 tmp = tcg_temp_new_i32();
@@ -2333,8 +2327,9 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x24:
/* ITOFT */
- if (!(ctx->amask & AMASK_FIX))
+ if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
goto invalid_opc;
+ }
if (likely(rc != 31)) {
if (ra != 31)
tcg_gen_mov_i64(cpu_fir[rc], cpu_ir[ra]);
@@ -2344,16 +2339,18 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x2A:
/* SQRTG */
- if (!(ctx->amask & AMASK_FIX))
- goto invalid_opc;
- gen_fsqrtg(rb, rc);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
+ gen_fsqrtg(rb, rc);
+ break;
+ }
+ goto invalid_opc;
case 0x02B:
/* SQRTT */
- if (!(ctx->amask & AMASK_FIX))
- goto invalid_opc;
- gen_fsqrtt(ctx, rb, rc, fn11);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_FIX) {
+ gen_fsqrtt(ctx, rb, rc, fn11);
+ break;
+ }
+ goto invalid_opc;
default:
goto invalid_opc;
}
@@ -2654,14 +2651,13 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x19:
/* HW_MFPR (PALcode) */
-#if defined (CONFIG_USER_ONLY)
- goto invalid_opc;
-#else
- if (!ctx->pal_mode)
- goto invalid_opc;
- gen_mfpr(ra, insn & 0xffff);
- break;
+#ifndef CONFIG_USER_ONLY
+ if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
+ gen_mfpr(ra, insn & 0xffff);
+ break;
+ }
#endif
+ goto invalid_opc;
case 0x1A:
/* JMP, JSR, RET, JSR_COROUTINE. These only differ by the branch
prediction stack action, which of course we don't implement. */
@@ -2677,13 +2673,15 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x1B:
/* HW_LD (PALcode) */
-#if defined (CONFIG_USER_ONLY)
- goto invalid_opc;
-#else
- if (!ctx->pal_mode)
- goto invalid_opc;
- if (ra != 31) {
- TCGv addr = tcg_temp_new();
+#ifndef CONFIG_USER_ONLY
+ if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
+ TCGv addr;
+
+ if (ra == 31) {
+ break;
+ }
+
+ addr = tcg_temp_new();
if (rb != 31)
tcg_gen_addi_i64(addr, cpu_ir[rb], disp12);
else
@@ -2750,15 +2748,17 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
}
tcg_temp_free(addr);
+ break;
}
- break;
#endif
+ goto invalid_opc;
case 0x1C:
switch (fn7) {
case 0x00:
/* SEXTB */
- if (!(ctx->amask & AMASK_BWX))
+ if ((ctx->tb->flags & TB_FLAGS_AMASK_BWX) == 0) {
goto invalid_opc;
+ }
if (likely(rc != 31)) {
if (islit)
tcg_gen_movi_i64(cpu_ir[rc], (int64_t)((int8_t)lit));
@@ -2768,138 +2768,164 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x01:
/* SEXTW */
- if (!(ctx->amask & AMASK_BWX))
- goto invalid_opc;
- if (likely(rc != 31)) {
- if (islit)
- tcg_gen_movi_i64(cpu_ir[rc], (int64_t)((int16_t)lit));
- else
- tcg_gen_ext16s_i64(cpu_ir[rc], cpu_ir[rb]);
+ if (ctx->tb->flags & TB_FLAGS_AMASK_BWX) {
+ if (likely(rc != 31)) {
+ if (islit) {
+ tcg_gen_movi_i64(cpu_ir[rc], (int64_t)((int16_t)lit));
+ } else {
+ tcg_gen_ext16s_i64(cpu_ir[rc], cpu_ir[rb]);
+ }
+ }
+ break;
}
- break;
+ goto invalid_opc;
case 0x30:
/* CTPOP */
- if (!(ctx->amask & AMASK_CIX))
- goto invalid_opc;
- if (likely(rc != 31)) {
- if (islit)
- tcg_gen_movi_i64(cpu_ir[rc], ctpop64(lit));
- else
- gen_helper_ctpop(cpu_ir[rc], cpu_ir[rb]);
+ if (ctx->tb->flags & TB_FLAGS_AMASK_CIX) {
+ if (likely(rc != 31)) {
+ if (islit) {
+ tcg_gen_movi_i64(cpu_ir[rc], ctpop64(lit));
+ } else {
+ gen_helper_ctpop(cpu_ir[rc], cpu_ir[rb]);
+ }
+ }
+ break;
}
- break;
+ goto invalid_opc;
case 0x31:
/* PERR */
- if (!(ctx->amask & AMASK_MVI))
- goto invalid_opc;
- gen_perr(ra, rb, rc, islit, lit);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
+ gen_perr(ra, rb, rc, islit, lit);
+ break;
+ }
+ goto invalid_opc;
case 0x32:
/* CTLZ */
- if (!(ctx->amask & AMASK_CIX))
- goto invalid_opc;
- if (likely(rc != 31)) {
- if (islit)
- tcg_gen_movi_i64(cpu_ir[rc], clz64(lit));
- else
- gen_helper_ctlz(cpu_ir[rc], cpu_ir[rb]);
+ if (ctx->tb->flags & TB_FLAGS_AMASK_CIX) {
+ if (likely(rc != 31)) {
+ if (islit) {
+ tcg_gen_movi_i64(cpu_ir[rc], clz64(lit));
+ } else {
+ gen_helper_ctlz(cpu_ir[rc], cpu_ir[rb]);
+ }
+ }
+ break;
}
- break;
+ goto invalid_opc;
case 0x33:
/* CTTZ */
- if (!(ctx->amask & AMASK_CIX))
- goto invalid_opc;
- if (likely(rc != 31)) {
- if (islit)
- tcg_gen_movi_i64(cpu_ir[rc], ctz64(lit));
- else
- gen_helper_cttz(cpu_ir[rc], cpu_ir[rb]);
+ if (ctx->tb->flags & TB_FLAGS_AMASK_CIX) {
+ if (likely(rc != 31)) {
+ if (islit) {
+ tcg_gen_movi_i64(cpu_ir[rc], ctz64(lit));
+ } else {
+ gen_helper_cttz(cpu_ir[rc], cpu_ir[rb]);
+ }
+ }
+ break;
}
- break;
+ goto invalid_opc;
case 0x34:
/* UNPKBW */
- if (!(ctx->amask & AMASK_MVI))
- goto invalid_opc;
- if (real_islit || ra != 31)
- goto invalid_opc;
- gen_unpkbw (rb, rc);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
+ if (real_islit || ra != 31) {
+ goto invalid_opc;
+ }
+ gen_unpkbw(rb, rc);
+ break;
+ }
+ goto invalid_opc;
case 0x35:
/* UNPKBL */
- if (!(ctx->amask & AMASK_MVI))
- goto invalid_opc;
- if (real_islit || ra != 31)
- goto invalid_opc;
- gen_unpkbl (rb, rc);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
+ if (real_islit || ra != 31) {
+ goto invalid_opc;
+ }
+ gen_unpkbl(rb, rc);
+ break;
+ }
+ goto invalid_opc;
case 0x36:
/* PKWB */
- if (!(ctx->amask & AMASK_MVI))
- goto invalid_opc;
- if (real_islit || ra != 31)
- goto invalid_opc;
- gen_pkwb (rb, rc);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
+ if (real_islit || ra != 31) {
+ goto invalid_opc;
+ }
+ gen_pkwb(rb, rc);
+ break;
+ }
+ goto invalid_opc;
case 0x37:
/* PKLB */
- if (!(ctx->amask & AMASK_MVI))
- goto invalid_opc;
- if (real_islit || ra != 31)
- goto invalid_opc;
- gen_pklb (rb, rc);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
+ if (real_islit || ra != 31) {
+ goto invalid_opc;
+ }
+ gen_pklb(rb, rc);
+ break;
+ }
+ goto invalid_opc;
case 0x38:
/* MINSB8 */
- if (!(ctx->amask & AMASK_MVI))
- goto invalid_opc;
- gen_minsb8 (ra, rb, rc, islit, lit);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
+ gen_minsb8(ra, rb, rc, islit, lit);
+ break;
+ }
+ goto invalid_opc;
case 0x39:
/* MINSW4 */
- if (!(ctx->amask & AMASK_MVI))
- goto invalid_opc;
- gen_minsw4 (ra, rb, rc, islit, lit);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
+ gen_minsw4(ra, rb, rc, islit, lit);
+ break;
+ }
+ goto invalid_opc;
case 0x3A:
/* MINUB8 */
- if (!(ctx->amask & AMASK_MVI))
- goto invalid_opc;
- gen_minub8 (ra, rb, rc, islit, lit);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
+ gen_minub8(ra, rb, rc, islit, lit);
+ break;
+ }
+ goto invalid_opc;
case 0x3B:
/* MINUW4 */
- if (!(ctx->amask & AMASK_MVI))
- goto invalid_opc;
- gen_minuw4 (ra, rb, rc, islit, lit);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
+ gen_minuw4(ra, rb, rc, islit, lit);
+ break;
+ }
+ goto invalid_opc;
case 0x3C:
/* MAXUB8 */
- if (!(ctx->amask & AMASK_MVI))
- goto invalid_opc;
- gen_maxub8 (ra, rb, rc, islit, lit);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
+ gen_maxub8(ra, rb, rc, islit, lit);
+ break;
+ }
+ goto invalid_opc;
case 0x3D:
/* MAXUW4 */
- if (!(ctx->amask & AMASK_MVI))
- goto invalid_opc;
- gen_maxuw4 (ra, rb, rc, islit, lit);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
+ gen_maxuw4(ra, rb, rc, islit, lit);
+ break;
+ }
+ goto invalid_opc;
case 0x3E:
/* MAXSB8 */
- if (!(ctx->amask & AMASK_MVI))
- goto invalid_opc;
- gen_maxsb8 (ra, rb, rc, islit, lit);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
+ gen_maxsb8(ra, rb, rc, islit, lit);
+ break;
+ }
+ goto invalid_opc;
case 0x3F:
/* MAXSW4 */
- if (!(ctx->amask & AMASK_MVI))
- goto invalid_opc;
- gen_maxsw4 (ra, rb, rc, islit, lit);
- break;
+ if (ctx->tb->flags & TB_FLAGS_AMASK_MVI) {
+ gen_maxsw4(ra, rb, rc, islit, lit);
+ break;
+ }
+ goto invalid_opc;
case 0x70:
/* FTOIT */
- if (!(ctx->amask & AMASK_FIX))
+ if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
goto invalid_opc;
+ }
if (likely(rc != 31)) {
if (ra != 31)
tcg_gen_mov_i64(cpu_ir[rc], cpu_fir[ra]);
@@ -2909,8 +2935,9 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x78:
/* FTOIS */
- if (!(ctx->amask & AMASK_FIX))
+ if ((ctx->tb->flags & TB_FLAGS_AMASK_FIX) == 0) {
goto invalid_opc;
+ }
if (rc != 31) {
TCGv_i32 tmp1 = tcg_temp_new_i32();
if (ra != 31)
@@ -2930,42 +2957,36 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
break;
case 0x1D:
/* HW_MTPR (PALcode) */
-#if defined (CONFIG_USER_ONLY)
- goto invalid_opc;
-#else
- if (!ctx->pal_mode)
- goto invalid_opc;
- gen_mtpr(rb, insn & 0xffff);
- break;
+#ifndef CONFIG_USER_ONLY
+ if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
+ gen_mtpr(rb, insn & 0xffff);
+ break;
+ }
#endif
+ goto invalid_opc;
case 0x1E:
/* HW_RET (PALcode) */
-#if defined (CONFIG_USER_ONLY)
- goto invalid_opc;
-#else
- if (!ctx->pal_mode)
- goto invalid_opc;
- if (rb == 31) {
- /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
- address from EXC_ADDR. This turns out to be useful for our
- emulation PALcode, so continue to accept it. */
- TCGv tmp = tcg_temp_new();
- tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUState, exc_addr));
- gen_helper_hw_ret(tmp);
- tcg_temp_free(tmp);
- } else {
- gen_helper_hw_ret(cpu_ir[rb]);
+#ifndef CONFIG_USER_ONLY
+ if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
+ if (rb == 31) {
+ /* Pre-EV6 CPUs interpreted this as HW_REI, loading the return
+ address from EXC_ADDR. This turns out to be useful for our
+ emulation PALcode, so continue to accept it. */
+ TCGv tmp = tcg_temp_new();
+ tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUState, exc_addr));
+ gen_helper_hw_ret(tmp);
+ tcg_temp_free(tmp);
+ } else {
+ gen_helper_hw_ret(cpu_ir[rb]);
+ }
+ return EXIT_PC_UPDATED;
}
- return EXIT_PC_UPDATED;
#endif
+ goto invalid_opc;
case 0x1F:
/* HW_ST (PALcode) */
-#if defined (CONFIG_USER_ONLY)
- goto invalid_opc;
-#else
- if (!ctx->pal_mode)
- goto invalid_opc;
- else {
+#ifndef CONFIG_USER_ONLY
+ if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
TCGv addr, val;
addr = tcg_temp_new();
if (rb != 31)
@@ -3035,9 +3056,10 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
if (ra == 31)
tcg_temp_free(val);
tcg_temp_free(addr);
+ break;
}
- break;
#endif
+ goto invalid_opc;
case 0x20:
/* LDF */
gen_load_mem(ctx, &gen_qemu_ldf, ra, rb, disp16, 1, 0);
@@ -3188,8 +3210,8 @@ static inline void gen_intermediate_code_internal(CPUState *env,
ctx.tb = tb;
ctx.env = env;
ctx.pc = pc_start;
- ctx.amask = env->amask;
- ctx.mem_idx = cpu_mmu_index(env);
+ ctx.mem_idx = (tb->flags & TB_FLAGS_USER_MODE
+ ? MMU_USER_IDX : MMU_KERNEL_IDX);
/* ??? Every TB begins with unset rounding mode, to be initialized on
the first fp insn of the TB. Alternately we could define a proper
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 16/24] target-alpha: Disable interrupts properly.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (14 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 15/24] target-alpha: All ISA checks to use TB->FLAGS Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 17/24] target-alpha: Implement more CALL_PAL values inline Richard Henderson
` (8 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
Interrupts are disabled in PALmode, and when the PS IL is
high enough. We don't actually get the interrupt levels
correct yet; settle for interrupts enabled only at IL0.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
cpu-exec.c | 16 +++++++++++++---
target-alpha/exec.h | 7 ++++++-
2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/cpu-exec.c b/cpu-exec.c
index 5d6c9a8..68c3d1d 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -529,9 +529,19 @@ int cpu_exec(CPUState *env1)
next_tb = 0;
}
#elif defined(TARGET_ALPHA)
- if (interrupt_request & CPU_INTERRUPT_HARD) {
- do_interrupt(env);
- next_tb = 0;
+ if (env->pal_mode == 0 && (env->ps & PS_INT_MASK) == 0) {
+ int idx = -1;
+ if (interrupt_request & CPU_INTERRUPT_HARD) {
+ idx = EXCP_DEV_INTERRUPT;
+ }
+ if (interrupt_request & CPU_INTERRUPT_TIMER) {
+ idx = EXCP_CLK_INTERRUPT;
+ }
+ if (idx >= 0) {
+ env->exception_index = idx;
+ do_interrupt(env);
+ next_tb = 0;
+ }
}
#elif defined(TARGET_CRIS)
if (interrupt_request & CPU_INTERRUPT_HARD
diff --git a/target-alpha/exec.h b/target-alpha/exec.h
index 6ae96d1..a504758 100644
--- a/target-alpha/exec.h
+++ b/target-alpha/exec.h
@@ -39,7 +39,12 @@ register struct CPUAlphaState *env asm(AREG0);
static inline int cpu_has_work(CPUState *env)
{
- return (env->interrupt_request & CPU_INTERRUPT_HARD);
+ /* ??? There's a model-specific mapping between external hardware
+ interrupt numbers and the Unix PALcode interrupt levels. */
+ int req = CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER;
+ return ((env->interrupt_request & req)
+ && env->pal_mode == 0
+ && (env->ps & PS_INT_MASK) == 0);
}
static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 17/24] target-alpha: Implement more CALL_PAL values inline.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (15 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 16/24] target-alpha: Disable interrupts properly Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 18/24] target-alpha: Add custom PALcode image for SX164 emulation Richard Henderson
` (7 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
In particular, SWPIPL is used quite a lot by the Linux kernel.
Doing this inline makes it significantly easier to step through
without the debugger getting confused by the mode switch.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/translate.c | 141 ++++++++++++++++++++++++++++++++++++----------
1 files changed, 110 insertions(+), 31 deletions(-)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 47fb4fb..c2db1ae 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -85,8 +85,10 @@ static TCGv cpu_pc;
static TCGv cpu_lock_addr;
static TCGv cpu_lock_st_addr;
static TCGv cpu_lock_value;
-#ifdef CONFIG_USER_ONLY
-static TCGv cpu_uniq;
+static TCGv cpu_unique;
+#ifndef CONFIG_USER_ONLY
+static TCGv cpu_sysval;
+static TCGv cpu_usp;
#endif
/* register names */
@@ -131,9 +133,13 @@ static void alpha_translate_init(void)
offsetof(CPUState, lock_value),
"lock_value");
-#ifdef CONFIG_USER_ONLY
- cpu_uniq = tcg_global_mem_new_i64(TCG_AREG0,
- offsetof(CPUState, unique), "uniq");
+ cpu_unique = tcg_global_mem_new_i64(TCG_AREG0,
+ offsetof(CPUState, unique), "unique");
+#ifndef CONFIG_USER_ONLY
+ cpu_sysval = tcg_global_mem_new_i64(TCG_AREG0,
+ offsetof(CPUState, sysval), "sysval");
+ cpu_usp = tcg_global_mem_new_i64(TCG_AREG0,
+ offsetof(CPUState, usp), "usp");
#endif
/* register helpers */
@@ -1460,6 +1466,104 @@ static void gen_rx(int ra, int set)
tcg_temp_free_i32(tmp);
}
+static ExitStatus gen_call_pal(DisasContext *ctx, int palcode)
+{
+ /* We're emulating OSF/1 PALcode. Many of these are trivial access
+ to internal cpu registers. */
+
+ /* Unprivileged PAL call */
+ if (palcode >= 0x80 && palcode < 0xC0) {
+ switch (palcode) {
+ case 0x86:
+ /* IMB */
+ /* No-op inside QEMU. */
+ break;
+ case 0x9E:
+ /* RDUNIQUE */
+ tcg_gen_mov_i64(cpu_ir[IR_V0], cpu_unique);
+ break;
+ case 0x9F:
+ /* WRUNIQUE */
+ tcg_gen_mov_i64(cpu_unique, cpu_ir[IR_A0]);
+ break;
+ default:
+ return gen_excp(ctx, EXCP_CALL_PAL, palcode & 0xbf);
+ }
+ return NO_EXIT;
+ }
+
+#ifndef CONFIG_USER_ONLY
+ /* Privileged PAL code */
+ if (palcode < 0x40 && (ctx->tb->flags & TB_FLAGS_USER_MODE) == 0) {
+ switch (palcode) {
+ case 0x01:
+ /* CFLUSH */
+ /* No-op inside QEMU. */
+ break;
+ case 0x02:
+ /* DRAINA */
+ /* No-op inside QEMU. */
+ break;
+ case 0x2D:
+ /* WRVPTPTR */
+ tcg_gen_st_i64(cpu_ir[IR_A0], cpu_env, offsetof(CPUState, vptptr));
+ break;
+ case 0x31:
+ /* WRVAL */
+ tcg_gen_mov_i64(cpu_sysval, cpu_ir[IR_A0]);
+ break;
+ case 0x32:
+ /* RDVAL */
+ tcg_gen_mov_i64(cpu_ir[IR_V0], cpu_sysval);
+ break;
+
+ case 0x35: {
+ /* SWPIPL */
+ TCGv tmp;
+
+ /* Note that we already know we're in kernel mode, so we know
+ that PS only contains the 3 IPL bits. */
+ tcg_gen_ld8u_i64(cpu_ir[IR_V0], cpu_env, offsetof(CPUState, ps));
+
+ /* But make sure and store only the 3 IPL bits from the user. */
+ tmp = tcg_temp_new();
+ tcg_gen_andi_i64(tmp, cpu_ir[IR_A0], PS_INT_MASK);
+ tcg_gen_st8_i64(tmp, cpu_env, offsetof(CPUState, ps));
+ tcg_temp_free(tmp);
+ break;
+ }
+
+ case 0x36:
+ /* RDPS */
+ tcg_gen_ld8u_i64(cpu_ir[IR_V0], cpu_env,
+ offsetof(CPUAlphaState, ps));
+ break;
+ case 0x38:
+ /* WRUSP */
+ tcg_gen_mov_i64(cpu_usp, cpu_ir[IR_A0]);
+ break;
+ case 0x3A:
+ /* RDUSP */
+ tcg_gen_mov_i64(cpu_ir[IR_V0], cpu_usp);
+ break;
+
+ /* TODO:
+ 0x3C Whami
+ These merely need more cooperation in designation of
+ internal processor registers w/ palcode. These are
+ currently stored in palcode scratch registers and
+ should be treated like UNIQUE. */
+
+ default:
+ return gen_excp(ctx, EXCP_CALL_PAL, palcode & 0x3f);
+ }
+ return NO_EXIT;
+ }
+#endif
+
+ return gen_invalid(ctx);
+}
+
#ifndef CONFIG_USER_ONLY
#define PR_BYTE 0x100000
@@ -1578,32 +1682,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
switch (opc) {
case 0x00:
/* CALL_PAL */
-#ifdef CONFIG_USER_ONLY
- if (palcode == 0x9E) {
- /* RDUNIQUE */
- tcg_gen_mov_i64(cpu_ir[IR_V0], cpu_uniq);
- break;
- } else if (palcode == 0x9F) {
- /* WRUNIQUE */
- tcg_gen_mov_i64(cpu_uniq, cpu_ir[IR_A0]);
- break;
- }
-#endif
- if (palcode >= 0x80 && palcode < 0xC0) {
- /* Unprivileged PAL call */
- ret = gen_excp(ctx, EXCP_CALL_PAL, palcode & 0xBF);
- break;
- }
-#ifndef CONFIG_USER_ONLY
- if (palcode < 0x40) {
- /* Privileged PAL code */
- if (ctx->mem_idx & 1)
- goto invalid_opc;
- ret = gen_excp(ctx, EXCP_CALL_PAL, palcode & 0x3F);
- }
-#endif
- /* Invalid PAL call */
- goto invalid_opc;
+ return gen_call_pal(ctx, palcode);
case 0x01:
/* OPC01 */
goto invalid_opc;
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 18/24] target-alpha: Add custom PALcode image for SX164 emulation.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (16 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 17/24] target-alpha: Implement more CALL_PAL values inline Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 19/24] target-alpha: Implement cpu_alpha_handle_mmu_fault for system mode Richard Henderson
` (6 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
.gitmodules | 3 +++
Makefile | 3 ++-
configure | 2 +-
pc-bios/palcode-sx164 | Bin 0 -> 107621 bytes
roms/qemu-palcode | 1 +
5 files changed, 7 insertions(+), 2 deletions(-)
create mode 100644 pc-bios/palcode-sx164
create mode 160000 roms/qemu-palcode
diff --git a/.gitmodules b/.gitmodules
index 44fdd1a..a9a30d4 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -7,3 +7,6 @@
[submodule "roms/SLOF"]
path = roms/SLOF
url = git://git.qemu.org/SLOF.git
+[submodule "roms/qemu-palcode"]
+ path = roms/qemu-palcode
+ url = git://repo.or.cz/qemu-palcode.git
diff --git a/Makefile b/Makefile
index dc39efd..d8a802e 100644
--- a/Makefile
+++ b/Makefile
@@ -187,7 +187,8 @@ pxe-rtl8139.bin pxe-virtio.bin \
bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
multiboot.bin linuxboot.bin \
s390-zipl.rom \
-spapr-rtas.bin slof.bin
+spapr-rtas.bin slof.bin \
+palcode-sx164
else
BLOBS=
endif
diff --git a/configure b/configure
index da2da04..4a93972 100755
--- a/configure
+++ b/configure
@@ -3454,7 +3454,7 @@ FILES="Makefile tests/Makefile"
FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
-for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-*; do
+for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-* $source_path/pc-bios/palcode-*; do
FILES="$FILES pc-bios/`basename $bios_file`"
done
mkdir -p $DIRS
diff --git a/pc-bios/palcode-sx164 b/pc-bios/palcode-sx164
new file mode 100644
index 0000000000000000000000000000000000000000..71626214e61173e7cdfdb18dacbfe16f8eba7b3b
GIT binary patch
literal 107621
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
literal 0
HcmV?d00001
diff --git a/roms/qemu-palcode b/roms/qemu-palcode
new file mode 160000
index 0000000..2eec0e4
--- /dev/null
+++ b/roms/qemu-palcode
@@ -0,0 +1 @@
+Subproject commit 2eec0e49ac23330ed8a866a4b3f268be4af09e34
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 19/24] target-alpha: Implement cpu_alpha_handle_mmu_fault for system mode.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (17 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 18/24] target-alpha: Add custom PALcode image for SX164 emulation Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 20/24] target-alpha: Trap for unassigned and unaligned addresses Richard Henderson
` (5 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
Reads the page table how PALcode would, except that the virtual
page table base register is not used.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/cpu.h | 12 +++++
target-alpha/helper.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 137 insertions(+), 4 deletions(-)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index d4edaf8..d133cc6 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -315,6 +315,18 @@ enum {
EXCP_STQ_C,
};
+enum {
+ PTE_VALID = 0x0001,
+ PTE_FOR = 0x0002, /* used for page protection (fault on read) */
+ PTE_FOW = 0x0004, /* used for page protection (fault on write) */
+ PTE_FOE = 0x0008, /* used for page protection (fault on exec) */
+ PTE_ASM = 0x0010,
+ PTE_KRE = 0x0100,
+ PTE_URE = 0x0200,
+ PTE_KWE = 0x1000,
+ PTE_UWE = 0x2000
+};
+
/* Hardware interrupt (entInt) constants. */
enum {
INT_K_IP,
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index ce5f257..aaf5108 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -200,14 +200,135 @@ void swap_shadow_regs(CPUState *env)
env->shadow[7] = i7;
}
-target_phys_addr_t cpu_get_phys_page_debug (CPUState *env, target_ulong addr)
+/* Returns the OSF/1 entMM failure indication, or -1 on success. */
+static int get_physical_address(CPUState *env, target_ulong addr,
+ int prot_need, int mmu_idx,
+ target_ulong *pphys, int *pprot)
{
- return -1;
+ target_long saddr = addr;
+ target_ulong phys = 0;
+ target_ulong L1pte, L2pte, L3pte;
+ target_ulong pt, index;
+ int prot = 0;
+ int ret = MM_K_ACV;
+
+ /* Ensure that the virtual address is properly sign-extended from
+ the last implemented virtual address bit. */
+ if (saddr >> TARGET_VIRT_ADDR_SPACE_BITS != saddr >> 63) {
+ goto exit;
+ }
+
+ /* Translate the superpage. */
+ /* ??? When we do more than emulate Unix PALcode, we'll need to
+ determine which superpage is actually active. */
+ if (saddr < 0 && (saddr >> (TARGET_VIRT_ADDR_SPACE_BITS - 2) & 3) == 2) {
+ /* User-space cannot access kseg addresses. */
+ if (mmu_idx != MMU_KERNEL_IDX) {
+ goto exit;
+ }
+
+ phys = saddr & ((1ull << 40) - 1);
+ prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ ret = -1;
+ goto exit;
+ }
+
+ /* Interpret the page table exactly like PALcode does. */
+
+ pt = env->ptbr;
+
+ /* L1 page table read. */
+ index = (addr >> (TARGET_PAGE_BITS + 20)) & 0x3ff;
+ L1pte = ldq_phys(pt + index*8);
+
+ if (unlikely((L1pte & PTE_VALID) == 0)) {
+ ret = MM_K_TNV;
+ goto exit;
+ }
+ if (unlikely((L1pte & PTE_KRE) == 0)) {
+ goto exit;
+ }
+ pt = L1pte >> 32 << TARGET_PAGE_BITS;
+
+ /* L2 page table read. */
+ index = (addr >> (TARGET_PAGE_BITS + 10)) & 0x3ff;
+ L2pte = ldq_phys(pt + index*8);
+
+ if (unlikely((L2pte & PTE_VALID) == 0)) {
+ ret = MM_K_TNV;
+ goto exit;
+ }
+ if (unlikely((L2pte & PTE_KRE) == 0)) {
+ goto exit;
+ }
+ pt = L2pte >> 32 << TARGET_PAGE_BITS;
+
+ /* L3 page table read. */
+ index = (addr >> TARGET_PAGE_BITS) & 0x3ff;
+ L3pte = ldq_phys(pt + index*8);
+
+ phys = L3pte >> 32 << TARGET_PAGE_BITS;
+ if (unlikely((L3pte & PTE_VALID) == 0)) {
+ ret = MM_K_TNV;
+ goto exit;
+ }
+
+#if PAGE_READ != 1 || PAGE_WRITE != 2 || PAGE_EXEC != 4
+# error page bits out of date
+#endif
+
+ /* Check access violations. */
+ if (L3pte & (PTE_KRE << mmu_idx)) {
+ prot |= PAGE_READ | PAGE_EXEC;
+ }
+ if (L3pte & (PTE_KWE << mmu_idx)) {
+ prot |= PAGE_WRITE;
+ }
+ if (unlikely((prot & prot_need) == 0 && prot_need)) {
+ goto exit;
+ }
+
+ /* Check fault-on-operation violations. */
+ prot &= ~(L3pte >> 1);
+ ret = -1;
+ if (unlikely((prot & prot_need) == 0)) {
+ ret = (prot_need & PAGE_EXEC ? MM_K_FOE :
+ prot_need & PAGE_WRITE ? MM_K_FOW :
+ prot_need & PAGE_READ ? MM_K_FOR : -1);
+ }
+
+ exit:
+ *pphys = phys;
+ *pprot = prot;
+ return ret;
}
-int cpu_alpha_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
- int mmu_idx, int is_softmmu)
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+{
+ target_ulong phys;
+ int prot, fail;
+
+ fail = get_physical_address(env, addr, 0, 0, &phys, &prot);
+ return (fail >= 0 ? -1 : phys);
+}
+
+int cpu_alpha_handle_mmu_fault(CPUState *env, target_ulong addr, int rw,
+ int mmu_idx, int is_softmmu)
{
+ target_ulong phys;
+ int prot, fail;
+
+ fail = get_physical_address(env, addr, 1 << rw, mmu_idx, &phys, &prot);
+ if (unlikely(fail >= 0)) {
+ env->exception_index = EXCP_MMFAULT;
+ env->trap_arg0 = addr;
+ env->trap_arg1 = fail;
+ env->trap_arg2 = (rw == 2 ? -1 : rw);
+ return 1;
+ }
+
+ tlb_set_page(env, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK,
+ prot, mmu_idx, TARGET_PAGE_SIZE);
return 0;
}
#endif /* USER_ONLY */
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 20/24] target-alpha: Trap for unassigned and unaligned addresses.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (18 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 19/24] target-alpha: Implement cpu_alpha_handle_mmu_fault for system mode Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 21/24] target-alpha: Include the PCC_OFS in the RPCC return value Richard Henderson
` (4 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
exec-all.h | 2 +-
exec.c | 12 ++++++------
target-alpha/cpu.h | 6 +++++-
target-alpha/op_helper.c | 39 ++++++++++++++++++++++++++++++++++++++-
4 files changed, 50 insertions(+), 9 deletions(-)
diff --git a/exec-all.h b/exec-all.h
index 496c001..e525662 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -323,7 +323,7 @@ static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong add
}
pd = env1->tlb_table[mmu_idx][page_index].addr_code & ~TARGET_PAGE_MASK;
if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
-#if defined(TARGET_SPARC) || defined(TARGET_MIPS)
+#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SPARC)
do_unassigned_access(addr, 0, 1, 0, 4);
#else
cpu_abort(env1, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
diff --git a/exec.c b/exec.c
index 994d51b..c3c2809 100644
--- a/exec.c
+++ b/exec.c
@@ -3095,7 +3095,7 @@ uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
#endif
-#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
+#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
do_unassigned_access(addr, 0, 0, 0, 1);
#endif
return 0;
@@ -3106,7 +3106,7 @@ uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr)
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
#endif
-#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
+#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
do_unassigned_access(addr, 0, 0, 0, 2);
#endif
return 0;
@@ -3117,7 +3117,7 @@ uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr)
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
#endif
-#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
+#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
do_unassigned_access(addr, 0, 0, 0, 4);
#endif
return 0;
@@ -3128,7 +3128,7 @@ void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
#endif
-#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
+#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
do_unassigned_access(addr, 1, 0, 0, 1);
#endif
}
@@ -3138,7 +3138,7 @@ void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
#endif
-#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
+#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
do_unassigned_access(addr, 1, 0, 0, 2);
#endif
}
@@ -3148,7 +3148,7 @@ void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
#endif
-#if defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
+#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
do_unassigned_access(addr, 1, 0, 0, 4);
#endif
}
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index d133cc6..f64dcd1 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -422,7 +422,11 @@ void do_interrupt (CPUState *env);
uint64_t cpu_alpha_load_fpcr (CPUState *env);
void cpu_alpha_store_fpcr (CPUState *env, uint64_t val);
-extern void swap_shadow_regs(CPUState *env);
+#ifndef CONFIG_USER_ONLY
+void swap_shadow_regs(CPUState *env);
+extern QEMU_NORETURN void do_unassigned_access(target_phys_addr_t addr,
+ int, int, int, int);
+#endif
/* Bits in TB->FLAGS that control how translation is processed. */
enum {
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index d502bca..cc8a33d 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1242,7 +1242,44 @@ uint64_t helper_stq_c_phys(uint64_t p, uint64_t v)
return ret;
}
+static void do_restore_state(void *pc_ptr)
+{
+ TranslationBlock *tb;
+ unsigned long pc = (unsigned long) pc_ptr;
+
+ tb = tb_find_pc(pc);
+ if (tb) {
+ cpu_restore_state(tb, env, pc, NULL);
+ }
+}
+
+static void QEMU_NORETURN do_unaligned_access(target_ulong addr, int is_write,
+ int is_user, void *retaddr)
+{
+ uint64_t pc;
+ uint32_t insn;
+
+ do_restore_state(retaddr);
+
+ pc = env->pc;
+ insn = ldl_code(pc);
+
+ env->trap_arg0 = addr;
+ env->trap_arg1 = insn >> 26; /* opcode */
+ env->trap_arg2 = (insn >> 21) & 31; /* dest regno */
+ helper_excp(EXCP_UNALIGN, 0);
+}
+
+void QEMU_NORETURN do_unassigned_access(target_phys_addr_t addr, int is_write,
+ int is_exec, int unused, int size)
+{
+ env->trap_arg0 = addr;
+ env->trap_arg1 = is_write;
+ helper_excp(EXCP_MCHK, 0);
+}
+
#define MMUSUFFIX _mmu
+#define ALIGNED_ONLY
#define SHIFT 0
#include "softmmu_template.h"
@@ -1272,7 +1309,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
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 (unlikely(ret != 0)) {
if (likely(retaddr)) {
/* now we have a real cpu fault */
pc = (unsigned long)retaddr;
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 21/24] target-alpha: Include the PCC_OFS in the RPCC return value.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (19 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 20/24] target-alpha: Trap for unassigned and unaligned addresses Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:04 ` [Qemu-devel] [PATCH 22/24] target-alpha: Implement TLB flush primitives Richard Henderson
` (3 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/op_helper.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index cc8a33d..5902cd6 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -44,7 +44,8 @@ static void QEMU_NORETURN arith_excp(int exc, uint64_t mask)
uint64_t helper_load_pcc (void)
{
/* ??? This isn't a timer for which we have any rate info. */
- return (uint32_t)cpu_get_real_ticks();
+ uint64_t ret = env->pcc_ofs;
+ return ret << 32 | (uint32_t)cpu_get_real_ticks();
}
uint64_t helper_load_fpcr (void)
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 22/24] target-alpha: Implement TLB flush primitives.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (20 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 21/24] target-alpha: Include the PCC_OFS in the RPCC return value Richard Henderson
@ 2011-04-19 15:04 ` Richard Henderson
2011-04-19 15:05 ` [Qemu-devel] [PATCH 23/24] target-alpha: Enable the alpha-softmmu target Richard Henderson
` (2 subsequent siblings)
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:04 UTC (permalink / raw)
To: qemu-devel
Expose these via MTPR, more or less like the real HW does.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/helper.h | 3 +++
target-alpha/op_helper.c | 11 ++++++++++-
target-alpha/translate.c | 32 +++++++++++++++++++++-----------
3 files changed, 34 insertions(+), 12 deletions(-)
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 9ffc372..2dec57e 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -110,6 +110,9 @@ 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)
+
+DEF_HELPER_FLAGS_0(tbia, TCG_CALL_CONST, void)
+DEF_HELPER_FLAGS_1(tbis, TCG_CALL_CONST, void, i64)
#endif
#include "def-helper.h"
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 5902cd6..718f87d 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1174,6 +1174,16 @@ void helper_hw_ret (uint64_t a)
swap_shadow_regs(env);
}
}
+
+void helper_tbia(void)
+{
+ tlb_flush(env, 1);
+}
+
+void helper_tbis(uint64_t p)
+{
+ tlb_flush_page(env, p);
+}
#endif
/*****************************************************************************/
@@ -1326,5 +1336,4 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
}
env = saved_env;
}
-
#endif
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index c2db1ae..fa0cb09 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1620,7 +1620,6 @@ static void gen_mfpr(int ra, int regno)
static void gen_mtpr(int rb, int regno)
{
TCGv tmp;
- int data;
if (rb == 31) {
tmp = tcg_const_i64(0);
@@ -1628,16 +1627,27 @@ static void gen_mtpr(int rb, int regno)
tmp = cpu_ir[rb];
}
- /* The basic registers are data only, and unknown registers
- are read-zero, write-ignore. */
- data = cpu_pr_data(regno);
- if (data != 0) {
- if (data & PR_BYTE) {
- tcg_gen_st8_i64(tmp, cpu_env, data & ~PR_BYTE);
- } else if (data & PR_LONG) {
- tcg_gen_st32_i64(tmp, cpu_env, data & ~PR_LONG);
- } else {
- tcg_gen_st_i64(tmp, cpu_env, data);
+ /* These two register numbers perform a TLB cache flush. Thankfully we
+ can only do this inside PALmode, which means that the current basic
+ block cannot be affected by the change in mappings. */
+ if (regno == 255) {
+ /* TBIA */
+ gen_helper_tbia();
+ } else if (regno == 254) {
+ /* TBIS */
+ gen_helper_tbis(tmp);
+ } else {
+ /* The basic registers are data only, and unknown registers
+ are read-zero, write-ignore. */
+ int data = cpu_pr_data(regno);
+ if (data != 0) {
+ if (data & PR_BYTE) {
+ tcg_gen_st8_i64(tmp, cpu_env, data & ~PR_BYTE);
+ } else if (data & PR_LONG) {
+ tcg_gen_st32_i64(tmp, cpu_env, data & ~PR_LONG);
+ } else {
+ tcg_gen_st_i64(tmp, cpu_env, data);
+ }
}
}
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 23/24] target-alpha: Enable the alpha-softmmu target.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (21 preceding siblings ...)
2011-04-19 15:04 ` [Qemu-devel] [PATCH 22/24] target-alpha: Implement TLB flush primitives Richard Henderson
@ 2011-04-19 15:05 ` Richard Henderson
2011-04-19 15:05 ` [Qemu-devel] [PATCH 24/24] target-alpha: Add SX164 emulation Richard Henderson
2011-04-20 9:06 ` [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Tristan Gingold
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:05 UTC (permalink / raw)
To: qemu-devel
Compiles, but no machine defined yet, so this will crash on startup.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
Makefile.target | 3 +-
configure | 1 +
default-configs/alpha-softmmu.mak | 9 ++++
target-alpha/machine.c | 87 +++++++++++++++++++++++++++++++++++++
4 files changed, 99 insertions(+), 1 deletions(-)
create mode 100644 default-configs/alpha-softmmu.mak
create mode 100644 target-alpha/machine.c
diff --git a/Makefile.target b/Makefile.target
index 5ea7ce1..443679b 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -362,7 +362,8 @@ obj-m68k-y += m68k-semi.o dummy_m68k.o
obj-s390x-y = s390-virtio-bus.o s390-virtio.o
-obj-alpha-y =
+obj-alpha-y += i8259.o mc146818rtc.o
+obj-alpha-y += vga.o cirrus_vga.o
main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
diff --git a/configure b/configure
index 4a93972..872747f 100755
--- a/configure
+++ b/configure
@@ -1011,6 +1011,7 @@ if test -z "$target_list" ; then
target_list="\
i386-softmmu \
x86_64-softmmu \
+alpha-softmmu \
arm-softmmu \
cris-softmmu \
lm32-softmmu \
diff --git a/default-configs/alpha-softmmu.mak b/default-configs/alpha-softmmu.mak
new file mode 100644
index 0000000..abadcff
--- /dev/null
+++ b/default-configs/alpha-softmmu.mak
@@ -0,0 +1,9 @@
+# Default configuration for alpha-softmmu
+
+include pci.mak
+CONFIG_SERIAL=y
+CONFIG_I8254=y
+CONFIG_VGA_PCI=y
+CONFIG_IDE_CORE=y
+CONFIG_IDE_QDEV=y
+CONFIG_VMWARE_VGA=y
diff --git a/target-alpha/machine.c b/target-alpha/machine.c
new file mode 100644
index 0000000..a13b66a
--- /dev/null
+++ b/target-alpha/machine.c
@@ -0,0 +1,87 @@
+#include "hw/hw.h"
+#include "hw/boards.h"
+
+static int get_fpcr(QEMUFile *f, void *opaque, size_t size)
+{
+ CPUAlphaState *env = opaque;
+ cpu_alpha_store_fpcr(env, qemu_get_be64(f));
+ return 0;
+}
+
+static void put_fpcr(QEMUFile *f, void *opaque, size_t size)
+{
+ CPUAlphaState *env = opaque;
+ qemu_put_be64(f, cpu_alpha_load_fpcr(env));
+}
+
+static const VMStateInfo vmstate_fpcr = {
+ .name = "fpcr",
+ .get = get_fpcr,
+ .put = put_fpcr,
+};
+
+static VMStateField vmstate_cpu_fields[] = {
+ VMSTATE_UINTTL_ARRAY(ir, CPUState, 31),
+ VMSTATE_UINTTL_ARRAY(fir, CPUState, 31),
+ /* Save the architecture value of the fpcr, not the internally
+ expanded version. Since this architecture value does not
+ exist in memory to be stored, this requires a but of hoop
+ jumping. We want OFFSET=0 so that we effectively pass ENV
+ to the helper functions, and we need to fill in the name by
+ hand since there's no field of that name. */
+ {
+ .name = "fpcr",
+ .version_id = 0,
+ .size = sizeof(uint64_t),
+ .info = &vmstate_fpcr,
+ .flags = VMS_SINGLE,
+ .offset = 0
+ },
+ VMSTATE_UINTTL(pc, CPUState),
+ VMSTATE_UINTTL(unique, CPUState),
+ VMSTATE_UINTTL(lock_addr, CPUState),
+ VMSTATE_UINTTL(lock_value, CPUState),
+ /* Note that lock_st_addr is not saved; it is a temporary
+ used during the execution of the st[lq]_c insns. */
+
+ VMSTATE_UINT8(ps, CPUState),
+ VMSTATE_UINT8(intr_flag, CPUState),
+ VMSTATE_UINT8(fen, CPUState),
+ VMSTATE_UINT8(pal_mode, CPUState),
+
+ VMSTATE_UINT32(pcc_ofs, CPUState),
+
+ VMSTATE_UINTTL(trap_arg0, CPUState),
+ VMSTATE_UINTTL(trap_arg1, CPUState),
+ VMSTATE_UINTTL(trap_arg2, CPUState),
+
+ VMSTATE_UINTTL(exc_addr, CPUState),
+ VMSTATE_UINTTL(palbr, CPUState),
+ VMSTATE_UINTTL(ptbr, CPUState),
+ VMSTATE_UINTTL(vptptr, CPUState),
+ VMSTATE_UINTTL(sysval, CPUState),
+ VMSTATE_UINTTL(usp, CPUState),
+
+ VMSTATE_UINTTL_ARRAY(shadow, CPUState, 8),
+ VMSTATE_UINTTL_ARRAY(scratch, CPUState, 24),
+
+ VMSTATE_END_OF_LIST()
+};
+
+static const VMStateDescription vmstate_cpu = {
+ .name = "cpu",
+ .version_id = CPU_SAVE_VERSION,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = vmstate_cpu_fields,
+};
+
+void cpu_save(QEMUFile *f, void *opaque)
+{
+ vmstate_save_state(f, &vmstate_cpu, opaque);
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+ return vmstate_load_state(f, &vmstate_cpu, opaque, version_id);
+}
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [Qemu-devel] [PATCH 24/24] target-alpha: Add SX164 emulation.
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (22 preceding siblings ...)
2011-04-19 15:05 ` [Qemu-devel] [PATCH 23/24] target-alpha: Enable the alpha-softmmu target Richard Henderson
@ 2011-04-19 15:05 ` Richard Henderson
2011-04-20 9:06 ` [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Tristan Gingold
24 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-19 15:05 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
Makefile.target | 1 +
hw/alpha_pci.c | 327 +++++++++++++++++
hw/alpha_pyxis.c | 1057 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/alpha_sx164.c | 195 ++++++++++
hw/alpha_sys.h | 41 +++
5 files changed, 1621 insertions(+), 0 deletions(-)
create mode 100644 hw/alpha_pci.c
create mode 100644 hw/alpha_pyxis.c
create mode 100644 hw/alpha_sx164.c
create mode 100644 hw/alpha_sys.h
diff --git a/Makefile.target b/Makefile.target
index 443679b..f702780 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -364,6 +364,7 @@ obj-s390x-y = s390-virtio-bus.o s390-virtio.o
obj-alpha-y += i8259.o mc146818rtc.o
obj-alpha-y += vga.o cirrus_vga.o
+obj-alpha-y += alpha_pci.o alpha_sx164.o alpha_pyxis.o
main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
diff --git a/hw/alpha_pci.c b/hw/alpha_pci.c
new file mode 100644
index 0000000..744b68b
--- /dev/null
+++ b/hw/alpha_pci.c
@@ -0,0 +1,327 @@
+/* There's nothing in here that's Alpha specific, really. */
+
+#include "config.h"
+#include "alpha_sys.h"
+#include "qemu-log.h"
+
+
+/* PCI IO reads, to byte-word addressable memory. */
+/* ??? Doesn't handle multiple PCI busses. */
+
+static uint32_t bw_io_readb(void *opaque, target_phys_addr_t addr)
+{
+ return cpu_inb(addr);
+}
+
+static uint32_t bw_io_readw(void *opaque, target_phys_addr_t addr)
+{
+ return cpu_inw(addr);
+}
+
+static uint32_t bw_io_readl(void *opaque, target_phys_addr_t addr)
+{
+ return cpu_inl(addr);
+}
+
+/* PCI IO writes, to byte-word addressable memory. */
+/* ??? Doesn't handle multiple PCI busses. */
+
+static void bw_io_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ cpu_outb(addr, val);
+}
+
+static void bw_io_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ cpu_outw(addr, val);
+}
+
+static void bw_io_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ cpu_outl(addr, val);
+}
+
+CPUReadMemoryFunc * const alpha_pci_bw_io_reads[] = {
+ bw_io_readb,
+ bw_io_readw,
+ bw_io_readl,
+};
+
+CPUWriteMemoryFunc * const alpha_pci_bw_io_writes[] = {
+ bw_io_writeb,
+ bw_io_writew,
+ bw_io_writel,
+};
+
+/* PCI config space reads, to byte-word addressable memory. */
+static uint32_t bw_conf1_readb(void *opaque, target_phys_addr_t addr)
+{
+ PCIHostState *s = opaque;
+ return pci_data_read(s->bus, addr, 1);
+}
+
+static uint32_t bw_conf1_readw(void *opaque, target_phys_addr_t addr)
+{
+ PCIHostState *s = opaque;
+ return pci_data_read(s->bus, addr, 2);
+}
+
+static uint32_t bw_conf1_readl(void *opaque, target_phys_addr_t addr)
+{
+ PCIHostState *s = opaque;
+ return pci_data_read(s->bus, addr, 4);
+}
+
+/* PCI config space writes, to byte-word addressable memory. */
+static void bw_conf1_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PCIHostState *s = opaque;
+ pci_data_write(s->bus, addr, val, 1);
+}
+
+static void bw_conf1_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PCIHostState *s = opaque;
+ pci_data_write(s->bus, addr, val, 2);
+}
+
+static void bw_conf1_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PCIHostState *s = opaque;
+ pci_data_write(s->bus, addr, val, 4);
+}
+
+CPUReadMemoryFunc * const alpha_pci_bw_conf1_reads[] = {
+ bw_conf1_readb,
+ bw_conf1_readw,
+ bw_conf1_readl,
+};
+
+CPUWriteMemoryFunc * const alpha_pci_bw_conf1_writes[] = {
+ bw_conf1_writeb,
+ bw_conf1_writew,
+ bw_conf1_writel,
+};
+
+/* PCI MEM access to dense (but not byte-word addressable) memory. */
+static uint32_t dense_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ PCIBus *b = opaque;
+ return ldl_phys(pci_to_cpu_addr(b, addr));
+}
+
+static void dense_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t v)
+{
+ PCIBus *b = opaque;
+ stl_phys(pci_to_cpu_addr(b, addr), v);
+}
+
+CPUReadMemoryFunc * const alpha_pci_dense_mem_reads[] = {
+ unassigned_mem_readb,
+ unassigned_mem_readw,
+ dense_mem_readl,
+};
+
+CPUWriteMemoryFunc * const alpha_pci_dense_mem_writes[] = {
+ unassigned_mem_writeb,
+ unassigned_mem_writew,
+ dense_mem_writel,
+};
+
+/* PCI IO to sparse memory. These are helper routines, which expect that the
+ relevant HAE has already been prepended to ADDR by the core-specific
+ routine that is actually registered with the memory region. */
+
+uint32_t alpha_sparse_io_read(target_phys_addr_t addr)
+{
+ int size = (addr >> 3) & 3;
+ uint32_t val;
+
+ addr >>= 5;
+ switch (size) {
+ case 0:
+ /* byte access */
+ val = cpu_inb(addr);
+ break;
+ case 1:
+ /* word access */
+ val = cpu_inw(addr);
+ break;
+ case 2:
+ /* tri-byte access; apparently possible with real pci lines. */
+ qemu_log("pci: tri-byte io read");
+ return ~0u;
+ default:
+ /* long access */
+ return cpu_inl(addr);
+ }
+
+ val <<= (addr & 3) * 8;
+ return val;
+}
+
+void alpha_sparse_io_write(target_phys_addr_t addr, uint32_t val)
+{
+ int size = (addr >> 3) & 3;
+
+ addr >>= 5;
+ switch (size) {
+ case 0:
+ /* byte access */
+ val >>= (addr & 3) * 8;
+ cpu_outb(addr, val);
+ break;
+ case 1:
+ /* word access */
+ val >>= (addr & 3) * 8;
+ cpu_outw(addr, val);
+ break;
+ case 2:
+ /* tri-byte access; apparently possible with real pci lines. */
+ qemu_log("pci: tri-byte io write");
+ break;
+ default:
+ /* long access */
+ cpu_outl(addr, val);
+ break;
+ }
+}
+
+uint32_t alpha_sparse_mem_read(PCIBus *b, target_phys_addr_t addr)
+{
+ int size = (addr >> 3) & 3;
+ uint32_t val;
+
+ addr = pci_to_cpu_addr(b, addr >> 5);
+ switch (size) {
+ case 0:
+ /* byte access */
+ val = ldub_phys(addr);
+ break;
+ case 1:
+ /* word access */
+ val = lduw_phys(addr);
+ break;
+ case 2:
+ /* tri-byte access; apparently possible with real pci lines. */
+ qemu_log("pci: tri-byte mem read");
+ return ~0u;
+ default:
+ /* long access */
+ return ldl_phys(addr);
+ }
+
+ val <<= (addr & 3) * 8;
+ return val;
+}
+
+void alpha_sparse_mem_write(PCIBus *b, target_phys_addr_t addr, uint32_t val)
+{
+ int size = (addr >> 3) & 3;
+
+ addr = pci_to_cpu_addr(b, addr >> 5);
+ switch (size) {
+ case 0:
+ /* byte access */
+ val >>= (addr & 3) * 8;
+ stb_phys(addr, val);
+ break;
+ case 1:
+ /* word access */
+ val >>= (addr & 3) * 8;
+ stw_phys(addr, val);
+ break;
+ case 2:
+ /* tri-byte access; apparently possible with real pci lines. */
+ qemu_log("pci: tri-byte mem write");
+ break;
+ default:
+ /* long access */
+ stl_phys(addr, val);
+ break;
+ }
+}
+
+uint32_t alpha_sparse_conf1_read(PCIBus *b, target_phys_addr_t addr)
+{
+ int size = ((addr >> 3) & 3) + 1;
+ uint32_t val;
+
+ if (size == 3) {
+ qemu_log("pci: tri-byte configuration read");
+ return ~0u;
+ }
+
+ addr >>= 5;
+ val = pci_data_read(b, addr, size);
+ val <<= (addr & 3) * 8;
+
+ return val;
+}
+
+void alpha_sparse_conf1_write(PCIBus *b, target_phys_addr_t addr, uint32_t val)
+{
+ int size = ((addr >> 3) & 3) + 1;
+
+ if (size == 3) {
+ qemu_log("pci: tri-byte configuration write");
+ return;
+ }
+
+ addr >>= 5;
+ val >>= (addr & 3) * 8;
+ pci_data_write(b, addr, val, size);
+}
+
+/* Configuration space accesses do not normall use an HAE. */
+static uint32_t sparse_conf1_readl(void *opaque, target_phys_addr_t addr)
+{
+ PCIBus *b = opaque;
+ return alpha_sparse_conf1_read(b, addr);
+}
+
+static void sparse_conf1_writel(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ PCIBus *b = opaque;
+ alpha_sparse_conf1_write(b, addr, val);
+}
+
+CPUReadMemoryFunc * const alpha_pci_sparse_conf1_reads[] = {
+ unassigned_mem_readb,
+ unassigned_mem_readw,
+ sparse_conf1_readl,
+};
+
+CPUWriteMemoryFunc * const alpha_pci_sparse_conf1_writes[] = {
+ unassigned_mem_writeb,
+ unassigned_mem_writew,
+ sparse_conf1_writel,
+};
+
+/* PCI/EISA Interrupt Acknowledge Cycle. */
+
+static uint32_t iack_readl(void *opaque, target_phys_addr_t addr)
+{
+ if (addr & 15) {
+ return unassigned_mem_readl(opaque, addr);
+ }
+ return pic_read_irq(isa_pic);
+}
+
+static void special_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ qemu_log("pci: special write cycle %08x", val);
+}
+
+CPUReadMemoryFunc * const alpha_pci_iack_reads[] = {
+ unassigned_mem_readb,
+ unassigned_mem_readw,
+ iack_readl,
+};
+
+CPUWriteMemoryFunc * const alpha_pci_special_writes[] = {
+ unassigned_mem_writeb,
+ unassigned_mem_writew,
+ special_writel,
+};
diff --git a/hw/alpha_pyxis.c b/hw/alpha_pyxis.c
new file mode 100644
index 0000000..0f4c038
--- /dev/null
+++ b/hw/alpha_pyxis.c
@@ -0,0 +1,1057 @@
+/*
+ * Qemu 21174 (PYXIS) chipset emulation.
+ *
+ * Written by Richard Henderson.
+ *
+ * This work is licensed under the GNU GPL license version 2 or later.
+ */
+
+#include "cpu.h"
+#include "exec-all.h"
+#include "hw.h"
+#include "devices.h"
+#include "sysemu.h"
+#include "alpha_sys.h"
+
+/* TODO:
+ ERR_MASK MEM_NEM controls do_unassigned_access behavior.
+
+ RT_COUNT is a 33Mhz free-running counter.
+ INT_TIME should generate interrupt on RT_COUNT match.
+*/
+
+typedef struct PyxisState {
+ PCIHostState host;
+ /* General registers. */
+ uint32_t pyxis_rev;
+ uint32_t pci_lat;
+ uint32_t pyxis_ctrl;
+ uint32_t pyxis_ctrl1;
+ uint32_t flash_ctrl;
+ uint32_t hae_mem;
+ uint32_t hae_io;
+ uint32_t cfg;
+ /* Diagnostic registers. */
+ uint32_t pyxis_diag;
+ uint32_t diag_check;
+ /* Performance monitor registers. */
+ uint32_t perf_monitor;
+ uint32_t perf_control;
+ /* Error registers. */
+ uint32_t pyxis_err;
+ uint32_t pyxis_stat;
+ uint32_t err_mask;
+ uint32_t pyxis_syn;
+ uint32_t pyxis_err_data;
+ uint32_t mear;
+ uint32_t mesr;
+ uint32_t pci_err0;
+ uint32_t pci_err1;
+ uint32_t pci_err2;
+ /* Memory controler registers. */
+ uint32_t mcr;
+ uint32_t mcmr;
+ uint32_t gtr;
+ uint32_t rtr;
+ uint32_t rhpr;
+ uint32_t mdr[2];
+ uint32_t bbar[8];
+ uint32_t bcr[8];
+ uint32_t btr[8];
+ uint32_t cvm;
+ /* PCI window control registers. */
+ uint32_t tbia;
+ uint32_t wbase[4];
+ uint32_t wmask[4];
+ uint32_t tbase[4];
+ uint32_t w_dac;
+ /* Scatter-gather address translation registers. */
+ uint32_t tb_tag[8];
+ uint32_t tb_page[8][4];
+ /* Misc registers. */
+ uint32_t ccr;
+ uint32_t clk_stat;
+ uint32_t reset;
+ /* Interrupt control registers. */
+ uint64_t int_req;
+ uint64_t int_mask;
+ uint32_t int_hilo;
+ uint32_t int_route;
+ uint64_t gpo;
+ uint64_t int_time;
+ uint32_t iic_ctrl;
+ uint32_t int_cnfg;
+ /* QEMU emulation state. */
+ uint32_t latch_tmp;
+ uint64_t ram_size;
+ /* Items with which to raise interrupts. */
+ qemu_irq *irqs;
+} PyxisState;
+
+/* Called when one of INT_REQ or INT_MASK changes,
+ adjust the signalled state of the cpu. */
+static void pyxis_irq_change(PyxisState *s)
+{
+ CPUState *env = first_cpu;
+ uint64_t req;
+
+ req = s->int_req & s->int_mask;
+
+ /* If there are any non-masked interrupts, tell the cpu. */
+ if (req) {
+ cpu_interrupt(env, CPU_INTERRUPT_HARD);
+ } else {
+ cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+ }
+}
+
+static void invalidate_tag(PyxisState *s, int i)
+{
+ s->tb_tag[i] = 0;
+ memset(s->tb_page[i], 0, sizeof(s->tb_page[i]));
+}
+
+static uint32_t dummy_read(void *opaque, target_phys_addr_t addr)
+{
+ return 0;
+}
+
+static CPUReadMemoryFunc * const dummy_reads[] = {
+ dummy_read,
+ dummy_read,
+ dummy_read,
+};
+
+static CPUWriteMemoryFunc * const dummy_writes[] = {
+ unassigned_mem_writeb,
+ unassigned_mem_writew,
+ unassigned_mem_writel,
+};
+
+static uint32_t sparse0_readl(void *opaque, target_phys_addr_t addr)
+{
+ PyxisState *s = opaque;
+ target_phys_addr_t hae;
+
+ hae = (s->hae_mem & 0xe0000000ull) << 5;
+ return alpha_sparse_mem_read(s->host.bus, hae + addr);
+}
+
+static void sparse0_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PyxisState *s = opaque;
+ target_phys_addr_t hae;
+
+ hae = (s->hae_mem & 0xe0000000ull) << 5;
+ alpha_sparse_mem_write(s->host.bus, hae + addr, val);
+}
+
+static uint32_t sparse1_readl(void *opaque, target_phys_addr_t addr)
+{
+ PyxisState *s = opaque;
+ target_phys_addr_t hae;
+
+ hae = ((s->hae_mem >> 11) & 0x1full) << (27 + 5);
+ return alpha_sparse_mem_read(s->host.bus, hae + addr);
+}
+
+static void sparse1_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PyxisState *s = opaque;
+ target_phys_addr_t hae;
+
+ hae = ((s->hae_mem >> 11) & 0x1full) << (27 + 5);
+ alpha_sparse_mem_write(s->host.bus, hae + addr, val);
+}
+
+static uint32_t sparse2_readl(void *opaque, target_phys_addr_t addr)
+{
+ PyxisState *s = opaque;
+ target_phys_addr_t hae;
+
+ hae = ((s->hae_mem >> 2) & 0x3full) << (26 + 5);
+ return alpha_sparse_mem_read(s->host.bus, hae + addr);
+}
+
+static void sparse2_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PyxisState *s = opaque;
+ target_phys_addr_t hae;
+
+ hae = ((s->hae_mem >> 2) & 0x3full) << (26 + 5);
+ alpha_sparse_mem_write(s->host.bus, hae + addr, val);
+}
+
+static uint32_t sparseA_inl(void *opaque, target_phys_addr_t addr)
+{
+ /* Region A is fixed at the lower 32MB of I/O space. */
+ return alpha_sparse_io_read(addr);
+}
+
+static void sparseA_outl(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ /* Region A is fixed at the lower 32MB of I/O space. */
+ alpha_sparse_io_write(addr, val);
+}
+
+static uint32_t sparseB_inl(void *opaque, target_phys_addr_t addr)
+{
+ PyxisState *s = opaque;
+ target_phys_addr_t hae;
+
+ hae = (s->hae_io & 0xfe000000ull) << 5;
+ return alpha_sparse_io_read(hae + addr);
+}
+
+static void sparseB_outl(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PyxisState *s = opaque;
+ target_phys_addr_t hae;
+
+ hae = (s->hae_io & 0xfe000000ull) << 5;
+ alpha_sparse_io_write(hae + addr, val);
+}
+
+static uint32_t csr_874_readl(void *opaque, target_phys_addr_t addr)
+{
+ PyxisState *s = opaque;
+
+ switch (addr) {
+ /* General Registers. */
+ case 0x0080: return s->pyxis_rev;
+ case 0x00c0: return s->pci_lat;
+ case 0x0100: return s->pyxis_ctrl;
+ case 0x0140: return s->pyxis_ctrl1;
+ case 0x0200: return s->flash_ctrl;
+ case 0x0400: return s->hae_mem;
+ case 0x0440: return s->hae_io;
+ case 0x0480: return s->cfg;
+
+ /* Diagnostic Registers. */
+ case 0x2000: return s->pyxis_diag;
+ case 0x3000: return s->diag_check;
+
+ /* Performance Monitor Registers. */
+ case 0x4000: return s->perf_monitor;
+ case 0x4040: return s->perf_control;
+
+ /* Error Registers. */
+ case 0x8200: return s->pyxis_err;
+ case 0x8240: return s->pyxis_stat;
+ case 0x8280: return s->err_mask;
+ case 0x8300: return s->pyxis_syn;
+ case 0x8308: return s->pyxis_err_data;
+ case 0x8400: return s->mear;
+ case 0x8440: return s->mesr;
+ case 0x8800: return s->pci_err0;
+ case 0x8840: return s->pci_err1;
+ case 0x8880: return s->pci_err2;
+
+ default:
+ do_unassigned_access(addr + 0x8740000000ull, 0, 0, 0, 4);
+ return -1;
+ }
+}
+
+static uint32_t csr_875_readl(void *opaque, target_phys_addr_t addr)
+{
+ PyxisState *s = opaque;
+
+ switch (addr) {
+ /* Memory Controller Registers. */
+ case 0x0000: return s->mcr;
+ case 0x0040: return s->mcmr;
+ case 0x0200: return s->gtr;
+ case 0x0300: return s->rtr;
+ case 0x0400: return s->rhpr;
+ case 0x0500: return s->mdr[0];
+ case 0x0540: return s->mdr[1];
+
+ case 0x0600:
+ case 0x0640:
+ case 0x0680:
+ case 0x06c0:
+ case 0x0700:
+ case 0x0740:
+ case 0x0780:
+ case 0x07c0:
+ return s->bbar[(addr - 0x0600) / 0x40];
+
+ case 0x0800:
+ case 0x0840:
+ case 0x0880:
+ case 0x08c0:
+ case 0x0900:
+ case 0x0940:
+ case 0x0980:
+ case 0x09c0:
+ return s->bcr[(addr - 0x0800) / 0x40];
+
+ case 0x0a00:
+ case 0x0a40:
+ case 0x0a80:
+ case 0x0ac0:
+ case 0x0b00:
+ case 0x0b40:
+ case 0x0b80:
+ case 0x0bc0:
+ return s->btr[(addr - 0x0a00) / 0x40];
+
+ case 0x0c00: return s->cvm;
+
+ default:
+ do_unassigned_access(addr + 0x8750000000ull, 0, 0, 0, 4);
+ return -1;
+ }
+}
+
+static uint32_t csr_876_readl(void *opaque, target_phys_addr_t addr)
+{
+ PyxisState *s = opaque;
+
+ switch (addr) {
+ /* PCI Window Control Registers. */
+ case 0x0100: return s->tbia;
+
+ case 0x0400:
+ case 0x0500:
+ case 0x0600:
+ case 0x0700:
+ return s->wbase[(addr - 0x0400) / 0x0100];
+
+ case 0x0440:
+ case 0x0540:
+ case 0x0640:
+ case 0x0740:
+ return s->wmask[(addr - 0x0440) / 0x0100];
+
+ case 0x0480:
+ case 0x0580:
+ case 0x0680:
+ case 0x0780:
+ return s->tbase[(addr - 0x0480) / 0x0100];
+
+ case 0x07c0: return s->w_dac;
+
+ /* Scatter-gather Address Translation Registers. */
+ case 0x0800:
+ case 0x0840:
+ case 0x0880:
+ case 0x08c0:
+ case 0x0900:
+ case 0x0940:
+ case 0x0980:
+ case 0x09c0:
+ return s->tb_tag[(addr - 0x0800) / 0x40];
+
+ case 0x1000: case 0x1040: case 0x1080: case 0x10c0:
+ case 0x1100: case 0x1140: case 0x1180: case 0x11c0:
+ case 0x1200: case 0x1240: case 0x1280: case 0x12c0:
+ case 0x1300: case 0x1340: case 0x1380: case 0x13c0:
+ case 0x1400: case 0x1440: case 0x1480: case 0x14c0:
+ case 0x1500: case 0x1540: case 0x1580: case 0x15c0:
+ case 0x1600: case 0x1640: case 0x1680: case 0x16c0:
+ case 0x1700: case 0x1740: case 0x1780: case 0x17c0:
+ return *(&s->tb_page[0][0] + ((addr - 0x1000) / 0x40));
+
+ default:
+ do_unassigned_access(addr + 0x8760000000ull, 0, 0, 0, 4);
+ return -1;
+ }
+}
+
+static uint32_t csr_878_readl(void *opaque, target_phys_addr_t addr)
+{
+ PyxisState *s = opaque;
+
+ switch (addr) {
+ /* Miscellaneous Registers. */
+ case 0x0000: return s->ccr;
+ case 0x0100: return s->clk_stat;
+ case 0x0900: return s->reset;
+
+ default:
+ do_unassigned_access(addr + 0x8780000000ull, 0, 0, 0, 4);
+ return -1;
+ }
+}
+
+static uint32_t csr_87a_readl(void *opaque, target_phys_addr_t addr)
+{
+ PyxisState *s = opaque;
+ uint64_t ret;
+
+ switch (addr) {
+ /* Interrupt Control Registers. */
+ case 0x0000:
+ ret = s->int_req;
+ break;
+ case 0x0040:
+ ret = s->int_mask;
+ break;
+ case 0x00c0:
+ ret = s->int_hilo;
+ break;
+ case 0x0140:
+ ret = s->int_route;
+ break;
+ case 0x0180:
+ ret = s->gpo;
+ break;
+ case 0x01c0: return s->int_cnfg;
+ case 0x0200:
+ /* The RT_COUNT clock runs at 66.66MHz. */
+ ret = qemu_get_clock_ns(vm_clock) / 15;
+ break;
+ case 0x0240:
+ ret = s->int_time;
+ break;
+ case 0x02c0:
+ return s->iic_ctrl;
+
+ case 0x0004:
+ case 0x0044:
+ case 0x00c4:
+ case 0x0144:
+ case 0x0184:
+ case 0x0204:
+ case 0x0244:
+ return s->latch_tmp;
+
+ default:
+ do_unassigned_access(addr + 0x87a0000000ull, 0, 0, 0, 4);
+ return -1;
+ }
+
+ s->latch_tmp = ret >> 32;
+ return ret;
+}
+
+static void csr_874_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PyxisState *s = opaque;
+
+ switch (addr) {
+ /* General Registers. */
+ case 0x0080:
+ /* pyxis_rev: RO */
+ break;
+ case 0x00c0:
+ s->pci_lat = val & 0xffff;
+ break;
+ case 0x0100:
+ s->pyxis_ctrl = val & 0x77703ffd;
+ break;
+ case 0x0140:
+ s->pyxis_ctrl1 = val & 0xffffff11;
+ break;
+ case 0x0200:
+ s->flash_ctrl = val & 0x3fff;
+ break;
+ case 0x0400:
+ s->hae_mem = val & 0xe000f8fc;
+ break;
+ case 0x0440:
+ s->hae_io = val & 0xfe000000;
+ break;
+ case 0x0480:
+ s->cfg = val & 3;
+ break;
+
+ /* Diagnostic Registers. */
+ case 0x2000:
+ s->pyxis_diag = val & 0xb0000003;
+ break;
+ case 0x3000:
+ s->diag_check = val & 0xff;
+ break;
+
+ /* Performance Monitor Registers. */
+ case 0x4000:
+ /* perf_monitor: RO */
+ break;
+ case 0x4040:
+ /* perf_control: */
+ /* If LOW_COUNT_CLR set, zero the low counter. */
+ if (val & (1 << 13)) {
+ s->perf_monitor &= 0xffff0000;
+ }
+ /* If HIGH_COUNT_CLR set, zero the high counter. */
+ if (val & (1 << 29)) {
+ s->perf_monitor &= 0x0000ffff;
+ }
+ s->perf_control = val & 0xd007d007;
+ break;
+
+ /* Error Registers. */
+ case 0x8200:
+ /* pyxis_err */
+ /* Zap the RW1C fields; the rest are RO. */
+ s->pyxis_err &= ~(val & 0xbff);
+ break;
+
+ case 0x8240:
+ /* pyxis_stat: RO */
+ break;
+ case 0x8280:
+ s->err_mask = val & 0x5ff;
+ break;
+ case 0x8300:
+ /* pyxis_syn: RO */
+ break;
+ case 0x8308:
+ /* pyxis_err_data: RO */
+ break;
+ case 0x8400:
+ /* mear: RO */
+ break;
+ case 0x8440:
+ /* mesr: */
+ /* There are a bunch of RO fields in here; preserve them. */
+ s->mesr = (s->mesr & ~0xfe000000) | (val & 0xfe000000);
+ break;
+ case 0x8800:
+ /* pci_err0: RO */
+ break;
+ case 0x8840:
+ /* pci_err1: RO */
+ break;
+ case 0x8880:
+ /* pci_err2: RO */
+ break;
+
+ default:
+ do_unassigned_access(addr + 0x8740000000ull, 1, 0, 0, 4);
+ return;
+ }
+}
+
+static void csr_875_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PyxisState *s = opaque;
+
+ switch (addr) {
+ /* Memory Controller Registers. */
+ case 0x0000: /* mcr: */
+ /* The SERVER_MODE and BCACHE_TYPE fields are RO. */
+ s->mcr = (s->mcr & 0x300) | (val & 0x3ffffc01);
+ break;
+ case 0x0040:
+ s->mcmr = val & 0xffff;
+ break;
+ case 0x0200:
+ s->gtr = val & 0x0737;
+ break;
+ case 0x0300:
+ s->rtr = val & 0x9ff0;
+ break;
+ case 0x0400:
+ s->rhpr = val & 0xffff;
+ break;
+ case 0x0500:
+ s->mdr[0] = val & 0xbf3f3f3f;
+ break;
+ case 0x0540:
+ s->mdr[1] = val & 0xbf3f3f3f;
+ break;
+
+ case 0x0600: case 0x0640: case 0x0680: case 0x06c0:
+ case 0x0700: case 0x0740: case 0x0780: case 0x07c0:
+ s->bbar[(addr - 0x0600) / 0x40] = val & 0xffc0;
+ break;
+
+ case 0x0800: case 0x0840: case 0x0880: case 0x08c0:
+ case 0x0900: case 0x0940: case 0x0980: case 0x09c0:
+ s->bcr[(addr - 0x0800) / 0x40] = val & 0xff;
+ break;
+
+ case 0x0a00: case 0x0a40: case 0x0a80: case 0x0ac0:
+ case 0x0b00: case 0x0b40: case 0x0b80: case 0x0bc0:
+ s->btr[(addr - 0x0a00) / 0x40] = val & 0x23;
+ break;
+
+ case 0x0c00: /* cvm: */
+ /* All bits are RW1C. */
+ s->cvm &= ~val;
+ break;
+
+ default:
+ do_unassigned_access(addr + 0x8750000000ull, 1, 0, 0, 4);
+ return;
+ }
+}
+
+static void csr_876_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PyxisState *s = opaque;
+ int i;
+
+ switch (addr) {
+ /* PCI Window Control Registers. */
+ case 0x0100:
+ switch (val & 3) {
+ case 0: /* No operation. */
+ break;
+ case 1: /* Invalidate and unlock TLB tags that are locked. */
+ for (i = 0; i < 4; ++i) {
+ if (s->tb_tag[i] & 2) {
+ invalidate_tag(s, i);
+ }
+ }
+ break;
+ case 2: /* Invalidate and unlock TLB tags that are unlocked. */
+ for (i = 0; i < 4; ++i) {
+ if ((s->tb_tag[i] & 2) == 0) {
+ invalidate_tag(s, i);
+ }
+ }
+ break;
+ case 3: /* Invalidate and unlock all TLB tag entries. */
+ memset(s->tb_tag, 0, sizeof(s->tb_tag));
+ memset(s->tb_page, 0, sizeof(s->tb_page));
+ break;
+ }
+ break;
+
+ case 0x0400: case 0x0500: case 0x0600: case 0x0700:
+ s->wbase[(addr - 0x0400) / 0x0100] = val & 0xfff0000f;
+ break;
+
+ case 0x0440: case 0x0540: case 0x0640: case 0x0740:
+ s->wmask[(addr - 0x0440) / 0x0100] = val & 0xfff00000;
+ break;
+
+ case 0x0480: case 0x0580: case 0x0680: case 0x0780:
+ s->tbase[(addr - 0x0480) / 0x0100] = val & 0xffffff00;
+ break;
+
+ case 0x07c0:
+ s->w_dac = val & 0xffffff00;
+ break;
+
+ /* Scatter-gather Address Translation Registers. */
+ case 0x0800: case 0x0840: case 0x0880: case 0x08c0: /* lockable */
+ s->tb_tag[(addr - 0x0800) / 0x40] = val & 0xffff8007;
+ break;
+ case 0x0900: case 0x0940: case 0x0980: case 0x09c0: /* not lockable */
+ s->tb_tag[(addr - 0x0800) / 0x40] = val & 0xffff8005;
+ break;
+
+ case 0x1000: case 0x1040: case 0x1080: case 0x10c0:
+ case 0x1100: case 0x1140: case 0x1180: case 0x11c0:
+ case 0x1200: case 0x1240: case 0x1280: case 0x12c0:
+ case 0x1300: case 0x1340: case 0x1380: case 0x13c0:
+ case 0x1400: case 0x1440: case 0x1480: case 0x14c0:
+ case 0x1500: case 0x1540: case 0x1580: case 0x15c0:
+ case 0x1600: case 0x1640: case 0x1680: case 0x16c0:
+ case 0x1700: case 0x1740: case 0x1780: case 0x17c0:
+ *(&s->tb_page[0][0] + ((addr - 0x1000) / 0x40)) = val & 0x003fffff;
+ break;
+
+ default:
+ do_unassigned_access(addr + 0x8760000000ull, 1, 0, 0, 4);
+ return;
+ }
+}
+
+static void csr_878_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PyxisState *s = opaque;
+
+ switch (addr) {
+ /* Miscellaneous Registers. */
+ case 0x0000:
+ s->ccr = val & 0xff071773;
+ break;
+ case 0x0100:
+ /* clk_stat: RO */
+ break;
+ case 0x0900:
+ /* reset: */
+ /* Yes, the value is architected. Jokers... */
+ if (val == 0x0000dead) {
+ /* ??? This should be reset, but shutdown makes for easier
+ debugging for the moment. */
+ qemu_system_shutdown_request();
+ }
+ break;
+
+ default:
+ do_unassigned_access(addr + 0x8780000000ull, 1, 0, 0, 4);
+ return;
+ }
+}
+
+/* ??? We should probably not accept partial writes to the 64-bit registers.
+ In particular, INT_MASK, RT_COUNT and INT_TIME are likely to do the wrong
+ thing with partial writes. */
+
+static void csr_87a_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PyxisState *s = opaque;
+ uint64_t val64 = ((uint64_t)val << 32) | s->latch_tmp;
+
+ switch (addr) {
+ /* Interrupt Control Registers. */
+ case 0x0000:
+ s->latch_tmp = val;
+ break;
+ case 0x0004:
+ s->int_req &= ~(val64 & 0x7ffffffffffffffful);
+ pyxis_irq_change(s);
+ break;
+ case 0x0040:
+ s->latch_tmp = val;
+ break;
+ case 0x0044:
+ s->int_mask = val64;
+ pyxis_irq_change(s);
+ break;
+ case 0x00c0:
+ s->int_hilo = val & 0x7f;
+ break;
+ case 0x00c4:
+ /* int_hilo highpart all 0 */
+ break;
+ case 0x0140:
+ s->int_route = val & 0x7f;
+ break;
+ case 0x0144:
+ /* int_route highpart all 0 */
+ break;
+ case 0x0180:
+ s->latch_tmp = val;
+ break;
+ case 0x0184:
+ s->gpo = val64;
+ break;
+ case 0x01c0:
+ s->int_cnfg = val;
+ break;
+ case 0x0200:
+ /* rt_count low */
+ break;
+ case 0x0204:
+ /* rt_count high */
+ break;
+ case 0x0240:
+ s->latch_tmp = val;
+ break;
+ case 0x0244:
+ s->int_time = val64;
+ break;
+ case 0x02c0:
+ s->iic_ctrl = val;
+ break;
+
+ default:
+ do_unassigned_access(addr + 0x87a0000000ull, 1, 0, 0, 4);
+ return;
+ }
+}
+
+static CPUReadMemoryFunc * const sparse0_reads[] = {
+ unassigned_mem_readb,
+ unassigned_mem_readw,
+ sparse0_readl
+};
+
+static CPUWriteMemoryFunc * const sparse0_writes[] = {
+ unassigned_mem_writeb,
+ unassigned_mem_writew,
+ sparse0_writel
+};
+
+static CPUReadMemoryFunc * const sparse1_reads[] = {
+ unassigned_mem_readb,
+ unassigned_mem_readw,
+ sparse1_readl
+};
+
+static CPUWriteMemoryFunc * const sparse1_writes[] = {
+ unassigned_mem_writeb,
+ unassigned_mem_writew,
+ sparse1_writel
+};
+
+static CPUReadMemoryFunc * const sparse2_reads[] = {
+ unassigned_mem_readb,
+ unassigned_mem_readw,
+ sparse2_readl
+};
+
+static CPUWriteMemoryFunc * const sparse2_writes[] = {
+ unassigned_mem_writeb,
+ unassigned_mem_writew,
+ sparse2_writel
+};
+
+static CPUReadMemoryFunc * const sparseA_reads[] = {
+ unassigned_mem_readb,
+ unassigned_mem_readw,
+ sparseA_inl
+};
+
+static CPUWriteMemoryFunc * const sparseA_writes[] = {
+ unassigned_mem_writeb,
+ unassigned_mem_writew,
+ sparseA_outl
+};
+
+static CPUReadMemoryFunc * const sparseB_reads[] = {
+ unassigned_mem_readb,
+ unassigned_mem_readw,
+ sparseB_inl
+};
+
+static CPUWriteMemoryFunc * const sparseB_writes[] = {
+ unassigned_mem_writeb,
+ unassigned_mem_writew,
+ sparseB_outl
+};
+
+static CPUReadMemoryFunc * const csr_874_reads[] = {
+ unassigned_mem_readb,
+ unassigned_mem_readw,
+ csr_874_readl
+};
+
+static CPUWriteMemoryFunc * const csr_874_writes[] = {
+ unassigned_mem_writeb,
+ unassigned_mem_writew,
+ csr_874_writel
+};
+
+static CPUReadMemoryFunc * const csr_875_reads[] = {
+ unassigned_mem_readb,
+ unassigned_mem_readw,
+ csr_875_readl
+};
+
+static CPUWriteMemoryFunc * const csr_875_writes[] = {
+ unassigned_mem_writeb,
+ unassigned_mem_writew,
+ csr_875_writel
+};
+
+static CPUReadMemoryFunc * const csr_876_reads[] = {
+ unassigned_mem_readb,
+ unassigned_mem_readw,
+ csr_876_readl
+};
+
+static CPUWriteMemoryFunc * const csr_876_writes[] = {
+ unassigned_mem_writeb,
+ unassigned_mem_writew,
+ csr_876_writel
+};
+
+static CPUReadMemoryFunc * const csr_878_reads[] = {
+ unassigned_mem_readb,
+ unassigned_mem_readw,
+ csr_878_readl
+};
+
+static CPUWriteMemoryFunc * const csr_878_writes[] = {
+ unassigned_mem_writeb,
+ unassigned_mem_writew,
+ csr_878_writel
+};
+
+static CPUReadMemoryFunc * const csr_87a_reads[] = {
+ unassigned_mem_readb,
+ unassigned_mem_readw,
+ csr_87a_readl
+};
+
+static CPUWriteMemoryFunc * const csr_87a_writes[] = {
+ unassigned_mem_writeb,
+ unassigned_mem_writew,
+ csr_87a_writel
+};
+
+
+static void pyxis_line_change(void *opaque, int irq, int level)
+{
+ PyxisState *s = opaque;
+ uint64_t req;
+
+ /* Set/Reset the bit in INT_REQ based on IRQ+LEVEL. */
+ req = s->int_req;
+ if (level) {
+ req |= 1ull << irq;
+ } else {
+ req &= ~(1ull << irq);
+ }
+ s->int_req = req;
+
+ pyxis_irq_change(s);
+}
+
+static void pyxis_pci_set_irq(void *opaque, int irq_num, int level)
+{
+ qemu_irq *irqs = opaque;
+ qemu_set_irq(irqs[irq_num], level);
+}
+
+static int pyxis_pci_map_irq(PCIDevice *d, int irq_num)
+{
+ int slot = (d->devfn >> 3) & 3;
+
+ assert(irq_num >= 0 && irq_num <= 3);
+
+ return irq_num * 4 + (11 - slot);
+}
+
+PCIBus *pyxis_init(uint64_t ram_size, qemu_irq *p_isa_irq)
+{
+ const uint64_t GB = 1024 * 1024 * 1024;
+ DeviceState *dev;
+ PCIHostState *p;
+ PyxisState *s;
+ PCIBus *b;
+ int region;
+
+ dev = qdev_create(NULL, "pyxis-pcihost");
+ p = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
+ s = container_of(p, PyxisState, host);
+
+ s->irqs = qemu_allocate_irqs(pyxis_line_change, s, 64);
+ *p_isa_irq = s->irqs[7];
+
+ b = pci_register_bus(&s->host.busdev.qdev, "pci", pyxis_pci_set_irq,
+ pyxis_pci_map_irq, s->irqs, 0, 32);
+ s->host.bus = b;
+
+ qdev_init_nofail(dev);
+
+ /* Main memory region, 0x00.0000.0000, 8GB. */
+
+ /* Dummy memory region, 0x0e.0000.0000, 4GB. */
+ region = cpu_register_io_memory(dummy_reads, dummy_writes, s,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0xe00000000ull, 4*GB, region);
+
+ /* PCI Sparse memory region 0, 0x80.0000.0000, 16GB (covers 512MB). */
+ region = cpu_register_io_memory(sparse0_reads, sparse0_writes, s,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x8000000000ull, 16*GB, region);
+
+ /* PCI Sparse memory region 1, 0x84.0000.0000, 4GB (covers 128MB). */
+ region = cpu_register_io_memory(sparse1_reads, sparse1_writes, s,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x8400000000ull, 4*GB, region);
+
+ /* PCI Sparse memory region 2, 0x85.0000.0000, 2GB (covers 64MB). */
+ region = cpu_register_io_memory(sparse2_reads, sparse2_writes, s,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x8500000000ull, 2*GB, region);
+
+ /* PCI Sparse I/O region A, 0x85.8000.0000, 1GB (covers 32MB). */
+ region = cpu_register_io_memory(sparseA_reads, sparseA_writes, s,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x8580000000ull, 1*GB, region);
+
+ /* PCI Sparse I/O region B, 0x85.C000.0000, 1GB (covers 32MB). */
+ region = cpu_register_io_memory(sparseB_reads, sparseB_writes, s,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x85c0000000ull, 1*GB, region);
+
+ /* PCI Dense memory, 0x86.0000.0000, 4GB. */
+ region = cpu_register_io_memory(alpha_pci_dense_mem_reads,
+ alpha_pci_dense_mem_writes, b,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x8600000000ull, 4*GB, region);
+
+ /* Sparse configuration space, 0x87.0000.0000, 512MB. */
+ /* ??? Best I can tell, type 0 and type 1 accesses really only differ
+ when it comes to the actual bits placed on the PCI bus lines.
+ Which does not matter inside QEMU. Which means that the contents
+ of the CFG register doesn't really matter. */
+ region = cpu_register_io_memory(alpha_pci_sparse_conf1_reads,
+ alpha_pci_sparse_conf1_writes, b,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x8700000000ull, GB/2, region);
+
+ /* PCI special/interrupt acknowledge 0x87.2000.0000, 512MB. */
+ region = cpu_register_io_memory(alpha_pci_iack_reads,
+ alpha_pci_special_writes, b,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x8720000000ull, GB/2, region);
+
+ /* PYXIS Main CSRs, 0x87.4000.0000, 128MB. */
+ region = cpu_register_io_memory(csr_874_reads, csr_874_writes, s,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x8740000000ull, GB/4, region);
+
+ /* PYXIS Memory Control CSRs, 0x87.5000.0000, 128MB. */
+ region = cpu_register_io_memory(csr_875_reads, csr_875_writes, s,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x8750000000ull, GB/4, region);
+
+ /* PYXIS Address Translation CSRs, 0x87.6000.0000, 128MB. */
+ region = cpu_register_io_memory(csr_876_reads, csr_876_writes, s,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x8760000000ull, GB/4, region);
+
+ /* PYXIS Miscellaneous CSRs, 0x87.8000.0000, 128MB. */
+ region = cpu_register_io_memory(csr_878_reads, csr_878_writes, s,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x8780000000ull, GB/4, region);
+
+ /* ??? PYXIS Power Management CSRs, 0x87.9000.0000, 128MB. */
+
+ /* PYXIS Interrupt Control CSRs, 0x87.a000.0000, 128MB. */
+ region = cpu_register_io_memory(csr_87a_reads, csr_87a_writes, s,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x87a0000000ull, GB/4, region);
+
+ /* ??? Flash ROM read/write space, 0x87.c000.0000, 1GB. */
+
+ /* PCI BW memory, 0x88.0000.0000, 4GB. */
+ pci_bus_set_mem_base(b, 0x8800000000ull);
+
+ /* PCI BW I/O, 0x89.0000.0000, 4GB. */
+ region = cpu_register_io_memory(alpha_pci_bw_io_reads,
+ alpha_pci_bw_io_writes, b,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x8900000000ull, 4*GB, region);
+
+ /* PCI configuration space type 0, 0x8a.0000.0000, 4GB. */
+ /* ??? Best I can tell, type 0 and type 1 accesses really only differ
+ when it comes to the actual bits placed on the PCI bus lines.
+ Which does not matter inside QEMU. */
+ region = cpu_register_io_memory(alpha_pci_bw_conf1_reads,
+ alpha_pci_bw_conf1_writes, b,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x8a00000000ull, 4*GB, region);
+
+ /* PCI configuration space type 1, 0x8b.0000.0000, 4GB. */
+ region = cpu_register_io_memory(alpha_pci_bw_conf1_reads,
+ alpha_pci_bw_conf1_writes, b,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x8b00000000ull, 4*GB, region);
+
+ s->ram_size = ram_size;
+ /* Call reset function. */
+
+ return b;
+}
+
+static int pyxis_pcihost_init(SysBusDevice *dev)
+{
+ return 0;
+}
+
+static SysBusDeviceInfo pyxis_pcihost_info = {
+ .init = pyxis_pcihost_init,
+ .qdev.name = "pyxis-pcihost",
+ .qdev.size = sizeof(PyxisState),
+ .qdev.no_user = 1
+};
+
+static void pyxis_register(void)
+{
+ sysbus_register_withprop(&pyxis_pcihost_info);
+}
+device_init(pyxis_register);
diff --git a/hw/alpha_sx164.c b/hw/alpha_sx164.c
new file mode 100644
index 0000000..95e297c
--- /dev/null
+++ b/hw/alpha_sx164.c
@@ -0,0 +1,195 @@
+/*
+ * QEMU Alpha SX164 hardware system emulator.
+ */
+
+#include "hw.h"
+#include "elf.h"
+#include "loader.h"
+#include "boards.h"
+#include "alpha_sys.h"
+#include "sysemu.h"
+#include "mc146818rtc.h"
+
+
+#define MAX_IDE_BUS 2
+
+
+static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr)
+{
+ if (((addr >> 41) & 3) == 2) {
+ addr &= 0xffffffffffull;
+ }
+ return addr;
+}
+
+static void rtc_set_irq(void *opaque, int irq_num, int level)
+{
+ CPUState *env = first_cpu;
+ if (level) {
+ cpu_interrupt(env, CPU_INTERRUPT_TIMER);
+ } else {
+ cpu_reset_interrupt(env, CPU_INTERRUPT_TIMER);
+ }
+}
+
+static void sx164_init(ram_addr_t ram_size,
+ const char *boot_device,
+ const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename,
+ const char *cpu_model)
+{
+ CPUState *env = NULL;
+ ram_addr_t ram_offset;
+ PCIBus *pci_bus;
+ ISABus *isa_bus;
+ qemu_irq isa_pci_irq, *rtc_irqs, *isa_irqs;
+ long size, i;
+ const char *palcode_filename;
+ uint64_t palcode_entry, palcode_low, palcode_high;
+ uint64_t kernel_entry, kernel_low, kernel_high;
+
+ env = cpu_init(cpu_model ? cpu_model : "pca56");
+
+ env->trap_arg0 = ram_size;
+ env->trap_arg1 = 0;
+ env->trap_arg2 = 0;
+
+ ram_offset = qemu_ram_alloc(NULL, "ram", ram_size);
+ cpu_register_physical_memory(0, ram_size, ram_offset);
+
+ /* Init pyxis. */
+ pci_bus = pyxis_init(ram_size, &isa_pci_irq);
+
+ /* ??? There should be a Cypress CY82C693U SuperIO chip here
+ providing the PCI-to-ISA bridge. But the generic ISA support
+ doesn't expect a bridge, so we sort-of hard-code things in.
+ Ideally, the SuperIO device would capture all unhandled accesses
+ within the PCI space and then forward to the ISA bus. If the
+ access is unhandled within the ISA bus only then report to the
+ CPU via machine check. */
+ isa_bus = isa_bus_new(NULL);
+ isa_mem_base = 0x8800000000ull;
+
+ isa_irqs = i8259_init(isa_pci_irq);
+ isa_bus_irqs(isa_irqs);
+
+ /* ??? This isn't 100% correct, but should be Good Enough given that
+ we hide most of the actual details inside our custom PALcode.
+ The real HW somehow routes the TOY clock to cpu_int<2> (Int22).
+ How this relates to either the i8259 or the 21174 interrupt masks
+ is not documented. */
+ rtc_irqs = qemu_allocate_irqs(rtc_set_irq, NULL, 1);
+ rtc_init(1980, rtc_irqs[0]);
+
+ pit_init(0x40, 0);
+
+ /* VGA setup. Don't bother loading the bios. */
+ pci_vga_init(pci_bus);
+
+ for (i = 0; i < MAX_SERIAL_PORTS; ++i) {
+ if (serial_hds[i]) {
+ serial_isa_init(i, serial_hds[i]);
+ }
+ }
+
+#if 0
+ /* IDE setup. */
+ /* ??? Real SX164 actually has a Cypress CY82C693U. */
+ {
+ DriveInfo * hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+
+ if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
+ hw_error("qemu: too many IDE buses\n");
+ exit(1);
+ }
+
+ for (i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
+ hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
+ }
+ pci_cmd646_ide_init(pci_bus, hd, 0);
+ }
+#endif
+
+#if 0
+ /* USB setup. The Cypress chip is OHCI compliant; this ought not
+ be too far off Really Correct. */
+ usb_ohci_init_pci(pci_bus, -1);
+#endif
+
+ /* Network setup. NE2K is good enough, failing Tulip support. */
+ for (i = 0; i < nb_nics; i++) {
+ pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL);
+ }
+
+ /* Load PALcode. Given that this is not "real" cpu palcode,
+ but one explicitly written for the emulation, we might as
+ well load it directly from and ELF image. */
+ palcode_filename = (bios_name ? bios_name : "palcode-sx164");
+ palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, palcode_filename);
+ if (palcode_filename == NULL) {
+ hw_error("qemu: no palcode provided\n");
+ exit(1);
+ }
+ size = load_elf(palcode_filename, cpu_alpha_superpage_to_phys,
+ NULL, &palcode_entry, &palcode_low, &palcode_high,
+ 0, EM_ALPHA, 0);
+ if (size < 0) {
+ hw_error("qemu: could not load palcode '%s'\n", palcode_filename);
+ exit(1);
+ }
+ env->pc = palcode_entry;
+ env->palbr = palcode_entry;
+
+ /* Load a kernel. */
+ if (kernel_filename) {
+ uint64_t param_offset;
+
+ size = load_elf(kernel_filename, cpu_alpha_superpage_to_phys,
+ NULL, &kernel_entry, &kernel_low, &kernel_high,
+ 0, EM_ALPHA, 0);
+ if (size < 0) {
+ hw_error("qemu: could not load kernel '%s'\n", kernel_filename);
+ exit(1);
+ }
+
+ env->trap_arg1 = kernel_entry;
+
+ param_offset = kernel_low - 0x6000;
+
+ if (kernel_cmdline) {
+ pstrcpy_targphys("cmdline", param_offset, 0x100, kernel_cmdline);
+ }
+
+ if (initrd_filename) {
+ long initrd_base, initrd_size;
+
+ initrd_base = (kernel_high | TARGET_PAGE_SIZE) + 1;
+ initrd_size = load_image_targphys(initrd_filename, initrd_base,
+ ram_size - initrd_base);
+ if (initrd_size < 0) {
+ hw_error("qemu: could not load initial ram disk '%s'\n",
+ initrd_filename);
+ exit(1);
+ }
+
+ stq_phys(param_offset + 0x100, initrd_base);
+ stq_phys(param_offset + 0x108, initrd_size);
+ }
+ }
+}
+
+static QEMUMachine sx164_machine = {
+ .name = "sx164",
+ .desc = "Alpha SX164",
+ .init = sx164_init,
+ .max_cpus = 1,
+ .is_default = 1,
+};
+
+static void sx164_machine_init(void)
+{
+ qemu_register_machine(&sx164_machine);
+}
+
+machine_init(sx164_machine_init);
diff --git a/hw/alpha_sys.h b/hw/alpha_sys.h
new file mode 100644
index 0000000..43e9892
--- /dev/null
+++ b/hw/alpha_sys.h
@@ -0,0 +1,41 @@
+/* Alpha cores and system support chips. */
+
+#ifndef HW_ALPHA_H
+#define HW_ALPHA_H 1
+
+#include "pci.h"
+#include "pci_host.h"
+#include "ide.h"
+#include "net.h"
+#include "pc.h"
+#include "usb-ohci.h"
+#include "irq.h"
+
+
+extern PCIBus *pyxis_init(uint64_t, qemu_irq *);
+
+/* alpha_pci.c. */
+extern CPUReadMemoryFunc * const alpha_pci_bw_io_reads[];
+extern CPUWriteMemoryFunc * const alpha_pci_bw_io_writes[];
+extern CPUReadMemoryFunc * const alpha_pci_bw_conf1_reads[];
+extern CPUWriteMemoryFunc * const alpha_pci_bw_conf1_writes[];
+
+extern CPUReadMemoryFunc * const alpha_pci_dense_mem_reads[];
+extern CPUWriteMemoryFunc * const alpha_pci_dense_mem_writes[];
+
+extern CPUReadMemoryFunc * const alpha_pci_sparse_conf1_reads[];
+extern CPUWriteMemoryFunc * const alpha_pci_sparse_conf1_writes[];
+
+extern CPUReadMemoryFunc * const alpha_pci_iack_reads[];
+extern CPUWriteMemoryFunc * const alpha_pci_special_writes[];
+
+extern uint32_t alpha_sparse_io_read(target_phys_addr_t);
+extern void alpha_sparse_io_write(target_phys_addr_t, uint32_t);
+
+extern uint32_t alpha_sparse_mem_read(PCIBus *, target_phys_addr_t);
+extern void alpha_sparse_mem_write(PCIBus *, target_phys_addr_t, uint32_t);
+
+extern uint32_t alpha_sparse_conf1_read(PCIBus *, target_phys_addr_t);
+extern void alpha_sparse_conf1_write(PCIBus *, target_phys_addr_t, uint32_t);
+
+#endif
--
1.7.3.4
^ permalink raw reply related [flat|nested] 35+ messages in thread
* Re: [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2
2011-04-19 15:04 [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Richard Henderson
` (23 preceding siblings ...)
2011-04-19 15:05 ` [Qemu-devel] [PATCH 24/24] target-alpha: Add SX164 emulation Richard Henderson
@ 2011-04-20 9:06 ` Tristan Gingold
2011-04-20 14:13 ` Brian Wheeler
2011-04-20 14:46 ` Richard Henderson
24 siblings, 2 replies; 35+ messages in thread
From: Tristan Gingold @ 2011-04-20 9:06 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Apr 19, 2011, at 5:04 PM, Richard Henderson wrote:
> Changes from v1 to v2:
> - Split patch 5 up into little pieces. These pieces were compile
> tested by applying patch 23 (Enable alpha-softmmu) out of sequence
> so that both softmmu and linux-user targets were built. But in
> the end I chickened out and re-ordered the enable patch to last.
>
> - The TB->FLAGS patch is more comprehensive. In doing the split I
> noticed that we were doing funny things with AMASK that really
> ought to have belonged in the TB in the first place.
>
> - The patch for unassigned addresses is more comprehensive. I had
> previously failed to do the if-deffing dance in the generic part
> of QEMU.
>
> - The PALcode source is added as a submodule.
Richard,
it looks like I miss the v1. Anyway, some random comments:
* thank you for working on that!
* sx164 is ev56 based, isn't it ? It would be nice if cpu version specific code is clearly marked.
In particular (and IIRC), pal mode for ev6 is much closer to ev4 than to ev5. Don't know about ev7.
It would be nice if we could easily support both ev5 and ev6.
* Yes, executive and supervisor are used only by VMS (well AFAIK). I'd like to support it.
Did you try to also support the windows mmu mode ?
* Again, thank you for working on that.
Tristan.
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2
2011-04-20 9:06 ` [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Tristan Gingold
@ 2011-04-20 14:13 ` Brian Wheeler
2011-04-20 14:46 ` Richard Henderson
1 sibling, 0 replies; 35+ messages in thread
From: Brian Wheeler @ 2011-04-20 14:13 UTC (permalink / raw)
To: Tristan Gingold; +Cc: qemu-devel, Richard Henderson
I'd like to second Tristan in saying that I'm glad someone is working on
alpha system emulation -- its long overdue!
Brian
On Wed, 2011-04-20 at 11:06 +0200, Tristan Gingold wrote:
> On Apr 19, 2011, at 5:04 PM, Richard Henderson wrote:
>
> > Changes from v1 to v2:
> > - Split patch 5 up into little pieces. These pieces were compile
> > tested by applying patch 23 (Enable alpha-softmmu) out of sequence
> > so that both softmmu and linux-user targets were built. But in
> > the end I chickened out and re-ordered the enable patch to last.
> >
> > - The TB->FLAGS patch is more comprehensive. In doing the split I
> > noticed that we were doing funny things with AMASK that really
> > ought to have belonged in the TB in the first place.
> >
> > - The patch for unassigned addresses is more comprehensive. I had
> > previously failed to do the if-deffing dance in the generic part
> > of QEMU.
> >
> > - The PALcode source is added as a submodule.
>
> Richard,
>
> it looks like I miss the v1. Anyway, some random comments:
>
> * thank you for working on that!
>
> * sx164 is ev56 based, isn't it ? It would be nice if cpu version specific code is clearly marked.
> In particular (and IIRC), pal mode for ev6 is much closer to ev4 than to ev5. Don't know about ev7.
> It would be nice if we could easily support both ev5 and ev6.
>
> * Yes, executive and supervisor are used only by VMS (well AFAIK). I'd like to support it.
> Did you try to also support the windows mmu mode ?
>
> * Again, thank you for working on that.
>
> Tristan.
>
>
>
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2
2011-04-20 9:06 ` [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2 Tristan Gingold
2011-04-20 14:13 ` Brian Wheeler
@ 2011-04-20 14:46 ` Richard Henderson
2011-04-20 15:46 ` Tristan Gingold
1 sibling, 1 reply; 35+ messages in thread
From: Richard Henderson @ 2011-04-20 14:46 UTC (permalink / raw)
To: Tristan Gingold; +Cc: qemu-devel
On 04/20/2011 02:06 AM, Tristan Gingold wrote:
> * sx164 is ev56 based, isn't it ? It would be nice if cpu version specific code is clearly marked.
Yes, but most importantly it is the most evolved of the single hose systems.
QEMU is nowhere near ready to deal with multiple PCI host controllers, and
multiple ISA buses.
I actually planned on emulating an EV67 but using the SX164 HW. I think the
Linux kernel will be that forgiving...
> In particular (and IIRC), pal mode for ev6 is much closer to ev4 than to ev5. Don't know about ev7.
> It would be nice if we could easily support both ev5 and ev6.
Ah, see, here's where there may be some confusion...
I'm not implementing any of the real cpu ISRs. I'm not using any of the real
PALcode. I'm implementing my own QEMU-specific ISRs and and writing my own
PALcode, starting with MILO's PALcode but I've diverged significantly since.
I'm also cheating a bit and implementing a number of the simple CALL_PALs
inline in QEMU. But that really started when I discovered how confused gdb
could get attempting to step across a transition to/from PALmode.
> * Yes, executive and supervisor are used only by VMS (well AFAIK). I'd like to support it.
Well, if you'd like to help write the PALcode for VMS, sure. It certainly
looks like a larger job than the Unix PALcode.
> Did you try to also support the windows mmu mode ?
Nope. I can't really imagine that being of interest to anyone.
r~
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2
2011-04-20 14:46 ` Richard Henderson
@ 2011-04-20 15:46 ` Tristan Gingold
2011-04-20 15:54 ` Richard Henderson
0 siblings, 1 reply; 35+ messages in thread
From: Tristan Gingold @ 2011-04-20 15:46 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Apr 20, 2011, at 4:46 PM, Richard Henderson wrote:
> On 04/20/2011 02:06 AM, Tristan Gingold wrote:
>> * sx164 is ev56 based, isn't it ? It would be nice if cpu version specific code is clearly marked.
>
> Yes, but most importantly it is the most evolved of the single hose systems.
> QEMU is nowhere near ready to deal with multiple PCI host controllers, and
> multiple ISA buses.
Right, but you could create an ev67 machine with a single PCI controller (or put all the devices on the same
PCI controller).
> I actually planned on emulating an EV67 but using the SX164 HW. I think the
> Linux kernel will be that forgiving...
>
>> In particular (and IIRC), pal mode for ev6 is much closer to ev4 than to ev5. Don't know about ev7.
>> It would be nice if we could easily support both ev5 and ev6.
>
> Ah, see, here's where there may be some confusion...
>
> I'm not implementing any of the real cpu ISRs. I'm not using any of the real
> PALcode. I'm implementing my own QEMU-specific ISRs and and writing my own
> PALcode, starting with MILO's PALcode but I've diverged significantly since.
Ah, ok I understand. I fear that if you implement your own ISR, you will only be able to boot linux...
which I suppose is your primary target. OTOH, it will be much faster than a native ISR.
Tristan.
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2
2011-04-20 15:46 ` Tristan Gingold
@ 2011-04-20 15:54 ` Richard Henderson
2011-04-21 12:31 ` Tristan Gingold
0 siblings, 1 reply; 35+ messages in thread
From: Richard Henderson @ 2011-04-20 15:54 UTC (permalink / raw)
To: Tristan Gingold; +Cc: qemu-devel
On 04/20/2011 08:46 AM, Tristan Gingold wrote:
> Right, but you could create an ev67 machine with a single PCI
> controller (or put all the devices on the same PCI controller).
Even the lowly ds10 has two hoses.
I'll admit I hadn't considered engineering the second hose to
be "present" but always appear empty. It's something to consider.
> Ah, ok I understand. I fear that if you implement your own ISR, you will only be able to boot linux...
> which I suppose is your primary target. OTOH, it will be much faster than a native ISR.
Yes, Linux is the primary goal.
But I suspect that if I implemented enough of CALL_PAL CSERVE,
you could boot Tru64, or at least one of the BSDs.
r~
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2
2011-04-20 15:54 ` Richard Henderson
@ 2011-04-21 12:31 ` Tristan Gingold
2011-04-21 13:37 ` Brian Wheeler
0 siblings, 1 reply; 35+ messages in thread
From: Tristan Gingold @ 2011-04-21 12:31 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
On Apr 20, 2011, at 5:54 PM, Richard Henderson wrote:
> On 04/20/2011 08:46 AM, Tristan Gingold wrote:
>> Right, but you could create an ev67 machine with a single PCI
>> controller (or put all the devices on the same PCI controller).
>
> Even the lowly ds10 has two hoses.
>
> I'll admit I hadn't considered engineering the second hose to
> be "present" but always appear empty. It's something to consider.
>
>> Ah, ok I understand. I fear that if you implement your own ISR, you will only be able to boot linux...
>> which I suppose is your primary target. OTOH, it will be much faster than a native ISR.
>
> Yes, Linux is the primary goal.
>
> But I suspect that if I implemented enough of CALL_PAL CSERVE,
> you could boot Tru64, or at least one of the BSDs.
BSD should be doable, but I doubt for Tru64. Do you have technical doc about the SRM ?
IIRC, the SRM uses its own palcode and SRM specific pal calls.
Tristan.
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2
2011-04-21 12:31 ` Tristan Gingold
@ 2011-04-21 13:37 ` Brian Wheeler
2011-04-21 13:43 ` Tristan Gingold
0 siblings, 1 reply; 35+ messages in thread
From: Brian Wheeler @ 2011-04-21 13:37 UTC (permalink / raw)
To: Tristan Gingold; +Cc: qemu-devel, Richard Henderson
On Thu, 2011-04-21 at 14:31 +0200, Tristan Gingold wrote:
> On Apr 20, 2011, at 5:54 PM, Richard Henderson wrote:
>
> > On 04/20/2011 08:46 AM, Tristan Gingold wrote:
> >> Right, but you could create an ev67 machine with a single PCI
> >> controller (or put all the devices on the same PCI controller).
> >
> > Even the lowly ds10 has two hoses.
> >
> > I'll admit I hadn't considered engineering the second hose to
> > be "present" but always appear empty. It's something to consider.
> >
> >> Ah, ok I understand. I fear that if you implement your own ISR, you will only be able to boot linux...
> >> which I suppose is your primary target. OTOH, it will be much faster than a native ISR.
> >
> > Yes, Linux is the primary goal.
> >
> > But I suspect that if I implemented enough of CALL_PAL CSERVE,
> > you could boot Tru64, or at least one of the BSDs.
>
> BSD should be doable, but I doubt for Tru64. Do you have technical doc about the SRM ?
> IIRC, the SRM uses its own palcode and SRM specific pal calls.
>
The palcode with milo was a subset of the tru64 palcode, I think.
Looking at the arch reference manual and assuming that the calls take
the same parameters, the only difference is that tru64 has "urti -
return from user mode trap" and linux doesn't.
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2
2011-04-21 13:37 ` Brian Wheeler
@ 2011-04-21 13:43 ` Tristan Gingold
2011-04-21 14:48 ` Brian Wheeler
0 siblings, 1 reply; 35+ messages in thread
From: Tristan Gingold @ 2011-04-21 13:43 UTC (permalink / raw)
To: Brian Wheeler; +Cc: qemu-devel, Richard Henderson
On Apr 21, 2011, at 3:37 PM, Brian Wheeler wrote:
> On Thu, 2011-04-21 at 14:31 +0200, Tristan Gingold wrote:
>> On Apr 20, 2011, at 5:54 PM, Richard Henderson wrote:
>>
>>> On 04/20/2011 08:46 AM, Tristan Gingold wrote:
>>>> Right, but you could create an ev67 machine with a single PCI
>>>> controller (or put all the devices on the same PCI controller).
>>>
>>> Even the lowly ds10 has two hoses.
>>>
>>> I'll admit I hadn't considered engineering the second hose to
>>> be "present" but always appear empty. It's something to consider.
>>>
>>>> Ah, ok I understand. I fear that if you implement your own ISR, you will only be able to boot linux...
>>>> which I suppose is your primary target. OTOH, it will be much faster than a native ISR.
>>>
>>> Yes, Linux is the primary goal.
>>>
>>> But I suspect that if I implemented enough of CALL_PAL CSERVE,
>>> you could boot Tru64, or at least one of the BSDs.
>>
>> BSD should be doable, but I doubt for Tru64. Do you have technical doc about the SRM ?
>> IIRC, the SRM uses its own palcode and SRM specific pal calls.
>>
>
> The palcode with milo was a subset of the tru64 palcode, I think.
> Looking at the arch reference manual and assuming that the calls take
> the same parameters, the only difference is that tru64 has "urti -
> return from user mode trap" and linux doesn't.
Yes, Linux runs on Tru64 palcode. But the issue is booting the Tru64 kernel.
Tristan.
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2
2011-04-21 13:43 ` Tristan Gingold
@ 2011-04-21 14:48 ` Brian Wheeler
2011-04-21 14:57 ` Richard Henderson
0 siblings, 1 reply; 35+ messages in thread
From: Brian Wheeler @ 2011-04-21 14:48 UTC (permalink / raw)
To: Tristan Gingold; +Cc: qemu-devel, Richard Henderson
On Thu, 2011-04-21 at 15:43 +0200, Tristan Gingold wrote:
> On Apr 21, 2011, at 3:37 PM, Brian Wheeler wrote:
>
> > On Thu, 2011-04-21 at 14:31 +0200, Tristan Gingold wrote:
> >> On Apr 20, 2011, at 5:54 PM, Richard Henderson wrote:
> >>
> >>> On 04/20/2011 08:46 AM, Tristan Gingold wrote:
> >>>> Right, but you could create an ev67 machine with a single PCI
> >>>> controller (or put all the devices on the same PCI controller).
> >>>
> >>> Even the lowly ds10 has two hoses.
> >>>
> >>> I'll admit I hadn't considered engineering the second hose to
> >>> be "present" but always appear empty. It's something to consider.
> >>>
> >>>> Ah, ok I understand. I fear that if you implement your own ISR, you will only be able to boot linux...
> >>>> which I suppose is your primary target. OTOH, it will be much faster than a native ISR.
> >>>
> >>> Yes, Linux is the primary goal.
> >>>
> >>> But I suspect that if I implemented enough of CALL_PAL CSERVE,
> >>> you could boot Tru64, or at least one of the BSDs.
> >>
> >> BSD should be doable, but I doubt for Tru64. Do you have technical doc about the SRM ?
> >> IIRC, the SRM uses its own palcode and SRM specific pal calls.
> >>
> >
> > The palcode with milo was a subset of the tru64 palcode, I think.
> > Looking at the arch reference manual and assuming that the calls take
> > the same parameters, the only difference is that tru64 has "urti -
> > return from user mode trap" and linux doesn't.
>
> Yes, Linux runs on Tru64 palcode. But the issue is booting the Tru64 kernel.
>
> Tristan.
>
Ah, gotcha. It almost seems like the console could actually be
implemented in qemu itself, rather than a guest side thing, as long as
it looks like part III of the ARM :) It might simplify things quite a
bit: the console callbacks look like they can be translated into qemu
calls and the bootstrapping looks like its a read block zero of selected
device + other blocks specified, setup hwrpb and start emulation. It
looks like its standard across all OSes, with the possible exception of
NT.
*shrug* I'm just an innocent bystander, though.
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [Qemu-devel] [PATCH 00/24] Alpha system emulation, v2
2011-04-21 14:48 ` Brian Wheeler
@ 2011-04-21 14:57 ` Richard Henderson
0 siblings, 0 replies; 35+ messages in thread
From: Richard Henderson @ 2011-04-21 14:57 UTC (permalink / raw)
To: Brian Wheeler; +Cc: Tristan Gingold, qemu-devel
On 04/21/2011 07:48 AM, Brian Wheeler wrote:
> On Thu, 2011-04-21 at 15:43 +0200, Tristan Gingold wrote:
>> On Apr 21, 2011, at 3:37 PM, Brian Wheeler wrote:
>>
>>> On Thu, 2011-04-21 at 14:31 +0200, Tristan Gingold wrote:
>>>> On Apr 20, 2011, at 5:54 PM, Richard Henderson wrote:
>>>>
>>>>> On 04/20/2011 08:46 AM, Tristan Gingold wrote:
>>>> BSD should be doable, but I doubt for Tru64. Do you have technical doc about the SRM ?
>>>> IIRC, the SRM uses its own palcode and SRM specific pal calls.
IIRC the main thing that was lacking between SRM and the Evaluation Board PALcode
that was used in MILO is the Console Callback (CCB) structure and routines.
> Ah, gotcha. It almost seems like the console could actually be
> implemented in qemu itself, rather than a guest side thing, as long as
> it looks like part III of the ARM :)
My first try last year was going down this path. It turned out to be irritatingly
difficult to manage the data setup inside QEMU itself. Thus I came to be writing a
custom PALcode image that makes a number of simplifying assumptions based on the
ability to off-load some work to QEMU.
r~
^ permalink raw reply [flat|nested] 35+ messages in thread