Commit 962a7e51 authored by Anton Blanchard's avatar Anton Blanchard

ppc64: updates from Dave Engebretsen in 2.4

parent 46609240
...@@ -50,6 +50,13 @@ ...@@ -50,6 +50,13 @@
/* /*
* Note: pte --> Linux PTE * Note: pte --> Linux PTE
* HPTE --> PowerPC Hashed Page Table Entry * HPTE --> PowerPC Hashed Page Table Entry
*
* Execution context:
* htab_initialize is called with the MMU off (of course), but
* the kernel has been copied down to zero so it can directly
* reference global data. At this point it is very difficult
* to print debug info.
*
*/ */
HTAB htab_data = {NULL, 0, 0, 0, 0}; HTAB htab_data = {NULL, 0, 0, 0, 0};
...@@ -57,20 +64,23 @@ HTAB htab_data = {NULL, 0, 0, 0, 0}; ...@@ -57,20 +64,23 @@ HTAB htab_data = {NULL, 0, 0, 0, 0};
extern unsigned long _SDR1; extern unsigned long _SDR1;
extern unsigned long klimit; extern unsigned long klimit;
extern unsigned long reloc_offset(void);
#define PTRRELOC(x) ((typeof(x))((unsigned long)(x) - offset))
#define PTRUNRELOC(x) ((typeof(x))((unsigned long)(x) + offset))
#define RELOC(x) (*PTRRELOC(&(x)))
#define KB (1024) #define KB (1024)
#define MB (1024*KB) #define MB (1024*KB)
static inline void
loop_forever(void)
{
volatile unsigned long x = 1;
for(;x;x|=1)
;
}
static inline void static inline void
create_pte_mapping(unsigned long start, unsigned long end, create_pte_mapping(unsigned long start, unsigned long end,
unsigned long mode, unsigned long mask, int large) unsigned long mode, unsigned long mask, int large)
{ {
unsigned long addr, offset = reloc_offset(); unsigned long addr;
HTAB *_htab_data = PTRRELOC(&htab_data); HPTE *htab = (HPTE *)__v2a(htab_data.htab);
HPTE *htab = (HPTE *)__v2a(_htab_data->htab);
unsigned int step; unsigned int step;
if (large) if (large)
...@@ -96,15 +106,12 @@ htab_initialize(void) ...@@ -96,15 +106,12 @@ htab_initialize(void)
unsigned long table, htab_size_bytes; unsigned long table, htab_size_bytes;
unsigned long pteg_count; unsigned long pteg_count;
unsigned long mode_rw, mask; unsigned long mode_rw, mask;
unsigned long offset = reloc_offset();
struct naca_struct *_naca = RELOC(naca);
HTAB *_htab_data = PTRRELOC(&htab_data);
/* /*
* Calculate the required size of the htab. We want the number of * Calculate the required size of the htab. We want the number of
* PTEGs to equal one half the number of real pages. * PTEGs to equal one half the number of real pages.
*/ */
htab_size_bytes = 1UL << _naca->pftSize; htab_size_bytes = 1UL << naca->pftSize;
pteg_count = htab_size_bytes >> 7; pteg_count = htab_size_bytes >> 7;
/* For debug, make the HTAB 1/8 as big as it normally would be. */ /* For debug, make the HTAB 1/8 as big as it normally would be. */
...@@ -113,41 +120,44 @@ htab_initialize(void) ...@@ -113,41 +120,44 @@ htab_initialize(void)
htab_size_bytes = pteg_count << 7; htab_size_bytes = pteg_count << 7;
} }
_htab_data->htab_num_ptegs = pteg_count; htab_data.htab_num_ptegs = pteg_count;
_htab_data->htab_hash_mask = pteg_count - 1; htab_data.htab_hash_mask = pteg_count - 1;
if (naca->platform == PLATFORM_PSERIES) { if (naca->platform == PLATFORM_PSERIES) {
/* Find storage for the HPT. Must be contiguous in /* Find storage for the HPT. Must be contiguous in
* the absolute address space. * the absolute address space.
*/ */
table = lmb_alloc(htab_size_bytes, htab_size_bytes); table = lmb_alloc(htab_size_bytes, htab_size_bytes);
if ( !table ) if ( !table ) {
panic("ERROR, cannot find space for HPTE\n"); ppc64_terminate_msg(0x20, "hpt space");
_htab_data->htab = (HPTE *)__a2v(table); loop_forever();
}
htab_data.htab = (HPTE *)__a2v(table);
/* htab absolute addr + encoded htabsize */ /* htab absolute addr + encoded htabsize */
RELOC(_SDR1) = table + __ilog2(pteg_count) - 11; _SDR1 = table + __ilog2(pteg_count) - 11;
/* Initialize the HPT with no entries */ /* Initialize the HPT with no entries */
memset((void *)table, 0, htab_size_bytes); memset((void *)table, 0, htab_size_bytes);
} else { } else {
_htab_data->htab = NULL; /* Using a hypervisor which owns the htab */
RELOC(_SDR1) = 0; htab_data.htab = NULL;
_SDR1 = 0;
} }
mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX; mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
mask = pteg_count-1; mask = pteg_count-1;
/* XXX we currently map kernel text rw, should fix this */ /* XXX we currently map kernel text rw, should fix this */
if (cpu_has_largepage() && _naca->physicalMemorySize > 256*MB) { if (cpu_has_largepage() && naca->physicalMemorySize > 256*MB) {
create_pte_mapping((unsigned long)KERNELBASE, create_pte_mapping((unsigned long)KERNELBASE,
KERNELBASE + 256*MB, mode_rw, mask, 0); KERNELBASE + 256*MB, mode_rw, mask, 0);
create_pte_mapping((unsigned long)KERNELBASE + 256*MB, create_pte_mapping((unsigned long)KERNELBASE + 256*MB,
KERNELBASE + (_naca->physicalMemorySize), KERNELBASE + (naca->physicalMemorySize),
mode_rw, mask, 1); mode_rw, mask, 1);
} else { } else {
create_pte_mapping((unsigned long)KERNELBASE, create_pte_mapping((unsigned long)KERNELBASE,
KERNELBASE+(_naca->physicalMemorySize), KERNELBASE+(naca->physicalMemorySize),
mode_rw, mask, 0); mode_rw, mask, 0);
} }
} }
...@@ -300,7 +310,7 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid, ...@@ -300,7 +310,7 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
hpteflags = (pte_val(new_pte) & 0x1f8) | newpp; hpteflags = (pte_val(new_pte) & 0x1f8) | newpp;
/* XXX fix large pte flag */ /* XXX fix large pte flag */
slot = ppc_md.insert_hpte(hpte_group, vpn, prpn, 0, slot = ppc_md.hpte_insert(hpte_group, vpn, prpn, 0,
hpteflags, 0, 0); hpteflags, 0, 0);
/* Primary is full, try the secondary */ /* Primary is full, try the secondary */
...@@ -309,13 +319,13 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid, ...@@ -309,13 +319,13 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
hpte_group = ((~hash & htab_data.htab_hash_mask) * hpte_group = ((~hash & htab_data.htab_hash_mask) *
HPTES_PER_GROUP) & ~0x7UL; HPTES_PER_GROUP) & ~0x7UL;
/* XXX fix large pte flag */ /* XXX fix large pte flag */
slot = ppc_md.insert_hpte(hpte_group, vpn, prpn, slot = ppc_md.hpte_insert(hpte_group, vpn, prpn,
1, hpteflags, 0, 0); 1, hpteflags, 0, 0);
if (slot == -1) { if (slot == -1) {
if (mftb() & 0x1) if (mftb() & 0x1)
hpte_group = ((hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; hpte_group = ((hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL;
ppc_md.remove_hpte(hpte_group); ppc_md.hpte_remove(hpte_group);
goto repeat; goto repeat;
} }
} }
...@@ -363,21 +373,20 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) ...@@ -363,21 +373,20 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
vsid = get_kernel_vsid(ea); vsid = get_kernel_vsid(ea);
break; break;
case IO_UNMAPPED_REGION_ID: case IO_UNMAPPED_REGION_ID:
udbg_printf("EEH Error ea = 0x%lx\n", ea); /*
PPCDBG_ENTER_DEBUGGER(); * Should only be hit if there is an access to MMIO space
panic("EEH Error ea = 0x%lx\n", ea); * which is protected by EEH.
break; * Send the problem up to do_page_fault
*/
case KERNEL_REGION_ID: case KERNEL_REGION_ID:
/* /*
* As htab_initialize is now, we shouldn't ever get here since * Should never get here - entire 0xC0... region is bolted.
* we're bolting the entire 0xC0... region. * Send the problem up to do_page_fault
*/ */
udbg_printf("Little faulted on kernel address 0x%lx\n", ea);
PPCDBG_ENTER_DEBUGGER();
panic("Little faulted on kernel address 0x%lx\n", ea);
break;
default: default:
/* Not a valid range, send the problem up to do_page_fault */ /* Not a valid range
* Send the problem up to do_page_fault
*/
return 1; return 1;
break; break;
} }
......
...@@ -86,7 +86,7 @@ static inline void pSeries_unlock_hpte(HPTE *hptep) ...@@ -86,7 +86,7 @@ static inline void pSeries_unlock_hpte(HPTE *hptep)
static spinlock_t pSeries_tlbie_lock = SPIN_LOCK_UNLOCKED; static spinlock_t pSeries_tlbie_lock = SPIN_LOCK_UNLOCKED;
static long pSeries_insert_hpte(unsigned long hpte_group, unsigned long vpn, static long pSeries_hpte_insert(unsigned long hpte_group, unsigned long vpn,
unsigned long prpn, int secondary, unsigned long prpn, int secondary,
unsigned long hpteflags, int bolted, int large) unsigned long hpteflags, int bolted, int large)
{ {
...@@ -144,7 +144,7 @@ static long pSeries_insert_hpte(unsigned long hpte_group, unsigned long vpn, ...@@ -144,7 +144,7 @@ static long pSeries_insert_hpte(unsigned long hpte_group, unsigned long vpn,
return i; return i;
} }
static long pSeries_remove_hpte(unsigned long hpte_group) static long pSeries_hpte_remove(unsigned long hpte_group)
{ {
HPTE *hptep; HPTE *hptep;
Hpte_dword0 dw0; Hpte_dword0 dw0;
...@@ -455,8 +455,8 @@ void hpte_init_pSeries(void) ...@@ -455,8 +455,8 @@ void hpte_init_pSeries(void)
ppc_md.hpte_invalidate = pSeries_hpte_invalidate; ppc_md.hpte_invalidate = pSeries_hpte_invalidate;
ppc_md.hpte_updatepp = pSeries_hpte_updatepp; ppc_md.hpte_updatepp = pSeries_hpte_updatepp;
ppc_md.hpte_updateboltedpp = pSeries_hpte_updateboltedpp; ppc_md.hpte_updateboltedpp = pSeries_hpte_updateboltedpp;
ppc_md.insert_hpte = pSeries_insert_hpte; ppc_md.hpte_insert = pSeries_hpte_insert;
ppc_md.remove_hpte = pSeries_remove_hpte; ppc_md.hpte_remove = pSeries_hpte_remove;
ppc_md.make_pte = pSeries_make_pte; ppc_md.make_pte = pSeries_make_pte;
/* Disable TLB batching on nighthawk */ /* Disable TLB batching on nighthawk */
......
...@@ -457,7 +457,7 @@ void pSeries_lpar_make_pte(HPTE *htab, unsigned long va, unsigned long pa, ...@@ -457,7 +457,7 @@ void pSeries_lpar_make_pte(HPTE *htab, unsigned long va, unsigned long pa,
*/ */
} }
static long pSeries_lpar_insert_hpte(unsigned long hpte_group, static long pSeries_lpar_hpte_insert(unsigned long hpte_group,
unsigned long vpn, unsigned long prpn, unsigned long vpn, unsigned long prpn,
int secondary, unsigned long hpteflags, int secondary, unsigned long hpteflags,
int bolted, int large) int bolted, int large)
...@@ -522,7 +522,7 @@ static long pSeries_lpar_insert_hpte(unsigned long hpte_group, ...@@ -522,7 +522,7 @@ static long pSeries_lpar_insert_hpte(unsigned long hpte_group,
static spinlock_t pSeries_lpar_tlbie_lock = SPIN_LOCK_UNLOCKED; static spinlock_t pSeries_lpar_tlbie_lock = SPIN_LOCK_UNLOCKED;
static long pSeries_lpar_remove_hpte(unsigned long hpte_group) static long pSeries_lpar_hpte_remove(unsigned long hpte_group)
{ {
unsigned long slot_offset; unsigned long slot_offset;
unsigned long lpar_rc; unsigned long lpar_rc;
...@@ -695,11 +695,11 @@ void pSeries_lpar_flush_hash_range(unsigned long context, unsigned long number, ...@@ -695,11 +695,11 @@ void pSeries_lpar_flush_hash_range(unsigned long context, unsigned long number,
void pSeries_lpar_mm_init(void) void pSeries_lpar_mm_init(void)
{ {
ppc_md.hpte_invalidate = pSeries_lpar_hpte_invalidate; ppc_md.hpte_invalidate = pSeries_lpar_hpte_invalidate;
ppc_md.hpte_updatepp = pSeries_lpar_hpte_updatepp; ppc_md.hpte_updatepp = pSeries_lpar_hpte_updatepp;
ppc_md.hpte_updateboltedpp = pSeries_lpar_hpte_updateboltedpp; ppc_md.hpte_updateboltedpp = pSeries_lpar_hpte_updateboltedpp;
ppc_md.insert_hpte = pSeries_lpar_insert_hpte; ppc_md.hpte_insert = pSeries_lpar_hpte_insert;
ppc_md.remove_hpte = pSeries_lpar_remove_hpte; ppc_md.hpte_remove = pSeries_lpar_hpte_remove;
ppc_md.make_pte = pSeries_lpar_make_pte; ppc_md.make_pte = pSeries_lpar_make_pte;
ppc_md.flush_hash_range = pSeries_lpar_flush_hash_range; ppc_md.flush_hash_range = pSeries_lpar_flush_hash_range;
} }
...@@ -116,8 +116,6 @@ udbg_puts(const char *s) ...@@ -116,8 +116,6 @@ udbg_puts(const char *s)
if (s && *s != '\0') { if (s && *s != '\0') {
while ((c = *s++) != '\0') while ((c = *s++) != '\0')
ppc_md.udbg_putc(c); ppc_md.udbg_putc(c);
} else {
udbg_puts("NULL");
} }
} else { } else {
printk("%s", s); printk("%s", s);
...@@ -135,8 +133,7 @@ udbg_write(const char *s, int n) ...@@ -135,8 +133,7 @@ udbg_write(const char *s, int n)
while ( (( c = *s++ ) != '\0') && (remain-- > 0)) { while ( (( c = *s++ ) != '\0') && (remain-- > 0)) {
ppc_md.udbg_putc(c); ppc_md.udbg_putc(c);
} }
} else }
udbg_puts("NULL");
return n - remain; return n - remain;
} }
......
...@@ -40,14 +40,14 @@ struct machdep_calls { ...@@ -40,14 +40,14 @@ struct machdep_calls {
int large); int large);
void (*hpte_updateboltedpp)(unsigned long newpp, void (*hpte_updateboltedpp)(unsigned long newpp,
unsigned long ea); unsigned long ea);
long (*insert_hpte)(unsigned long hpte_group, long (*hpte_insert)(unsigned long hpte_group,
unsigned long vpn, unsigned long vpn,
unsigned long prpn, unsigned long prpn,
int secondary, int secondary,
unsigned long hpteflags, unsigned long hpteflags,
int bolted, int bolted,
int large); int large);
long (*remove_hpte)(unsigned long hpte_group); long (*hpte_remove)(unsigned long hpte_group);
void (*flush_hash_range)(unsigned long context, void (*flush_hash_range)(unsigned long context,
unsigned long number, unsigned long number,
int local); int local);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment