target/hppa: Enhancements and fixes

Some enhancements and fixes for the hppa target.
 
 The major change is, that this patchset adds a new SeaBIOS-hppa firmware
 which is built as 32- and 64-bit firmware.
 The new 64-bit firmware is necessary to fully support 64-bit operating systems
 (HP-UX, Linux, NetBSD,...).
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQS86RI+GtKfB8BJu973ErUQojoPXwUCZcquAQAKCRD3ErUQojoP
 X9pjAQCVsWyuYlGCW2paIGVWKV0vsOpwetUrbhRtFUZGqZxb4AD9FbMsXRcCN/oq
 CotBPY/a8MEzIQcwYl5QbcI5nNW4ygs=
 =RA0B
 -----END PGP SIGNATURE-----

Merge tag 'hppa64-pull-request' of https://github.com/hdeller/qemu-hppa into staging

target/hppa: Enhancements and fixes

Some enhancements and fixes for the hppa target.

The major change is, that this patchset adds a new SeaBIOS-hppa firmware
which is built as 32- and 64-bit firmware.
The new 64-bit firmware is necessary to fully support 64-bit operating systems
(HP-UX, Linux, NetBSD,...).

# -----BEGIN PGP SIGNATURE-----
#
# iHUEABYKAB0WIQS86RI+GtKfB8BJu973ErUQojoPXwUCZcquAQAKCRD3ErUQojoP
# X9pjAQCVsWyuYlGCW2paIGVWKV0vsOpwetUrbhRtFUZGqZxb4AD9FbMsXRcCN/oq
# CotBPY/a8MEzIQcwYl5QbcI5nNW4ygs=
# =RA0B
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 12 Feb 2024 23:47:13 GMT
# 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 'hppa64-pull-request' of https://github.com/hdeller/qemu-hppa:
  hw/hppa/machine: Load 64-bit firmware on 64-bit machines
  target/hppa: Update SeaBIOS-hppa to version 16
  hw/net/tulip: add chip status register values
  target/hppa: PDC_BTLB_INFO uses 32-bit ints
  target/hppa: Allow read-access to PSW with rsm 0,reg instruction
  lasi: Add reset I/O ports for LASI audio and FDC
  target/hppa: Implement do_transaction_failed handler for I/O errors
  lasi: allow access to LAN MAC address registers
  hw/pci-host/astro: Implement Hard Fail and Soft Fail mode
  hw/pci-host/astro: Avoid aborting on access failure
  target/hppa: Add "diag 0x101" for console output support
  disas/hppa: Add disassembly for qemu specific instructions

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2024-02-13 13:56:46 +00:00
commit bc2e8b18fb
16 changed files with 150 additions and 43 deletions

View File

@ -1609,6 +1609,10 @@ static const struct pa_opcode pa_opcodes[] =
{ "call", 0xe800a000, 0xffe0e000, "nW", pa10, FLAG_STRICT}, { "call", 0xe800a000, 0xffe0e000, "nW", pa10, FLAG_STRICT},
{ "ret", 0xe840d000, 0xfffffffd, "n", pa20, FLAG_STRICT}, { "ret", 0xe840d000, 0xfffffffd, "n", pa20, FLAG_STRICT},
/* Opcodes assigned to QEMU, used by SeaBIOS firmware and Linux kernel */
{ "HALT QEMU", 0xfffdead0, 0xfffffffd, "n", pa10, FLAG_STRICT},
{ "RESET QEMU", 0xfffdead1, 0xfffffffd, "n", pa10, FLAG_STRICT},
{ "RESTORE SHR",0xfffdead2, 0xfffffffd, "n", pa10, FLAG_STRICT},
}; };
#define NUMOPCODES ((sizeof pa_opcodes)/(sizeof pa_opcodes[0])) #define NUMOPCODES ((sizeof pa_opcodes)/(sizeof pa_opcodes[0]))

View File

