* [PATCH 0/8] HPPA architecture patches for HP-UX 9 and 715 machine
@ 2026-10-27 21:52 Helge Deller
2026-10-27 21:52 ` [PATCH 1/8] target/hppa: restore lazy FPU context isolation Helge Deller
` (7 more replies)
0 siblings, 8 replies; 9+ messages in thread
From: Helge Deller @ 2026-10-27 21:52 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Keith Monahan, Kirill A . Korinsky,
Helge Deller
From: Helge Deller <deller@gmx.de>
A series of patches which allow to boot HP-UX 9.05 on the 715/64 machine.
Includes an graphics/artist fix, adjustment to 15 bits for protection IDs on
the 32-bit CPUs and various other parts which were missing up to now.
Included is also the FPU patche from Kirill A. Korinsky.
What's missing to fully support HP-UX 9 is an additional NCR710 patch series
(which will be sent seperately later), and a SeaBIOS update which will be
included in the pull request.
Many thanks to Keith Monahan who did all the debugging and analysis why HP-UX 9
failed up to now, and who came up with most patches which we cleaned up
together.
Helge Deller (2):
hw/misc/lasi: LASI Harmony Audio presence emulation
target/hppa: Map CPUs at same addresses as on physical machines
Keith Monahan (5):
target/hppa: Use 15 bit protection IDs on PA1.1 CPUs
target/hppa: Only allow 8 BTLB entries for HP-UX 9.05
target/hppa: Implement local broadcast I/O space
target/hppa: Preload I/O-space BTLB entries for LASI and the central
bus
artist: Redraw screen on colormap changes
Kirill A. Korinsky (1):
target/hppa: restore lazy FPU context isolation
hw/display/artist.c | 6 +
hw/hppa/machine.c | 106 +++++++-
hw/misc/lasi.c | 15 +-
target/hppa/cpu.c | 1 +
target/hppa/cpu.h | 4 +-
target/hppa/helper.h | 1 +
target/hppa/mem_helper.c | 25 +-
target/hppa/translate.c | 61 ++++-
tests/functional/hppa/test_seabios.py | 6 +-
tests/qtest/hppa-fpu-test.c | 371 ++++++++++++++++++++++++++
tests/qtest/meson.build | 2 +
11 files changed, 577 insertions(+), 21 deletions(-)
create mode 100644 tests/qtest/hppa-fpu-test.c
--
2.54.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/8] target/hppa: restore lazy FPU context isolation
2026-10-27 21:52 [PATCH 0/8] HPPA architecture patches for HP-UX 9 and 715 machine Helge Deller
@ 2026-10-27 21:52 ` Helge Deller
2026-10-27 21:52 ` [PATCH 2/8] target/hppa: Use 15 bit protection IDs on PA1.1 CPUs Helge Deller
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Helge Deller @ 2026-10-27 21:52 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Keith Monahan, Kirill A . Korinsky,
Helge Deller
From: "Kirill A. Korinsky" <kirill@korins.ky>
Raise assist emulation trap 22 when CCR disables FP execution;
this restores lazy FPU context isolation, stabilizes OpenBSD/hppa, and
fixes unexplained SSH "incorrect signature" failures.
I keep FP enabled on firmware entry because SeaBIOS uses FP registers
before configuring CCR.
The regression test is based on lazy.elf and eager.elf, compiled from
firmware.ld and fpu-state.s with OpenBSD/hppa 8.0's patched GCC 4.2.1
and BFD 2.17.
Closes: https://gitlab.com/qemu-project/qemu/-/work_items/4715
Signed-off-by: Kirill A. Korinsky <kirill@korins.ky>
Signed-off-by: Helge Deller <deller@gmx.de>
---
hw/hppa/machine.c | 2 +
target/hppa/cpu.c | 1 +
target/hppa/cpu.h | 1 +
target/hppa/helper.h | 1 +
target/hppa/mem_helper.c | 15 ++
target/hppa/translate.c | 61 ++++-
tests/functional/hppa/test_seabios.py | 6 +-
tests/qtest/hppa-fpu-test.c | 371 ++++++++++++++++++++++++++
tests/qtest/meson.build | 2 +
9 files changed, 456 insertions(+), 4 deletions(-)
create mode 100644 tests/qtest/hppa-fpu-test.c
diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index 0b0a8047ed..96d57b9b0f 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -842,6 +842,8 @@ static void hppa_machine_reset(MachineState *ms, ResetType type)
cpu_set_pc(cs, firmware_entry);
cpu[i]->env.psw = PSW_Q;
+ /* Firmware uses FP registers before configuring CCR. */
+ cpu[i]->env.cr[CR_SCRCCR] = 0xc0;
cpu[i]->env.gr[5] = CPU_HPA + i * 0x1000;
}
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index 9d64322398..83104ae0c7 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -91,6 +91,7 @@ static TCGTBCPUState hppa_get_tb_cpu_state(CPUState *cs)
#ifdef CONFIG_USER_ONLY
flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus;
#else
+ flags |= TB_FLAG_FPU_DISABLED * !(env->cr[CR_SCRCCR] & 0xc0);
if ((env->sr[4] == env->sr[5])
& (env->sr[4] == env->sr[6])
& (env->sr[4] == env->sr[7])) {
diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 8818d47dcd..c0ba787974 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -372,6 +372,7 @@ hwaddr hppa_abs_to_phys_pa2_w1(uint8_t phys_addr_bits, vaddr addr);
#define TB_FLAG_PRIV_SHIFT 8
#define TB_FLAG_UNALIGN 0x400
#define TB_FLAG_SPHASH 0x800
+#define TB_FLAG_FPU_DISABLED 0x1000
#define CS_BASE_DIFFPAGE (1 << 12)
#define CS_BASE_DIFFSPACE (1 << 13)
diff --git a/target/hppa/helper.h b/target/hppa/helper.h
index 8d7fa1ae34..449818f9dd 100644
--- a/target/hppa/helper.h
+++ b/target/hppa/helper.h
@@ -82,6 +82,7 @@ DEF_HELPER_FLAGS_4(fmpynfadd_d, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
DEF_HELPER_FLAGS_0(read_interval_timer, TCG_CALL_NO_RWG, tl)
#ifndef CONFIG_USER_ONLY
+DEF_HELPER_5(fpu_mem, noreturn, env, tl, i32, i32, i32)
DEF_HELPER_1(hppa_halt, noreturn, env)
DEF_HELPER_1(hppa_reset, noreturn, env)
DEF_HELPER_1(rfi, void, env)
diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
index 2393a15507..a5da0bc851 100644
--- a/target/hppa/mem_helper.c
+++ b/target/hppa/mem_helper.c
@@ -427,6 +427,21 @@ raise_exception_with_ior(CPUHPPAState *env, int excp, uintptr_t retaddr,
cpu_loop_exit(cs);
}
+G_NORETURN void HELPER(fpu_mem)(CPUHPPAState *env, target_ulong addr,
+ uint32_t mmu_idx, uint32_t mop, uint32_t type)
+{
+ hwaddr phys;
+ int prot, excp;
+
+ /* Memory faults take priority over the assist emulation trap. */
+ excp = hppa_get_physical_address(env, addr, mmu_idx, type, mop, &phys, &prot);
+ if (excp < 0) {
+ excp = EXCP_ASSIST_EMU;
+ }
+ raise_exception_with_ior(env, excp, GETPC(), addr,
+ MMU_IDX_MMU_DISABLED(mmu_idx));
+}
+
void hppa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
vaddr addr, unsigned size,
MMUAccessType access_type,
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index befdb58e9a..6a4072a630 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -1711,8 +1711,30 @@ static bool do_floadw(DisasContext *ctx, unsigned rt, unsigned rb,
return nullify_end(ctx);
}
+static bool gen_fmem_excp(DisasContext *ctx, arg_ldst *a, MemOp mop, int type)
+{
+#ifndef CONFIG_USER_ONLY
+ TCGv_i64 addr, ofs;
+
+ nullify_over(ctx);
+ form_gva(ctx, &addr, &ofs, a->b, a->x,
+ a->scale ? mop & MO_SIZE : 0, a->disp, a->sp, a->m,
+ MMU_DISABLED(ctx));
+ gen_helper_fpu_mem(tcg_env, addr, tcg_constant_i32(ctx->mmu_idx),
+ tcg_constant_i32(mop | ctx->mo_align | mo_endian(ctx)),
+ tcg_constant_i32(type));
+ ctx->base.is_jmp = DISAS_NORETURN;
+ return nullify_end(ctx);
+#else
+ g_assert_not_reached();
+#endif
+}
+
static bool trans_fldw(DisasContext *ctx, arg_ldst *a)
{
+ if (ctx->tb_flags & TB_FLAG_FPU_DISABLED) {
+ return gen_fmem_excp(ctx, a, MO_UL, PAGE_READ);
+ }
return do_floadw(ctx, a->t, a->b, a->x, a->scale ? 2 : 0,
a->disp, a->sp, a->m);
}
@@ -1738,6 +1760,9 @@ static bool do_floadd(DisasContext *ctx, unsigned rt, unsigned rb,
static bool trans_fldd(DisasContext *ctx, arg_ldst *a)
{
+ if (ctx->tb_flags & TB_FLAG_FPU_DISABLED) {
+ return gen_fmem_excp(ctx, a, MO_UQ, PAGE_READ);
+ }
return do_floadd(ctx, a->t, a->b, a->x, a->scale ? 3 : 0,
a->disp, a->sp, a->m);
}
@@ -1767,6 +1792,9 @@ static bool do_fstorew(DisasContext *ctx, unsigned rt, unsigned rb,
static bool trans_fstw(DisasContext *ctx, arg_ldst *a)
{
+ if (ctx->tb_flags & TB_FLAG_FPU_DISABLED) {
+ return gen_fmem_excp(ctx, a, MO_UL, PAGE_WRITE);
+ }
return do_fstorew(ctx, a->t, a->b, a->x, a->scale ? 2 : 0,
a->disp, a->sp, a->m);
}
@@ -1787,6 +1815,9 @@ static bool do_fstored(DisasContext *ctx, unsigned rt, unsigned rb,
static bool trans_fstd(DisasContext *ctx, arg_ldst *a)
{
+ if (ctx->tb_flags & TB_FLAG_FPU_DISABLED) {
+ return gen_fmem_excp(ctx, a, MO_UQ, PAGE_WRITE);
+ }
return do_fstored(ctx, a->t, a->b, a->x, a->scale ? 3 : 0,
a->disp, a->sp, a->m);
}
@@ -2311,8 +2342,9 @@ static bool trans_mtctl(DisasContext *ctx, arg_mtctl *a)
#endif
break;
+ case CR_SCRCCR:
case CR_EIEM:
- /* Exit to re-evaluate interrupts in the main loop. */
+ /* Exit to re-evaluate translation flags and interrupts. */
ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT;
/* FALLTHRU */
default:
@@ -4721,6 +4753,31 @@ static void hppa_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
ctx->insn_start_updated = false;
}
+static bool decode_insn(DisasContext *ctx, uint32_t insn)
+{
+#ifndef CONFIG_USER_ONLY
+ if (ctx->tb_flags & TB_FLAG_FPU_DISABLED) {
+ switch (insn >> 26) {
+ case 0x0b:
+ /* Both floating-point uids trap when the coprocessor is disabled. */
+ insn &= ~0x40;
+ break;
+ case 0x0c:
+ if (extract32(insn, 7, 2)) {
+ break;
+ }
+ /* fall through */
+ case 0x06:
+ case 0x0e:
+ case 0x26:
+ case 0x2e:
+ return gen_excp_iir(ctx, EXCP_ASSIST_EMU);
+ }
+ }
+#endif
+ return decode(ctx, insn);
+}
+
static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
{
DisasContext *ctx = container_of(dcbase, DisasContext, base);
@@ -4754,7 +4811,7 @@ static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
ret = DISAS_NEXT;
} else {
ctx->insn = insn;
- if (!decode(ctx, insn)) {
+ if (!decode_insn(ctx, insn)) {
gen_illegal(ctx);
}
ret = ctx->base.is_jmp;
diff --git a/tests/functional/hppa/test_seabios.py b/tests/functional/hppa/test_seabios.py
index bdb9d534ef..9fd42d70ac 100755
--- a/tests/functional/hppa/test_seabios.py
+++ b/tests/functional/hppa/test_seabios.py
@@ -20,8 +20,10 @@ def boot_seabios(self):
self.vm.add_args('-no-shutdown')
self.vm.set_console()
self.vm.launch()
- wait_for_console_pattern(self, f'SeaBIOS PA-RISC {bits}-bit Firmware')
- wait_for_console_pattern(self, f'Emulated machine: HP {mach} ({bits}-bit')
+ wait_for_console_pattern(self, f'SeaBIOS PA-RISC {bits}-bit Firmware',
+ failure_message='SeaBIOS: Detected trap')
+ wait_for_console_pattern(self, f'Emulated machine: HP {mach} ({bits}-bit',
+ failure_message='SeaBIOS: Detected trap')
def test_hppa_32(self):
self.set_machine('B160L')
diff --git a/tests/qtest/hppa-fpu-test.c b/tests/qtest/hppa-fpu-test.c
new file mode 100644
index 0000000000..af4ff2a162
--- /dev/null
+++ b/tests/qtest/hppa-fpu-test.c
@@ -0,0 +1,371 @@
+/*
+ * HPPA CCR floating-point enable and lazy context switching tests.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+
+#define BOOT 0x1000
+#define CODE 0x1100
+#define FP_CODE 0x1300
+#define ASSIST 0x1400
+#define UNEXPECTED 0x1500
+#define HALT 0x1600
+#define DATA 0x1800
+#define RESULT 0x1900
+#define LOG 0x1a00
+
+/* Enable interruption-state collection through IPSW before entering CODE. */
+static const uint32_t bootstrap[] = {
+ 0x34010010, /* ldi 8,r1 */
+ 0x02c11840, /* mtctl r1,ipsw */
+ 0x02201840, /* mtctl r0,iiasq */
+ 0x02201840, /* mtctl r0,iiasq */
+ 0x34012200, /* ldi 0x1100,r1 */
+ 0x02411840, /* mtctl r1,iiaoq */
+ 0x34012208, /* ldi 0x1104,r1 */
+ 0x02411840, /* mtctl r1,iiaoq */
+ 0x00000c00, /* rfi */
+};
+
+/*
+ * r20 counts assists. After the first call, the shared CCR writer is entered
+ * with FP enabled. Alternating its input must reselect the next translation.
+ */
+static const uint32_t fp_guest[] = {
+ 0x34011000, /* ldi 0x800,r1 */
+ 0x01c11840, /* mtctl r1,iva */
+ 0x08000240, /* nop */
+ 0x34103000, /* ldi 0x1800,r16 */
+ 0x34113200, /* ldi 0x1900,r17 */
+ 0x341a3400, /* ldi 0x1a00,r26 */
+ 0x34140000, /* ldi 0,r20 */
+ 0x34010180, /* ldi 0xc0,r1 */
+ 0x01411840, /* mtctl r1,ccr */
+ 0x2e00100c, /* fldd 0(r16),fr12 */
+ 0x34010000, /* ldi 0,r1 */
+ 0x01411840, /* mtctl r1,ccr */
+ 0x08142880, /* cmpclr,= r20,r0,r0: nullify the next instruction */
+ 0x08000240, /* replaced by the FP instruction under test */
+ 0x6a340008, /* stw r20,4(r17) */
+ 0x34010180, /* ldi 0xc0,r1 */
+ 0xe8400370, /* bl 0x1300,rp */
+ 0x08000240, /* nop */
+ 0x6a340010, /* stw r20,8(r17) */
+ 0x34010000, /* ldi 0,r1 */
+ 0xe8400350, /* bl 0x1300,rp */
+ 0x08000240, /* nop */
+ 0x6a340018, /* stw r20,12(r17) */
+ 0x34010180, /* ldi 0xc0,r1 */
+ 0xe8400330, /* bl 0x1300,rp */
+ 0x08000240, /* nop */
+ 0x6a340020, /* stw r20,16(r17) */
+ 0x34010000, /* ldi 0,r1 */
+ 0xe8400310, /* bl 0x1300,rp */
+ 0x08000240, /* nop */
+ 0x6a340028, /* stw r20,20(r17) */
+ 0x34010180, /* ldi 0xc0,r1 */
+ 0xe84002f0, /* bl 0x1300,rp */
+ 0x08000240, /* nop */
+ 0x6a340030, /* stw r20,24(r17) */
+ 0x34010000, /* ldi 0,r1 */
+ 0xe84002d0, /* bl 0x1300,rp */
+ 0x08000240, /* nop */
+ 0x6a340038, /* stw r20,28(r17) */
+ 0x34010180, /* ldi 0xc0,r1 */
+ 0x01411840, /* mtctl r1,ccr */
+ 0x2e10120c, /* fstd fr12,8(r16) */
+ 0x36100010, /* ldo 8(r16),r16 */
+ 0x2e10120d, /* fstd fr13,8(r16) */
+ 0x34010002, /* ldi 1,r1 */
+ 0x6a210000, /* stw r1,0(r17): completion */
+ 0xe8000882, /* b,n 0x1600 */
+};
+
+static const uint32_t fp_site[] = {
+ 0x01411840, /* mtctl r1,ccr */
+ 0x08000240, /* replaced by the FP instruction under test */
+ 0xe840c002, /* bv,n 0(rp) */
+};
+
+/* r20 and r26 are outside the shadow register set restored by rfir. */
+static const uint32_t assist_handler[] = {
+ 0x026008a1, /* mfctl iir,r1 */
+ 0x6b410000, /* stw r1,0(r26) */
+ 0x024008a1, /* mfctl iiaoq,r1 */
+ 0x6b410008, /* stw r1,4(r26) */
+ 0x028008a1, /* mfctl isr,r1 */
+ 0x6b410010, /* stw r1,8(r26) */
+ 0x02a008a1, /* mfctl ior,r1 */
+ 0x6b410018, /* stw r1,12(r26) */
+ 0x375a0020, /* ldo 16(r26),r26 */
+ 0x36940002, /* ldo 1(r20),r20 */
+ 0x34010180, /* ldi 0xc0,r1 */
+ 0x01411840, /* mtctl r1,ccr */
+ 0x00000ca0, /* rfir: retry the faulting instruction */
+};
+
+static const uint32_t unexpected_handler[] = {
+ 0x026008a1, /* mfctl iir,r1 */
+ 0x6a210008, /* stw r1,4(r17) */
+ 0x024008a1, /* mfctl iiaoq,r1 */
+ 0x6a210010, /* stw r1,8(r17) */
+ 0x028008a1, /* mfctl isr,r1 */
+ 0x6a210018, /* stw r1,12(r17) */
+ 0x02a008a1, /* mfctl ior,r1 */
+ 0x6a210020, /* stw r1,16(r17) */
+ 0x6a380000, /* stw r24,0(r17): 0x100 | exception number */
+ 0xe80001aa, /* b,n 0x1600 */
+};
+
+/* r18 owns the live FP state; r19 requests the next logical context. */
+static const uint32_t lazy_guest[] = {
+ 0x34011000, /* ldi 0x800,r1 */
+ 0x01c11840, /* mtctl r1,iva */
+ 0x08000240, /* nop */
+ 0x34123000, /* ldi 0x1800,r18: owner A */
+ 0x34113200, /* ldi 0x1900,r17 */
+ 0x34140000, /* ldi 0,r20 */
+ 0x34010180, /* ldi 0xc0,r1 */
+ 0x01411840, /* mtctl r1,ccr */
+ 0x2e40100c, /* fldd 0(r18),fr12 */
+ 0x318c0e0c, /* fadd,d fr12,fr12,fr12: A = 2 */
+ 0x34173240, /* ldi 0x1920,r23 */
+ 0x34133020, /* ldi 0x1810,r19: request B */
+ 0xe8400390, /* bl 0x1300,rp */
+ 0x08000240, /* nop */
+ 0x318c0e0c, /* fadd,d fr12,fr12,fr12: B = 32 */
+ 0x36f70010, /* ldo 8(r23),r23 */
+ 0x34133000, /* ldi 0x1800,r19: request A */
+ 0xe8400368, /* bl 0x1300,rp */
+ 0x08000240, /* nop */
+ 0x318c0e0c, /* fadd,d fr12,fr12,fr12: A = 4 */
+ 0x36f70010, /* ldo 8(r23),r23 */
+ 0x34133020, /* ldi 0x1810,r19: request B */
+ 0xe8400340, /* bl 0x1300,rp */
+ 0x08000240, /* nop */
+ 0x318c0e0c, /* fadd,d fr12,fr12,fr12: B = 64 */
+ 0x36f70010, /* ldo 8(r23),r23 */
+ 0x34133000, /* ldi 0x1800,r19: request A */
+ 0xe8400318, /* bl 0x1300,rp */
+ 0x08000240, /* nop */
+ 0x6a340008, /* stw r20,4(r17) */
+ 0x34010002, /* ldi 1,r1 */
+ 0x6a210000, /* stw r1,0(r17) */
+ 0xe80008f2, /* b,n 0x1600 */
+};
+
+static const uint32_t lazy_site[] = {
+ 0x01401840, /* mtctl r0,ccr */
+ 0x2ee0120c, /* fstd fr12,0(r23) */
+ 0xe840c002, /* bv,n 0(rp) */
+};
+
+static const uint32_t lazy_handler[] = {
+ 0x34010180, /* ldi 0xc0,r1 */
+ 0x01411840, /* mtctl r1,ccr */
+ 0x2e40120c, /* fstd fr12,0(r18): save owner */
+ 0x2e60100c, /* fldd 0(r19),fr12: restore requested context */
+ 0x08130252, /* copy r19,r18 */
+ 0x36940002, /* ldo 1(r20),r20 */
+ 0x00000ca0, /* rfir */
+};
+
+static void write_words(QTestState *qts, uint32_t addr,
+ const uint32_t *words, size_t count)
+{
+ for (size_t i = 0; i < count; i++) {
+ qtest_writel(qts, addr + 4 * i, words[i]);
+ }
+}
+
+static uint32_t branch(uint32_t pc, uint32_t target)
+{
+ uint32_t d = (target - pc - 8) / 4;
+
+ return 0xe8000002 | ((d & 0x10000) >> 16) | ((d & 0xf800) << 5) |
+ ((d & 0x400) >> 8) | ((d & 0x3ff) << 3);
+}
+
+static QTestState *start_guest(bool retry_assist)
+{
+ QTestState *qts = qtest_init("-machine none -cpu pa-7300lc -m 1M "
+ "-S -accel tcg -no-shutdown "
+ "-device loader,addr=0x1000,cpu-num=0");
+
+ write_words(qts, BOOT, bootstrap, G_N_ELEMENTS(bootstrap));
+ /* Shutdown may re-enter this TB before the main loop stops the CPU. */
+ qtest_writel(qts, HALT, 0xfffdead0);
+ write_words(qts, UNEXPECTED, unexpected_handler,
+ G_N_ELEMENTS(unexpected_handler));
+ for (unsigned int i = 0; i < 32; i++) {
+ uint32_t pc = 0x800 + i * 32;
+ uint32_t target = retry_assist && i == 22 ? ASSIST : UNEXPECTED;
+
+ qtest_writel(qts, pc, 0x34180000 | ((0x100 | i) << 1));
+ qtest_writel(qts, pc + 4, branch(pc + 4, target));
+ }
+ return qts;
+}
+
+static void run_guest(QTestState *qts, uint32_t expected)
+{
+ uint32_t result;
+
+ qtest_qmp_assert_success(qts, "{'execute':'cont'}");
+ qtest_qmp_eventwait(qts, "SHUTDOWN");
+ result = qtest_readl(qts, RESULT);
+ g_test_message("completion=0x%x, result[1]=0x%x, result[2]=0x%x",
+ result, qtest_readl(qts, RESULT + 4),
+ qtest_readl(qts, RESULT + 8));
+ g_assert_cmphex(result, ==, expected);
+}
+
+typedef struct FPTest {
+ const char *name;
+ uint32_t instruction;
+ bool memory;
+ uint64_t fr13;
+} FPTest;
+
+static const FPTest fp_tests[] = {
+ { "fldw", 0x2600100c, true },
+ { "fstw", 0x2600120c, true },
+ { "fldd", 0x2e00100c, true },
+ { "fstd", 0x2e00120c, true },
+ { "fid", 0x30000000 },
+ { "fadd-double", 0x318c0e0d, false, 0x4010000000000000ULL },
+ { "fadd-double-extended", 0x398c0e0d, false, 0x4010000000000000ULL },
+ { "fmpyadd-single", 0x188541e6 }, /* fr20L,fr21L,fr22L,fr23L,fr24L */
+ { "fmpysub-double", 0x988541c6 }, /* fr4,fr5,fr6,fr7,fr8 */
+};
+
+static void test_fp(const void *opaque)
+{
+ const FPTest *test = opaque;
+ static const uint32_t counts[] = { 0, 0, 1, 1, 2, 2, 3 };
+ QTestState *qts = start_guest(true);
+
+ write_words(qts, CODE, fp_guest, G_N_ELEMENTS(fp_guest));
+ write_words(qts, FP_CODE, fp_site, G_N_ELEMENTS(fp_site));
+ write_words(qts, ASSIST, assist_handler, G_N_ELEMENTS(assist_handler));
+ qtest_writel(qts, CODE + 13 * 4, test->instruction);
+ qtest_writel(qts, FP_CODE + 4, test->instruction);
+ qtest_writeq(qts, DATA, 0x4000000000000000ULL); /* double 2 */
+ run_guest(qts, 1);
+ for (size_t i = 0; i < G_N_ELEMENTS(counts); i++) {
+ g_assert_cmpuint(qtest_readl(qts, RESULT + 4 + 4 * i), ==, counts[i]);
+ }
+ for (unsigned int i = 0; i < 3; i++) {
+ g_assert_cmphex(qtest_readl(qts, LOG + 16 * i), ==, test->instruction);
+ g_assert_cmphex(qtest_readl(qts, LOG + 16 * i + 4), ==, FP_CODE + 4);
+ if (test->memory) {
+ g_assert_cmphex(qtest_readl(qts, LOG + 16 * i + 8), ==, 0);
+ g_assert_cmphex(qtest_readl(qts, LOG + 16 * i + 12), ==, DATA);
+ }
+ }
+ g_assert_cmphex(qtest_readq(qts, DATA + 8), ==, 0x4000000000000000ULL);
+ g_assert_cmphex(qtest_readq(qts, DATA + 16), ==, test->fr13);
+ qtest_quit(qts);
+}
+
+static void test_lazy(void)
+{
+ static const uint64_t markers[] = {
+ 0x4030000000000000ULL, /* B = 16 */
+ 0x4000000000000000ULL, /* A = 2 */
+ 0x4040000000000000ULL, /* B = 32 */
+ 0x4010000000000000ULL, /* A = 4 */
+ };
+ QTestState *qts = start_guest(true);
+
+ write_words(qts, CODE, lazy_guest, G_N_ELEMENTS(lazy_guest));
+ write_words(qts, FP_CODE, lazy_site, G_N_ELEMENTS(lazy_site));
+ write_words(qts, ASSIST, lazy_handler, G_N_ELEMENTS(lazy_handler));
+ qtest_writeq(qts, DATA, 0x3ff0000000000000ULL); /* A = 1 */
+ qtest_writeq(qts, DATA + 16, markers[0]);
+ run_guest(qts, 1);
+ g_assert_cmpuint(qtest_readl(qts, RESULT + 4), ==, 4);
+ for (size_t i = 0; i < G_N_ELEMENTS(markers); i++) {
+ g_assert_cmphex(qtest_readq(qts, RESULT + 32 + 8 * i), ==, markers[i]);
+ }
+ g_assert_cmphex(qtest_readq(qts, DATA), ==, 0x4010000000000000ULL);
+ g_assert_cmphex(qtest_readq(qts, DATA + 16), ==, 0x4050000000000000ULL);
+ qtest_quit(qts);
+}
+
+static const uint32_t fault_guest[] = {
+ 0x34011000, /* ldi 0x800,r1 */
+ 0x01c11840, /* mtctl r1,iva */
+ 0x34103000, /* ldi 0x1800,r16: replaced for unaligned cases */
+ 0x34113200, /* ldi 0x1900,r17 */
+ 0x01401840, /* mtctl r0,ccr */
+ 0x08000240, /* replaced by ssm 2,r0 for data translation */
+ 0x08000240, /* replaced by the FP instruction under test */
+ 0x34010002, /* ldi 1,r1 */
+ 0x6a210000, /* stw r1,0(r17): unexpectedly completed */
+ 0xe80009aa, /* b,n 0x1600 */
+};
+
+typedef struct FaultTest {
+ const char *name;
+ uint32_t instruction;
+ unsigned int exception;
+ uint32_t address;
+ bool dtlb;
+ bool memory;
+} FaultTest;
+
+static const FaultTest fault_tests[] = {
+ { "unaligned-load", 0x2e00100c, 28, DATA + 2, false, true },
+ { "unaligned-store", 0x2e00120c, 28, DATA + 2, false, true },
+ { "dtlb-load", 0x2e00100c, 15, DATA, true, true },
+ { "dtlb-store", 0x2e00120c, 15, DATA, true, true },
+ { "disabled-uid1-arithmetic", 0x30000040, 22, DATA, false, false },
+ { "disabled-uid1-memory", 0x2e00104c, 22, DATA, false, true },
+};
+
+static void test_fault(const void *opaque)
+{
+ const FaultTest *test = opaque;
+ uint32_t addr = test->address;
+ QTestState *qts = start_guest(false);
+
+ write_words(qts, CODE, fault_guest, G_N_ELEMENTS(fault_guest));
+ qtest_writel(qts, CODE + 8, 0x34100000 | (addr << 1));
+ if (test->dtlb) {
+ qtest_writel(qts, CODE + 20, 0x00020d60); /* ssm 2,r0 */
+ }
+ qtest_writel(qts, CODE + 24, test->instruction);
+ run_guest(qts, 0x100 | test->exception);
+ g_assert_cmphex(qtest_readl(qts, RESULT + 4), ==, test->instruction);
+ g_assert_cmphex(qtest_readl(qts, RESULT + 8), ==, CODE + 24);
+ if (test->memory) {
+ g_assert_cmphex(qtest_readl(qts, RESULT + 12), ==, 0);
+ g_assert_cmphex(qtest_readl(qts, RESULT + 16), ==, addr);
+ }
+ qtest_quit(qts);
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+ if (!qtest_has_accel("tcg")) {
+ g_test_skip("TCG accelerator required");
+ return 0;
+ }
+ for (size_t i = 0; i < G_N_ELEMENTS(fp_tests); i++) {
+ g_autofree char *name = g_strdup_printf("fpu/%s", fp_tests[i].name);
+
+ qtest_add_data_func(name, &fp_tests[i], test_fp);
+ }
+ qtest_add_func("fpu/lazy-contexts", test_lazy);
+ for (size_t i = 0; i < G_N_ELEMENTS(fault_tests); i++) {
+ g_autofree char *name = g_strdup_printf("fpu/%s", fault_tests[i].name);
+
+ qtest_add_data_func(name, &fault_tests[i], test_fault);
+ }
+ return g_test_run();
+}
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 46685d6d46..9d422886d8 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -158,6 +158,8 @@ qtests_alpha = ['boot-serial-test'] + \
qtests_avr = [ 'boot-serial-test' ]
qtests_hppa = \
+ (config_all_accel.has_key('CONFIG_TCG') and \
+ config_all_devices.has_key('CONFIG_GENERIC_LOADER') ? ['hppa-fpu-test'] : []) + \
qtests_filter + \
(config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : [])
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/8] target/hppa: Use 15 bit protection IDs on PA1.1 CPUs
2026-10-27 21:52 [PATCH 0/8] HPPA architecture patches for HP-UX 9 and 715 machine Helge Deller
2026-10-27 21:52 ` [PATCH 1/8] target/hppa: restore lazy FPU context isolation Helge Deller
@ 2026-10-27 21:52 ` Helge Deller
2026-10-27 21:52 ` [PATCH 3/8] target/hppa: Only allow 8 BTLB entries for HP-UX 9.05 Helge Deller
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Helge Deller @ 2026-10-27 21:52 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Keith Monahan, Kirill A . Korinsky,
Helge Deller
From: Keith Monahan <keith@techtravels.org>
HP-UX 9.05 only supports 15-bit protection IDs and gets a protection
fault on its own interrupt stack when allowing 18-bits.
Since the architecture manual states that if smaller than 18-bit access IDs
are physically implemented in the CPU, only the appropriate number of
rightmost bits of GR[r]{13..30} are stored in the TLB.
PA7100 and PA7100LC only support 15 bit protection IDs, so use this
amount of bits here.
Signed-off-by: Keith Monahan <keith@techtravels.org>
Signed-off-by: Helge Deller <deller@gmx.de>
---
target/hppa/mem_helper.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
index a5da0bc851..7a316f59ea 100644
--- a/target/hppa/mem_helper.c
+++ b/target/hppa/mem_helper.c
@@ -538,7 +538,15 @@ void HELPER(itlba_pa11)(CPUHPPAState *env, target_ulong addr, target_ulong reg)
static void set_access_bits_pa11(CPUHPPAState *env, HPPATLBEntry *ent,
target_ulong reg)
{
- ent->access_id = extract32(reg, 1, 18);
+ /*
+ * The architecture manual states that if smaller than 18-bit access IDs
+ * are physically implemented in the CPU, only the appropriate number of
+ * rightmost bits of GR[r]{13..30} are stored in the TLB. Older parisc
+ * chips (PCXS, PCXT, PCXL, PCXL2) only support 15 bit protection IDs.
+ * PCXT' (pa7200) has 18 bit protection IDs, but only 16 bit spaceids.
+ * We currently emulate PA7100 and PA7100LC CPUs, so use 15 bits here.
+ */
+ ent->access_id = extract32(reg, 1, 15); /* 15-bit PA1.1 PIDs */
ent->u = extract32(reg, 19, 1);
ent->ar_pl2 = extract32(reg, 20, 2);
ent->ar_pl1 = extract32(reg, 22, 2);
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/8] target/hppa: Only allow 8 BTLB entries for HP-UX 9.05
2026-10-27 21:52 [PATCH 0/8] HPPA architecture patches for HP-UX 9 and 715 machine Helge Deller
2026-10-27 21:52 ` [PATCH 1/8] target/hppa: restore lazy FPU context isolation Helge Deller
2026-10-27 21:52 ` [PATCH 2/8] target/hppa: Use 15 bit protection IDs on PA1.1 CPUs Helge Deller
@ 2026-10-27 21:52 ` Helge Deller
2026-10-27 21:52 ` [PATCH 4/8] target/hppa: Implement local broadcast I/O space Helge Deller
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Helge Deller @ 2026-10-27 21:52 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Keith Monahan, Kirill A . Korinsky,
Helge Deller
From: Keith Monahan <keith@techtravels.org>
The physical PA100LC and PA7300LC CPUs implement 8 BTLB entries only.
HP-UX 9.05 seems to have problems if more are available, so reduce the
number to 8 entries to allow HP-UX 9.05 to boot.
Signed-off-by: Keith Monahan <keith@techtravels.org>
Signed-off-by: Helge Deller <deller@gmx.de>
---
target/hppa/cpu.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index c0ba787974..da48a78569 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -248,7 +248,7 @@ typedef struct CPUArchState {
* ??? The number of entries isn't specified by the architecture.
* BTLBs are not supported in 64-bit machines.
*/
-#define PA10_BTLB_FIXED 16
+#define PA10_BTLB_FIXED 8
#define PA10_BTLB_VARIABLE 0
#define HPPA_TLB_ENTRIES 256
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/8] target/hppa: Implement local broadcast I/O space
2026-10-27 21:52 [PATCH 0/8] HPPA architecture patches for HP-UX 9 and 715 machine Helge Deller
` (2 preceding siblings ...)
2026-10-27 21:52 ` [PATCH 3/8] target/hppa: Only allow 8 BTLB entries for HP-UX 9.05 Helge Deller
@ 2026-10-27 21:52 ` Helge Deller
2026-10-27 21:52 ` [PATCH 5/8] target/hppa: Preload I/O-space BTLB entries for LASI and the central bus Helge Deller
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Helge Deller @ 2026-10-27 21:52 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Keith Monahan, Kirill A . Korinsky,
Helge Deller
From: Keith Monahan <keith@techtravels.org>
The local broadcast I/O space is used by older operating systems like HP-UX 9.05
to send an interrupt to all CPUs, or to issue a system reset.
Wire it up on the emulated 715 machine to allow HP-UX 9.05 to run.
Signed-off-by: Keith Monahan <keith@techtravels.org>
Signed-off-by: Helge Deller <deller@gmx.de>
---
hw/hppa/machine.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index 96d57b9b0f..8d378385b2 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -573,6 +573,47 @@ static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus,
cpu[0]->env.kernel_entry = kernel_entry;
}
+/*
+ * Local broadcast I/O space: a write to IO_EIR (offset 0) posts an external
+ * interrupt on all processors, CMD_RESET (5) written to IO_COMMAND (0x30)
+ * resets the system. HP-UX 9 reboots through the latter.
+ */
+#define HPPA_BROADCAST_HPA 0xfffc0000
+#define HPPA_IO_COMMAND 0x30
+#define HPPA_CMD_RESET 5
+
+static uint64_t hppa_broadcast_read(void *opaque, hwaddr addr, unsigned size)
+{
+ return 0;
+}
+
+static void hppa_broadcast_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ unsigned int i;
+
+ switch (addr) {
+ case 0:
+ for (i = 0; i < current_machine->smp.cpus; i++) {
+ hppa_io_eir_ops.write(cpu[i], 0, val, 4);
+ }
+ break;
+ case HPPA_IO_COMMAND:
+ if (val == HPPA_CMD_RESET) {
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+ }
+ break;
+ }
+}
+
+static const MemoryRegionOps hppa_broadcast_ops = {
+ .read = hppa_broadcast_read,
+ .write = hppa_broadcast_write,
+ .endianness = DEVICE_BIG_ENDIAN,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+};
+
/*
* Create HP 715/64 workstation
*/
@@ -597,6 +638,14 @@ static void machine_HP_715_init(MachineState *machine)
isa_bus = hppa_isa_bus(translate(NULL, IDE_HPA));
assert(isa_bus);
+ /* Local broadcast I/O space */
+ MemoryRegion *dev_mr_bcast = g_new(MemoryRegion, 1);
+ memory_region_init_io(dev_mr_bcast, NULL, &hppa_broadcast_ops, NULL,
+ "local-broadcast", 0x1000);
+ memory_region_add_subregion(addr_space,
+ translate(NULL, HPPA_BROADCAST_HPA),
+ dev_mr_bcast);
+
/* Init Lasi chip */
lasi_dev = DEVICE(lasi_init());
hpm->lasi_dev = lasi_dev;
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 5/8] target/hppa: Preload I/O-space BTLB entries for LASI and the central bus
2026-10-27 21:52 [PATCH 0/8] HPPA architecture patches for HP-UX 9 and 715 machine Helge Deller
` (3 preceding siblings ...)
2026-10-27 21:52 ` [PATCH 4/8] target/hppa: Implement local broadcast I/O space Helge Deller
@ 2026-10-27 21:52 ` Helge Deller
2026-10-27 21:52 ` [PATCH 6/8] artist: Redraw screen on colormap changes Helge Deller
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Helge Deller @ 2026-10-27 21:52 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Keith Monahan, Kirill A . Korinsky,
Helge Deller
From: Keith Monahan <keith@techtravels.org>
Set up the BTLB to allow operating systems to access LASI and central
bus addresses.
Signed-off-by: Keith Monahan <keith@techtravels.org>
Signed-off-by: Helge Deller <deller@gmx.de>
---
hw/hppa/machine.c | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index 8d378385b2..e403ae5fc9 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -896,6 +896,38 @@ static void hppa_machine_reset(MachineState *ms, ResetType type)
cpu[i]->env.gr[5] = CPU_HPA + i * 0x1000;
}
+ /*
+ * BTLB equivalence maps for the I/O ranges HP-UX 9 uses
+ * without creating page directory entries: the LASI block and the
+ * central bus (CPU HPA, broadcast). Must not cover other I/O space, as
+ * HP-UX probes with LPA and skips pdir setup for already mapped pages.
+ */
+ if (!hppa_is_pa20(&cpu[0]->env)) {
+ static const struct { uint32_t start, last; } io_btlb[] = {
+ { 0xf0100000, 0xf01fffff }, /* LASI */
+ { 0xfff80000, 0xffffffff }, /* central bus */
+ };
+ CPUHPPAState *env = &cpu[0]->env;
+
+ for (i = 0; i < ARRAY_SIZE(io_btlb); i++) {
+ HPPATLBEntry *ent = &env->tlb[HPPA_BTLB_ENTRIES(env) - 1 - i];
+
+ ent->itree.start = io_btlb[i].start;
+ ent->itree.last = io_btlb[i].last;
+ ent->pa = io_btlb[i].start;
+ ent->access_id = 0;
+ ent->u = 1;
+ ent->ar_pl2 = 0;
+ ent->ar_pl1 = 0;
+ ent->ar_type = 1;
+ ent->b = 0;
+ ent->d = 1;
+ ent->t = 0;
+ ent->entry_valid = 1;
+ interval_tree_insert(&ent->itree, &env->tlb_root);
+ }
+ }
+
cpu[0]->env.gr[26] = ms->ram_size;
cpu[0]->env.gr[25] = cpu[0]->env.kernel_entry;
cpu[0]->env.gr[24] = cpu[0]->env.cmdline_or_bootorder;
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 6/8] artist: Redraw screen on colormap changes
2026-10-27 21:52 [PATCH 0/8] HPPA architecture patches for HP-UX 9 and 715 machine Helge Deller
` (4 preceding siblings ...)
2026-10-27 21:52 ` [PATCH 5/8] target/hppa: Preload I/O-space BTLB entries for LASI and the central bus Helge Deller
@ 2026-10-27 21:52 ` Helge Deller
2026-10-27 21:52 ` [PATCH 7/8] hw/misc/lasi: LASI Harmony Audio presence emulation Helge Deller
2026-10-27 21:52 ` [PATCH 8/8] target/hppa: Map CPUs at same addresses as on physical machines Helge Deller
7 siblings, 0 replies; 9+ messages in thread
From: Helge Deller @ 2026-10-27 21:52 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Keith Monahan, Kirill A . Korinsky,
Helge Deller
From: Keith Monahan <keith@techtravels.org>
Invalidate screen on colormap change, as it affects every pixel on screen.
This fixes VUE GUI on HP-UX 9.05.
Signed-off-by: Keith Monahan <keith@techtravels.org>
Signed-off-by: Helge Deller <deller@gmx.de>
---
hw/display/artist.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/hw/display/artist.c b/hw/display/artist.c
index 288d466ec6..300ad40e72 100644
--- a/hw/display/artist.c
+++ b/hw/display/artist.c
@@ -855,6 +855,12 @@ static int vram_bit_write(ARTISTState *s, uint32_t pos, int posy,
vram_write_bufidx(s) == ARTIST_BUFFER_CURSOR2) {
artist_invalidate_cursor(s);
}
+
+ if (vram_write_bufidx(s) == ARTIST_BUFFER_CMAP) {
+ /* A colormap change affects every pixel on screen. */
+ artist_invalidate(s);
+ }
+
return pos;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 7/8] hw/misc/lasi: LASI Harmony Audio presence emulation
2026-10-27 21:52 [PATCH 0/8] HPPA architecture patches for HP-UX 9 and 715 machine Helge Deller
` (5 preceding siblings ...)
2026-10-27 21:52 ` [PATCH 6/8] artist: Redraw screen on colormap changes Helge Deller
@ 2026-10-27 21:52 ` Helge Deller
2026-10-27 21:52 ` [PATCH 8/8] target/hppa: Map CPUs at same addresses as on physical machines Helge Deller
7 siblings, 0 replies; 9+ messages in thread
From: Helge Deller @ 2026-10-27 21:52 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Keith Monahan, Kirill A . Korinsky,
Helge Deller
From: Helge Deller <deller@gmx.de>
HP-UX 9 beeps through the harmony audio chip, and it panics if there
isn't one, because the 715/64 has no HIL keyboard to beep through
instead. Emulate the bare minimum of the chip's registers and report a
running audio clock. There's still no sound.
In the long run we plan to add a Harmony driver, but for now this is
sufficient.
Suggested-by: Keith Monahan <keith@techtravels.org>
Signed-off-by: Helge Deller <deller@gmx.de>
---
hw/misc/lasi.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/hw/misc/lasi.c b/hw/misc/lasi.c
index f0dfd78b4d..76029804e1 100644
--- a/hw/misc/lasi.c
+++ b/hw/misc/lasi.c
@@ -36,8 +36,7 @@ static bool lasi_chip_mem_valid(void *opaque, hwaddr addr,
case LASI_IAR:
case LASI_LPT:
- case LASI_AUDIO:
- case LASI_AUDIO + 4:
+ case LASI_AUDIO ... LASI_AUDIO + 0xFF:
case LASI_UART:
case LASI_LAN:
case LASI_LAN + 12: /* LASI LAN MAC */
@@ -87,6 +86,13 @@ static MemTxResult lasi_chip_read_with_attrs(void *opaque, hwaddr addr,
val = s->iar;
break;
+ case LASI_AUDIO ... LASI_AUDIO + 0xFF:
+ /*
+ * Harmony audio not yet emulated. DIAG (0x3c) reports a running
+ * sample clock, which HP-UX 9 checks before using the beeper.
+ */
+ val = (addr == LASI_AUDIO + 0x3c);
+ break;
case LASI_LPT:
case LASI_UART:
case LASI_LAN:
@@ -158,9 +164,8 @@ static MemTxResult lasi_chip_write_with_attrs(void *opaque, hwaddr addr,
case LASI_LPT:
/* XXX: reset parallel port */
break;
- case LASI_AUDIO:
- case LASI_AUDIO + 4:
- /* XXX: reset audio port */
+ case LASI_AUDIO ... LASI_AUDIO + 0xFF:
+ /* XXX: Harmony audio is not emulated */
break;
case LASI_UART:
/* XXX: reset serial port */
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 8/8] target/hppa: Map CPUs at same addresses as on physical machines
2026-10-27 21:52 [PATCH 0/8] HPPA architecture patches for HP-UX 9 and 715 machine Helge Deller
` (6 preceding siblings ...)
2026-10-27 21:52 ` [PATCH 7/8] hw/misc/lasi: LASI Harmony Audio presence emulation Helge Deller
@ 2026-10-27 21:52 ` Helge Deller
7 siblings, 0 replies; 9+ messages in thread
From: Helge Deller @ 2026-10-27 21:52 UTC (permalink / raw)
To: qemu-devel
Cc: Richard Henderson, Keith Monahan, Kirill A . Korinsky,
Helge Deller
From: Helge Deller <deller@gmx.de>
SeaBIOS version 26 allows to use random addresses for CPU_HPA, so drop
the hardcoded CPU_HPA which was used until now for all machines, and use
individual addresses which correspond to the CPU HPA on the physical
machines.
Signed-off-by: Helge Deller <deller@gmx.de>
---
hw/hppa/machine.c | 23 +++++++++++++----------
target/hppa/cpu.h | 1 +
2 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index e403ae5fc9..f23936fc5b 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -241,11 +241,11 @@ static FWCfgState *create_fw_cfg(MachineState *ms, PCIBus *pci_bus,
fw_cfg_add_file(fw_cfg, "/etc/hppa/power-button-addr",
g_memdup2(&val, sizeof(val)), sizeof(val));
- val = cpu_to_le64(CPU_HPA + 16);
+ val = cpu_to_le64(cpu[0]->env.cpu_hpa + 16);
fw_cfg_add_file(fw_cfg, "/etc/hppa/rtc-addr",
g_memdup2(&val, sizeof(val)), sizeof(val));
- val = cpu_to_le64(CPU_HPA + 24);
+ val = cpu_to_le64(cpu[0]->env.cpu_hpa + 24);
fw_cfg_add_file(fw_cfg, "/etc/hppa/DebugOutputPort",
g_memdup2(&val, sizeof(val)), sizeof(val));
@@ -286,7 +286,8 @@ static DinoState *dino_init(MemoryRegion *addr_space)
/*
* Step 1: Create CPUs and Memory
*/
-static TranslateFn *machine_HP_common_init_cpus(MachineState *machine)
+static TranslateFn *machine_HP_common_init_cpus(MachineState *machine,
+ target_ulong initial_cpu_hpa)
{
MemoryRegion *addr_space = get_system_memory();
unsigned int smp_cpus = machine->smp.cpus;
@@ -299,6 +300,7 @@ static TranslateFn *machine_HP_common_init_cpus(MachineState *machine)
/* Create CPUs. */
for (unsigned int i = 0; i < smp_cpus; i++) {
cpu[i] = HPPA_CPU(cpu_create(machine->cpu_type));
+ cpu[i]->env.cpu_hpa = initial_cpu_hpa + i * 0x1000;
}
/* Initialize memory */
@@ -321,7 +323,7 @@ static TranslateFn *machine_HP_common_init_cpus(MachineState *machine)
memory_region_init_io(cpu_region, OBJECT(cpu[i]), &hppa_io_eir_ops,
cpu[i], name, 4);
memory_region_add_subregion(addr_space,
- translate(NULL, CPU_HPA + i * 0x1000),
+ translate(NULL, cpu[i]->env.cpu_hpa),
cpu_region);
if (!hppa_is_pa20(&cpu[0]->env)) {
@@ -339,7 +341,7 @@ static TranslateFn *machine_HP_common_init_cpus(MachineState *machine)
memory_region_init_io(cflush, NULL, &hppa_pci_ignore_ops,
NULL, cflush_name, 4);
memory_region_add_subregion(addr_space,
- translate(NULL, CPU_HPA + i * 0x1000 + 0x500),
+ translate(NULL, cpu[i]->env.cpu_hpa + 0x500),
cflush);
}
@@ -347,7 +349,8 @@ static TranslateFn *machine_HP_common_init_cpus(MachineState *machine)
cpu_region = g_new(MemoryRegion, 1);
memory_region_init_io(cpu_region, OBJECT(cpu[0]), &hppa_io_helper_ops,
cpu[0], "cpu0-io-rtc", 2 * sizeof(uint64_t));
- memory_region_add_subregion(addr_space, translate(NULL, CPU_HPA + 16),
+ memory_region_add_subregion(addr_space,
+ translate(NULL, cpu[0]->env.cpu_hpa + 16),
cpu_region);
/* Main memory region. */
@@ -626,7 +629,7 @@ static void machine_HP_715_init(MachineState *machine)
ISABus *isa_bus;
/* Create CPUs and RAM. */
- translate = machine_HP_common_init_cpus(machine);
+ translate = machine_HP_common_init_cpus(machine, 0xfffbe000);
if (hppa_is_pa20(&cpu[0]->env)) {
error_report("The HP 715/64 workstation requires a 32-bit "
@@ -713,7 +716,7 @@ static void machine_HP_B160L_init(MachineState *machine)
PCIBus *pci_bus;
/* Create CPUs and RAM. */
- translate = machine_HP_common_init_cpus(machine);
+ translate = machine_HP_common_init_cpus(machine, 0xfff10000);
if (hppa_is_pa20(&cpu[0]->env)) {
error_report("The HP B160L workstation requires a 32-bit "
@@ -810,7 +813,7 @@ static void machine_HP_C3700_init(MachineState *machine)
bool is_C3700 = strcmp(mc->name, "C3700") == 0;
/* Create CPUs and RAM. */
- translate = machine_HP_common_init_cpus(machine);
+ translate = machine_HP_common_init_cpus(machine, 0xfffa0000);
if (!hppa_is_pa20(&cpu[0]->env)) {
error_report("The HP C3000 workstation requires a 64-bit CPU. "
@@ -893,7 +896,7 @@ static void hppa_machine_reset(MachineState *ms, ResetType type)
cpu[i]->env.psw = PSW_Q;
/* Firmware uses FP registers before configuring CCR. */
cpu[i]->env.cr[CR_SCRCCR] = 0xc0;
- cpu[i]->env.gr[5] = CPU_HPA + i * 0x1000;
+ cpu[i]->env.gr[5] = cpu[i]->env.cpu_hpa;
}
/*
diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index da48a78569..7b708a564b 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -272,6 +272,7 @@ typedef struct CPUArchState {
/* Fields up to this point are cleared by a CPU reset */
struct {} end_reset_fields;
+ target_ulong cpu_hpa; /* HPA of this CPU */
target_ulong kernel_entry; /* Linux kernel was loaded here */
target_ulong cmdline_or_bootorder;
target_ulong initrd_base, initrd_end;
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-10-27 21:54 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-27 21:52 [PATCH 0/8] HPPA architecture patches for HP-UX 9 and 715 machine Helge Deller
2026-10-27 21:52 ` [PATCH 1/8] target/hppa: restore lazy FPU context isolation Helge Deller
2026-10-27 21:52 ` [PATCH 2/8] target/hppa: Use 15 bit protection IDs on PA1.1 CPUs Helge Deller
2026-10-27 21:52 ` [PATCH 3/8] target/hppa: Only allow 8 BTLB entries for HP-UX 9.05 Helge Deller
2026-10-27 21:52 ` [PATCH 4/8] target/hppa: Implement local broadcast I/O space Helge Deller
2026-10-27 21:52 ` [PATCH 5/8] target/hppa: Preload I/O-space BTLB entries for LASI and the central bus Helge Deller
2026-10-27 21:52 ` [PATCH 6/8] artist: Redraw screen on colormap changes Helge Deller
2026-10-27 21:52 ` [PATCH 7/8] hw/misc/lasi: LASI Harmony Audio presence emulation Helge Deller
2026-10-27 21:52 ` [PATCH 8/8] target/hppa: Map CPUs at same addresses as on physical machines Helge Deller
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.