Message ID | 7ea8b1211bceb8193154b51ad4241e7c0b86547d.1567326213.git.noring@nocrew.org (mailing list archive) |
---|---|
State | RFC |
Headers | show |
Series | Linux for the PlayStation 2 | expand |
在 2019/9/1 23:46, Fredrik Noring 写道: > PlayStation 2 hardware such as the Graphics Synthesizer requires 64-bit > register reads and writes[1], also in 32-bit kernels. Interrupts must be > disabled when manipulating 64-bit registers unless the kernel saves and > restores 64-bit registers in the interrupt and context switch handlers. Hi Fredrik, Why don't we just build a 64bit kernel rather than do these hacks? Any hardware/firmware issue blocks 64bit kernel? -- Jiaxun Yang > References: > > [1] "EE User's Manual", version 6.0, Sony Computer Entertainment Inc., > p. 26: GS privileged registers must be accessed using LD/SD > instructions. > > Signed-off-by: Fredrik Noring<noring@nocrew.org> > ---
On Wed, 4 Sep 2019, Jiaxun Yang wrote: > > PlayStation 2 hardware such as the Graphics Synthesizer requires 64-bit > > register reads and writes[1], also in 32-bit kernels. Interrupts must be > > disabled when manipulating 64-bit registers unless the kernel saves and > > restores 64-bit registers in the interrupt and context switch handlers. > > Hi Fredrik, > > Why don't we just build a 64bit kernel rather than do these hacks? > > Any hardware/firmware issue blocks 64bit kernel? One issue I recall with the R5900 is $pc is 32-bit (as if with CP0.Status.PX=1 on modern hardware) and is zero- rather than sign-extended when copied to a GPR with instructions like JALR, BLTZAL, etc. This is contrary to MIPS architecture requirements and unlike other 64-bit MIPS processors. This does not cause an issue in the user mode (because USEG addresses have bit #31 set to 0 anyway) or with the JR and JALR instructions (because these ignore the upper 32 bits in the source GPR). This however breaks in the kernel mode whenever the value retrieved from $pc is used for any kind of calculation, meaning that the kernel will have to be audited for such use before we can run 64-bit kernel code. This means it's much easier to have a 32-bit kernel running, with a small and simple sanitanisation change posted as 003/120, and have all the platform and driver infrastructure verified before this processor quirk is addressed. Maciej
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index 97a280640daf..f7115472f530 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -420,10 +420,32 @@ static inline void pfx##out##bwlq##p(type val, unsigned long port) \ \ __val = pfx##ioswab##bwlq(__addr, val); \ \ - /* Really, we want this to be atomic */ \ - BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \ + if (sizeof(type) != sizeof(u64) || sizeof(u64) == sizeof(long)) { \ + *__addr = __val; \ + } else if (cpu_has_64bits) { \ + unsigned long __flags; \ + type __tmp; \ \ - *__addr = __val; \ + /* Manipulating 64-bit registers in a 32-bit kernel */ \ + /* requires disabling interrupts, since only 32-bit */ \ + /* registers are saved/restored by interrupts. */ \ + local_irq_save(__flags); \ + __asm__ __volatile__( \ + ".set push" "\t\t# __writeq""\n\t" \ + ".set mips3" "\n\t" \ + "dsll32 %L0, %L0, 0" "\n\t" \ + "dsrl32 %L0, %L0, 0" "\n\t" \ + "dsll32 %M0, %M0, 0" "\n\t" \ + "or %L0, %L0, %M0" "\n\t" \ + "sd %L0, %2" "\n\t" \ + "sll %L0, %L0, 0" "\n\t" \ + "sll %M0, %M0, 0" "\n\t" \ + ".set pop" "\n" \ + : "=r" (__tmp) \ + : "0" (__val), "m" (*__addr)); \ + local_irq_restore(__flags); \ + } else \ + BUG(); \ } \ \ static inline type pfx##in##bwlq##p(unsigned long port) \ @@ -433,12 +455,30 @@ static inline type pfx##in##bwlq##p(unsigned long port) \ \ __addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \ \ - BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long)); \ - \ if (barrier) \ iobarrier_rw(); \ \ - __val = *__addr; \ + if (sizeof(type) != sizeof(u64) || sizeof(u64) == sizeof(long)) { \ + __val = *__addr; \ + } else if (cpu_has_64bits) { \ + unsigned long __flags; \ + \ + /* Manipulating 64-bit registers in a 32-bit kernel */ \ + /* requires disabling interrupts, since only 32-bit */ \ + /* registers are saved/restored by interrupts. */ \ + local_irq_save(__flags); \ + __asm__ __volatile__( \ + ".set push" "\t\t# __outq" "\n\t" \ + ".set mips3" "\n\t" \ + "ld %L0, %1" "\n\t" \ + "dsra32 %M0, %L0, 0" "\n\t" \ + "sll %L0, %L0, 0" "\n\t" \ + ".set pop" "\n" \ + : "=r" (__val) \ + : "m" (*__addr)); \ + local_irq_restore(__flags); \ + } else \ + BUG(); \ \ /* prevent prefetching of coherent DMA data prematurely */ \ if (!relax) \ @@ -478,7 +518,7 @@ __BUILD_MEMORY_PFX(__mem_, q, u64, 0) BUILDIO_IOPORT(b, u8) BUILDIO_IOPORT(w, u16) BUILDIO_IOPORT(l, u32) -#ifdef CONFIG_64BIT +#if defined(CONFIG_64BIT) || defined(CONFIG_CPU_R5900) BUILDIO_IOPORT(q, u64) #endif
PlayStation 2 hardware such as the Graphics Synthesizer requires 64-bit register reads and writes[1], also in 32-bit kernels. Interrupts must be disabled when manipulating 64-bit registers unless the kernel saves and restores 64-bit registers in the interrupt and context switch handlers. References: [1] "EE User's Manual", version 6.0, Sony Computer Entertainment Inc., p. 26: GS privileged registers must be accessed using LD/SD instructions. Signed-off-by: Fredrik Noring <noring@nocrew.org> --- arch/mips/include/asm/io.h | 54 +++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 7 deletions(-)