Author: agraf Date: Sun Jan 6 14:29:59 2013 New Revision: 1081 URL: http://tracker.coreboot.org/trac/openbios/changeset/1081
Log: PPC: Fix next slot eviction
This patch fixes next slot eviction in the MMU code when our HTAB is full.
The basic problem behind this is that the next slot id is stored in .bss which is automatically resolved to an address that resides in a r/o area.
This is not an issue usually, because in virtual addressing mode OpenBIOS swizzles accesses to the r/o ROM area to the r/w shadow in RAM. But since the MMU code runs in real mode, this logic doesn't apply.
The solution is simple: Access the global variable using its shadowed address, not the ROM address.
Based upon an original patch by
Mark Cave-Ayland mark.cave-ayland@ilande.co.uk
Signed-off-by: Alexander Graf agraf@suse.de
Modified: trunk/openbios-devel/arch/ppc/qemu/ofmem.c
Modified: trunk/openbios-devel/arch/ppc/qemu/ofmem.c ============================================================================== --- trunk/openbios-devel/arch/ppc/qemu/ofmem.c Thu Dec 13 22:30:25 2012 (r1080) +++ trunk/openbios-devel/arch/ppc/qemu/ofmem.c Sun Jan 6 14:29:59 2013 (r1081) @@ -311,10 +311,32 @@ return phys; }
+/* Converts a global variable (from .data or .bss) into a pointer that + can be accessed from real mode */ +static void * +global_ptr_real(void *p) +{ + return (void*)((uintptr_t)p - OF_CODE_START + get_rom_base()); +} + +/* Return the next slot to evict, in the range of [0..7] */ +static int +next_evicted_slot(void) +{ + static int next_grab_slot; + int *next_grab_slot_va; + int r; + + next_grab_slot_va = global_ptr_real(&next_grab_slot); + r = *next_grab_slot_va; + *next_grab_slot_va = (r + 1) % 8; + + return r; +} + static void hash_page_64(unsigned long ea, phys_addr_t phys, ucell mode) { - static int next_grab_slot = 0; uint64_t vsid_mask, page_mask, pgidx, hash; uint64_t htab_mask, mask, avpn; unsigned long pgaddr; @@ -349,10 +371,8 @@ found = 1;
/* out of slots, just evict one */ - if (!found) { - i = next_grab_slot + 1; - next_grab_slot = (next_grab_slot + 1) % 8; - } + if (!found) + i = next_evicted_slot() + 1; i--; { mPTE_64_t p = { @@ -381,7 +401,6 @@ hash_page_32(unsigned long ea, phys_addr_t phys, ucell mode) { #ifndef __powerpc64__ - static int next_grab_slot = 0; unsigned long *upte, cmp, hash1; int i, vsid, found; mPTE_t *pp; @@ -407,10 +426,8 @@ found = 1;
/* out of slots, just evict one */ - if (!found) { - i = next_grab_slot + 1; - next_grab_slot = (next_grab_slot + 1) % 8; - } + if (!found) + i = next_evicted_slot() + 1; i--; upte[i * 2] = cmp; upte[i * 2 + 1] = (phys & ~0xfff) | mode;