@ -13,6 +13,7 @@
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "sysemu/reset.h" #include "sysemu/reset.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "sysemu/qtest.h"
#include "sysemu/runstate.h" #include "sysemu/runstate.h"
#include "hw/rtc/mc146818rtc.h" #include "hw/rtc/mc146818rtc.h"
#include "hw/timer/i8254.h" #include "hw/timer/i8254.h"
@ -333,6 +334,7 @@ static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus,
const char *kernel_filename = machine->kernel_filename; const char *kernel_filename = machine->kernel_filename;
const char *kernel_cmdline = machine->kernel_cmdline; const char *kernel_cmdline = machine->kernel_cmdline;
const char *initrd_filename = machine->initrd_filename; const char *initrd_filename = machine->initrd_filename;
const char *firmware = machine->firmware;
MachineClass *mc = MACHINE_GET_CLASS(machine); MachineClass *mc = MACHINE_GET_CLASS(machine);
DeviceState *dev; DeviceState *dev;
PCIDevice *pci_dev; PCIDevice *pci_dev;
@ -408,31 +410,37 @@ static void machine_HP_common_init_tail(MachineState *machine, PCIBus *pci_bus,
/* Load firmware. Given that this is not "real" firmware, /* Load firmware. Given that this is not "real" firmware,
but one explicitly written for the emulation, we might as but one explicitly written for the emulation, we might as
well load it directly from an ELF image. */ well load it directly from an ELF image. Load the 64-bit
firmware_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, firmware on 64-bit machines by default if not specified
machine->firmware ?: "hppa-firmware.img"); on command line. */
if (firmware_filename == NULL) { if (!qtest_enabled()) {
error_report("no firmware provided"); if (!firmware) {
exit(1); firmware = lasi_dev ? "hppa-firmware.img" : "hppa-firmware64.img";
} }
firmware_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, firmware);
if (firmware_filename == NULL) {
error_report("no firmware provided");
exit(1);
}
size = load_elf(firmware_filename, NULL, translate, NULL, size = load_elf(firmware_filename, NULL, translate, NULL,
&firmware_entry, &firmware_low, &firmware_high, NULL, &firmware_entry, &firmware_low, &firmware_high, NULL,
true, EM_PARISC, 0, 0); true, EM_PARISC, 0, 0);
if (size < 0) { if (size < 0) {
error_report("could not load firmware '%s'", firmware_filename); error_report("could not load firmware '%s'", firmware_filename);
exit(1); exit(1);
}
qemu_log_mask(CPU_LOG_PAGE, "Firmware loaded at 0x%08" PRIx64
"-0x%08" PRIx64 ", entry at 0x%08" PRIx64 ".\n",
firmware_low, firmware_high, firmware_entry);
if (firmware_low < translate(NULL, FIRMWARE_START) ||
firmware_high >= translate(NULL, FIRMWARE_END)) {
error_report("Firmware overlaps with memory or IO space");
exit(1);
}
g_free(firmware_filename);
} }
qemu_log_mask(CPU_LOG_PAGE, "Firmware loaded at 0x%08" PRIx64
"-0x%08" PRIx64 ", entry at 0x%08" PRIx64 ".\n",
firmware_low, firmware_high, firmware_entry);
if (firmware_low < translate(NULL, FIRMWARE_START) ||
firmware_high >= translate(NULL, FIRMWARE_END)) {
error_report("Firmware overlaps with memory or IO space");
exit(1);
}
g_free(firmware_filename);
rom_region = g_new(MemoryRegion, 1); rom_region = g_new(MemoryRegion, 1);
memory_region_init_ram(rom_region, NULL, "firmware", memory_region_init_ram(rom_region, NULL, "firmware",

View File

@ -36,9 +36,13 @@ static bool lasi_chip_mem_valid(void *opaque, hwaddr addr,
case LASI_IAR: case LASI_IAR:
case LASI_LPT: case LASI_LPT:
case LASI_AUDIO:
case LASI_AUDIO + 4:
case LASI_UART: case LASI_UART:
case LASI_LAN: case LASI_LAN:
case LASI_LAN + 12: /* LASI LAN MAC */
case LASI_RTC: case LASI_RTC:
case LASI_FDC:
case LASI_PCR ... LASI_AMR: case LASI_PCR ... LASI_AMR:
ret = true; ret = true;
@ -78,6 +82,8 @@ static MemTxResult lasi_chip_read_with_attrs(void *opaque, hwaddr addr,
case LASI_LPT: case LASI_LPT:
case LASI_UART: case LASI_UART:
case LASI_LAN: case LASI_LAN:
case LASI_LAN + 12:
case LASI_FDC:
val = 0; val = 0;
break; break;
case LASI_RTC: case LASI_RTC:
@ -143,12 +149,19 @@ static MemTxResult lasi_chip_write_with_attrs(void *opaque, hwaddr addr,
case LASI_LPT: case LASI_LPT:
/* XXX: reset parallel port */ /* XXX: reset parallel port */
break; break;
case LASI_AUDIO:
case LASI_AUDIO + 4:
/* XXX: reset audio port */
break;
case LASI_UART: case LASI_UART:
/* XXX: reset serial port */ /* XXX: reset serial port */
break; break;
case LASI_LAN: case LASI_LAN:
/* XXX: reset LAN card */ /* XXX: reset LAN card */
break; break;
case LASI_FDC:
/* XXX: reset Floppy controller */
break;
case LASI_RTC: case LASI_RTC:
s->rtc_ref = val - time(NULL); s->rtc_ref = val - time(NULL);
break; break;

View File

@ -421,7 +421,7 @@ static uint16_t tulip_mdi_default[] = {
/* MDI Registers 8 - 15 */ /* MDI Registers 8 - 15 */
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
/* MDI Registers 16 - 31 */ /* MDI Registers 16 - 31 */
0x0003, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0003, 0x0000, 0x0001, 0x0000, 0x3b40, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
}; };
@ -429,7 +429,7 @@ static uint16_t tulip_mdi_default[] = {
static const uint16_t tulip_mdi_mask[] = { static const uint16_t tulip_mdi_mask[] = {
0x0000, 0xffff, 0xffff, 0xffff, 0xc01f, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xc01f, 0xffff, 0xffff, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0fff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0fff, 0x0000, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
}; };

View File

@ -122,10 +122,6 @@ static MemTxResult elroy_chip_read_with_attrs(void *opaque, hwaddr addr,
case 0x0800: /* IOSAPIC_REG_SELECT */ case 0x0800: /* IOSAPIC_REG_SELECT */
val = s->iosapic_reg_select; val = s->iosapic_reg_select;
break; break;
case 0x0808:
val = UINT64_MAX; /* XXX: tbc. */
g_assert_not_reached();
break;
case 0x0810: /* IOSAPIC_REG_WINDOW */ case 0x0810: /* IOSAPIC_REG_WINDOW */
switch (s->iosapic_reg_select) { switch (s->iosapic_reg_select) {
case 0x01: /* IOSAPIC_REG_VERSION */ case 0x01: /* IOSAPIC_REG_VERSION */
@ -135,15 +131,21 @@ static MemTxResult elroy_chip_read_with_attrs(void *opaque, hwaddr addr,
if (s->iosapic_reg_select < ARRAY_SIZE(s->iosapic_reg)) { if (s->iosapic_reg_select < ARRAY_SIZE(s->iosapic_reg)) {
val = s->iosapic_reg[s->iosapic_reg_select]; val = s->iosapic_reg[s->iosapic_reg_select];
} else { } else {
trace_iosapic_reg_read(s->iosapic_reg_select, size, val); goto check_hf;
g_assert_not_reached();
} }
} }
trace_iosapic_reg_read(s->iosapic_reg_select, size, val); trace_iosapic_reg_read(s->iosapic_reg_select, size, val);
break; break;
default: default:
trace_elroy_read(addr, size, val); check_hf:
g_assert_not_reached(); if (s->status_control & HF_ENABLE) {
val = 0;
ret = MEMTX_DECODE_ERROR;
} else {
/* return -1ULL if HardFail is disabled */
val = ~0;
ret = MEMTX_OK;
}
} }
trace_elroy_read(addr, size, val); trace_elroy_read(addr, size, val);
@ -191,7 +193,7 @@ static MemTxResult elroy_chip_write_with_attrs(void *opaque, hwaddr addr,
if (s->iosapic_reg_select < ARRAY_SIZE(s->iosapic_reg)) { if (s->iosapic_reg_select < ARRAY_SIZE(s->iosapic_reg)) {
s->iosapic_reg[s->iosapic_reg_select] = val; s->iosapic_reg[s->iosapic_reg_select] = val;
} else { } else {
g_assert_not_reached(); goto check_hf;
} }
break; break;
case 0x0840: /* IOSAPIC_REG_EOI */ case 0x0840: /* IOSAPIC_REG_EOI */
@ -204,7 +206,10 @@ static MemTxResult elroy_chip_write_with_attrs(void *opaque, hwaddr addr,
} }
break; break;
default: default:
g_assert_not_reached(); check_hf:
if (s->status_control & HF_ENABLE) {
return MEMTX_DECODE_ERROR;
}
} }
return MEMTX_OK; return MEMTX_OK;
} }
@ -594,8 +599,8 @@ static MemTxResult astro_chip_read_with_attrs(void *opaque, hwaddr addr,
#undef EMPTY_PORT #undef EMPTY_PORT
default: default:
trace_astro_chip_read(addr, size, val); val = 0;
g_assert_not_reached(); ret = MEMTX_DECODE_ERROR;
} }
/* for 32-bit accesses mask return value */ /* for 32-bit accesses mask return value */
@ -610,6 +615,7 @@ static MemTxResult astro_chip_write_with_attrs(void *opaque, hwaddr addr,
uint64_t val, unsigned size, uint64_t val, unsigned size,
MemTxAttrs attrs) MemTxAttrs attrs)
{ {
MemTxResult ret = MEMTX_OK;
AstroState *s = opaque; AstroState *s = opaque;
trace_astro_chip_write(addr, size, val); trace_astro_chip_write(addr, size, val);
@ -686,11 +692,9 @@ static MemTxResult astro_chip_write_with_attrs(void *opaque, hwaddr addr,
#undef EMPTY_PORT #undef EMPTY_PORT
default: default:
/* Controlled by astro_chip_mem_valid above. */ ret = MEMTX_DECODE_ERROR;
trace_astro_chip_write(addr, size, val);
g_assert_not_reached();
} }
return MEMTX_OK; return ret;
} }
static const MemoryRegionOps astro_chip_ops = { static const MemoryRegionOps astro_chip_ops = {

View File

@ -26,9 +26,11 @@ OBJECT_DECLARE_SIMPLE_TYPE(LasiState, LASI_CHIP)
#define LASI_IAR 0x10 #define LASI_IAR 0x10
#define LASI_LPT 0x02000 #define LASI_LPT 0x02000
#define LASI_AUDIO 0x04000
#define LASI_UART 0x05000 #define LASI_UART 0x05000
#define LASI_LAN 0x07000 #define LASI_LAN 0x07000
#define LASI_RTC 0x09000 #define LASI_RTC 0x09000
#define LASI_FDC 0x0A000
#define LASI_PCR 0x0C000 /* LASI Power Control register */ #define LASI_PCR 0x0C000 /* LASI Power Control register */
#define LASI_ERRLOG 0x0C004 /* LASI Error Logging register */ #define LASI_ERRLOG 0x0C004 /* LASI Error Logging register */

View File

@ -27,6 +27,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(ElroyState, ELROY_PCI_HOST_BRIDGE)
#define IOS_DIST_BASE_ADDR 0xfffee00000ULL #define IOS_DIST_BASE_ADDR 0xfffee00000ULL
#define IOS_DIST_BASE_SIZE 0x10000ULL #define IOS_DIST_BASE_SIZE 0x10000ULL
#define HF_ENABLE 0x40 /* enable HF mode (default is -1 mode) */
struct AstroState; struct AstroState;
struct ElroyState { struct ElroyState {

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

Binary file not shown.

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

Binary file not shown.

@ -1 +1 @@
Subproject commit e4eac85880e8677f96d8b9e94de9f2eec9c0751f Subproject commit 03774edaad3bfae090ac96ca5450353c641637d1

View File

@ -191,6 +191,7 @@ static const TCGCPUOps hppa_tcg_ops = {
.cpu_exec_interrupt = hppa_cpu_exec_interrupt, .cpu_exec_interrupt = hppa_cpu_exec_interrupt,
.do_interrupt = hppa_cpu_do_interrupt, .do_interrupt = hppa_cpu_do_interrupt,
.do_unaligned_access = hppa_cpu_do_unaligned_access, .do_unaligned_access = hppa_cpu_do_unaligned_access,
.do_transaction_failed = hppa_cpu_do_transaction_failed,
#endif /* !CONFIG_USER_ONLY */ #endif /* !CONFIG_USER_ONLY */
}; };

View File

@ -381,6 +381,11 @@ bool hppa_cpu_exec_interrupt(CPUState *cpu, int int_req);
int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
int type, hwaddr *pphys, int *pprot, int type, hwaddr *pphys, int *pprot,
HPPATLBEntry **tlb_entry); HPPATLBEntry **tlb_entry);
void hppa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
vaddr addr, unsigned size,
MMUAccessType access_type,
int mmu_idx, MemTxAttrs attrs,
MemTxResult response, uintptr_t retaddr);
extern const MemoryRegionOps hppa_io_eir_ops; extern const MemoryRegionOps hppa_io_eir_ops;
extern const VMStateDescription vmstate_hppa_cpu; extern const VMStateDescription vmstate_hppa_cpu;
void hppa_cpu_alarm_timer(void *); void hppa_cpu_alarm_timer(void *);

