hppa 64-bit mfdiag improvements

The 64-bit hppa qemu emulation still fails to boot 64-bit HP-UX.
 This patch series improves the emulation a lot, since it enables us to boot
 64-bit HP-UX installer silently up until an endless loop where the machine
 reports that it's up an running (it crashed before). This still needs further
 analysis, but it's a big step forward.
 
 Main changes to archieve this includes:
 - Implementing diagnose registers (especially %dr2 for space-register hashing)
 - a new SeaBIOS-hppa version 18, which includes those fixes and enhancements:
   - Fix IRT table entries to use slot number
   - Increase PCI alignment for memory bars to 64k
   - Fix PDC_CACHE/PDC_CACHE_RET_SPID return value
   - Allow up to 256 GB RAM on 64-bit machines
 
 V2:
 - fix linux-user build by adding missing "#ifndef CONFIG_USER_ONLY ... #endif"
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQS86RI+GtKfB8BJu973ErUQojoPXwUCZ5yWTwAKCRD3ErUQojoP
 X1p5AP4iSfKlBsUZrww2/M1ArqB9jZuJBO1kdZ7OcCN2Jn0yxgEAx0CPUof7NnZV
 EY7u3Qq4E8ZnOk4XgHt06bsdNcJN+gc=
 =RoAh
 -----END PGP SIGNATURE-----

Merge tag 'hppa-system-mfdiag-for-v10-pull-request' of https://github.com/hdeller/qemu-hppa into staging

hppa 64-bit mfdiag improvements

The 64-bit hppa qemu emulation still fails to boot 64-bit HP-UX.
This patch series improves the emulation a lot, since it enables us to boot
64-bit HP-UX installer silently up until an endless loop where the machine
reports that it's up an running (it crashed before). This still needs further
analysis, but it's a big step forward.

Main changes to archieve this includes:
- Implementing diagnose registers (especially %dr2 for space-register hashing)
- a new SeaBIOS-hppa version 18, which includes those fixes and enhancements:
  - Fix IRT table entries to use slot number
  - Increase PCI alignment for memory bars to 64k
  - Fix PDC_CACHE/PDC_CACHE_RET_SPID return value
  - Allow up to 256 GB RAM on 64-bit machines

V2:
- fix linux-user build by adding missing "#ifndef CONFIG_USER_ONLY ... #endif"

# -----BEGIN PGP SIGNATURE-----
#
# iHUEABYKAB0WIQS86RI+GtKfB8BJu973ErUQojoPXwUCZ5yWTwAKCRD3ErUQojoP
# X1p5AP4iSfKlBsUZrww2/M1ArqB9jZuJBO1kdZ7OcCN2Jn0yxgEAx0CPUof7NnZV
# EY7u3Qq4E8ZnOk4XgHt06bsdNcJN+gc=
# =RoAh
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 31 Jan 2025 04:22:23 EST
# gpg:                using EDDSA key BCE9123E1AD29F07C049BBDEF712B510A23A0F5F
# gpg: Good signature from "Helge Deller <deller@gmx.de>" [unknown]
# gpg:                 aka "Helge Deller <deller@kernel.org>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 4544 8228 2CD9 10DB EF3D  25F8 3E5F 3D04 A7A2 4603
#      Subkey fingerprint: BCE9 123E 1AD2 9F07 C049  BBDE F712 B510 A23A 0F5F

* tag 'hppa-system-mfdiag-for-v10-pull-request' of https://github.com/hdeller/qemu-hppa:
  target/hppa: Update SeaBIOS-hppa to version 18
  target/hppa: Implement space register hashing for 64-bit HP-UX
  target/hppa: 64-bit CPUs start with space register hashing enabled
  target/hppa: Add instruction decoding for mfdiag and mtdiag
  target/hppa: Drop diag_getshadowregs_pa2 and diag_putshadowregs_pa2
  target/hppa: Add CPU diagnose registers
  disas/hppa: implement mfdiag/mtdiag disassembly
  hppa: Sync contents of hppa_hardware.h header file with SeaBIOS-hppa
  MAINTAINERS: Add myself as HPPA maintainer

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2025-02-02 11:08:48 -05:00
commit 4d93b13910
16 changed files with 150 additions and 43 deletions

View File

