A recent attempt to restrict the use of rfi on 64bit cpus in qemu broke 32bit OpenBIOS when run under a 970.
This patches memory to replace rfi instructions with rfid in the vector code.
Signed-off-by: Cédric Le Goater clg@kaod.org Suggested-by: Alexander Graf agraf@suse.de ---
Tested on qemu.
Changes since v3 :
- fix pointer comparison - make comments clearer
Changes since v2 :
- make it nicer
arch/ppc/qemu/ofmem.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+)
Index: openbios.git/arch/ppc/qemu/ofmem.c =================================================================== --- openbios.git.orig/arch/ppc/qemu/ofmem.c +++ openbios.git/arch/ppc/qemu/ofmem.c @@ -478,6 +478,36 @@ isi_exception(void) hash_page(nip, phys, mode); }
+/* + * Power ISA 2.x has deleted the rfi instruction and rfid shoud be + * used instead on cpus following this instruction set or later. + * + * OpenBIOS 32bits is compiled to use rfi. But, when it runs on a + * Power ISA 2.x cpu (a 970 for instance), we need to replace the rfi + * instructions with rfid in the vectors' memory section. Else we + * won't go any futher than the first exception ... + */ +#define RFI 0x4c000064 +#define RFID 0x4c000024 + +extern char __vectors[]; +extern char __vectors_end[]; + +static void patch_rfi(void) +{ + uint32_t* ptr; + uint32_t* vec_start = (uint32_t*) 0x100UL; + uint32_t* vec_end = (uint32_t*) (__vectors_end - __vectors); + + if (!is_ppc64()) + return; + + for (ptr = vec_start; ptr != vec_end; ptr++) { + if (*ptr == RFI) + *ptr = RFID; + } + flush_icache_range((char*) vec_start , (char*) vec_end); +}
/************************************************************************/ /* init / cleanup */ @@ -532,6 +562,8 @@ setup_mmu(unsigned long ramsize)
memcpy((void *)get_rom_base(), (void *)OF_CODE_START, OF_CODE_SIZE);
+ patch_rfi(); + /* Enable MMU */
mtmsr(mfmsr() | MSR_IR | MSR_DR);