diff options
Diffstat (limited to 'sys/arch/powerpc')
-rw-r--r-- | sys/arch/powerpc/include/cpu.h | 11 | ||||
-rw-r--r-- | sys/arch/powerpc/powerpc/pmap.c | 103 |
2 files changed, 107 insertions, 7 deletions
diff --git a/sys/arch/powerpc/include/cpu.h b/sys/arch/powerpc/include/cpu.h index de9c477b74a..5a270eca04f 100644 --- a/sys/arch/powerpc/include/cpu.h +++ b/sys/arch/powerpc/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.32 2007/12/04 22:36:39 kettenis Exp $ */ +/* $OpenBSD: cpu.h,v 1.33 2008/04/26 22:37:41 drahn Exp $ */ /* $NetBSD: cpu.h,v 1.1 1996/09/30 16:34:21 ws Exp $ */ /* @@ -57,6 +57,7 @@ struct cpu_info { volatile int ci_cpl; volatile int ci_iactive; volatile int ci_ipending; + int ci_intrdepth; char *ci_intstk; #define CPUSAVE_LEN 8 @@ -64,6 +65,14 @@ struct cpu_info { register_t ci_ddbsave[CPUSAVE_LEN]; #define DISISAVE_LEN 4 register_t ci_disisave[DISISAVE_LEN]; + + volatile u_int64_t ci_nexttimerevent; + volatile u_int64_t ci_prevtb; + volatile u_int64_t ci_lasttb; + volatile u_int64_t ci_nextstatevent; + int ci_statspending; + + u_long ci_randseed; }; static __inline struct cpu_info * diff --git a/sys/arch/powerpc/powerpc/pmap.c b/sys/arch/powerpc/powerpc/pmap.c index fbd61b827fe..e2cedd6a540 100644 --- a/sys/arch/powerpc/powerpc/pmap.c +++ b/sys/arch/powerpc/powerpc/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.103 2007/11/04 13:43:39 martin Exp $ */ +/* $OpenBSD: pmap.c,v 1.104 2008/04/26 22:37:41 drahn Exp $ */ /* * Copyright (c) 2001, 2002, 2007 Dale Rahn. @@ -48,6 +48,8 @@ #include <ddb/db_extern.h> #include <ddb/db_output.h> +#include <powerpc/lock.h> + struct pmap kernel_pmap_; static struct mem_region *pmap_mem, *pmap_avail; struct mem_region pmap_allocated[10]; @@ -154,6 +156,64 @@ int pmap_initialized = 0; int physmem; int physmaxaddr; +void pmap_hash_lock_init(void); +void pmap_hash_lock(int entry); +void pmap_hash_unlock(int entry); +int pmap_hash_lock_try(int entry); + +volatile unsigned int pmap_hash_lock_word = 0; + +void +pmap_hash_lock_init() +{ + pmap_hash_lock_word = 0; +} + +int +pmap_hash_lock_try(int entry) +{ + int val = 1 << entry; + int success, tmp; + __asm volatile ( + "1: lwarx %0, 0, %3 \n" + " and. %1, %2, %0 \n" + " li %1, 0 \n" + " bne 2f \n" + " or %0, %2, %0 \n" + " stwcx. %0, 0, %3 \n" + " li %1, 1 \n" + " bne- 1b \n" + "2: \n" + : "=&r" (tmp), "=&r" (success) + : "r" (val), "r" (&pmap_hash_lock_word) + : "memory"); + return success; +} + + +void +pmap_hash_lock(int entry) +{ + int attempt = 0; + int locked = 0; + do { + if (pmap_hash_lock_word & (1 << entry)) { + attempt++; + if(attempt >0x20000000) + panic("unable to obtain lock on entry %d\n", + entry); + continue; + } + locked = pmap_hash_lock_try(entry); + } while (locked == 0); +} + +void +pmap_hash_unlock(int entry) +{ + atomic_clearbits_int(&pmap_hash_lock_word, 1 << entry); +} + /* virtual to physical helpers */ static inline int VP_SR(vaddr_t va) @@ -828,8 +888,10 @@ pmap_hash_remove(struct pte_desc *pted) /* determine which pteg mapping is present in */ if (ppc_proc_is_64b) { + int entry = PTED_PTEGIDX(pted); ptp64 = pmap_ptable64 + (idx * 8); - ptp64 += PTED_PTEGIDX(pted); /* increment by index into pteg */ + ptp64 += entry; /* increment by entry into pteg */ + pmap_hash_lock(entry); /* * We now have the pointer to where it will be, if it is * currently mapped. If the mapping was thrown away in @@ -840,9 +902,12 @@ pmap_hash_remove(struct pte_desc *pted) (PTED_HID(pted) ? PTE_HID_64 : 0)) == ptp64->pte_hi) { pte_zap((void*)ptp64, pted); } + pmap_hash_unlock(entry); } else { + int entry = PTED_PTEGIDX(pted); ptp32 = pmap_ptable32 + (idx * 8); - ptp32 += PTED_PTEGIDX(pted); /* increment by index into pteg */ + ptp32 += entry; /* increment by entry into pteg */ + pmap_hash_lock(entry); /* * We now have the pointer to where it will be, if it is * currently mapped. If the mapping was thrown away in @@ -853,6 +918,7 @@ pmap_hash_remove(struct pte_desc *pted) (PTED_HID(pted) ? PTE_HID_32 : 0)) == ptp32->pte_hi) { pte_zap((void*)ptp32, pted); } + pmap_hash_unlock(entry); } } @@ -2267,7 +2333,6 @@ pte_insert64(struct pte_desc *pted) int sr, idx; int i; - /* HASH lock? */ sr = ptesr(pted->pted_pmap->pm_sr, pted->pted_va); idx = pteidx(sr, pted->pted_va); @@ -2293,6 +2358,8 @@ pte_insert64(struct pte_desc *pted) for (i = 0; i < 8; i++) { if (ptp64[i].pte_hi & PTE_VALID_64) continue; + if (pmap_hash_lock_try(i) == 0) + continue; /* not valid, just load */ pted->pted_va |= i; @@ -2302,6 +2369,8 @@ pte_insert64(struct pte_desc *pted) __asm__ volatile ("sync"); ptp64[i].pte_hi |= PTE_VALID_64; __asm volatile ("sync"); + + pmap_hash_unlock(i); return; } /* try fill of secondary hash */ @@ -2309,6 +2378,8 @@ pte_insert64(struct pte_desc *pted) for (i = 0; i < 8; i++) { if (ptp64[i].pte_hi & PTE_VALID_64) continue; + if (pmap_hash_lock_try(i) == 0) + continue; pted->pted_va |= (i | PTED_VA_HID_M); ptp64[i].pte_hi = @@ -2317,12 +2388,19 @@ pte_insert64(struct pte_desc *pted) __asm__ volatile ("sync"); ptp64[i].pte_hi |= PTE_VALID_64; __asm volatile ("sync"); + + pmap_hash_unlock(i); return; } /* need decent replacement algorithm */ +busy: __asm__ volatile ("mftb %0" : "=r"(off)); secondary = off & 8; + + if (pmap_hash_lock_try(off & 7) == 0) + goto busy; + pted->pted_va |= off & (PTED_VA_PTEGIDX_M|PTED_VA_HID_M); idx = (idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0)); @@ -2362,6 +2440,8 @@ pte_insert64(struct pte_desc *pted) ptp64->pte_lo = pted->p.pted_pte64.pte_lo; __asm__ volatile ("sync"); ptp64->pte_hi |= PTE_VALID_64; + + pmap_hash_unlock(off & 7); } void @@ -2373,8 +2453,6 @@ pte_insert32(struct pte_desc *pted) int sr, idx; int i; - /* HASH lock? */ - sr = ptesr(pted->pted_pmap->pm_sr, pted->pted_va); idx = pteidx(sr, pted->pted_va); @@ -2401,6 +2479,8 @@ pte_insert32(struct pte_desc *pted) for (i = 0; i < 8; i++) { if (ptp32[i].pte_hi & PTE_VALID_32) continue; + if (pmap_hash_lock_try(i) == 0) + continue; /* not valid, just load */ pted->pted_va |= i; @@ -2409,6 +2489,8 @@ pte_insert32(struct pte_desc *pted) __asm__ volatile ("sync"); ptp32[i].pte_hi |= PTE_VALID_32; __asm volatile ("sync"); + + pmap_hash_unlock(i); return; } /* try fill of secondary hash */ @@ -2416,6 +2498,8 @@ pte_insert32(struct pte_desc *pted) for (i = 0; i < 8; i++) { if (ptp32[i].pte_hi & PTE_VALID_32) continue; + if (pmap_hash_lock_try(i) == 0) + continue; pted->pted_va |= (i | PTED_VA_HID_M); ptp32[i].pte_hi = @@ -2424,12 +2508,18 @@ pte_insert32(struct pte_desc *pted) __asm__ volatile ("sync"); ptp32[i].pte_hi |= PTE_VALID_32; __asm volatile ("sync"); + + pmap_hash_unlock(i); return; } /* need decent replacement algorithm */ +busy: __asm__ volatile ("mftb %0" : "=r"(off)); secondary = off & 8; + if (pmap_hash_lock_try(off & 7) == 0) + goto busy; + pted->pted_va |= off & (PTED_VA_PTEGIDX_M|PTED_VA_HID_M); idx = (idx ^ (PTED_HID(pted) ? pmap_ptab_mask : 0)); @@ -2460,6 +2550,7 @@ pte_insert32(struct pte_desc *pted) __asm__ volatile ("sync"); ptp32->pte_hi |= PTE_VALID_32; + pmap_hash_unlock(off & 7); } #ifdef DEBUG_PMAP |