diff options
author | Helge Deller <deller@gmx.de> | 2024-01-03 00:08:29 +0100 |
---|---|---|
committer | Helge Deller <deller@gmx.de> | 2024-01-04 18:48:58 +0100 |
commit | 292ee73331f6f1e55122691a1b9bd59399a5c199 (patch) | |
tree | 021de4844bf2521861f461450beaa291a3a54ad4 | |
parent | a7efc718498cdbc1d547938bfbb308e177c45a8e (diff) | |
download | seabios-hppa-292ee73331f6f1e55122691a1b9bd59399a5c199.zip seabios-hppa-292ee73331f6f1e55122691a1b9bd59399a5c199.tar.gz seabios-hppa-292ee73331f6f1e55122691a1b9bd59399a5c199.tar.bz2 |
parisc: Fix 64-bit firmware build
Signed-off-by: Helge Deller <deller@gmx.de>
-rw-r--r-- | src/boot.c | 2 | ||||
-rw-r--r-- | src/parisc/head.S | 71 | ||||
-rw-r--r-- | src/parisc/hppa.h | 4 | ||||
-rw-r--r-- | src/parisc/pafirmware.lds.S | 9 | ||||
-rw-r--r-- | src/parisc/parisc.c | 71 | ||||
-rw-r--r-- | src/types.h | 4 | ||||
-rw-r--r-- | vgasrc/vgainit.c | 2 |
7 files changed, 116 insertions, 47 deletions
@@ -932,7 +932,7 @@ bcv_prepboot(void) static void call_boot_entry(struct segoff_s bootsegip, u8 bootdrv) { - dprintf(1, "Booting from %04x:%04x\n", bootsegip.seg, bootsegip.offset); + dprintf(1, "Booting from %04x:%04lx\n", bootsegip.seg, bootsegip.offset); struct bregs br; memset(&br, 0, sizeof(br)); br.flags = F_IF; diff --git a/src/parisc/head.S b/src/parisc/head.S index da89558..c9b96b7 100644 --- a/src/parisc/head.S +++ b/src/parisc/head.S @@ -14,8 +14,17 @@ .macro load32 value, reg ldil L%\value, \reg ldo R%\value(\reg), \reg +#ifdef CONFIG_64BIT + depdi 0, 31, 32, \reg +#endif .endm +;! set the W bit +#define set_PSW_W .level 2.0 ! ssm PSW_W_SM, %r0 ! .level LEVEL + +;! nuke the W bit +#define clear_PSW_W .level 2.0 ! rsm PSW_W_SM, %r0 ! .level LEVEL + #define ENTRY(name) \ .export name !\ .align 4 !\ @@ -31,11 +40,16 @@ name: #define BOOTADDR(x) (x) .macro loadgp +#ifdef CONFIG_64BIT + copy %r0, %r27 +#else ldil L%$global$, %r27 ldo R%$global$(%r27), %r27 +#endif .endm #ifdef CONFIG_64BIT +#define LEVEL 2.0w #define LDREG ldd #define STREG std #define LDREGX ldd,s @@ -51,6 +65,7 @@ name: #define WORD_LEN 8 #define INT_LEN 4 #else /* CONFIG_64BIT */ +#define LEVEL 1.1 #define LDREG ldw #define STREG stw #define LDREGX ldwx,s @@ -78,7 +93,7 @@ name: .import $global$ .section ".head.text","ax" - .level 1.1 + .level LEVEL /* On HPMC, the CPUs will start here at 0xf0000000 */ hpmc_entry: @@ -103,6 +118,20 @@ ENTRY(startup) rsm PSW_I, %r0 /* disable local irqs */ ssm PSW_Q, %r0 /* enable PSW_Q flag */ +#ifdef CONFIG_64BIT + /* check if we really run on 64-bit CPU */ + ldo -1(%r0), %r1 + mtctl %r1,%cr11 + mfctl,w %cr11, %r1 + ldo -31(%r1),%r1 + cmpib,<>,n 0,%r1,1f + .word 0xfffdead0 /* immediately halt the emulator */ +1: + // set_PSW_W +#else + clear_PSW_W +#endif + /* Make sure space registers are set to zero */ mtsp %r0,%sr0 mtsp %r0,%sr1 @@ -113,11 +142,6 @@ ENTRY(startup) mtsp %r0,%sr6 mtsp %r0,%sr7 - ;! nuke the W bit - .level 2.0 - rsm PSW_W_SM, %r0 - .level 1.1 - /* If CPU HPA is already set in CPU_HPA_CR_REG then the * CPU is already initialized and the machine was only reset */ mfctl CPU_HPA_CR_REG, %r1 @@ -190,14 +214,14 @@ $smp_exit_loop: $is_monarch_cpu: /* Save boot_args in PAGE0->pad608[]. Only monarch CPU does this once. */ load32 BOOTADDR(0x608),%r1 - stw,ma %r26,4(%r1) - stw,ma %r25,4(%r1) - stw,ma %r24,4(%r1) - stw,ma %r23,4(%r1) - stw,ma %r22,4(%r1) - stw,ma %r21,4(%r1) - stw,ma %r20,4(%r1) - stw,ma %r19,4(%r1) + STREGM %r26,WORD_LEN(%r1) + STREGM %r25,WORD_LEN(%r1) + STREGM %r24,WORD_LEN(%r1) + STREGM %r23,WORD_LEN(%r1) + STREGM %r22,WORD_LEN(%r1) + STREGM %r21,WORD_LEN(%r1) + STREGM %r20,WORD_LEN(%r1) + STREGM %r19,WORD_LEN(%r1) $is_monarch_cpu_reboot: /* Initialize stack pointer */ @@ -215,7 +239,7 @@ $is_monarch_cpu_reboot: load32 BOOTADDR(_ebss),%r4 $bss_loop: cmpb,<<,n %r3,%r4,$bss_loop - stw,ma %r0,4(%r3) + STREGM %r0,WORD_LEN(%r3) load32 BOOTADDR(start_parisc_firmware),%r3 bv 0(%r3) @@ -268,7 +292,8 @@ ENTRY(toc_asm_entry) /* save all general registers */ .set loop,0 .rept 32 - STREGM loop, WORD_LEN(PIM_PTR) + copy loop,TEMP + STREGM TEMP, WORD_LEN(PIM_PTR) .set loop,loop+1 .endr @@ -376,16 +401,13 @@ ENTRY(pdc_entry) bv %r0(%rp) /* return with setting PSW_W */ .level 2.0 nop // ssm PSW_W_SM,%r0 - .level 1.1 + .level LEVEL 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 + clear_PSW_W bv,n %r0(%r1) END(pdc_entry_table) @@ -408,10 +430,7 @@ ENTRY(iodc_entry) stw %arg1,-40(%sp) stw %arg2,-44(%sp) stw %arg3,-48(%sp) - ;! nuke the W bit - .level 2.0 - rsm PSW_W_SM, %r31 - .level 1.1 + clear_PSW_W stw %r31,PSW_OFFSET2(%r0) /* store PSW_W */ ldo -FRAME_SIZE(%sp),%arg0 @@ -433,7 +452,7 @@ ENTRY(iodc_entry) bv %r0(%rp) /* return with setting PSW_W */ .level 2.0 nop // ssm PSW_W_SM,%r0 - .level 1.1 + .level LEVEL END(iodc_entry) /**************************************************************** diff --git a/src/parisc/hppa.h b/src/parisc/hppa.h index 9c82b70..3b7e7bb 100644 --- a/src/parisc/hppa.h +++ b/src/parisc/hppa.h @@ -6,6 +6,10 @@ #define SEABIOS_HPPA_VERSION 13 #define SEABIOS_HPPA_VERSION_STR "13" +#ifdef __LP64__ +#define CONFIG_64BIT +#endif + #include "parisc/hppa_hardware.h" #ifndef __ASSEMBLY__ diff --git a/src/parisc/pafirmware.lds.S b/src/parisc/pafirmware.lds.S index 9975596..4af3865 100644 --- a/src/parisc/pafirmware.lds.S +++ b/src/parisc/pafirmware.lds.S @@ -1,11 +1,20 @@ #include "parisc/hppa_hardware.h" +#if BITS == 64 +OUTPUT_FORMAT("elf64-hppa-linux") +OUTPUT_ARCH(hppa:hppa2.0w) +#else OUTPUT_FORMAT("elf32-hppa-linux") OUTPUT_ARCH(hppa) +#endif ENTRY(startup) SECTIONS { +#if BITS == 64 + . = 0xfffffff000000000 + FIRMWARE_START; +#else . = FIRMWARE_START; +#endif /* align on next page boundary */ . = ALIGN(4096); diff --git a/src/parisc/parisc.c b/src/parisc/parisc.c index c90902d..df85f1c 100644 --- a/src/parisc/parisc.c +++ b/src/parisc/parisc.c @@ -52,7 +52,13 @@ union { struct pdc_toc_pim_20 pim20; } pim_toc_data[HPPA_MAX_CPUS] __VISIBLE __aligned(8); -#define is_64bit() 0 /* we only support 32-bit PDC for now. */ +#if defined(__LP64__) +# define is_64bit() 1 /* 64-bit PDC */ +# define cpu_bit_width 64 +#else +# define is_64bit() 0 /* 32-bit PDC */ +char cpu_bit_width; +#endif u8 BiosChecksum; @@ -98,7 +104,7 @@ void wrmsr_smp(u32 index, u64 val) { } ********************************************************/ /* boot_args[] variables provided by qemu */ -#define boot_args PAGE0->pad608 +#define boot_args ((unsigned long *)(uintptr_t)&PAGE0->pad608) #define ram_size boot_args[0] #define linux_kernel_entry boot_args[1] #define cmdline boot_args[2] @@ -124,7 +130,6 @@ int sti_font; char qemu_version[16] = "unknown version"; char qemu_machine[16] = "B160L"; -char cpu_bit_width; char has_astro; #define PCI_HPA DINO_HPA /* initial temp. PCI bus */ unsigned long pci_hpa = PCI_HPA; /* HPA of Dino or Elroy0 */ @@ -254,7 +259,7 @@ void flush_data_cache(char *start, size_t length) void memdump(void *mem, unsigned long len) { - printf("memdump @ 0x%x : ", (unsigned int) mem); + printf("memdump @ 0x%lx : ", (unsigned long) mem); while (len--) { printf("0x%x ", (unsigned int) *(unsigned char *)mem); mem++; @@ -1867,8 +1872,8 @@ static int pdc_mem(unsigned int *arg) unsigned long option = ARG1; unsigned long *result = (unsigned long *)ARG2; - // only implemented on 64bit PDC! - if (sizeof(unsigned long) == sizeof(unsigned int)) + // only implemented on 64bit PDC variants + if (!is_64bit()) return PDC_BAD_PROC; switch (option) { @@ -1885,6 +1890,10 @@ static int pdc_mem(unsigned int *arg) case PDC_MEM_GOODMEM: GoldenMemory = ARG3; return PDC_OK; + case PDC_MEM_GET_MEMORY_SYSTEM_TABLES_SIZE: + case PDC_MEM_GET_MEMORY_SYSTEM_TABLES: + /* not yet implemented for 64-bit */ + return PDC_BAD_PROC; } dprintf(0, "\n\nSeaBIOS: Check PDC_MEM option %ld ARG3=%x ARG4=%x ARG5=%x\n", option, ARG3, ARG4, ARG5); return PDC_BAD_PROC; @@ -2254,6 +2263,18 @@ static int pdc_pat_pd(unsigned int *arg) return PDC_BAD_OPTION; } +static int pdc_pat_mem(unsigned int *arg) +{ + unsigned long option = ARG1; + + switch (option) { + default: + break; + } + dprintf(0, "\n\nSeaBIOS: Unimplemented PDC_PAT_MEM function %ld ARG3=%x ARG4=%x ARG5=%x\n", option, ARG3, ARG4, ARG5); + return PDC_BAD_OPTION; +} + int __VISIBLE parisc_pdc_entry(unsigned int *arg FUNC_MANY_ARGS) { @@ -2394,6 +2415,11 @@ int __VISIBLE parisc_pdc_entry(unsigned int *arg FUNC_MANY_ARGS) if (firmware_width_locked) return PDC_BAD_PROC; return pdc_pat_pd(arg); + + case PDC_PAT_MEM: + if (firmware_width_locked) + return PDC_BAD_PROC; + return pdc_pat_mem(arg); } printf("\n** WARNING **: SeaBIOS: Unimplemented PDC proc %s(%d) option %d result=%x ARG3=%x ", @@ -2751,37 +2777,44 @@ static int parisc_boot_menu(unsigned long *iplstart, unsigned long *iplend, * FIRMWARE MAIN ENTRY POINT ********************************************************/ -static const struct pz_device mem_cons_sti_boot = { +static struct pz_device mem_cons_sti_boot = { .hpa = LASI_GFX_HPA, - .iodc_io = (unsigned long)&iodc_entry, .cl_class = CL_DISPL, }; static struct pz_device mem_kbd_sti_boot = { .hpa = LASI_PS2KBD_HPA, - .iodc_io = (unsigned long)&iodc_entry, .cl_class = CL_KEYBD, }; static struct pz_device mem_cons_boot = { .hpa = PARISC_SERIAL_CONSOLE - 0x800, - .iodc_io = (unsigned long)&iodc_entry, .cl_class = CL_DUPLEX, }; static struct pz_device mem_kbd_boot = { .hpa = PARISC_SERIAL_CONSOLE - 0x800, - .iodc_io = (unsigned long)&iodc_entry, .cl_class = CL_KEYBD, }; static struct pz_device mem_boot_boot = { .dp.path.flags = PF_AUTOBOOT, .hpa = DINO_SCSI_HPA, // will be overwritten - .iodc_io = (unsigned long) &iodc_entry, .cl_class = CL_RANDOM, }; +static void initialize_iodc_entry(void) +{ + unsigned long iodc_p = (unsigned long) &iodc_entry; + + /* need to initialize at runtime, required on 64-bit firmware */ + mem_cons_sti_boot.iodc_io = iodc_p; + mem_kbd_sti_boot.iodc_io = iodc_p; + mem_cons_boot.iodc_io = iodc_p; + mem_kbd_boot.iodc_io = iodc_p; + mem_boot_boot.iodc_io = iodc_p; +} + #if 0 static void find_pci_slot_for_dev(unsigned int vendor, char *pci_slot) { @@ -2912,6 +2945,9 @@ void __VISIBLE start_parisc_firmware(void) char bootdrive = (char)cmdline; // c = hdd, d = CD/DVD show_boot_menu = (linux_kernel_entry == 1); + initialize_iodc_entry(); + +#ifndef __LP64__ // detect if we emulate a 32- or 64-bit CPU. // set all bits in cr11, read back, and if the return // value is 63 this is a 64-bit capable CPU. @@ -2920,13 +2956,14 @@ void __VISIBLE start_parisc_firmware(void) /* this is: mfctl,w sar,r1: */ asm(".word 0x016048a0 + 1 ! copy %%r1,%0\n" : "=r" (i): : "r1"); cpu_bit_width = (i == 63) ? 64 : 32; +#endif /* lock all 64-bit and PAT functions until unlocked from OS * via PDC_MODEL/PDC_MODEL_CAPABILITIES call */ firmware_width_locked = 1; psw_defaults = PDC_PSW_ENDIAN_BIT; - if (0 && cpu_bit_width == 64) { + if (is_64bit() && cpu_bit_width == 64) { /* enable 64-bit PSW by default */ psw_defaults |= PDC_PSW_WIDE_BIT; current_machine->pdc_model.width = 1; @@ -3074,7 +3111,7 @@ void __VISIBLE start_parisc_firmware(void) if (artist_present()) { sti_rom_init(); sti_console_init(&sti_proc_rom); - PAGE0->proc_sti = (u32)&sti_proc_rom; + PAGE0->proc_sti = (uintptr_t)&sti_proc_rom; if (has_astro) kbd_init(); else @@ -3107,13 +3144,13 @@ void __VISIBLE start_parisc_firmware(void) chassis_code = 0; cpu_hz = 100 * PAGE0->mem_10msec; /* Hz of this PARISC */ - dprintf(1, "\nPARISC SeaBIOS Firmware, %d x %d-bit PA-RISC CPU at %d.%06d MHz, %d MB RAM.\n", + dprintf(1, "\nPARISC SeaBIOS Firmware, %ld x %d-bit PA-RISC CPU at %d.%06d MHz, %ld MB RAM.\n", smp_cpus, cpu_bit_width, cpu_hz / 1000000, cpu_hz % 1000000, ram_size/1024/1024); if (ram_size < MIN_RAM_SIZE) { printf("\nSeaBIOS: Machine configured with too little " - "memory (%d MB), minimum is %d MB.\n\n", + "memory (%ld MB), minimum is %d MB.\n\n", ram_size/1024/1024, MIN_RAM_SIZE/1024/1024); hlt(); } @@ -3176,7 +3213,7 @@ void __VISIBLE start_parisc_firmware(void) i < 10 ? " ":"", i, i?"Idle ":"Active"); printf("\n\n"); printf(" Emulated machine: HP %s (%d-bit %s)\n" - " Available memory: %u MB\n" + " Available memory: %lu MB\n" " Good memory required: %d MB\n\n", qemu_machine, cpu_bit_width, (cpu_bit_width == 64) ? "PA2.0" : "PA1.1", ram_size/1024/1024, MIN_RAM_SIZE/1024/1024); diff --git a/src/types.h b/src/types.h index 5887ecf..cadefcb 100644 --- a/src/types.h +++ b/src/types.h @@ -24,7 +24,7 @@ union u64_u32_u { #if MODE16 == 1 typedef u16 portaddr_t; #else -typedef unsigned int portaddr_t; +typedef unsigned long portaddr_t; #endif // Definition for common 16bit segment/offset pointers. @@ -120,7 +120,7 @@ extern void __force_link_error__only_in_16bit(void) __noreturn; # define ASSERT32FLAT() do { } while (0) #endif -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER) #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) diff --git a/vgasrc/vgainit.c b/vgasrc/vgainit.c index 56222b4..4b6ed74 100644 --- a/vgasrc/vgainit.c +++ b/vgasrc/vgainit.c @@ -54,7 +54,7 @@ allocate_pmm(u32 size, int highmem, int aligned) if (checksum_far(SEG_BIOS, pmm, GET_FARVAR(SEG_BIOS, pmm->length))) continue; struct segoff_s entry = GET_FARVAR(SEG_BIOS, pmm->entry); - dprintf(1, "Attempting to allocate %u bytes %s via pmm call to %04x:%04x\n" + dprintf(1, "Attempting to allocate %u bytes %s via pmm call to %04x:%04lx\n" , size, highmem ? "highmem" : "lowmem" , entry.seg, entry.offset); u16 res1, res2; |