[PATCH v3] ppc: use rfid when running under a CPU from the 970 family.

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 v2 : - make it nicer arch/ppc/qemu/ofmem.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 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,30 @@ isi_exception(void) hash_page(nip, phys, mode); } +/* When running on ppc64, we cannot use rfi anymore. Let's patch the + * vectors to use rfid instead. + */ +#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 +556,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);

Am 22.06.2016 um 09:29 schrieb Cédric Le Goater <clg@kaod.org>:
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 v2 :
- make it nicer
arch/ppc/qemu/ofmem.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 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,30 @@ isi_exception(void) hash_page(nip, phys, mode); }
+/* When running on ppc64, we cannot use rfi anymore. Let's patch the + * vectors to use rfid instead.
Please use /* * Comments like this */ and explain exactly why "we can not use rfi anymore", so that someone looking at the code in 5 years will still know what's going on.
+ */ +#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++) {
Last time I asked < was not really defined for pointers. You can only match (==, !=) or convert to numbers (uintptr_t) them. The smaller comparison might work for now, but I can't guarantee it won't break in gcc7 or so. In short, please just make it != :). Alex
+ if (*ptr == RFI) + *ptr = RFID; + } + flush_icache_range((char*) vec_start , (char*) vec_end); +}
/************************************************************************/ /* init / cleanup */ @@ -532,6 +556,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);

On 06/22/2016 09:41 AM, Alexander Graf wrote:
Am 22.06.2016 um 09:29 schrieb Cédric Le Goater <clg@kaod.org>:
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 v2 :
- make it nicer
arch/ppc/qemu/ofmem.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 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,30 @@ isi_exception(void) hash_page(nip, phys, mode); }
+/* When running on ppc64, we cannot use rfi anymore. Let's patch the + * vectors to use rfid instead.
Please use
/* * Comments like this */
and explain exactly why "we can not use rfi anymore", so that someone looking at the code in 5 years will still know what's going on.
yep.
+ */ +#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++) {
Last time I asked < was not really defined for pointers. You can only match (==, !=) or convert to numbers (uintptr_t) them. The smaller comparison might work for now, but I can't guarantee it won't break in gcc7 or so.
oh yes. that is true.
In short, please just make it != :).
Thanks, C.
Alex
+ if (*ptr == RFI) + *ptr = RFID; + } + flush_icache_range((char*) vec_start , (char*) vec_end); +}
/************************************************************************/ /* init / cleanup */ @@ -532,6 +556,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);
participants (2)
-
Alexander Graf
-
Cédric Le Goater