* [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4
@ 2011-05-09 21:34 Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 01/35] Export the unassigned_mem read/write functions Richard Henderson
` (35 more replies)
0 siblings, 36 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 UTC (permalink / raw)
To: qemu-devel
Since virtio devices intentionally access memory directly, we
are not actually dependant on the iommu patches in order to
make progress. Merely fixing the PCI interrupt setup was
enough to get the virtio-pci interface working.
We now make it quite a long way into the Debian Lenny install.
At some random point during the install, it hangs. I assume
we're somehow losing an interrupt or something, but it's very
hard to tell. The cpu is still running, servicing timer
interrupts, but the userland process is stuck.
I hope to get the vga console working next. That should allow
me multiple vt's, which should allow me to poke at the install
process from within the VM.
I still havn't gotten any substantive review of the hw/ side
of the patches, which is the part of Qemu that I'm least
familiar with. Pretty please?
r~
Changes from v3 -> v4
* Rebased vs mainline (85097db).
* PCI IDE, VGA devices added;
* PS2 keyboard device added.
* PCI interrupt setup fixed.
* Git submodule and blob updated to current.
- Copyright notices added, as appropritate
- PCI initialization added.
- Very beginnings of an SRM prompt.
Changes from v2 -> v3
* Emulation target is now CLIPPER instead of SX164.
* Allow the CPU to halt til the next interrupt.
* Allow the CPU access to the host clock, and a high-res alarm.
* Fix gdb single-stepping in the presence of timer interrupts.
* Fix gdb single-stepping past branches.
* We now make it all the way into userland.
Richard Henderson (35):
Export the unassigned_mem read/write functions.
target-alpha: Disassemble EV6 PALcode instructions.
pci: Export pci_to_cpu_addr.
target-alpha: Single-step properly across branches.
target-alpha: Remove partial support for palcode emulation.
target-alpha: Enable the alpha-softmmu target.
target-alpha: Tidy exception constants.
target-alpha: Rationalize internal processor registers.
target-alpha: Cleanup MMU modes.
target-alpha: Fixup translation of PALmode instructions.
target-alpha: Add IPRs to be used by the emulation PALcode.
target-alpha: Tidy up arithmetic exceptions.
target-alpha: Use do_restore_state for arithmetic exceptions.
target-alpha: Merge HW_REI and HW_RET implementations.
target-alpha: Implement do_interrupt for system mode.
target-alpha: Swap shadow registers moving to/from PALmode.
target-alpha: Add various symbolic constants.
target-alpha: Use kernel mmu_idx for pal_mode.
target-alpha: All ISA checks to use TB->FLAGS.
target-alpha: Disable interrupts properly.
target-alpha: Implement more CALL_PAL values inline.
target-alpha: Implement cpu_alpha_handle_mmu_fault for system mode.
target-alpha: Remap PIO space for 43-bit KSEG for EV6.
target-alpha: Trap for unassigned and unaligned addresses.
target-alpha: Include the PCC_OFS in the RPCC return value.
target-alpha: Use a fixed frequency for the RPCC in system mode.
target-alpha: Implement TLB flush primitives.
target-alpha: Add custom PALcode image for CLIPPER emulation.
target-alpha: Add CLIPPER emulation.
target-alpha: Implement WAIT IPR.
target-alpha: Implement HALT IPR.
target-alpha: Add high-resolution access to wall clock and an alarm.
target-alpha: Properly select the VGA controler to use.
target-alpha: Enable PCI IDE
target-alpha: Add ps2 keyboard.
.gitmodules | 3 +
Makefile | 3 +-
Makefile.target | 4 +-
alpha-dis.c | 4 -
configure | 9 +-
cpu-common.h | 7 +
cpu-exec.c | 33 +-
default-configs/alpha-softmmu.mak | 11 +
dis-asm.h | 3 +
disas.c | 2 +-
exec-all.h | 2 +-
exec.c | 24 +-
hw/alpha_dp264.c | 188 +++++++
hw/alpha_palcode.c | 1048 -------------------------------------
hw/alpha_pci.c | 358 +++++++++++++
hw/alpha_sys.h | 44 ++
hw/alpha_typhoon.c | 799 ++++++++++++++++++++++++++++
hw/pci.c | 3 +-
hw/pci.h | 1 +
linux-user/main.c | 50 +--
pc-bios/README | 3 +
pc-bios/palcode-clipper | Bin 0 -> 176851 bytes
roms/qemu-palcode | 1 +
target-alpha/cpu.h | 378 ++++++--------
target-alpha/exec.h | 12 +-
target-alpha/helper.c | 589 +++++++++------------
target-alpha/helper.h | 37 +-
target-alpha/machine.c | 87 +++
target-alpha/op_helper.c | 289 +++++------
target-alpha/translate.c | 836 +++++++++++++++++------------
30 files changed, 2659 insertions(+), 2169 deletions(-)
create mode 100644 default-configs/alpha-softmmu.mak
create mode 100644 hw/alpha_dp264.c
delete mode 100644 hw/alpha_palcode.c
create mode 100644 hw/alpha_pci.c
create mode 100644 hw/alpha_sys.h
create mode 100644 hw/alpha_typhoon.c
create mode 100755 pc-bios/palcode-clipper
create mode 160000 roms/qemu-palcode
create mode 100644 target-alpha/machine.c
--
1.7.4.4
^ permalink raw reply [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 01/35] Export the unassigned_mem read/write functions.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 02/35] target-alpha: Disassemble EV6 PALcode instructions Richard Henderson
` (34 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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 6410ccc..6e48917 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -56,6 +56,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 308a86d..0b8ab5b 100644
--- a/exec.c
+++ b/exec.c
@@ -3107,7 +3107,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);
@@ -3118,7 +3118,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);
@@ -3129,7 +3129,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);
@@ -3140,7 +3140,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);
@@ -3150,7 +3150,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);
@@ -3160,7 +3160,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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 02/35] target-alpha: Disassemble EV6 PALcode instructions.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 01/35] Export the unassigned_mem read/write functions Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 03/35] pci: Export pci_to_cpu_addr Richard Henderson
` (33 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 03/35] pci: Export pci_to_cpu_addr.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 01/35] Export the unassigned_mem read/write functions Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 02/35] target-alpha: Disassemble EV6 PALcode instructions Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 04/35] target-alpha: Single-step properly across branches Richard Henderson
` (32 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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 0875654..0b2b943 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -800,8 +800,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 c6a6eb6..8615cc2 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -246,6 +246,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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 04/35] target-alpha: Single-step properly across branches.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (2 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 03/35] pci: Export pci_to_cpu_addr Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 05/35] target-alpha: Remove partial support for palcode emulation Richard Henderson
` (31 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 UTC (permalink / raw)
To: qemu-devel
We were failing to generate EXC_DEBUG in the EXIT_PC_UPDATED path.
This caused us not to stop at the instruction after a branch, but
on the instruction afterward.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/translate.c | 35 ++++++++++++++++++++---------------
1 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 456ba51..194a286 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -147,17 +147,21 @@ static void alpha_translate_init(void)
done_init = 1;
}
-static ExitStatus gen_excp(DisasContext *ctx, int exception, int error_code)
+static void gen_excp_1(int exception, int error_code)
{
TCGv_i32 tmp1, tmp2;
- tcg_gen_movi_i64(cpu_pc, ctx->pc);
tmp1 = tcg_const_i32(exception);
tmp2 = tcg_const_i32(error_code);
gen_helper_excp(tmp1, tmp2);
tcg_temp_free_i32(tmp2);
tcg_temp_free_i32(tmp1);
+}
+static ExitStatus gen_excp(DisasContext *ctx, int exception, int error_code)
+{
+ tcg_gen_movi_i64(cpu_pc, ctx->pc);
+ gen_excp_1(exception, error_code);
return EXIT_NORETURN;
}
@@ -3211,18 +3215,15 @@ static inline void gen_intermediate_code_internal(CPUState *env,
ctx.pc += 4;
ret = translate_one(ctxp, insn);
- if (ret == NO_EXIT) {
- /* If we reach a page boundary, are single stepping,
- or exhaust instruction count, stop generation. */
- if (env->singlestep_enabled) {
- gen_excp(&ctx, EXCP_DEBUG, 0);
- ret = EXIT_PC_UPDATED;
- } else if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0
- || gen_opc_ptr >= gen_opc_end
- || num_insns >= max_insns
- || singlestep) {
- ret = EXIT_PC_STALE;
- }
+ /* If we reach a page boundary, are single stepping,
+ or exhaust instruction count, stop generation. */
+ if (ret == NO_EXIT
+ && ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0
+ || gen_opc_ptr >= gen_opc_end
+ || num_insns >= max_insns
+ || singlestep
+ || env->singlestep_enabled)) {
+ ret = EXIT_PC_STALE;
}
} while (ret == NO_EXIT);
@@ -3238,7 +3239,11 @@ static inline void gen_intermediate_code_internal(CPUState *env,
tcg_gen_movi_i64(cpu_pc, ctx.pc);
/* FALLTHRU */
case EXIT_PC_UPDATED:
- tcg_gen_exit_tb(0);
+ if (env->singlestep_enabled) {
+ gen_excp_1(EXCP_DEBUG, 0);
+ } else {
+ tcg_gen_exit_tb(0);
+ }
break;
default:
abort();
--
1.7.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 05/35] target-alpha: Remove partial support for palcode emulation.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (3 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 04/35] target-alpha: Single-step properly across branches Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 06/35] target-alpha: Enable the alpha-softmmu target Richard Henderson
` (30 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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 21f864a..3abecd2 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -364,7 +364,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 194a286..c9fd16f 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3335,8 +3335,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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 06/35] target-alpha: Enable the alpha-softmmu target.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (4 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 05/35] target-alpha: Remove partial support for palcode emulation Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 07/35] target-alpha: Tidy exception constants Richard Henderson
` (29 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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 3abecd2..2f842c1 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -364,7 +364,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 6f75e2e..214aabc 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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 07/35] target-alpha: Tidy exception constants.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (5 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 06/35] target-alpha: Enable the alpha-softmmu target Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 08/35] target-alpha: Rationalize internal processor registers Richard Henderson
` (28 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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.
---
linux-user/main.c | 44 ++++++++++++++------------------------------
target-alpha/cpu.h | 34 ++++++++++++++--------------------
target-alpha/helper.c | 6 +-----
target-alpha/translate.c | 4 ++--
4 files changed, 31 insertions(+), 57 deletions(-)
diff --git a/linux-user/main.c b/linux-user/main.c
index a1e37e4..2a29088 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2526,19 +2526,13 @@ 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_SMP_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 +2541,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 +2558,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 +2662,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..8c73d5d 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -391,26 +391,20 @@ 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_SMP_INTERRUPT,
+ 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 c9fd16f..63a0321 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1516,7 +1516,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
@@ -1524,7 +1524,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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 08/35] target-alpha: Rationalize internal processor registers.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (6 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 07/35] target-alpha: Tidy exception constants Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 09/35] target-alpha: Cleanup MMU modes Richard Henderson
` (27 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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 2a29088..839c547 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2536,9 +2536,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:
@@ -2546,7 +2546,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 8c73d5d..1fc21dc 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
@@ -467,8 +344,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 4ccb10b..fde14c4 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;
@@ -1174,21 +1174,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 63a0321..d81e617 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3330,42 +3330,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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 09/35] target-alpha: Cleanup MMU modes.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (7 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 08/35] target-alpha: Rationalize internal processor registers Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 10/35] target-alpha: Fixup translation of PALmode instructions Richard Henderson
` (26 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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 1fc21dc..bdd396c 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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 10/35] target-alpha: Fixup translation of PALmode instructions.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (8 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 09/35] target-alpha: Cleanup MMU modes Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 11/35] target-alpha: Add IPRs to be used by the emulation PALcode Richard Henderson
` (25 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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 bdd396c..60b753f 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 fde14c4..73e5805 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1156,167 +1156,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 d81e617..b14b8fc 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -326,7 +326,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) {
@@ -349,7 +349,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) {
@@ -357,7 +357,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);
@@ -2580,11 +2580,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:
@@ -2616,27 +2612,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 */
@@ -2646,51 +2641,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);
@@ -2879,18 +2856,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:
@@ -2900,21 +2866,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:
@@ -2940,30 +2892,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;
@@ -2984,18 +2932,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;
@@ -3160,12 +3100,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
@@ -3334,8 +3269,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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 11/35] target-alpha: Add IPRs to be used by the emulation PALcode.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (9 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 10/35] target-alpha: Fixup translation of PALmode instructions Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 12/35] target-alpha: Tidy up arithmetic exceptions Richard Henderson
` (24 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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 60b753f..60445dc 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 b14b8fc..9e1576d 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1468,6 +1468,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;
@@ -2580,7 +2663,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:
@@ -2856,7 +2939,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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 12/35] target-alpha: Tidy up arithmetic exceptions.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (10 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 11/35] target-alpha: Add IPRs to be used by the emulation PALcode Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 13/35] target-alpha: Use do_restore_state for " Richard Henderson
` (23 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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 73e5805..672940e 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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 13/35] target-alpha: Use do_restore_state for arithmetic exceptions.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (11 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 12/35] target-alpha: Tidy up arithmetic exceptions Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 14/35] target-alpha: Merge HW_REI and HW_RET implementations Richard Henderson
` (22 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 UTC (permalink / raw)
To: qemu-devel
This gets the PC right after an arithmetic exception. Also tidies
the code in the TLB fault handlers to use common code.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/op_helper.c | 49 ++++++++++++++++++++++++++++-----------------
1 files changed, 30 insertions(+), 19 deletions(-)
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 672940e..fc5020a 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -25,20 +25,42 @@
/*****************************************************************************/
/* Exceptions processing helpers */
-void QEMU_NORETURN helper_excp (int excp, int error)
+
+/* This should only be called from translate, via gen_excp.
+ We expect that ENV->PC has already been updated. */
+void QEMU_NORETURN helper_excp(int excp, int error)
+{
+ env->exception_index = excp;
+ env->error_code = error;
+ cpu_loop_exit();
+}
+
+static void do_restore_state(void *retaddr)
+{
+ unsigned long pc = (unsigned long)retaddr;
+
+ if (pc) {
+ TranslationBlock *tb = tb_find_pc(pc);
+ if (tb) {
+ cpu_restore_state(tb, env, pc);
+ }
+ }
+}
+
+/* This may be called from any of the helpers to set up EXCEPTION_INDEX. */
+static void QEMU_NORETURN dynamic_excp(int excp, int error)
{
env->exception_index = excp;
env->error_code = error;
+ do_restore_state(GETPC());
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();
+ dynamic_excp(EXCP_ARITH, 0);
}
uint64_t helper_load_pcc (void)
@@ -521,7 +543,7 @@ static inline float32 f_to_float32(uint64_t a)
if (unlikely(!exp && mant_sig)) {
/* Reserved operands / Dirty zero */
- helper_excp(EXCP_OPCDEC, 0);
+ dynamic_excp(EXCP_OPCDEC, 0);
}
if (exp < 3) {
@@ -651,7 +673,7 @@ static inline float64 g_to_float64(uint64_t a)
if (!exp && mant_sig) {
/* Reserved operands / Dirty zero */
- helper_excp(EXCP_OPCDEC, 0);
+ dynamic_excp(EXCP_OPCDEC, 0);
}
if (exp < 3) {
@@ -1260,9 +1282,7 @@ uint64_t helper_stq_c_phys(uint64_t p, uint64_t v)
/* XXX: fix it to restore all registers */
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
{
- TranslationBlock *tb;
CPUState *saved_env;
- unsigned long pc;
int ret;
/* XXX: hack to restore env in all cases, even if not called from
@@ -1270,17 +1290,8 @@ 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 (likely(retaddr)) {
- /* now we have a real cpu fault */
- pc = (unsigned long)retaddr;
- tb = tb_find_pc(pc);
- if (likely(tb)) {
- /* the PC is inside the translated code. It means that we have
- a virtual CPU fault */
- cpu_restore_state(tb, env, pc);
- }
- }
+ if (unlikely(ret != 0)) {
+ do_restore_state(retaddr);
/* Exception index and error code are already set */
cpu_loop_exit();
}
--
1.7.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 14/35] target-alpha: Merge HW_REI and HW_RET implementations.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (12 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 13/35] target-alpha: Use do_restore_state for " Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 15/35] target-alpha: Implement do_interrupt for system mode Richard Henderson
` (21 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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 9e1576d..09edb0f 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2943,14 +2943,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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 15/35] target-alpha: Implement do_interrupt for system mode.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (13 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 14/35] target-alpha: Merge HW_REI and HW_RET implementations Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 16/35] target-alpha: Swap shadow registers moving to/from PALmode Richard Henderson
` (20 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/helper.c | 121 +++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 111 insertions(+), 10 deletions(-)
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index c5479fd..a49f632 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,121 @@ 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_SMP_INTERRUPT:
+ name = "smp_interrupt";
+ 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_SMP_INTERRUPT:
+ i = 0x0100;
+ break;
+ case EXCP_CLK_INTERRUPT:
+ i = 0x0180;
+ break;
+ case EXCP_DEV_INTERRUPT:
+ i = 0x0200;
+ break;
+ case EXCP_MMFAULT:
+ i = 0x0280;
+ break;
+ case EXCP_UNALIGN:
+ i = 0x0300;
+ break;
+ case EXCP_OPCDEC:
+ i = 0x0380;
+ break;
+ case EXCP_ARITH:
+ i = 0x0400;
+ break;
+ case EXCP_FEN:
+ i = 0x0480;
+ 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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 16/35] target-alpha: Swap shadow registers moving to/from PALmode.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (14 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 15/35] target-alpha: Implement do_interrupt for system mode Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 17/35] target-alpha: Add various symbolic constants Richard Henderson
` (19 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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 60445dc..7e4c46f 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -381,6 +381,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 a49f632..4f706f2 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;
@@ -290,7 +322,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 fc5020a..03b5091 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1189,9 +1189,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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 17/35] target-alpha: Add various symbolic constants.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (15 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 16/35] target-alpha: Swap shadow registers moving to/from PALmode Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 18/35] target-alpha: Use kernel mmu_idx for pal_mode Richard Henderson
` (18 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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 7e4c46f..50a8109 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 {
@@ -321,14 +316,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 09edb0f..42a80e6 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -3359,7 +3359,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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 18/35] target-alpha: Use kernel mmu_idx for pal_mode.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (16 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 17/35] target-alpha: Add various symbolic constants Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 19/35] target-alpha: All ISA checks to use TB->FLAGS Richard Henderson
` (17 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/cpu.h | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 50a8109..88281bb 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -357,7 +357,13 @@ enum {
static inline int cpu_mmu_index (CPUState *env)
{
- return (env->ps & PS_USER_MODE) != 0;
+ if (env->pal_mode) {
+ return MMU_KERNEL_IDX;
+ } else if (env->ps & PS_USER_MODE) {
+ return MMU_USER_IDX;
+ } else {
+ return MMU_KERNEL_IDX;
+ }
}
enum {
--
1.7.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 19/35] target-alpha: All ISA checks to use TB->FLAGS.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (17 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 18/35] target-alpha: Use kernel mmu_idx for pal_mode Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 20/35] target-alpha: Disable interrupts properly Richard Henderson
` (16 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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 88281bb..c1ccf01 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -419,12 +419,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 42a80e6..28ccf6b 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;
@@ -1653,20 +1649,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);
@@ -2070,20 +2068,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;
@@ -2297,8 +2287,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();
@@ -2311,20 +2302,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();
@@ -2337,8 +2331,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]);
@@ -2348,16 +2343,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;
}
@@ -2658,14 +2655,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. */
@@ -2681,13 +2677,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
@@ -2754,15 +2752,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));
@@ -2772,138 +2772,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]);
@@ -2913,8 +2939,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)
@@ -2934,42 +2961,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)
@@ -3039,9 +3060,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);
@@ -3192,8 +3214,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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 20/35] target-alpha: Disable interrupts properly.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (18 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 19/35] target-alpha: All ISA checks to use TB->FLAGS Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 21/35] target-alpha: Implement more CALL_PAL values inline Richard Henderson
` (15 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 UTC (permalink / raw)
To: qemu-devel
Interrupts are disabled in PALmode, and when the PS IL is high enough.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
cpu-exec.c | 33 ++++++++++++++++++++++++++++++---
target-alpha/cpu.h | 5 +++++
target-alpha/exec.h | 12 +++++++++++-
3 files changed, 46 insertions(+), 4 deletions(-)
diff --git a/cpu-exec.c b/cpu-exec.c
index 6d43726..fbaa21e 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -525,9 +525,36 @@ int cpu_exec(CPUState *env1)
next_tb = 0;
}
#elif defined(TARGET_ALPHA)
- if (interrupt_request & CPU_INTERRUPT_HARD) {
- do_interrupt(env);
- next_tb = 0;
+ {
+ int idx = -1;
+ /* ??? This hard-codes the OSF/1 interrupt levels. */
+ switch (env->pal_mode ? 7 : env->ps & PS_INT_MASK) {
+ case 0 ... 3:
+ if (interrupt_request & CPU_INTERRUPT_HARD) {
+ idx = EXCP_DEV_INTERRUPT;
+ }
+ /* FALLTHRU */
+ case 4:
+ if (interrupt_request & CPU_INTERRUPT_TIMER) {
+ idx = EXCP_CLK_INTERRUPT;
+ }
+ /* FALLTHRU */
+ case 5:
+ if (interrupt_request & CPU_INTERRUPT_SMP) {
+ idx = EXCP_SMP_INTERRUPT;
+ }
+ /* FALLTHRU */
+ case 6:
+ if (interrupt_request & CPU_INTERRUPT_MCHK) {
+ idx = EXCP_MCHK;
+ }
+ }
+ if (idx >= 0) {
+ env->exception_index = idx;
+ env->error_code = 0;
+ do_interrupt(env);
+ next_tb = 0;
+ }
}
#elif defined(TARGET_CRIS)
if (interrupt_request & CPU_INTERRUPT_HARD
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index c1ccf01..b439751 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -316,6 +316,11 @@ enum {
EXCP_STQ_C,
};
+/* Alpha-specific interrupt pending bits. */
+#define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_EXT_0
+#define CPU_INTERRUPT_SMP CPU_INTERRUPT_TGT_EXT_1
+#define CPU_INTERRUPT_MCHK CPU_INTERRUPT_TGT_EXT_2
+
/* Hardware interrupt (entInt) constants. */
enum {
INT_K_IP,
diff --git a/target-alpha/exec.h b/target-alpha/exec.h
index 6ae96d1..7a325e7 100644
--- a/target-alpha/exec.h
+++ b/target-alpha/exec.h
@@ -39,7 +39,17 @@ register struct CPUAlphaState *env asm(AREG0);
static inline int cpu_has_work(CPUState *env)
{
- return (env->interrupt_request & CPU_INTERRUPT_HARD);
+ /* Here we are checking to see if the CPU should wake up from HALT.
+ We will have gotten into this state only for WTINT from PALmode. */
+ /* ??? I'm not sure how the IPL state works with WTINT to keep a CPU
+ asleep even if (some) interrupts have been asserted. For now,
+ assume that if a CPU really wants to stay asleep, it will mask
+ interrupts at the chipset level, which will prevent these bits
+ from being set in the first place. */
+ return env->interrupt_request & (CPU_INTERRUPT_HARD
+ | CPU_INTERRUPT_TIMER
+ | CPU_INTERRUPT_SMP
+ | CPU_INTERRUPT_MCHK);
}
static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
--
1.7.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 21/35] target-alpha: Implement more CALL_PAL values inline.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (19 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 20/35] target-alpha: Disable interrupts properly Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 22/35] target-alpha: Implement cpu_alpha_handle_mmu_fault for system mode Richard Henderson
` (14 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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 28ccf6b..8b9dded 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 */
@@ -1464,6 +1470,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
@@ -1582,32 +1686,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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 22/35] target-alpha: Implement cpu_alpha_handle_mmu_fault for system mode.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (20 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 21/35] target-alpha: Implement more CALL_PAL values inline Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 23/35] target-alpha: Remap PIO space for 43-bit KSEG for EV6 Richard Henderson
` (13 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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 | 13 +++++
target-alpha/helper.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 138 insertions(+), 4 deletions(-)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index b439751..fc0cd61 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -321,6 +321,19 @@ enum {
#define CPU_INTERRUPT_SMP CPU_INTERRUPT_TGT_EXT_1
#define CPU_INTERRUPT_MCHK CPU_INTERRUPT_TGT_EXT_2
+/* OSF/1 Page table bits. */
+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 4f706f2..96b407b 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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 23/35] target-alpha: Remap PIO space for 43-bit KSEG for EV6.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (21 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 22/35] target-alpha: Implement cpu_alpha_handle_mmu_fault for system mode Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 24/35] target-alpha: Trap for unassigned and unaligned addresses Richard Henderson
` (12 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/helper.c | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/target-alpha/helper.c b/target-alpha/helper.c
index 96b407b..bd3af38 100644
--- a/target-alpha/helper.c
+++ b/target-alpha/helper.c
@@ -220,14 +220,18 @@ static int get_physical_address(CPUState *env, target_ulong addr,
/* 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. */
+ determine which KSEG is actually active. */
+ if (saddr < 0 && ((saddr >> 41) & 3) == 2) {
+ /* User-space cannot access KSEG addresses. */
if (mmu_idx != MMU_KERNEL_IDX) {
goto exit;
}
+ /* For the benefit of the Typhoon chipset, move bit 40 to bit 43.
+ We would not do this if the 48-bit KSEG is enabled. */
phys = saddr & ((1ull << 40) - 1);
+ phys |= (saddr & (1ull << 40)) << 3;
+
prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
ret = -1;
goto exit;
--
1.7.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 24/35] target-alpha: Trap for unassigned and unaligned addresses.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (22 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 23/35] target-alpha: Remap PIO space for 43-bit KSEG for EV6 Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 25/35] target-alpha: Include the PCC_OFS in the RPCC return value Richard Henderson
` (11 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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 | 26 ++++++++++++++++++++++++++
4 files changed, 38 insertions(+), 8 deletions(-)
diff --git a/exec-all.h b/exec-all.h
index 7c2d29f..6d3ae77 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -322,7 +322,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 0b8ab5b..8627500 100644
--- a/exec.c
+++ b/exec.c
@@ -3112,7 +3112,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;
@@ -3123,7 +3123,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;
@@ -3134,7 +3134,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;
@@ -3145,7 +3145,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
}
@@ -3155,7 +3155,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
}
@@ -3165,7 +3165,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 fc0cd61..d26a870 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -435,7 +435,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 03b5091..91ef90a 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1265,7 +1265,33 @@ uint64_t helper_stq_c_phys(uint64_t p, uint64_t v)
return ret;
}
+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;
+ dynamic_excp(EXCP_MCHK, 0);
+}
+
#define MMUSUFFIX _mmu
+#define ALIGNED_ONLY
#define SHIFT 0
#include "softmmu_template.h"
--
1.7.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 25/35] target-alpha: Include the PCC_OFS in the RPCC return value.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (23 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 24/35] target-alpha: Trap for unassigned and unaligned addresses Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 26/35] target-alpha: Use a fixed frequency for the RPCC in system mode Richard Henderson
` (10 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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 91ef90a..42fec07 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -66,7 +66,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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 26/35] target-alpha: Use a fixed frequency for the RPCC in system mode.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (24 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 25/35] target-alpha: Include the PCC_OFS in the RPCC return value Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 27/35] target-alpha: Implement TLB flush primitives Richard Henderson
` (9 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/cpu.h | 2 --
target-alpha/op_helper.c | 14 +++++++++++---
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index d26a870..c94becf 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -256,7 +256,6 @@ 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;
@@ -266,7 +265,6 @@ struct CPUAlphaState {
uint64_t usp;
uint64_t shadow[8];
uint64_t scratch[24];
-#endif
#if TARGET_LONG_BITS > HOST_LONG_BITS
/* temporary fixed-point registers
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 42fec07..36b8289 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -65,9 +65,17 @@ 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. */
- uint64_t ret = env->pcc_ofs;
- return ret << 32 | (uint32_t)cpu_get_real_ticks();
+#ifndef CONFIG_USER_ONLY
+ /* In system mode we have access to a decent high-resolution clock.
+ In order to make OS-level time accounting work with the RPCC,
+ present it with a well-timed clock fixed at 250MHz. */
+ return (((uint64_t)env->pcc_ofs << 32)
+ | (uint32_t)(qemu_get_clock_ns(vm_clock) >> 2));
+#else
+ /* In user-mode, vm_clock doesn't exist. Just pass through the host cpu
+ clock ticks. Also, don't bother taking PCC_OFS into account. */
+ return (uint32_t)cpu_get_real_ticks();
+#endif
}
uint64_t helper_load_fpcr (void)
--
1.7.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 27/35] target-alpha: Implement TLB flush primitives.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (25 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 26/35] target-alpha: Use a fixed frequency for the RPCC in system mode Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 28/35] target-alpha: Add custom PALcode image for CLIPPER emulation Richard Henderson
` (8 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 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 36b8289..d332719 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1205,6 +1205,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
/*****************************************************************************/
@@ -1335,5 +1345,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 8b9dded..8107d19 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1624,7 +1624,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);
@@ -1632,16 +1631,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.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 28/35] target-alpha: Add custom PALcode image for CLIPPER emulation.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (26 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 27/35] target-alpha: Implement TLB flush primitives Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 29/35] target-alpha: Add " Richard Henderson
` (7 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
.gitmodules | 3 +++
Makefile | 3 ++-
configure | 8 +++++++-
pc-bios/README | 3 +++
pc-bios/palcode-clipper | Bin 0 -> 176851 bytes
roms/qemu-palcode | 1 +
6 files changed, 16 insertions(+), 2 deletions(-)
create mode 100755 pc-bios/palcode-clipper
create mode 160000 roms/qemu-palcode
diff --git a/.gitmodules b/.gitmodules
index 7884471..528743d 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -10,3 +10,6 @@
[submodule "roms/ipxe"]
path = roms/ipxe
url = git://git.qemu.org/ipxe.git
+[submodule "roms/qemu-palcode"]
+ path = roms/qemu-palcode
+ url = git://repo.or.cz/qemu-palcode.git
diff --git a/Makefile b/Makefile
index 67c0268..c7eb076 100644
--- a/Makefile
+++ b/Makefile
@@ -185,7 +185,8 @@ pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
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 214aabc..47aa1f3 100755
--- a/configure
+++ b/configure
@@ -3464,7 +3464,13 @@ 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/*.rom $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-*; do
+for bios_file in \
+ $source_path/pc-bios/*.bin \
+ $source_path/pc-bios/*.rom \
+ $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/README b/pc-bios/README
index fe221a9..339eebd 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -31,3 +31,6 @@
- The S390 zipl loader is an addition to the official IBM s390-tools
package. That fork is maintained in its own git repository at:
git://repo.or.cz/s390-tools.git
+
+- The Alpha palcode image is available from:
+ git://repo.or.cz/qemu-palcode.git
diff --git a/pc-bios/palcode-clipper b/pc-bios/palcode-clipper
new file mode 100755
index 0000000000000000000000000000000000000000..26045ce48ea82e032a93353bc2200fee2d42f34d
GIT binary patch
literal 176851
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
Pn4a=>pGRNCJoSG7$|(%`
literal 0
HcmV?d00001
diff --git a/roms/qemu-palcode b/roms/qemu-palcode
new file mode 160000
index 0000000..4f4608b
--- /dev/null
+++ b/roms/qemu-palcode
@@ -0,0 +1 @@
+Subproject commit 4f4608beab5ad6cbd1547b415154dc8af154f48b
--
1.7.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 29/35] target-alpha: Add CLIPPER emulation.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (27 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 28/35] target-alpha: Add custom PALcode image for CLIPPER emulation Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 30/35] target-alpha: Implement WAIT IPR Richard Henderson
` (6 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 UTC (permalink / raw)
To: qemu-devel
This is a DP264 variant, SMP capable, no unusual hardware present.
The emulation does not currently include any PCI IOMMU code.
Hopefully the generic support for that can be merged to HEAD soon.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
Makefile.target | 1 +
hw/alpha_dp264.c | 177 ++++++++++++
hw/alpha_pci.c | 327 ++++++++++++++++++++++
hw/alpha_sys.h | 42 +++
hw/alpha_typhoon.c | 781 ++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 1328 insertions(+), 0 deletions(-)
create mode 100644 hw/alpha_dp264.c
create mode 100644 hw/alpha_pci.c
create mode 100644 hw/alpha_sys.h
create mode 100644 hw/alpha_typhoon.c
diff --git a/Makefile.target b/Makefile.target
index 2f842c1..7f69f72 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -366,6 +366,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_dp264.o alpha_typhoon.o
main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c
new file mode 100644
index 0000000..c061b0a
--- /dev/null
+++ b/hw/alpha_dp264.c
@@ -0,0 +1,177 @@
+/*
+ * QEMU Alpha DP264/CLIPPER hardware system emulator.
+ *
+ * Choose CLIPPER IRQ mappings over, say, DP264, MONET, or WEBBRICK
+ * variants because CLIPPER doesn't have an SMC669 SuperIO controler
+ * that we need to emulate as well.
+ */
+
+#include "hw.h"
+#include "elf.h"
+#include "loader.h"
+#include "boards.h"
+#include "alpha_sys.h"
+#include "sysemu.h"
+#include "mc146818rtc.h"
+
+
+static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr)
+{
+ if (((addr >> 41) & 3) == 2) {
+ addr &= 0xffffffffffull;
+ }
+ return addr;
+}
+
+/* Note that there are at least 3 viewpoints of IRQ numbers on Alpha systems.
+ (0) The dev_irq_n lines into the cpu, which we totally ignore,
+ (1) The DRIR lines in the typhoon chipset,
+ (2) The "vector" aka mangled interrupt number reported by SRM PALcode,
+ (3) The interrupt number assigned by the kernel.
+ The following function is concerned with (1) only. */
+
+static int clipper_pci_map_irq(PCIDevice *d, int irq_num)
+{
+ int slot = d->devfn >> 3;
+
+ assert(irq_num >= 0 && irq_num <= 3);
+
+ return (slot + 1) * 4 + irq_num;
+}
+
+static void clipper_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 *cpus[4];
+ ram_addr_t ram_offset;
+ PCIBus *pci_bus;
+ ISABus *isa_bus;
+ qemu_irq isa_pci_irq, rtc_irq, *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;
+
+ /* Create up to 4 cpus. */
+ memset(cpus, 0, sizeof(cpus));
+ for (i = 0; i < smp_cpus; ++i) {
+ cpus[i] = cpu_init(cpu_model ? cpu_model : "ev67");
+ }
+
+ cpus[0]->trap_arg0 = ram_size;
+ cpus[0]->trap_arg1 = 0;
+ cpus[0]->trap_arg2 = smp_cpus;
+
+ ram_offset = qemu_ram_alloc(NULL, "ram", ram_size);
+ cpu_register_physical_memory(0, ram_size, ram_offset);
+
+ /* Init the chipset. */
+ pci_bus = typhoon_init(&isa_pci_irq, &rtc_irq, cpus, clipper_pci_map_irq);
+
+ /* Init the ISA bus. */
+ isa_bus = isa_bus_new(NULL);
+ isa_mem_base = pci_to_cpu_addr(pci_bus, 0);
+
+ isa_irqs = i8259_init(isa_pci_irq);
+ isa_bus_irqs(isa_irqs);
+
+ rtc_init(1980, rtc_irq);
+ pit_init(0x40, 0);
+
+ /* VGA setup. Don't bother loading the bios. */
+ pci_vga_init(pci_bus);
+
+ /* Serial code setup. */
+ for (i = 0; i < MAX_SERIAL_PORTS; ++i) {
+ if (serial_hds[i]) {
+ serial_isa_init(i, serial_hds[i]);
+ }
+ }
+
+ /* Network setup. e1000 is good enough, failing Tulip support. */
+ for (i = 0; i < nb_nics; i++) {
+ pci_nic_init_nofail(&nd_table[i], "e1000", 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-clipper");
+ palcode_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, palcode_filename);
+ if (palcode_filename == NULL) {
+ hw_error("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("could not load palcode '%s'\n", palcode_filename);
+ exit(1);
+ }
+
+ /* Start all cpus at the PALcode RESET entry point. */
+ for (i = 0; i < smp_cpus; ++i) {
+ cpus[i]->pc = palcode_entry;
+ cpus[i]->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("could not load kernel '%s'\n", kernel_filename);
+ exit(1);
+ }
+
+ cpus[0]->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_size = get_image_size(initrd_filename);
+ if (initrd_size < 0) {
+ hw_error("could not load initial ram disk '%s'\n",
+ initrd_filename);
+ exit(1);
+ }
+
+ /* Put the initrd image as high in memory as possible. */
+ initrd_base = (ram_size - initrd_size) & TARGET_PAGE_MASK;
+ load_image_targphys(initrd_filename, initrd_base,
+ ram_size - initrd_base);
+
+ stq_phys(param_offset + 0x100, initrd_base + 0xfffffc0000000000UL);
+ stq_phys(param_offset + 0x108, initrd_size);
+ }
+ }
+}
+
+static QEMUMachine clipper_machine = {
+ .name = "clipper",
+ .desc = "Alpha DP264/CLIPPER",
+ .init = clipper_init,
+ .max_cpus = 4,
+ .is_default = 1,
+};
+
+static void clipper_machine_init(void)
+{
+ qemu_register_machine(&clipper_machine);
+}
+
+machine_init(clipper_machine_init);
diff --git a/hw/alpha_pci.c b/hw/alpha_pci.c
new file mode 100644
index 0000000..d0d727c
--- /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)
+{
+ PCIBus *b = opaque;
+ return pci_data_read(b, addr, 1);
+}
+
+static uint32_t bw_conf1_readw(void *opaque, target_phys_addr_t addr)
+{
+ PCIBus *b = opaque;
+ return pci_data_read(b, addr, 2);
+}
+
+static uint32_t bw_conf1_readl(void *opaque, target_phys_addr_t addr)
+{
+ PCIBus *b = opaque;
+ return pci_data_read(b, 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)
+{
+ PCIBus *b = opaque;
+ pci_data_write(b, addr, val, 1);
+}
+
+static void bw_conf1_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PCIBus *b = opaque;
+ pci_data_write(b, addr, val, 2);
+}
+
+static void bw_conf1_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PCIBus *b = opaque;
+ pci_data_write(b, 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_sys.h b/hw/alpha_sys.h
new file mode 100644
index 0000000..272a107
--- /dev/null
+++ b/hw/alpha_sys.h
@@ -0,0 +1,42 @@
+/* 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 *typhoon_init(qemu_irq *p_isa_irq, qemu_irq *p_rtc_irq,
+ CPUState *cpus[3], pci_map_irq_fn sys_map_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
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
new file mode 100644
index 0000000..7cdf7d3
--- /dev/null
+++ b/hw/alpha_typhoon.c
@@ -0,0 +1,781 @@
+/*
+ * DEC 21272 (TSUNAMI/TYPHOON) 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"
+
+typedef struct TyphoonCchip {
+ uint64_t misc;
+ uint64_t drir;
+ uint64_t dim[4];
+ uint32_t iic[4];
+ CPUState *cpu[4];
+} TyphoonCchip;
+
+typedef struct TyphoonWindow {
+ uint32_t base_addr;
+ uint32_t mask;
+ uint32_t translated_base_pfn;
+} TyphoonWindow;
+
+typedef struct TyphoonPchip {
+ uint64_t ctl;
+ TyphoonWindow win[4];
+} TyphoonPchip;
+
+typedef struct TyphoonState {
+ PCIHostState host;
+
+ TyphoonCchip cchip;
+ TyphoonPchip pchip;
+
+ /* QEMU emulation state. */
+ uint32_t latch_tmp;
+} TyphoonState;
+
+/* Called when one of DRIR or DIM changes. */
+static void cpu_irq_change(CPUState *env, uint64_t req)
+{
+ /* If there are any non-masked interrupts, tell the cpu. */
+ if (env) {
+ if (req) {
+ cpu_interrupt(env, CPU_INTERRUPT_HARD);
+ } else {
+ cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
+ }
+ }
+}
+
+static uint32_t cchip_readl(void *opaque, target_phys_addr_t addr)
+{
+ CPUState *env = cpu_single_env;
+ TyphoonState *s = opaque;
+ uint64_t ret = 0;
+
+ if (addr & 4) {
+ return s->latch_tmp;
+ }
+
+ switch (addr) {
+ case 0x0000:
+ /* CSC: Cchip System Configuration Register. */
+ /* All sorts of data here; probably the only thing relevant is
+ PIP<14> Pchip 1 Present = 0. */
+ break;
+
+ case 0x0040:
+ /* MTR: Memory Timing Register. */
+ /* All sorts of stuff related to real DRAM. */
+ break;
+
+ case 0x0080:
+ /* MISC: Miscellaneous Register. */
+ ret = s->cchip.misc | (env->cpu_index & 3);
+ break;
+
+ case 0x00c0:
+ /* MPD: Memory Presence Detect Register. */
+ break;
+
+ case 0x0100: /* AAR0 */
+ case 0x0140: /* AAR1 */
+ case 0x0180: /* AAR2 */
+ case 0x01c0: /* AAR3 */
+ /* AAR: Array Address Register. */
+ /* All sorts of information about DRAM. */
+ break;
+
+ case 0x0200:
+ /* DIM0: Device Interrupt Mask Register, CPU0. */
+ ret = s->cchip.dim[0];
+ break;
+ case 0x0240:
+ /* DIM1: Device Interrupt Mask Register, CPU1. */
+ ret = s->cchip.dim[1];
+ break;
+ case 0x0280:
+ /* DIR0: Device Interrupt Request Register, CPU0. */
+ ret = s->cchip.dim[0] & s->cchip.drir;
+ break;
+ case 0x02c0:
+ /* DIR1: Device Interrupt Request Register, CPU1. */
+ ret = s->cchip.dim[1] & s->cchip.drir;
+ break;
+ case 0x0300:
+ /* DRIR: Device Raw Interrupt Request Register. */
+ ret = s->cchip.drir;
+ break;
+
+ case 0x0340:
+ /* PRBEN: Probe Enable Register. */
+ break;
+
+ case 0x0380:
+ /* IIC0: Interval Ignore Count Register, CPU0. */
+ ret = s->cchip.iic[0];
+ break;
+ case 0x03c0:
+ /* IIC1: Interval Ignore Count Register, CPU1. */
+ ret = s->cchip.iic[1];
+ break;
+
+ case 0x0400: /* MPR0 */
+ case 0x0440: /* MPR1 */
+ case 0x0480: /* MPR2 */
+ case 0x04c0: /* MPR3 */
+ /* MPR: Memory Programming Register. */
+ break;
+
+ case 0x0580:
+ /* TTR: TIGbus Timing Register. */
+ /* All sorts of stuff related to interrupt delivery timings. */
+ break;
+ case 0x05c0:
+ /* TDR: TIGbug Device Timing Register. */
+ break;
+
+ case 0x0600:
+ /* DIM2: Device Interrupt Mask Register, CPU2. */
+ ret = s->cchip.dim[2];
+ break;
+ case 0x0640:
+ /* DIM3: Device Interrupt Mask Register, CPU3. */
+ ret = s->cchip.dim[3];
+ break;
+ case 0x0680:
+ /* DIR2: Device Interrupt Request Register, CPU2. */
+ ret = s->cchip.dim[2] & s->cchip.drir;
+ break;
+ case 0x06c0:
+ /* DIR3: Device Interrupt Request Register, CPU3. */
+ ret = s->cchip.dim[3] & s->cchip.drir;
+ break;
+
+ case 0x0700:
+ /* IIC2: Interval Ignore Count Register, CPU2. */
+ ret = s->cchip.iic[2];
+ break;
+ case 0x0740:
+ /* IIC3: Interval Ignore Count Register, CPU3. */
+ ret = s->cchip.iic[3];
+ break;
+
+ case 0x0780:
+ /* PWR: Power Management Control. */
+ break;
+
+ case 0x0c00: /* CMONCTLA */
+ case 0x0c40: /* CMONCTLB */
+ case 0x0c80: /* CMONCNT01 */
+ case 0x0cc0: /* CMONCNT23 */
+ break;
+
+ default:
+ do_unassigned_access(addr, 0, 0, 0, 4);
+ return -1;
+ }
+
+ s->latch_tmp = ret >> 32;
+ return ret;
+}
+
+static uint32_t dchip_readl(void *opaque, target_phys_addr_t addr)
+{
+ /* Skip this. It's all related to DRAM timing and setup. */
+ return 0;
+}
+
+static uint32_t pchip_readl(void *opaque, target_phys_addr_t addr)
+{
+ TyphoonState *s = opaque;
+ uint64_t ret = 0;
+
+ if (addr & 4) {
+ return s->latch_tmp;
+ }
+
+ switch (addr) {
+ case 0x0000:
+ /* WSBA0: Window Space Base Address Register. */
+ ret = s->pchip.win[0].base_addr;
+ break;
+ case 0x0040:
+ /* WSBA1 */
+ ret = s->pchip.win[1].base_addr;
+ break;
+ case 0x0080:
+ /* WSBA2 */
+ ret = s->pchip.win[2].base_addr;
+ break;
+ case 0x00c0:
+ /* WSBA3 */
+ ret = s->pchip.win[3].base_addr;
+ break;
+
+ case 0x0100:
+ /* WSM0: Window Space Mask Register. */
+ ret = s->pchip.win[0].mask;
+ break;
+ case 0x0140:
+ /* WSM1 */
+ ret = s->pchip.win[1].mask;
+ break;
+ case 0x0180:
+ /* WSM2 */
+ ret = s->pchip.win[2].mask;
+ break;
+ case 0x01c0:
+ /* WSM3 */
+ ret = s->pchip.win[3].mask;
+ break;
+
+ case 0x0200:
+ /* TBA0: Translated Base Address Register. */
+ ret = (uint64_t)s->pchip.win[0].translated_base_pfn << 10;
+ break;
+ case 0x0240:
+ /* TBA1 */
+ ret = (uint64_t)s->pchip.win[1].translated_base_pfn << 10;
+ break;
+ case 0x0280:
+ /* TBA2 */
+ ret = (uint64_t)s->pchip.win[2].translated_base_pfn << 10;
+ break;
+ case 0x02c0:
+ /* TBA3 */
+ ret = (uint64_t)s->pchip.win[3].translated_base_pfn << 10;
+ break;
+
+ case 0x0300:
+ /* PCTL: Pchip Control Register. */
+ ret = s->pchip.ctl;
+ break;
+ case 0x0340:
+ /* PLAT: Pchip Master Latency Register. */
+ break;
+ case 0x03c0:
+ /* PERROR: Pchip Error Register. */
+ break;
+ case 0x0400:
+ /* PERRMASK: Pchip Error Mask Register. */
+ break;
+ case 0x0440:
+ /* PERRSET: Pchip Error Set Register. */
+ break;
+ case 0x0480:
+ /* TLBIV: Translation Buffer Invalidate Virtual Register (WO). */
+ break;
+ case 0x04c0:
+ /* TLBIA: Translation Buffer Invalidate All Register (WO). */
+ break;
+ case 0x0500: /* PMONCTL */
+ case 0x0540: /* PMONCNT */
+ case 0x0800: /* SPRST */
+ break;
+
+ default:
+ do_unassigned_access(addr, 0, 0, 0, 4);
+ return -1;
+ }
+
+ s->latch_tmp = ret >> 32;
+ return ret;
+}
+
+static void cchip_writel(void *opaque, target_phys_addr_t addr, uint32_t v32)
+{
+ TyphoonState *s = opaque;
+ uint64_t val, oldval, newval;
+
+ if (addr & 4) {
+ val = (uint64_t)v32 << 32 | s->latch_tmp;
+ addr ^= 4;
+ } else {
+ s->latch_tmp = v32;
+ return;
+ }
+
+ switch (addr) {
+ case 0x0000:
+ /* CSC: Cchip System Configuration Register. */
+ /* All sorts of data here; nothing relevant RW. */
+ break;
+
+ case 0x0040:
+ /* MTR: Memory Timing Register. */
+ /* All sorts of stuff related to real DRAM. */
+ break;
+
+ case 0x0080:
+ /* MISC: Miscellaneous Register. */
+ newval = oldval = s->cchip.misc;
+ newval &= ~(val & 0x10000ff0); /* W1C fields */
+ if (val & 0x100000) {
+ newval &= ~0xff0000ull; /* ACL clears ABT and ABW */
+ } else {
+ newval |= val & 0x00f00000; /* ABT field is W1S */
+ if ((newval & 0xf0000) == 0) {
+ newval |= val & 0xf0000; /* ABW field is W1S iff zero */
+ }
+ }
+ newval |= (val & 0xf000) >> 4; /* IPREQ field sets IPINTR. */
+
+ newval &= ~0xf0000000000ull; /* WO and RW fields */
+ newval |= val & 0xf0000000000ull;
+ s->cchip.misc = newval;
+
+ /* Pass on changes to IPI and ITI state. */
+ if ((newval ^ oldval) & 0xff0) {
+ int i;
+ for (i = 0; i < 4; ++i) {
+ CPUState *env = s->cchip.cpu[i];
+ if (env) {
+ /* IPI can be either cleared or set by the write. */
+ if (newval & (1 << (i + 8))) {
+ cpu_interrupt(env, CPU_INTERRUPT_SMP);
+ } else {
+ cpu_reset_interrupt(env, CPU_INTERRUPT_SMP);
+ }
+
+ /* ITI can only be cleared by the write. */
+ if ((newval & (1 << (i + 4))) == 0) {
+ cpu_reset_interrupt(env, CPU_INTERRUPT_TIMER);
+ }
+ }
+ }
+ }
+ break;
+
+ case 0x00c0:
+ /* MPD: Memory Presence Detect Register. */
+ break;
+
+ case 0x0100: /* AAR0 */
+ case 0x0140: /* AAR1 */
+ case 0x0180: /* AAR2 */
+ case 0x01c0: /* AAR3 */
+ /* AAR: Array Address Register. */
+ /* All sorts of information about DRAM. */
+ break;
+
+ case 0x0200: /* DIM0 */
+ /* DIM: Device Interrupt Mask Register, CPU0. */
+ s->cchip.dim[0] = val;
+ cpu_irq_change(s->cchip.cpu[0], val & s->cchip.drir);
+ break;
+ case 0x0240: /* DIM1 */
+ /* DIM: Device Interrupt Mask Register, CPU1. */
+ s->cchip.dim[0] = val;
+ cpu_irq_change(s->cchip.cpu[1], val & s->cchip.drir);
+ break;
+
+ case 0x0280: /* DIR0 (RO) */
+ case 0x02c0: /* DIR1 (RO) */
+ case 0x0300: /* DRIR (RO) */
+ break;
+
+ case 0x0340:
+ /* PRBEN: Probe Enable Register. */
+ break;
+
+ case 0x0380: /* IIC0 */
+ s->cchip.iic[0] = val & 0xffffff;
+ break;
+ case 0x03c0: /* IIC1 */
+ s->cchip.iic[1] = val & 0xffffff;
+ break;
+
+ case 0x0400: /* MPR0 */
+ case 0x0440: /* MPR1 */
+ case 0x0480: /* MPR2 */
+ case 0x04c0: /* MPR3 */
+ /* MPR: Memory Programming Register. */
+ break;
+
+ case 0x0580:
+ /* TTR: TIGbus Timing Register. */
+ /* All sorts of stuff related to interrupt delivery timings. */
+ break;
+ case 0x05c0:
+ /* TDR: TIGbug Device Timing Register. */
+ break;
+
+ case 0x0600:
+ /* DIM2: Device Interrupt Mask Register, CPU2. */
+ s->cchip.dim[2] = val;
+ cpu_irq_change(s->cchip.cpu[2], val & s->cchip.drir);
+ break;
+ case 0x0640:
+ /* DIM3: Device Interrupt Mask Register, CPU3. */
+ s->cchip.dim[3] = val;
+ cpu_irq_change(s->cchip.cpu[3], val & s->cchip.drir);
+ break;
+
+ case 0x0680: /* DIR2 (RO) */
+ case 0x06c0: /* DIR3 (RO) */
+ break;
+
+ case 0x0700: /* IIC2 */
+ s->cchip.iic[2] = val & 0xffffff;
+ break;
+ case 0x0740: /* IIC3 */
+ s->cchip.iic[3] = val & 0xffffff;
+ break;
+
+ case 0x0780:
+ /* PWR: Power Management Control. */
+ break;
+
+ case 0x0c00: /* CMONCTLA */
+ case 0x0c40: /* CMONCTLB */
+ case 0x0c80: /* CMONCNT01 */
+ case 0x0cc0: /* CMONCNT23 */
+ break;
+
+ default:
+ do_unassigned_access(addr, 1, 0, 0, 4);
+ return;
+ }
+}
+
+static void dchip_writel(void *opaque, target_phys_addr_t addr, uint32_t v32)
+{
+ /* Skip this. It's all related to DRAM timing and setup. */
+}
+
+static void pchip_writel(void *opaque, target_phys_addr_t addr, uint32_t v32)
+{
+ TyphoonState *s = opaque;
+ uint64_t val, oldval;
+
+ switch (addr) {
+ case 0x0000:
+ /* WSBA0: Window Space Base Address Register. */
+ s->pchip.win[0].base_addr = v32;
+ break;
+ case 0x0040:
+ /* WSBA1 */
+ s->pchip.win[1].base_addr = v32;
+ break;
+ case 0x0080:
+ /* WSBA2 */
+ s->pchip.win[2].base_addr = v32;
+ break;
+ case 0x00c0:
+ /* WSBA3 */
+ s->pchip.win[3].base_addr = v32;
+ break;
+
+ case 0x0100:
+ /* WSM0: Window Space Mask Register. */
+ s->pchip.win[0].mask = v32;
+ break;
+ case 0x0140:
+ /* WSM1 */
+ s->pchip.win[1].mask = v32;
+ break;
+ case 0x0180:
+ /* WSM2 */
+ s->pchip.win[2].mask = v32;
+ break;
+ case 0x01c0:
+ /* WSM3 */
+ s->pchip.win[3].mask = v32;
+ break;
+
+ case 0x0200:
+ /* TBA0: Translated Base Address Register. */
+ s->pchip.win[0].translated_base_pfn = v32 >> 10;
+ break;
+ case 0x0240:
+ /* TBA1 */
+ s->pchip.win[1].translated_base_pfn = v32 >> 10;
+ break;
+ case 0x0280:
+ /* TBA2 */
+ s->pchip.win[2].translated_base_pfn = v32 >> 10;
+ break;
+ case 0x02c0:
+ /* TBA3 */
+ s->pchip.win[3].translated_base_pfn = v32 >> 10;
+ break;
+
+ case 0x0004:
+ case 0x0044:
+ case 0x0084:
+ case 0x00c4:
+ case 0x0104:
+ case 0x0144:
+ case 0x0184:
+ case 0x01c4:
+ case 0x0204:
+ case 0x0244:
+ case 0x0284:
+ case 0x02c4:
+ /* MBZ high-part portions of the above registers. */
+ break;
+
+ case 0x0300:
+ /* PCTL: Pchip Control Register. */
+ s->latch_tmp = v32;
+ break;
+ case 0x0304:
+ val = (uint64_t)v32 << 32 | s->latch_tmp;
+
+ oldval = s->pchip.ctl;
+ oldval &= ~0x00001cff0fc7ffull; /* RW fields */
+ oldval |= val & 0x00001cff0fc7ffull;
+
+ s->pchip.ctl = oldval;
+ break;
+
+ case 0x0340: case 0x0344:
+ /* PLAT: Pchip Master Latency Register. */
+ break;
+ case 0x03c0: case 0x03c4:
+ /* PERROR: Pchip Error Register. */
+ break;
+ case 0x0400: case 0x0404:
+ /* PERRMASK: Pchip Error Mask Register. */
+ break;
+ case 0x0440: case 0x0444:
+ /* PERRSET: Pchip Error Set Register. */
+ break;
+
+ case 0x0480:
+ /* TLBIV: Translation Buffer Invalidate Virtual Register. */
+ s->latch_tmp = v32;
+ break;
+ case 0x0484:
+ val = (uint64_t)v32 << 32 | s->latch_tmp;
+ break;
+
+ case 0x04c0:
+ /* TLBIA: Translation Buffer Invalidate All Register (WO). */
+ break;
+ case 0x04c4:
+ break;
+
+ case 0x0500: case 0x0504:
+ /* PMONCTL */
+ case 0x0540: case 0x0544:
+ /* PMONCNT */
+ case 0x0800: case 0x0804:
+ /* SPRST */
+ break;
+
+ default:
+ do_unassigned_access(addr, 1, 0, 0, 4);
+ return;
+ }
+}
+
+static CPUReadMemoryFunc * const cchip_reads[] = {
+ NULL,
+ NULL,
+ cchip_readl
+};
+
+static CPUWriteMemoryFunc * const cchip_writes[] = {
+ NULL,
+ NULL,
+ cchip_writel
+};
+
+static CPUReadMemoryFunc * const dchip_reads[] = {
+ NULL,
+ NULL,
+ dchip_readl
+};
+
+static CPUWriteMemoryFunc * const dchip_writes[] = {
+ NULL,
+ NULL,
+ dchip_writel
+};
+
+static CPUReadMemoryFunc * const pchip_reads[] = {
+ NULL,
+ NULL,
+ pchip_readl
+};
+
+static CPUWriteMemoryFunc * const pchip_writes[] = {
+ NULL,
+ NULL,
+ pchip_writel
+};
+
+static void typhoon_set_irq(void *opaque, int irq, int level)
+{
+ TyphoonState *s = opaque;
+ uint64_t drir;
+ int i;
+
+ /* Set/Reset the bit in CCHIP.DRIR based on IRQ+LEVEL. */
+ drir = s->cchip.drir;
+ if (level) {
+ drir |= 1ull << irq;
+ } else {
+ drir &= ~(1ull << irq);
+ }
+ s->cchip.drir = drir;
+
+ for (i = 0; i < 4; ++i) {
+ cpu_irq_change(s->cchip.cpu[i], s->cchip.dim[i] & drir);
+ }
+}
+
+static void typhoon_set_isa_irq(void *opaque, int irq, int level)
+{
+ typhoon_set_irq(opaque, 55, level);
+}
+
+static void typhoon_set_timer_irq(void *opaque, int irq, int level)
+{
+ TyphoonState *s = opaque;
+ int i;
+
+ /* Thankfully, the mc146818rtc code doesn't track the IRQ state,
+ and so we don't have to worry about missing interrupts just
+ because we never actually ACK the interrupt. Just ignore any
+ case of the interrupt level going low. */
+ if (level == 0) {
+ return;
+ }
+
+ /* Deliver the interrupt to each CPU, considering each CPU's IIC. */
+ for (i = 0; i < 4; ++i) {
+ CPUState *env = s->cchip.cpu[i];
+ if (env) {
+ uint32_t iic = s->cchip.iic[i];
+
+ /* ??? The verbage in Section 10.2.2.10 isn't 100% clear.
+ Bit 24 is the OverFlow bit, RO, and set when the count
+ decrements past 0. When is OF cleared? My guess is that
+ OF is actually cleared when the IIC is written, and that
+ the ICNT field always decrements. At least, that's an
+ interpretation that makes sense, and "allows the CPU to
+ determine exactly how mant interval timer ticks were
+ skipped". At least within the next 4M ticks... */
+
+ iic = ((iic - 1) & 0x1ffffff) | (iic & 0x1000000);
+ s->cchip.iic[i] = iic;
+
+ if (iic & 0x1000000) {
+ /* Set the ITI bit for this cpu. */
+ s->cchip.misc |= 1 << (i + 4);
+ /* And signal the interrupt. */
+ cpu_interrupt(env, CPU_INTERRUPT_TIMER);
+ }
+ }
+ }
+}
+
+PCIBus *typhoon_init(qemu_irq *p_isa_irq, qemu_irq *p_rtc_irq,
+ CPUState *cpus[3], pci_map_irq_fn sys_map_irq)
+{
+ const uint64_t MB = 1024 * 1024;
+ DeviceState *dev;
+ PCIHostState *p;
+ TyphoonState *s;
+ PCIBus *b;
+ int region;
+
+ dev = qdev_create(NULL, "typhoon-pcihost");
+ p = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
+ s = container_of(p, TyphoonState, host);
+
+ /* Remember the CPUs so that we can deliver interrupts to them. */
+ memcpy(s->cchip.cpu, cpus, 4 * sizeof(CPUState *));
+
+ *p_isa_irq = *qemu_allocate_irqs(typhoon_set_isa_irq, s, 1);
+ *p_rtc_irq = *qemu_allocate_irqs(typhoon_set_timer_irq, s, 1);
+
+ b = pci_register_bus(&s->host.busdev.qdev, "pci", typhoon_set_irq,
+ sys_map_irq, s, 0, 64);
+ s->host.bus = b;
+
+ qdev_init_nofail(dev);
+
+ /* Main memory region, 0x00.0000.0000. Real hardware supports 32GB,
+ but the address space hole reserved at this point is 8TB. */
+
+ /* Pchip0 PCI memory, 0x800.0000.0000, 4GB. */
+ pci_bus_set_mem_base(b, 0x80000000000ull);
+
+ /* TIGbus, 0x801.0000.0000, 1GB. */
+ /* ??? The TIGbus is used for delivering interrupts, and access to
+ the flash ROM. I'm not sure that we need to implement it at all. */
+
+ /* Pchip0 CSRs, 0x801.8000.0000, 256MB. */
+ region = cpu_register_io_memory(pchip_reads, pchip_writes, s,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x80180000000, 256*MB, region);
+
+ /* Cchip CSRs, 0x801.A000.0000, 256MB. */
+ region = cpu_register_io_memory(cchip_reads, cchip_writes, s,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x801a0000000, 256*MB, region);
+
+ /* Dchip CSRs, 0x801.B000.0000, 256MB. */
+ region = cpu_register_io_memory(dchip_reads, dchip_writes, s,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x801b0000000, 256*MB, region);
+
+ /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB. */
+ region = cpu_register_io_memory(alpha_pci_iack_reads,
+ alpha_pci_special_writes, b,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x801f8000000, 64*MB, region);
+
+ /* Pchip0 PCI I/O, 0x801.FC00.0000, 32MB. */
+ region = cpu_register_io_memory(alpha_pci_bw_io_reads,
+ alpha_pci_bw_io_writes, b,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x801fc000000, 32*MB, region);
+
+ /* Pchip0 PCI configuration, 0x801.FE00.0000, 16MB. */
+ region = cpu_register_io_memory(alpha_pci_bw_conf1_reads,
+ alpha_pci_bw_conf1_writes, b,
+ DEVICE_LITTLE_ENDIAN);
+ cpu_register_physical_memory(0x801fe000000, 16*MB, region);
+
+ /* For the record, these are the mappings for the second PCI bus.
+ We can get away with not implementing them because we indicate
+ via the Cchip.CSC<PIP> bit that Pchip1 is not present. */
+ /* Pchip1 PCI memory, 0x802.0000.0000, 4GB. */
+ /* Pchip1 CSRs, 0x802.8000.0000, 256MB. */
+ /* Pchip1 PCI special/interrupt acknowledge, 0x802.F800.0000, 64MB. */
+ /* Pchip1 PCI I/O, 0x802.FC00.0000, 32MB. */
+ /* Pchip1 PCI configuration, 0x802.FE00.0000, 16MB. */
+
+ return b;
+}
+
+static int typhoon_pcihost_init(SysBusDevice *dev)
+{
+ return 0;
+}
+
+static SysBusDeviceInfo typhoon_pcihost_info = {
+ .init = typhoon_pcihost_init,
+ .qdev.name = "typhoon-pcihost",
+ .qdev.size = sizeof(TyphoonState),
+ .qdev.no_user = 1
+};
+
+static void typhoon_register(void)
+{
+ sysbus_register_withprop(&typhoon_pcihost_info);
+}
+device_init(typhoon_register);
--
1.7.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 30/35] target-alpha: Implement WAIT IPR.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (28 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 29/35] target-alpha: Add " Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 31/35] target-alpha: Implement HALT IPR Richard Henderson
` (5 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 UTC (permalink / raw)
To: qemu-devel
---
target-alpha/translate.c | 31 +++++++++++++++++++++----------
1 files changed, 21 insertions(+), 10 deletions(-)
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 8107d19..7b976be 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1621,9 +1621,10 @@ static void gen_mfpr(int ra, int regno)
}
}
-static void gen_mtpr(int rb, int regno)
+static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
{
TCGv tmp;
+ int data;
if (rb == 31) {
tmp = tcg_const_i64(0);
@@ -1631,19 +1632,27 @@ static void gen_mtpr(int rb, int regno)
tmp = cpu_ir[rb];
}
- /* 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) {
+ switch (regno) {
+ case 255:
/* TBIA */
gen_helper_tbia();
- } else if (regno == 254) {
+ break;
+
+ case 254:
/* TBIS */
gen_helper_tbis(tmp);
- } else {
+ break;
+
+ case 253:
+ /* WAIT */
+ tmp = tcg_const_i64(1);
+ tcg_gen_st32_i64(tmp, cpu_env, offsetof(CPUState, halted));
+ return gen_excp(ctx, EXCP_HLT, 0);
+
+ default:
/* The basic registers are data only, and unknown registers
are read-zero, write-ignore. */
- int data = cpu_pr_data(regno);
+ data = cpu_pr_data(regno);
if (data != 0) {
if (data & PR_BYTE) {
tcg_gen_st8_i64(tmp, cpu_env, data & ~PR_BYTE);
@@ -1653,11 +1662,14 @@ static void gen_mtpr(int rb, int regno)
tcg_gen_st_i64(tmp, cpu_env, data);
}
}
+ break;
}
if (rb == 31) {
tcg_temp_free(tmp);
}
+
+ return NO_EXIT;
}
#endif /* !USER_ONLY*/
@@ -3052,8 +3064,7 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
/* HW_MTPR (PALcode) */
#ifndef CONFIG_USER_ONLY
if (ctx->tb->flags & TB_FLAGS_PAL_MODE) {
- gen_mtpr(rb, insn & 0xffff);
- break;
+ return gen_mtpr(ctx, rb, insn & 0xffff);
}
#endif
goto invalid_opc;
--
1.7.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 31/35] target-alpha: Implement HALT IPR.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (29 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 30/35] target-alpha: Implement WAIT IPR Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 32/35] target-alpha: Add high-resolution access to wall clock and an alarm Richard Henderson
` (4 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
target-alpha/helper.h | 1 +
target-alpha/op_helper.c | 10 ++++++++++
target-alpha/translate.c | 5 +++++
3 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 2dec57e..c352c24 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -113,6 +113,7 @@ 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)
+DEF_HELPER_1(halt, void, i64);
#endif
#include "def-helper.h"
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index d332719..80656f5 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -21,6 +21,7 @@
#include "host-utils.h"
#include "softfloat.h"
#include "helper.h"
+#include "sysemu.h"
#include "qemu-timer.h"
/*****************************************************************************/
@@ -1215,6 +1216,15 @@ void helper_tbis(uint64_t p)
{
tlb_flush_page(env, p);
}
+
+void helper_halt(uint64_t restart)
+{
+ if (restart) {
+ qemu_system_reset_request();
+ } else {
+ qemu_system_shutdown_request();
+ }
+}
#endif
/*****************************************************************************/
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 7b976be..9edcd74 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1649,6 +1649,11 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
tcg_gen_st32_i64(tmp, cpu_env, offsetof(CPUState, halted));
return gen_excp(ctx, EXCP_HLT, 0);
+ case 252:
+ /* HALT */
+ gen_helper_halt(tmp);
+ return EXIT_PC_STALE;
+
default:
/* The basic registers are data only, and unknown registers
are read-zero, write-ignore. */
--
1.7.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 32/35] target-alpha: Add high-resolution access to wall clock and an alarm.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (30 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 31/35] target-alpha: Implement HALT IPR Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 33/35] target-alpha: Properly select the VGA controler to use Richard Henderson
` (3 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 UTC (permalink / raw)
To: qemu-devel
The alarm is a fully general one-shot time comparator, which will be
usable under Linux as a hrtimer source. It's much more flexible than
the RTC source available on real hardware.
The wall clock allows the guest access to the host timekeeping. Much
like the KVM wall clock source for other guests.
Both are accessed via the PALcode Cserve entry point.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
hw/alpha_typhoon.c | 22 ++++++++++++++++++++--
target-alpha/cpu.h | 4 ++++
target-alpha/helper.h | 4 ++++
target-alpha/op_helper.c | 15 +++++++++++++++
target-alpha/translate.c | 14 ++++++++++++++
5 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index 7cdf7d3..731b6ea 100644
--- a/hw/alpha_typhoon.c
+++ b/hw/alpha_typhoon.c
@@ -681,6 +681,16 @@ static void typhoon_set_timer_irq(void *opaque, int irq, int level)
}
}
+static void typhoon_alarm_timer(void *opaque)
+{
+ TyphoonState *s = (TyphoonState *)((uintptr_t)opaque & ~3);
+ int cpu = (uintptr_t)opaque & 3;
+
+ /* Set the ITI bit for this cpu. */
+ s->cchip.misc |= 1 << (cpu + 4);
+ cpu_interrupt(s->cchip.cpu[cpu], CPU_INTERRUPT_TIMER);
+}
+
PCIBus *typhoon_init(qemu_irq *p_isa_irq, qemu_irq *p_rtc_irq,
CPUState *cpus[3], pci_map_irq_fn sys_map_irq)
{
@@ -689,14 +699,22 @@ PCIBus *typhoon_init(qemu_irq *p_isa_irq, qemu_irq *p_rtc_irq,
PCIHostState *p;
TyphoonState *s;
PCIBus *b;
- int region;
+ int i, region;
dev = qdev_create(NULL, "typhoon-pcihost");
p = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
s = container_of(p, TyphoonState, host);
/* Remember the CPUs so that we can deliver interrupts to them. */
- memcpy(s->cchip.cpu, cpus, 4 * sizeof(CPUState *));
+ for (i = 0; i < 4; i++) {
+ CPUState *env = cpus[i];
+ s->cchip.cpu[i] = env;
+ if (env) {
+ env->alarm_timer = qemu_new_timer_ns(rtc_clock,
+ typhoon_alarm_timer,
+ (void *)((uintptr_t)s + i));
+ }
+ }
*p_isa_irq = *qemu_allocate_irqs(typhoon_set_isa_irq, s, 1);
*p_rtc_irq = *qemu_allocate_irqs(typhoon_set_timer_irq, s, 1);
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index c94becf..72efbbd 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -266,6 +266,10 @@ struct CPUAlphaState {
uint64_t shadow[8];
uint64_t scratch[24];
+ /* This alarm doesn't exist in real hardware; we wish it did. */
+ struct QEMUTimer *alarm_timer;
+ uint64_t alarm_expire;
+
#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/helper.h b/target-alpha/helper.h
index c352c24..b693cee 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -113,7 +113,11 @@ 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)
+
DEF_HELPER_1(halt, void, i64);
+
+DEF_HELPER_FLAGS_0(get_time, TCG_CALL_CONST, i64)
+DEF_HELPER_FLAGS_1(set_alarm, 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 80656f5..c37fb5f 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -1225,6 +1225,21 @@ void helper_halt(uint64_t restart)
qemu_system_shutdown_request();
}
}
+
+uint64_t helper_get_time(void)
+{
+ return qemu_get_clock_ns(rtc_clock);
+}
+
+void helper_set_alarm(uint64_t expire)
+{
+ if (expire) {
+ env->alarm_expire = expire;
+ qemu_mod_timer(env->alarm_timer, expire);
+ } else {
+ qemu_del_timer(env->alarm_timer);
+ }
+}
#endif
/*****************************************************************************/
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 9edcd74..f34c53e 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -1594,6 +1594,9 @@ static int cpu_pr_data(int pr)
return offsetof(CPUAlphaState, shadow[pr - 32]);
case 40 ... 63:
return offsetof(CPUAlphaState, scratch[pr - 40]);
+
+ case 251:
+ return offsetof(CPUAlphaState, alarm_expire);
}
return 0;
}
@@ -1608,6 +1611,12 @@ static void gen_mfpr(int ra, int regno)
return;
}
+ if (regno == 250) {
+ /* WALL_TIME */
+ gen_helper_get_time(cpu_ir[ra]);
+ return;
+ }
+
/* The basic registers are data only, and unknown registers
are read-zero, write-ignore. */
if (data == 0) {
@@ -1654,6 +1663,11 @@ static ExitStatus gen_mtpr(DisasContext *ctx, int rb, int regno)
gen_helper_halt(tmp);
return EXIT_PC_STALE;
+ case 251:
+ /* ALARM */
+ gen_helper_set_alarm(tmp);
+ break;
+
default:
/* The basic registers are data only, and unknown registers
are read-zero, write-ignore. */
--
1.7.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 33/35] target-alpha: Properly select the VGA controler to use.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (31 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 32/35] target-alpha: Add high-resolution access to wall clock and an alarm Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 34/35] target-alpha: Enable PCI IDE Richard Henderson
` (2 subsequent siblings)
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 UTC (permalink / raw)
To: qemu-devel
The existing code for this really shouldn't be in pc.c.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
hw/alpha_dp264.c | 2 +-
hw/alpha_pci.c | 33 ++++++++++++++++++++++++++++++++-
hw/alpha_sys.h | 2 ++
3 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c
index c061b0a..dea0ef6 100644
--- a/hw/alpha_dp264.c
+++ b/hw/alpha_dp264.c
@@ -83,7 +83,7 @@ static void clipper_init(ram_addr_t ram_size,
pit_init(0x40, 0);
/* VGA setup. Don't bother loading the bios. */
- pci_vga_init(pci_bus);
+ alpha_pci_vga_setup(pci_bus);
/* Serial code setup. */
for (i = 0; i < MAX_SERIAL_PORTS; ++i) {
diff --git a/hw/alpha_pci.c b/hw/alpha_pci.c
index d0d727c..b321772 100644
--- a/hw/alpha_pci.c
+++ b/hw/alpha_pci.c
@@ -1,8 +1,15 @@
-/* There's nothing in here that's Alpha specific, really. */
+/*
+ * QEMU Alpha PCI support functions.
+ *
+ * Some of this isn't very Alpha specific at all. Some of this is specific
+ * to sparse PCI access support for older Alpha systems.
+ */
#include "config.h"
#include "alpha_sys.h"
#include "qemu-log.h"
+#include "sysemu.h"
+#include "vmware_vga.h"
/* PCI IO reads, to byte-word addressable memory. */
@@ -325,3 +332,27 @@ CPUWriteMemoryFunc * const alpha_pci_special_writes[] = {
unassigned_mem_writew,
special_writel,
};
+\f
+void alpha_pci_vga_setup(PCIBus *pci_bus)
+{
+ switch (vga_interface_type) {
+#ifdef CONFIG_SPICE
+ case VGA_QXL:
+ pci_create_simple(pci_bus, -1, "qxl-vga");
+ return;
+#endif
+ case VGA_CIRRUS:
+ pci_cirrus_vga_init(pci_bus);
+ return;
+ case VGA_VMWARE:
+ if (pci_vmsvga_init(pci_bus)) {
+ return;
+ }
+ break;
+ }
+ /* If VGA is enabled at all, and one of the above didn't work, then
+ fallback to Standard VGA. */
+ if (vga_interface_type != VGA_NONE) {
+ pci_vga_init(pci_bus);
+ }
+}
diff --git a/hw/alpha_sys.h b/hw/alpha_sys.h
index 272a107..98e5351 100644
--- a/hw/alpha_sys.h
+++ b/hw/alpha_sys.h
@@ -39,4 +39,6 @@ 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);
+void alpha_pci_vga_setup(PCIBus *pci_bus);
+
#endif
--
1.7.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 34/35] target-alpha: Enable PCI IDE
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (32 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 33/35] target-alpha: Properly select the VGA controler to use Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 35/35] target-alpha: Add ps2 keyboard Richard Henderson
2011-05-10 21:33 ` [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Paul Brook
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 UTC (permalink / raw)
To: qemu-devel
The CMD646 is the candidate that might be closest to something
that may have existed on real Alpha hardware.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
default-configs/alpha-softmmu.mak | 1 +
hw/alpha_dp264.c | 10 ++++++++++
2 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/default-configs/alpha-softmmu.mak b/default-configs/alpha-softmmu.mak
index abadcff..32167cd 100644
--- a/default-configs/alpha-softmmu.mak
+++ b/default-configs/alpha-softmmu.mak
@@ -7,3 +7,4 @@ CONFIG_VGA_PCI=y
CONFIG_IDE_CORE=y
CONFIG_IDE_QDEV=y
CONFIG_VMWARE_VGA=y
+CONFIG_IDE_CMD646=y
diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c
index dea0ef6..30ae567 100644
--- a/hw/alpha_dp264.c
+++ b/hw/alpha_dp264.c
@@ -13,7 +13,9 @@
#include "alpha_sys.h"
#include "sysemu.h"
#include "mc146818rtc.h"
+#include "ide.h"
+#define MAX_IDE_BUS 2
static uint64_t cpu_alpha_superpage_to_phys(void *opaque, uint64_t addr)
{
@@ -97,6 +99,14 @@ static void clipper_init(ram_addr_t ram_size,
pci_nic_init_nofail(&nd_table[i], "e1000", NULL);
}
+ /* IDE disk setup. */
+ {
+ DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+ ide_drive_get(hd, MAX_IDE_BUS);
+
+ pci_cmd646_ide_init(pci_bus, hd, 0);
+ }
+
/* 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. */
--
1.7.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* [Qemu-devel] [PATCH 35/35] target-alpha: Add ps2 keyboard.
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (33 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 34/35] target-alpha: Enable PCI IDE Richard Henderson
@ 2011-05-09 21:34 ` Richard Henderson
2011-05-10 21:33 ` [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Paul Brook
35 siblings, 0 replies; 39+ messages in thread
From: Richard Henderson @ 2011-05-09 21:34 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
default-configs/alpha-softmmu.mak | 1 +
hw/alpha_dp264.c | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/default-configs/alpha-softmmu.mak b/default-configs/alpha-softmmu.mak
index 32167cd..be86d0c 100644
--- a/default-configs/alpha-softmmu.mak
+++ b/default-configs/alpha-softmmu.mak
@@ -3,6 +3,7 @@
include pci.mak
CONFIG_SERIAL=y
CONFIG_I8254=y
+CONFIG_PCKBD=y
CONFIG_VGA_PCI=y
CONFIG_IDE_CORE=y
CONFIG_IDE_QDEV=y
diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c
index 30ae567..73a88fa 100644
--- a/hw/alpha_dp264.c
+++ b/hw/alpha_dp264.c
@@ -83,6 +83,7 @@ static void clipper_init(ram_addr_t ram_size,
rtc_init(1980, rtc_irq);
pit_init(0x40, 0);
+ isa_create_simple("i8042");
/* VGA setup. Don't bother loading the bios. */
alpha_pci_vga_setup(pci_bus);
--
1.7.4.4
^ permalink raw reply related [flat|nested] 39+ messages in thread
* Re: [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
` (34 preceding siblings ...)
2011-05-09 21:34 ` [Qemu-devel] [PATCH 35/35] target-alpha: Add ps2 keyboard Richard Henderson
@ 2011-05-10 21:33 ` Paul Brook
2011-05-10 22:09 ` Richard Henderson
35 siblings, 1 reply; 39+ messages in thread
From: Paul Brook @ 2011-05-10 21:33 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
> Since virtio devices intentionally access memory directly, we
> are not actually dependant on the iommu patches in order to
> make progress. Merely fixing the PCI interrupt setup was
> enough to get the virtio-pci interface working.
There should be nothing special about virtio-pci. These devices should access
memory in exactly the same way as any other PCI device. Bypassing the normal
PCI iommu is IMO a serious bug.
Paul
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4
2011-05-10 21:33 ` [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Paul Brook
@ 2011-05-10 22:09 ` Richard Henderson
2011-05-10 22:44 ` Paul Brook
0 siblings, 1 reply; 39+ messages in thread
From: Richard Henderson @ 2011-05-10 22:09 UTC (permalink / raw)
To: Paul Brook; +Cc: qemu-devel
On 05/10/2011 02:33 PM, Paul Brook wrote:
> There should be nothing special about virtio-pci. These devices should access
> memory in exactly the same way as any other PCI device. Bypassing the normal
> PCI iommu is IMO a serious bug.
I suspect that the argument is that virtio is implemented on several
busses, and ignoring any bus-specific stuff means that there's less
need for any code differences.
It doesn't bother me either way, so long as I know what to expect.
r~
^ permalink raw reply [flat|nested] 39+ messages in thread
* Re: [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4
2011-05-10 22:09 ` Richard Henderson
@ 2011-05-10 22:44 ` Paul Brook
0 siblings, 0 replies; 39+ messages in thread
From: Paul Brook @ 2011-05-10 22:44 UTC (permalink / raw)
To: qemu-devel; +Cc: Richard Henderson
> On 05/10/2011 02:33 PM, Paul Brook wrote:
> > There should be nothing special about virtio-pci. These devices should
> > access memory in exactly the same way as any other PCI device. Bypassing
> > the normal PCI iommu is IMO a serious bug.
>
> I suspect that the argument is that virtio is implemented on several
> busses, and ignoring any bus-specific stuff means that there's less
> need for any code differences.
It also has some horrifically bad implications. Not least of which is the
inability to sanely handle nested virtualization.
IMO the whole point of virtio-pci is that it avoids magical weirdness for
virtio devices devices. If you're going to start adding nonstandard
exceptions for virtio devices than there seem little point using PCI in the
first place. It's likely to cause more problems than it solves for the guest
drivers.
Paul
^ permalink raw reply [flat|nested] 39+ messages in thread
end of thread, other threads:[~2011-05-10 22:44 UTC | newest]
Thread overview: 39+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-09 21:34 [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 01/35] Export the unassigned_mem read/write functions Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 02/35] target-alpha: Disassemble EV6 PALcode instructions Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 03/35] pci: Export pci_to_cpu_addr Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 04/35] target-alpha: Single-step properly across branches Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 05/35] target-alpha: Remove partial support for palcode emulation Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 06/35] target-alpha: Enable the alpha-softmmu target Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 07/35] target-alpha: Tidy exception constants Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 08/35] target-alpha: Rationalize internal processor registers Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 09/35] target-alpha: Cleanup MMU modes Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 10/35] target-alpha: Fixup translation of PALmode instructions Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 11/35] target-alpha: Add IPRs to be used by the emulation PALcode Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 12/35] target-alpha: Tidy up arithmetic exceptions Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 13/35] target-alpha: Use do_restore_state for " Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 14/35] target-alpha: Merge HW_REI and HW_RET implementations Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 15/35] target-alpha: Implement do_interrupt for system mode Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 16/35] target-alpha: Swap shadow registers moving to/from PALmode Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 17/35] target-alpha: Add various symbolic constants Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 18/35] target-alpha: Use kernel mmu_idx for pal_mode Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 19/35] target-alpha: All ISA checks to use TB->FLAGS Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 20/35] target-alpha: Disable interrupts properly Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 21/35] target-alpha: Implement more CALL_PAL values inline Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 22/35] target-alpha: Implement cpu_alpha_handle_mmu_fault for system mode Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 23/35] target-alpha: Remap PIO space for 43-bit KSEG for EV6 Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 24/35] target-alpha: Trap for unassigned and unaligned addresses Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 25/35] target-alpha: Include the PCC_OFS in the RPCC return value Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 26/35] target-alpha: Use a fixed frequency for the RPCC in system mode Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 27/35] target-alpha: Implement TLB flush primitives Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 28/35] target-alpha: Add custom PALcode image for CLIPPER emulation Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 29/35] target-alpha: Add " Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 30/35] target-alpha: Implement WAIT IPR Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 31/35] target-alpha: Implement HALT IPR Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 32/35] target-alpha: Add high-resolution access to wall clock and an alarm Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 33/35] target-alpha: Properly select the VGA controler to use Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 34/35] target-alpha: Enable PCI IDE Richard Henderson
2011-05-09 21:34 ` [Qemu-devel] [PATCH 35/35] target-alpha: Add ps2 keyboard Richard Henderson
2011-05-10 21:33 ` [Qemu-devel] [PATCH 00/35] Alpha system emulation, v4 Paul Brook
2011-05-10 22:09 ` Richard Henderson
2011-05-10 22:44 ` Paul Brook
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).