@ -251,6 +251,7 @@ F: target/hexagon/gen_idef_parser_funcs.py
HPPA (PA-RISC) TCG CPUs HPPA (PA-RISC) TCG CPUs
M: Richard Henderson <richard.henderson@linaro.org> M: Richard Henderson <richard.henderson@linaro.org>
M: Helge Deller <deller@gmx.de>
S: Maintained S: Maintained
F: target/hppa/ F: target/hppa/
F: disas/hppa.c F: disas/hppa.c
@ -1189,8 +1190,8 @@ HP-PARISC Machines
------------------ ------------------
HP B160L, HP C3700 HP B160L, HP C3700
M: Richard Henderson <richard.henderson@linaro.org> M: Richard Henderson <richard.henderson@linaro.org>
R: Helge Deller <deller@gmx.de> M: Helge Deller <deller@gmx.de>
S: Odd Fixes S: Maintained
F: configs/devices/hppa-softmmu/default.mak F: configs/devices/hppa-softmmu/default.mak
F: hw/display/artist.c F: hw/display/artist.c
F: hw/hppa/ F: hw/hppa/

View File

@ -606,7 +606,7 @@ struct pa_opcode
In the args field, the following characters are unused: In the args field, the following characters are unused:
' " - / 34 6789:; ' ' " - / 34 678 :; '
'@ C M [\] ' '@ C M [\] '
'` e g } ' '` e g } '
@ -650,6 +650,7 @@ Also these:
| 6 bit field length at 19,27:31 (fixed extract/deposit) | 6 bit field length at 19,27:31 (fixed extract/deposit)
A 13 bit immediate at 18 (to support the BREAK instruction) A 13 bit immediate at 18 (to support the BREAK instruction)
^ like b, but describes a control register ^ like b, but describes a control register
9 like b, but describes a diagnose register
! sar (cr11) register ! sar (cr11) register
D 26 bit immediate at 31 (to support the DIAG instruction) D 26 bit immediate at 31 (to support the DIAG instruction)
$ 9 bit immediate at 28 (to support POPBTS) $ 9 bit immediate at 28 (to support POPBTS)
@ -1322,13 +1323,19 @@ static const struct pa_opcode pa_opcodes[] =
{ "fdce", 0x040012c0, 0xfc00ffdf, "cZx(b)", pa10, 0}, { "fdce", 0x040012c0, 0xfc00ffdf, "cZx(b)", pa10, 0},
{ "fdce", 0x040012c0, 0xfc003fdf, "cZx(s,b)", pa10, 0}, { "fdce", 0x040012c0, 0xfc003fdf, "cZx(s,b)", pa10, 0},
{ "fice", 0x040002c0, 0xfc001fdf, "cZx(S,b)", pa10, 0}, { "fice", 0x040002c0, 0xfc001fdf, "cZx(S,b)", pa10, 0},
{ "diag", 0x14000000, 0xfc000000, "D", pa10, 0},
{ "idtlbt", 0x04001800, 0xfc00ffff, "x,b", pa20, FLAG_STRICT}, { "idtlbt", 0x04001800, 0xfc00ffff, "x,b", pa20, FLAG_STRICT},
{ "iitlbt", 0x04000800, 0xfc00ffff, "x,b", pa20, FLAG_STRICT}, { "iitlbt", 0x04000800, 0xfc00ffff, "x,b", pa20, FLAG_STRICT},
/* completely undocumented, but used by ODE, HP-UX and Linux: */
{ "mfcpu_pcxu", 0x140008a0, 0xfc9fffe0, "9,t", pa20, 0}, /* PCXU: mfdiag */
{ "mtcpu_pcxu", 0x14001840, 0xfc00ffff, "x,9", pa20, 0},
/* These may be specific to certain versions of the PA. Joel claimed /* These may be specific to certain versions of the PA. Joel claimed
they were 72000 (7200?) specific. However, I'm almost certain the they were 72000 (7200?) specific. However, I'm almost certain the
mtcpu/mfcpu were undocumented, but available in the older 700 machines. */ mtcpu/mfcpu were undocumented, but available in the older 700 machines. */
{ "mfcpu_c", 0x14000600, 0xfc00ffff, "9,x", pa10, 0}, /* PCXL: for dr0 and dr8 only */
{ "mfcpu_t", 0x14001400, 0xfc9fffe0, "9,t", pa10, 0}, /* PCXL: all dr except dr0 and dr8 */
{ "mtcpu_pcxl", 0x14000240, 0xfc00ffff, "x,9", pa11, 0}, /* PCXL: mtcpu for dr0 and dr8 */
{ "mtcpu", 0x14001600, 0xfc00ffff, "x,^", pa10, 0}, { "mtcpu", 0x14001600, 0xfc00ffff, "x,^", pa10, 0},
{ "mfcpu", 0x14001A00, 0xfc00ffff, "^,x", pa10, 0}, { "mfcpu", 0x14001A00, 0xfc00ffff, "^,x", pa10, 0},
{ "tocen", 0x14403600, 0xffffffff, "", pa10, 0}, { "tocen", 0x14403600, 0xffffffff, "", pa10, 0},
@ -1336,6 +1343,9 @@ static const struct pa_opcode pa_opcodes[] =
{ "shdwgr", 0x14402600, 0xffffffff, "", pa10, 0}, { "shdwgr", 0x14402600, 0xffffffff, "", pa10, 0},
{ "grshdw", 0x14400620, 0xffffffff, "", pa10, 0}, { "grshdw", 0x14400620, 0xffffffff, "", pa10, 0},
/* instead of showing D only, show all other registers too */
{ "diag", 0x14000000, 0xfc000000, "D x,9,t", pa10, 0},
/* gfw and gfr are not in the HP PA 1.1 manual, but they are in either /* gfw and gfr are not in the HP PA 1.1 manual, but they are in either
the Timex FPU or the Mustang ERS (not sure which) manual. */ the Timex FPU or the Mustang ERS (not sure which) manual. */
{ "gfw", 0x04001680, 0xfc00ffdf, "cZx(b)", pa11, 0}, { "gfw", 0x04001680, 0xfc00ffdf, "cZx(b)", pa11, 0},
@ -1801,6 +1811,12 @@ fput_creg (unsigned reg, disassemble_info *info)
(*info->fprintf_func) (info->stream, "%s", control_reg[reg]); (*info->fprintf_func) (info->stream, "%s", control_reg[reg]);
} }
static void
fput_dreg (unsigned reg, disassemble_info *info)
{
(*info->fprintf_func) (info->stream, "dr%d", reg);
}
/* Print constants with sign. */ /* Print constants with sign. */
static void static void
@ -2007,6 +2023,9 @@ print_insn_hppa (bfd_vma memaddr, disassemble_info *info)
case '^': case '^':
fput_creg (GET_FIELD (insn, 6, 10), info); fput_creg (GET_FIELD (insn, 6, 10), info);
break; break;
case '9':
fput_dreg (GET_FIELD (insn, 6, 10), info);
break;
case 't': case 't':
fput_reg (GET_FIELD (insn, 27, 31), info); fput_reg (GET_FIELD (insn, 27, 31), info);
break; break;

