Clean up use of SDR1 fields.
IBM's "The Programming Environments for 32-Bit Microprocessors": The HTABMASK field in SDR1 contains a mask value that determines how many bits from the hash are used in the page table index. This mask must be of the form 0b00...011...1; that is, a string of 0 bits followed by a string of 1bits. The 1 bits determine how many additional bits (at least 10) from the hash are used in the index; HTABORG must have this same number of low-order bits equal to 0.
IBM's "The Programming Environments Manual for 64-bit Microprocessors" 3.0: The HTABSIZE field in SDR1 contains an integer value that determines how many bits from the hash are used in the page table index. This number must not exceed 28. HTABSIZE is used to generate a mask of the form 0b00...011...1; that is, a string of 0 bits followed by a string of 1-bits. The 1-bits determine how many additional bits (beyond the minimum of 11) from the hash are used in the index. The HTABORG must have this same number of low-order bits equal to 0.
Adjust masks and shifts to 64-bit SDR1.
v2: * Use HTABSIZE for ppc64, fix HTABMASK usage for ppc. Error spotted by Segher.
Cc: Alexander Graf agraf@suse.de Cc: Segher Boessenkool segher@kernel.crashing.org Signed-off-by: Andreas Färber andreas.faerber@web.de --- Note: This breaks 32-bit ppc at least.
arch/ppc/qemu/ofmem.c | 31 ++++++++++++++++++++++--------- 1 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/arch/ppc/qemu/ofmem.c b/arch/ppc/qemu/ofmem.c index fd417c2..6f2b86d 100644 --- a/arch/ppc/qemu/ofmem.c +++ b/arch/ppc/qemu/ofmem.c @@ -48,7 +48,8 @@ extern void setup_mmu( unsigned long code_base ); #define OF_CODE_START 0xfff00000UL #define IO_BASE 0x80000000
-#define HASH_SIZE (2 << 15) +#define HASH_BITS 15 +#define HASH_SIZE (2 << HASH_BITS) #define OFMEM_SIZE (2 * 1024 * 1024)
#define SEGR_USER BIT(2) @@ -57,21 +58,29 @@ extern void setup_mmu( unsigned long code_base ); static inline unsigned long get_hash_base( void ) { - unsigned long sdr1; + unsigned long sdr1;
- asm volatile("mfsdr1 %0" : "=r" (sdr1) ); + asm volatile("mfsdr1 %0" : "=r" (sdr1) );
- return (sdr1 & 0xffff0000); +#ifdef __powerpc64__ + return (sdr1 & 0x3FFFFFFFFFFC0000UL); +#else + return (sdr1 & 0xffff0000UL); +#endif }
static inline unsigned long get_hash_size( void ) { - unsigned long sdr1; + unsigned long sdr1;
- asm volatile("mfsdr1 %0" : "=r" (sdr1) ); + asm volatile("mfsdr1 %0" : "=r" (sdr1));
- return ((sdr1 << 16) | 0x0000ffff) + 1; +#ifdef __powerpc64__ + return 1UL << (sdr1 & 0x1f); +#else + return (((sdr1 & 0x1ff) << 10) | 0x3ff) + 1; +#endif }
static inline unsigned long @@ -389,14 +398,18 @@ setup_mmu( unsigned long ramsize ) ofmem_t *ofmem; unsigned long sdr1, sr_base, msr; unsigned long hash_base; - unsigned long hash_mask = 0xfff00000; /* alignment for ppc64 */ + unsigned long hash_mask = ~0x000fffffUL; /* alignment for ppc64 */ int i;
/* SDR1: Storage Description Register 1 */
hash_base = (ramsize - 0x00100000 - HASH_SIZE) & hash_mask; memset((void *)hash_base, 0, HASH_SIZE); - sdr1 = hash_base | ((HASH_SIZE-1) >> 16); +#ifdef __powerpc64__ + sdr1 = hash_base | HASH_BITS; +#else + sdr1 = hash_base | ((HASH_SIZE - 1) >> 10); +#endif asm volatile("mtsdr1 %0" :: "r" (sdr1) );
/* Segment Register */