aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2023-10-22 09:36:53 +0200
committerHelge Deller <deller@gmx.de>2023-10-22 09:36:53 +0200
commitedb1c29da0df2c33e62305d1c1c71a4cbd6bff67 (patch)
tree7679aff1450332749e413b5f962a50a9fe427f56
parentff162afa8a2d697d71f120ad1322233d9ace9545 (diff)
downloadseabios-hppa-edb1c29da0df2c33e62305d1c1c71a4cbd6bff67.zip
seabios-hppa-edb1c29da0df2c33e62305d1c1c71a4cbd6bff67.tar.gz
seabios-hppa-edb1c29da0df2c33e62305d1c1c71a4cbd6bff67.tar.bz2
parisc: Save and restore current PSW_W across PDC call
When called from a 64-bit kernel, pdc_psw may be called with PSW.W set, so save and restore it during the call. Signed-off-by: Helge Deller <deller@gmx.de>
-rw-r--r--src/parisc/head.S15
-rw-r--r--src/parisc/parisc.c9
2 files changed, 19 insertions, 5 deletions
diff --git a/src/parisc/head.S b/src/parisc/head.S
index 53b3ddd..7bc7c09 100644
--- a/src/parisc/head.S
+++ b/src/parisc/head.S
@@ -353,6 +353,7 @@ ENTRY(pdc_entry)
stw %arg1,-40(%sp)
stw %arg2,-44(%sp)
stw %arg3,-48(%sp)
+ stw %r31,-52(%sp) /* store PSW_W */
ldo -FRAME_SIZE(%sp),%arg0
loadgp
@@ -361,13 +362,25 @@ ENTRY(pdc_entry)
ldo -FRAME_SIZE(%sp),%sp
ldw -20(%sp),%rp
- bv %r0(%rp)
ldw -32(%sp),%dp
+ ldw -52(%sp),%r31
+ load32 0x8000000,%r1 /* mask PSW_W */
+ and,= %r31,%r1,%r0
+ bv %r0(%rp) /* return without setting PSW_W */
+ nop
+ bv %r0(%rp) /* return with setting PSW_W */
+ .level 2.0
+ ssm PSW_W_SM,%r0
+ .level 1.1
END(pdc_entry)
/* pdc_entry_table will be copied into low memory. */
ENTRY(pdc_entry_table)
load32 pdc_entry,%r1
+ ;! nuke the W bit
+ .level 2.0
+ rsm PSW_W_SM, %r31
+ .level 1.1
bv,n %r0(%r1)
END(pdc_entry_table)
diff --git a/src/parisc/parisc.c b/src/parisc/parisc.c
index cc55133..98e86f5 100644
--- a/src/parisc/parisc.c
+++ b/src/parisc/parisc.c
@@ -141,7 +141,7 @@ unsigned int tlb_entries = 256;
#define PARISC_SERIAL_CONSOLE PORT_SERIAL1
extern char pdc_entry;
-extern char pdc_entry_table[12];
+extern char pdc_entry_table[4*4];
extern char iodc_entry[512];
extern char iodc_entry_table[14*4];
@@ -1759,7 +1759,7 @@ static int pdc_psw(unsigned int *arg)
if (option == PDC_PSW_SET_DEFAULTS) {
psw_defaults = ARG2 & mask;
/* we do not yet support little endian mode */
- BUG_ON((psw_defaults & PDC_PSW_ENDIAN_BIT) == 0);
+ BUG_ON((psw_defaults & PDC_PSW_ENDIAN_BIT) == 1);
/* tell qemu the default mask */
mtctl(psw_defaults, CR_PSW_DEFAULT);
}
@@ -2677,6 +2677,7 @@ void __VISIBLE start_parisc_firmware(void)
cpu_bit_width = (i == 63) ? 64 : 32;
psw_defaults = PDC_PSW_ENDIAN_BIT;
+ /* if (cpu_bit_width == 64) psw_defaults |= PDC_PSW_WIDE_BIT; */
mtctl(psw_defaults, CR_PSW_DEFAULT);
if (smp_cpus > HPPA_MAX_CPUS)
@@ -2767,8 +2768,8 @@ void __VISIBLE start_parisc_firmware(void)
/* memset((void*)PAGE0, 0, sizeof(*PAGE0)); */
/* copy pdc_entry entry into low memory. */
- memcpy((void*)MEM_PDC_ENTRY, &pdc_entry_table, 3*4);
- flush_data_cache((char*)MEM_PDC_ENTRY, 3*4);
+ memcpy((void*)MEM_PDC_ENTRY, &pdc_entry_table, 4*4);
+ flush_data_cache((char*)MEM_PDC_ENTRY, 4*4);
PAGE0->memc_cont = ram_size;
PAGE0->memc_phsize = ram_size;