View File

@ -6,6 +6,11 @@
#define FIRMWARE_START 0xf0000000 #define FIRMWARE_START 0xf0000000
#define FIRMWARE_END 0xf0800000 #define FIRMWARE_END 0xf0800000
#define FIRMWARE_HIGH 0xfffffff0 /* upper 32-bits of 64-bit firmware address */
#define RAM_MAP_HIGH 0x0100000000 /* memory above 3.75 GB is mapped here */
#define MEM_PDC_ENTRY 0x4800 /* PDC entry address */
#define DEVICE_HPA_LEN 0x00100000 #define DEVICE_HPA_LEN 0x00100000
@ -18,6 +23,7 @@
#define LASI_UART_HPA 0xffd05000 #define LASI_UART_HPA 0xffd05000
#define LASI_SCSI_HPA 0xffd06000 #define LASI_SCSI_HPA 0xffd06000
#define LASI_LAN_HPA 0xffd07000 #define LASI_LAN_HPA 0xffd07000
#define LASI_RTC_HPA 0xffd09000
#define LASI_LPT_HPA 0xffd02000 #define LASI_LPT_HPA 0xffd02000
#define LASI_AUDIO_HPA 0xffd04000 #define LASI_AUDIO_HPA 0xffd04000
#define LASI_PS2KBD_HPA 0xffd08000 #define LASI_PS2KBD_HPA 0xffd08000
@ -27,16 +33,23 @@
#define CPU_HPA 0xfffb0000 #define CPU_HPA 0xfffb0000
#define MEMORY_HPA 0xfffff000 #define MEMORY_HPA 0xfffff000
#define PCI_HPA DINO_HPA /* PCI bus */
#define IDE_HPA 0xf9000000 /* Boot disc controller */ #define IDE_HPA 0xf9000000 /* Boot disc controller */
#define ASTRO_HPA 0xfed00000
#define ELROY0_HPA 0xfed30000
#define ELROY2_HPA 0xfed32000
#define ELROY8_HPA 0xfed38000
#define ELROYc_HPA 0xfed3c000
#define ASTRO_MEMORY_HPA 0xfed10200
#define SCSI_HPA 0xf1040000 /* emulated SCSI, needs to be in f region */
/* offsets to DINO HPA: */ /* offsets to DINO HPA: */
#define DINO_PCI_ADDR 0x064 #define DINO_PCI_ADDR 0x064
#define DINO_CONFIG_DATA 0x068 #define DINO_CONFIG_DATA 0x068
#define DINO_IO_DATA 0x06c #define DINO_IO_DATA 0x06c
#define PORT_PCI_CMD (PCI_HPA + DINO_PCI_ADDR) #define PORT_PCI_CMD hppa_port_pci_cmd
#define PORT_PCI_DATA (PCI_HPA + DINO_CONFIG_DATA) #define PORT_PCI_DATA hppa_port_pci_data
#define FW_CFG_IO_BASE 0xfffa0000 #define FW_CFG_IO_BASE 0xfffa0000
@ -46,9 +59,24 @@
#define HPPA_MAX_CPUS 16 /* max. number of SMP CPUs */ #define HPPA_MAX_CPUS 16 /* max. number of SMP CPUs */
#define CPU_CLOCK_MHZ 250 /* emulate a 250 MHz CPU */ #define CPU_CLOCK_MHZ 250 /* emulate a 250 MHz CPU */
#define CR_PSW_DEFAULT 6 /* used by SeaBIOS & QEMU for default PSW */
#define CPU_HPA_CR_REG 7 /* store CPU HPA in cr7 (SeaBIOS internal) */ #define CPU_HPA_CR_REG 7 /* store CPU HPA in cr7 (SeaBIOS internal) */
#define PIM_STORAGE_SIZE 600 /* storage size of pdc_pim_toc_struct (64bit) */ #define PIM_STORAGE_SIZE 600 /* storage size of pdc_pim_toc_struct (64bit) */
#define RAM_MAP_HIGH 0x0100000000 /* memory above 3.75 GB is mapped here */ #define ASTRO_BUS_MODULE 0x0a /* C3700: 0x0a, others maybe 0 ? */
/* ASTRO Memory and I/O regions */
#define ASTRO_BASE_HPA 0xfffed00000
#define ELROY0_BASE_HPA 0xfffed30000 /* ELROY0_HPA */
#define ROPES_PER_IOC 8 /* per Ike half or Pluto/Astro */
#define LMMIO_DIRECT0_BASE 0x300
#define LMMIO_DIRECT0_MASK 0x308
#define LMMIO_DIRECT0_ROUTE 0x310
/* space register hashing */
#define HPPA64_DIAG_SPHASH_ENABLE 0x200 /* DIAG_SPHASH_ENAB (bit 54) */
#define HPPA64_PDC_CACHE_RET_SPID_VAL 0xfe0 /* PDC return value on 64-bit CPU */
#endif #endif

