target/ppc: atomic path of Load Quadword instruction require address with write permission
Programs running on qemu-system-ppc64 with accel TCG and more than one core receive SIGSEGV when LQ is executed if the memory address does not have write permission. The oldest version of qemu I've been able to test so far, 5.2.50, already had the problem:
- Run qemu-system-ppc64 with -smp 2:
$ qemu-system-ppc64 -cpu power9 -accel tcg -smp 4 -m 4G -device virtio-scsi-pci -drive file=Debian10.qcow2,if=none,format=qcow2,id=hd0 -device scsi-hd,drive=hd0 -boot c -vga none -nographic
- Build and run the following code:
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main(void)
{
char *str = "0123456789ABCDEF";
uint64_t a = 0, b = 0;
asm("lq 4, %2 \n\t"
"mr %0, 4 \n\t"
"mr %1, 5 \n\t"
: "=r" (a), "=r" (b)
: "m" (*str)
: "r4", "r5");
printf("a=0x%"PRIx64"\nb=0x%"PRIx64"\n", a, b);
return 0;
}
The same program runs OK on qemu-ppc64{,le}, with -smp 1, and on real hardware. It also gives no error if str is declared as char str[] = "..."
.
When the problem occurs, ppc_radix64_check_prot
return true because need_prot
is 2 and prot
is 5. The same happens in ppc_hash64_handle_mmu_fault
when "disable_radix" is appended to the kernel cmdline.