View File

@ -103,4 +103,5 @@ 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_1(diag_btlb, void, env) DEF_HELPER_1(diag_btlb, void, env)
DEF_HELPER_1(diag_console_output, void, env)
#endif #endif

View File

@ -353,6 +353,25 @@ raise_exception_with_ior(CPUHPPAState *env, int excp, uintptr_t retaddr,
cpu_loop_exit_restore(cs, retaddr); cpu_loop_exit_restore(cs, retaddr);
} }
void hppa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
vaddr addr, unsigned size,
MMUAccessType access_type,
int mmu_idx, MemTxAttrs attrs,
MemTxResult response, uintptr_t retaddr)
{
CPUHPPAState *env = cpu_env(cs);
qemu_log_mask(LOG_GUEST_ERROR, "HPMC at " TARGET_FMT_lx ":" TARGET_FMT_lx
" while accessing I/O at %#08" HWADDR_PRIx "\n",
env->iasq_f, env->iaoq_f, physaddr);
/* FIXME: Enable HPMC exceptions when firmware has clean device probing */
if (0) {
raise_exception_with_ior(env, EXCP_HPMC, retaddr, addr,
MMU_IDX_MMU_DISABLED(mmu_idx));
}
}
bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
MMUAccessType type, int mmu_idx, MMUAccessType type, int mmu_idx,
bool probe, uintptr_t retaddr) bool probe, uintptr_t retaddr)
@ -665,7 +684,7 @@ void HELPER(diag_btlb)(CPUHPPAState *env)
case 0: case 0:
/* return BTLB parameters */ /* return BTLB parameters */
qemu_log_mask(CPU_LOG_MMU, "PDC_BLOCK_TLB: PDC_BTLB_INFO\n"); qemu_log_mask(CPU_LOG_MMU, "PDC_BLOCK_TLB: PDC_BTLB_INFO\n");
vaddr = probe_access(env, env->gr[24], 4 * sizeof(target_ulong), vaddr = probe_access(env, env->gr[24], 4 * sizeof(uint32_t),
MMU_DATA_STORE, mmu_idx, ra); MMU_DATA_STORE, mmu_idx, ra);
if (vaddr == NULL) { if (vaddr == NULL) {
env->gr[28] = -10; /* invalid argument */ env->gr[28] = -10; /* invalid argument */

View File

@ -23,6 +23,8 @@
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
#include "qemu/timer.h" #include "qemu/timer.h"
#include "sysemu/runstate.h" #include "sysemu/runstate.h"
#include "sysemu/sysemu.h"
#include "chardev/char-fe.h"
void HELPER(write_interval_timer)(CPUHPPAState *env, target_ulong val) void HELPER(write_interval_timer)(CPUHPPAState *env, target_ulong val)
{ {
@ -109,3 +111,37 @@ void HELPER(rfi_r)(CPUHPPAState *env)
helper_getshadowregs(env); helper_getshadowregs(env);
helper_rfi(env); helper_rfi(env);
} }
#ifndef CONFIG_USER_ONLY
/*
* diag_console_output() is a helper function used during the initial bootup
* process of the SeaBIOS-hppa firmware. During the bootup phase, addresses of
* serial ports on e.g. PCI busses are unknown and most other devices haven't
* been initialized and configured yet. With help of a simple "diag" assembler
* instruction and an ASCII character code in register %r26 firmware can easily
* print debug output without any dependencies to the first serial port and use
* that as serial console.
*/
void HELPER(diag_console_output)(CPUHPPAState *env)
{
CharBackend *serial_backend;
Chardev *serial_port;
unsigned char c;
/* find first serial port */
serial_port = serial_hd(0);
if (!serial_port) {
return;
}
/* get serial_backend for the serial port */
serial_backend = serial_port->be;
if (!serial_backend ||
!qemu_chr_fe_backend_connected(serial_backend)) {
return;
}
c = (unsigned char)env->gr[26];
qemu_chr_fe_write(serial_backend, &c, sizeof(c));
}
#endif

View File

@ -2156,10 +2156,16 @@ static bool trans_ldsid(DisasContext *ctx, arg_ldsid *a)
static bool trans_rsm(DisasContext *ctx, arg_rsm *a) static bool trans_rsm(DisasContext *ctx, arg_rsm *a)
{ {
#ifdef CONFIG_USER_ONLY
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
#ifndef CONFIG_USER_ONLY #else
TCGv_i64 tmp; TCGv_i64 tmp;
/* HP-UX 11i and HP ODE use rsm for read-access to PSW */
if (a->i) {
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
}
nullify_over(ctx); nullify_over(ctx);
tmp = tcg_temp_new_i64(); tmp = tcg_temp_new_i64();
@ -4411,6 +4417,12 @@ static bool trans_diag(DisasContext *ctx, arg_diag *a)
gen_helper_diag_btlb(tcg_env); gen_helper_diag_btlb(tcg_env);
return nullify_end(ctx); return nullify_end(ctx);
} }
if (a->i == 0x101) {
/* print char in %r26 to first serial console, used by SeaBIOS-hppa */
nullify_over(ctx);
gen_helper_diag_console_output(tcg_env);
return nullify_end(ctx);
}
#endif #endif
qemu_log_mask(LOG_UNIMP, "DIAG opcode 0x%04x ignored\n", a->i); qemu_log_mask(LOG_UNIMP, "DIAG opcode 0x%04x ignored\n", a->i);
return true; return true;