BIN
pc-bios/hppa-firmware.img Normal file → Executable file

Binary file not shown.

BIN
pc-bios/hppa-firmware64.img Normal file → Executable file

Binary file not shown.

@ -1 +1 @@
Subproject commit a528f01d7abd511d3cc71b7acaab6e036ee524bd Subproject commit 1c516b481339f511d83a4afba9a48d1ac904e93e

View File

@ -28,6 +28,7 @@
#include "exec/translation-block.h" #include "exec/translation-block.h"
#include "fpu/softfloat.h" #include "fpu/softfloat.h"
#include "tcg/tcg.h" #include "tcg/tcg.h"
#include "hw/hppa/hppa_hardware.h"
static void hppa_cpu_set_pc(CPUState *cs, vaddr value) static void hppa_cpu_set_pc(CPUState *cs, vaddr value)
{ {
@ -44,7 +45,8 @@ static vaddr hppa_cpu_get_pc(CPUState *cs)
{ {
CPUHPPAState *env = cpu_env(cs); CPUHPPAState *env = cpu_env(cs);
return hppa_form_gva_psw(env->psw, (env->psw & PSW_C ? env->iasq_f : 0), return hppa_form_gva_mask(env->gva_offset_mask,
(env->psw & PSW_C ? env->iasq_f : 0),
env->iaoq_f & -4); env->iaoq_f & -4);
} }
@ -90,6 +92,10 @@ void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
& (env->sr[4] == env->sr[7])) { & (env->sr[4] == env->sr[7])) {
flags |= TB_FLAG_SR_SAME; flags |= TB_FLAG_SR_SAME;
} }
if ((env->psw & PSW_W) &&
(env->dr[2] & HPPA64_DIAG_SPHASH_ENABLE)) {
flags |= TB_FLAG_SPHASH;
}
#endif #endif
*pcsbase = cs_base; *pcsbase = cs_base;
@ -217,6 +223,10 @@ static void hppa_cpu_reset_hold(Object *obj, ResetType type)
memset(env, 0, offsetof(CPUHPPAState, end_reset_fields)); memset(env, 0, offsetof(CPUHPPAState, end_reset_fields));
cpu_hppa_loaded_fr0(env); cpu_hppa_loaded_fr0(env);
/* 64-bit machines start with space-register hashing enabled in %dr2 */
env->dr[2] = hppa_is_pa20(env) ? HPPA64_DIAG_SPHASH_ENABLE : 0;
cpu_hppa_put_psw(env, PSW_M); cpu_hppa_put_psw(env, PSW_M);
} }

View File

@ -223,6 +223,7 @@ typedef struct CPUArchState {
target_ulong psw_cb; /* in least significant bit of next nibble */ target_ulong psw_cb; /* in least significant bit of next nibble */
target_ulong psw_cb_msb; /* boolean */ target_ulong psw_cb_msb; /* boolean */
uint64_t gva_offset_mask; /* cached address mask based on PSW and %dr2 */
uint64_t iasq_f; uint64_t iasq_f;
uint64_t iasq_b; uint64_t iasq_b;
@ -232,6 +233,7 @@ typedef struct CPUArchState {
target_ulong cr[32]; /* control registers */ target_ulong cr[32]; /* control registers */
target_ulong cr_back[2]; /* back of cr17/cr18 */ target_ulong cr_back[2]; /* back of cr17/cr18 */
target_ulong shadow[7]; /* shadow registers */ target_ulong shadow[7]; /* shadow registers */
target_ulong dr[32]; /* diagnose registers */
/* /*
* During unwind of a memory insn, the base register of the address. * During unwind of a memory insn, the base register of the address.
@ -319,27 +321,20 @@ void hppa_translate_code(CPUState *cs, TranslationBlock *tb,
#define CPU_RESOLVING_TYPE TYPE_HPPA_CPU #define CPU_RESOLVING_TYPE TYPE_HPPA_CPU
static inline uint64_t gva_offset_mask(target_ulong psw) static inline target_ulong hppa_form_gva_mask(uint64_t gva_offset_mask,
{ uint64_t spc, target_ulong off)
return (psw & PSW_W
? MAKE_64BIT_MASK(0, 62)
: MAKE_64BIT_MASK(0, 32));
}
static inline target_ulong hppa_form_gva_psw(target_ulong psw, uint64_t spc,
target_ulong off)
{ {
#ifdef CONFIG_USER_ONLY #ifdef CONFIG_USER_ONLY
return off & gva_offset_mask(psw); return off & gva_offset_mask;
#else #else
return spc | (off & gva_offset_mask(psw)); return spc | (off & gva_offset_mask);
#endif #endif
} }
static inline target_ulong hppa_form_gva(CPUHPPAState *env, uint64_t spc, static inline target_ulong hppa_form_gva(CPUHPPAState *env, uint64_t spc,
target_ulong off) target_ulong off)
{ {
return hppa_form_gva_psw(env->psw, spc, off); return hppa_form_gva_mask(env->gva_offset_mask, spc, off);
} }
hwaddr hppa_abs_to_phys_pa2_w0(vaddr addr); hwaddr hppa_abs_to_phys_pa2_w0(vaddr addr);
@ -353,6 +348,7 @@ hwaddr hppa_abs_to_phys_pa2_w1(vaddr addr);
#define TB_FLAG_SR_SAME PSW_I #define TB_FLAG_SR_SAME PSW_I
#define TB_FLAG_PRIV_SHIFT 8 #define TB_FLAG_PRIV_SHIFT 8
#define TB_FLAG_UNALIGN 0x400 #define TB_FLAG_UNALIGN 0x400
#define TB_FLAG_SPHASH 0x800
#define CS_BASE_DIFFPAGE (1 << 12) #define CS_BASE_DIFFPAGE (1 << 12)
#define CS_BASE_DIFFSPACE (1 << 13) #define CS_BASE_DIFFSPACE (1 << 13)
@ -361,6 +357,7 @@ void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
target_ulong cpu_hppa_get_psw(CPUHPPAState *env); target_ulong cpu_hppa_get_psw(CPUHPPAState *env);
void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong); void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong);
void update_gva_offset_mask(CPUHPPAState *env);
void cpu_hppa_loaded_fr0(CPUHPPAState *env); void cpu_hppa_loaded_fr0(CPUHPPAState *env);
#ifdef CONFIG_USER_ONLY #ifdef CONFIG_USER_ONLY

View File

@ -24,6 +24,7 @@
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "qemu/qemu-print.h" #include "qemu/qemu-print.h"
#include "hw/hppa/hppa_hardware.h"
target_ulong cpu_hppa_get_psw(CPUHPPAState *env) target_ulong cpu_hppa_get_psw(CPUHPPAState *env)
{ {
@ -59,6 +60,22 @@ target_ulong cpu_hppa_get_psw(CPUHPPAState *env)
return psw; return psw;
} }
void update_gva_offset_mask(CPUHPPAState *env)
{
uint64_t gom;
if (env->psw & PSW_W) {
gom = (env->dr[2] & HPPA64_DIAG_SPHASH_ENABLE)
? MAKE_64BIT_MASK(0, 62) &
~((uint64_t)HPPA64_PDC_CACHE_RET_SPID_VAL << 48)
: MAKE_64BIT_MASK(0, 62);
} else {
gom = MAKE_64BIT_MASK(0, 32);
}
env->gva_offset_mask = gom;
}
void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw) void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw)
{ {
uint64_t reserved; uint64_t reserved;
@ -98,6 +115,8 @@ void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw)
cb |= ((psw >> 9) & 1) << 8; cb |= ((psw >> 9) & 1) << 8;
cb |= ((psw >> 8) & 1) << 4; cb |= ((psw >> 8) & 1) << 4;
env->psw_cb = cb; env->psw_cb = cb;
update_gva_offset_mask(env);
} }
void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags) void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags)
@ -133,9 +152,11 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags)
qemu_fprintf(f, "IA_F %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n" qemu_fprintf(f, "IA_F %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n"
"IA_B %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n", "IA_B %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n",
env->iasq_f >> 32, w, m & env->iaoq_f, env->iasq_f >> 32, w, m & env->iaoq_f,
hppa_form_gva_psw(psw, env->iasq_f, env->iaoq_f), hppa_form_gva_mask(env->gva_offset_mask, env->iasq_f,
env->iaoq_f),
env->iasq_b >> 32, w, m & env->iaoq_b, env->iasq_b >> 32, w, m & env->iaoq_b,
hppa_form_gva_psw(psw, env->iasq_b, env->iaoq_b)); hppa_form_gva_mask(env->gva_offset_mask, env->iasq_b,
env->iaoq_b));
psw_c[0] = (psw & PSW_W ? 'W' : '-'); psw_c[0] = (psw & PSW_W ? 'W' : '-');
psw_c[1] = (psw & PSW_E ? 'E' : '-'); psw_c[1] = (psw & PSW_E ? 'E' : '-');

View File

@ -99,6 +99,7 @@ DEF_HELPER_FLAGS_2(ptlb_l, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_1(ptlbe, TCG_CALL_NO_RWG, void, env) DEF_HELPER_FLAGS_1(ptlbe, TCG_CALL_NO_RWG, void, env)
DEF_HELPER_FLAGS_2(lpa, TCG_CALL_NO_WG, tl, env, tl) DEF_HELPER_FLAGS_2(lpa, TCG_CALL_NO_WG, tl, env, tl)
DEF_HELPER_FLAGS_1(change_prot_id, TCG_CALL_NO_RWG, void, env) DEF_HELPER_FLAGS_1(change_prot_id, TCG_CALL_NO_RWG, void, env)
DEF_HELPER_FLAGS_1(update_gva_offset_mask, TCG_CALL_NO_RWG, void, env)
DEF_HELPER_1(diag_btlb, void, env) DEF_HELPER_1(diag_btlb, void, env)
DEF_HELPER_1(diag_console_output, void, env) DEF_HELPER_1(diag_console_output, void, env)
#endif #endif

View File

@ -644,10 +644,12 @@ xmpyu 001110 ..... ..... 010 .0111 .00 t:5 r1=%ra64 r2=%rb64
# For 32-bit PA-7300LC (PCX-L2) # For 32-bit PA-7300LC (PCX-L2)
diag_getshadowregs_pa1 000101 00 0000 0000 0001 1010 0000 0000 diag_getshadowregs_pa1 000101 00 0000 0000 0001 1010 0000 0000
diag_putshadowregs_pa1 000101 00 0000 0000 0001 1010 0100 0000 diag_putshadowregs_pa1 000101 00 0000 0000 0001 1010 0100 0000
diag_mfdiag 000101 dr:5 rt:5 0000 0110 0000 0000
diag_mtdiag 000101 dr:5 r1:5 0001 0110 0000 0000
# For 64-bit PA8700 (PCX-W2) # For 64-bit PA8700 (PCX-W2)
diag_getshadowregs_pa2 000101 00 0111 1000 0001 1000 0100 0000 diag_mfdiag 000101 dr:5 0 0000 0000 1000 101 rt:5
diag_putshadowregs_pa2 000101 00 0111 0000 0001 1000 0100 0000 diag_mtdiag 000101 dr:5 r1:5 0001 1000 0100 0000
] ]
diag_unimp 000101 i:26 diag_unimp 000101 i:26
} }

View File

@ -94,11 +94,12 @@ void hppa_cpu_do_interrupt(CPUState *cs)
HPPACPU *cpu = HPPA_CPU(cs); HPPACPU *cpu = HPPA_CPU(cs);
CPUHPPAState *env = &cpu->env; CPUHPPAState *env = &cpu->env;
int i = cs->exception_index; int i = cs->exception_index;
uint64_t old_psw; uint64_t old_psw, old_gva_offset_mask;
/* As documented in pa2.0 -- interruption handling. */ /* As documented in pa2.0 -- interruption handling. */
/* step 1 */ /* step 1 */
env->cr[CR_IPSW] = old_psw = cpu_hppa_get_psw(env); env->cr[CR_IPSW] = old_psw = cpu_hppa_get_psw(env);
old_gva_offset_mask = env->gva_offset_mask;
/* step 2 -- Note PSW_W is masked out again for pa1.x */ /* step 2 -- Note PSW_W is masked out again for pa1.x */
cpu_hppa_put_psw(env, cpu_hppa_put_psw(env,
@ -112,9 +113,9 @@ void hppa_cpu_do_interrupt(CPUState *cs)
*/ */
if (old_psw & PSW_C) { if (old_psw & PSW_C) {
env->cr[CR_IIASQ] = env->cr[CR_IIASQ] =
hppa_form_gva_psw(old_psw, env->iasq_f, env->iaoq_f) >> 32; hppa_form_gva_mask(old_gva_offset_mask, env->iasq_f, env->iaoq_f) >> 32;
env->cr_back[0] = env->cr_back[0] =
hppa_form_gva_psw(old_psw, env->iasq_b, env->iaoq_b) >> 32; hppa_form_gva_mask(old_gva_offset_mask, env->iasq_b, env->iaoq_b) >> 32;
} else { } else {
env->cr[CR_IIASQ] = 0; env->cr[CR_IIASQ] = 0;
env->cr_back[0] = 0; env->cr_back[0] = 0;
@ -165,7 +166,8 @@ void hppa_cpu_do_interrupt(CPUState *cs)
if (old_psw & PSW_C) { if (old_psw & PSW_C) {
int prot, t; int prot, t;
vaddr = hppa_form_gva_psw(old_psw, env->iasq_f, vaddr); vaddr = hppa_form_gva_mask(old_gva_offset_mask,
env->iasq_f, vaddr);
t = hppa_get_physical_address(env, vaddr, MMU_KERNEL_IDX, t = hppa_get_physical_address(env, vaddr, MMU_KERNEL_IDX,
0, 0, &paddr, &prot); 0, 0, &paddr, &prot);
if (t >= 0) { if (t >= 0) {

View File

@ -198,6 +198,7 @@ static const VMStateField vmstate_env_fields[] = {
VMSTATE_UINT64(iasq_b, CPUHPPAState), VMSTATE_UINT64(iasq_b, CPUHPPAState),
VMSTATE_UINT32(fr0_shadow, CPUHPPAState), VMSTATE_UINT32(fr0_shadow, CPUHPPAState),
VMSTATE_UINT64_ARRAY(dr, CPUHPPAState, 32),
VMSTATE_END_OF_LIST() VMSTATE_END_OF_LIST()
}; };
@ -208,8 +209,8 @@ static const VMStateDescription * const vmstate_env_subsections[] = {
static const VMStateDescription vmstate_env = { static const VMStateDescription vmstate_env = {
.name = "env", .name = "env",
.version_id = 3, .version_id = 4,
.minimum_version_id = 3, .minimum_version_id = 4,
.fields = vmstate_env_fields, .fields = vmstate_env_fields,
.subsections = vmstate_env_subsections, .subsections = vmstate_env_subsections,
}; };

View File

@ -824,3 +824,8 @@ uint64_t HELPER(b_gate_priv)(CPUHPPAState *env, uint64_t iaoq_f)
} }
return iaoq_f; return iaoq_f;
} }
void HELPER(update_gva_offset_mask)(CPUHPPAState *env)
{
update_gva_offset_mask(env);
}

View File

@ -73,7 +73,7 @@ target_ulong HELPER(swap_system_mask)(CPUHPPAState *env, target_ulong nsm)
* machines set the Q bit from 0 to 1 without an exception, * machines set the Q bit from 0 to 1 without an exception,
* so let this go without comment. * so let this go without comment.
*/ */
env->psw = (psw & ~PSW_SM) | (nsm & PSW_SM); cpu_hppa_put_psw(env, (psw & ~PSW_SM) | (nsm & PSW_SM));
return psw & PSW_SM; return psw & PSW_SM;
} }
@ -88,7 +88,7 @@ void HELPER(rfi)(CPUHPPAState *env)
* To recreate the space identifier, remove the offset bits. * To recreate the space identifier, remove the offset bits.
* For pa1.x, the mask reduces to no change to space. * For pa1.x, the mask reduces to no change to space.
*/ */
mask = gva_offset_mask(env->psw); mask = env->gva_offset_mask;
env->iaoq_f = env->cr[CR_IIAOQ]; env->iaoq_f = env->cr[CR_IIAOQ];
env->iaoq_b = env->cr_back[1]; env->iaoq_b = env->cr_back[1];

View File

@ -73,6 +73,7 @@ typedef struct DisasContext {
/* IAOQ_Front at entry to TB. */ /* IAOQ_Front at entry to TB. */
uint64_t iaoq_first; uint64_t iaoq_first;
uint64_t gva_offset_mask;
DisasCond null_cond; DisasCond null_cond;
TCGLabel *null_lab; TCGLabel *null_lab;
@ -1577,7 +1578,7 @@ static void form_gva(DisasContext *ctx, TCGv_i64 *pgva, TCGv_i64 *pofs,
*pofs = ofs; *pofs = ofs;
*pgva = addr = tcg_temp_new_i64(); *pgva = addr = tcg_temp_new_i64();
tcg_gen_andi_i64(addr, modify <= 0 ? ofs : base, tcg_gen_andi_i64(addr, modify <= 0 ? ofs : base,
gva_offset_mask(ctx->tb_flags)); ctx->gva_offset_mask);
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
if (!is_phys) { if (!is_phys) {
tcg_gen_or_i64(addr, addr, space_select(ctx, sp, base)); tcg_gen_or_i64(addr, addr, space_select(ctx, sp, base));
@ -4593,19 +4594,37 @@ static bool trans_diag_getshadowregs_pa1(DisasContext *ctx, arg_empty *a)
return !ctx->is_pa20 && do_getshadowregs(ctx); return !ctx->is_pa20 && do_getshadowregs(ctx);
} }
static bool trans_diag_getshadowregs_pa2(DisasContext *ctx, arg_empty *a)
{
return ctx->is_pa20 && do_getshadowregs(ctx);
}
static bool trans_diag_putshadowregs_pa1(DisasContext *ctx, arg_empty *a) static bool trans_diag_putshadowregs_pa1(DisasContext *ctx, arg_empty *a)
{ {
return !ctx->is_pa20 && do_putshadowregs(ctx); return !ctx->is_pa20 && do_putshadowregs(ctx);
} }
static bool trans_diag_putshadowregs_pa2(DisasContext *ctx, arg_empty *a) static bool trans_diag_mfdiag(DisasContext *ctx, arg_diag_mfdiag *a)
{ {
return ctx->is_pa20 && do_putshadowregs(ctx); CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
nullify_over(ctx);
TCGv_i64 dest = dest_gpr(ctx, a->rt);
tcg_gen_ld_i64(dest, tcg_env,
offsetof(CPUHPPAState, dr[a->dr]));
save_gpr(ctx, a->rt, dest);
return nullify_end(ctx);
}
static bool trans_diag_mtdiag(DisasContext *ctx, arg_diag_mtdiag *a)
{
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
nullify_over(ctx);
tcg_gen_st_i64(load_gpr(ctx, a->r1), tcg_env,
offsetof(CPUHPPAState, dr[a->dr]));
#ifndef CONFIG_USER_ONLY
if (ctx->is_pa20 && (a->dr == 2)) {
/* Update gva_offset_mask from the new value of %dr2 */
gen_helper_update_gva_offset_mask(tcg_env);
/* Exit to capture the new value for the next TB. */
ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
}
#endif
return nullify_end(ctx);
} }
static bool trans_diag_unimp(DisasContext *ctx, arg_diag_unimp *a) static bool trans_diag_unimp(DisasContext *ctx, arg_diag_unimp *a)
@ -4625,6 +4644,7 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ctx->tb_flags = ctx->base.tb->flags; ctx->tb_flags = ctx->base.tb->flags;
ctx->is_pa20 = hppa_is_pa20(cpu_env(cs)); ctx->is_pa20 = hppa_is_pa20(cpu_env(cs));
ctx->psw_xb = ctx->tb_flags & (PSW_X | PSW_B); ctx->psw_xb = ctx->tb_flags & (PSW_X | PSW_B);
ctx->gva_offset_mask = cpu_env(cs)->gva_offset_mask;
#ifdef CONFIG_USER_ONLY #ifdef CONFIG_USER_ONLY
ctx->privilege = PRIV_USER; ctx->privilege = PRIV_USER;