-/* $OpenBSD: cpu.h,v 1.110 2016/03/06 19:42:27 mpi Exp $ */
+/* $OpenBSD: cpu.h,v 1.111 2016/08/14 08:23:52 visa Exp $ */
/*-
* Copyright (c) 1992, 1993
uint32_t cp0_get_config_1(void);
uint32_t cp0_get_config_2(void);
uint32_t cp0_get_config_3(void);
+uint32_t cp0_get_pagegrain(void);
register_t cp0_get_prid(void);
void cp0_reset_cause(register_t);
void cp0_set_compare(u_int);
void cp0_set_config(register_t);
+void cp0_set_pagegrain(uint32_t);
void cp0_set_trapbase(register_t);
u_int cp1_get_prid(void);
-/* $OpenBSD: mips_cpu.h,v 1.3 2016/08/06 09:32:04 visa Exp $ */
+/* $OpenBSD: mips_cpu.h,v 1.4 2016/08/14 08:23:52 visa Exp $ */
/*-
* Copyright (c) 1992, 1993
#define FPC_ID $0
#define FPC_CSR $31
+/*
+ * Config3 register
+ */
+#define CONFIG3_M 0x80000000
+#define CONFIG3_BPG 0x40000000
+#define CONFIG3_CMGCR 0x20000000
+#define CONFIG3_IPLW 0x00600000
+#define CONFIG3_MMAR 0x001c0000
+#define CONFIG3_MCU 0x00020000
+#define CONFIG3_ISAOnExc 0x00010000
+#define CONFIG3_ISA 0x0000c000
+#define CONFIG3_ULRI 0x00002000
+#define CONFIG3_RXI 0x00001000
+#define CONFIG3_DSP2P 0x00000800
+#define CONFIG3_DSPP 0x00000400
+#define CONFIG3_CTXTC 0x00000200
+#define CONFIG3_ITL 0x00000100
+#define CONFIG3_LPA 0x00000080
+#define CONFIG3_VEIC 0x00000040
+#define CONFIG3_VInt 0x00000020
+#define CONFIG3_SP 0x00000010
+#define CONFIG3_CDMM 0x00000008
+#define CONFIG3_MT 0x00000004
+#define CONFIG3_SM 0x00000002
+#define CONFIG3_TL 0x00000001
+
/*
* PageGrain register
*/
-/* $OpenBSD: pte.h,v 1.18 2014/03/22 00:00:38 miod Exp $ */
+/* $OpenBSD: pte.h,v 1.19 2016/08/14 08:23:52 visa Exp $ */
/*
* Copyright (c) 1988 University of Utah.
#endif /* _LOCORE */
+#ifdef MIPS_PTE64
+#define PTE_BITS 64
+#else
+#define PTE_BITS 32
+#endif
+
+#ifdef CPU_MIPS64R2
+#define PTE_CLEAR_SWBITS(reg) \
+ .set push; \
+ .set mips64r2; \
+ /* Clear SW bits around PG_XI. */ \
+ dins reg, zero, (PTE_BITS - 1), 1; \
+ dins reg, zero, PG_FRAMEBITS, (PTE_BITS - 2 - PG_FRAMEBITS); \
+ .set pop
+#else
+#define PTE_CLEAR_SWBITS(reg) \
+ /* Clear SW bits left of PG_FRAMEBITS. */ \
+ dsll reg, reg, (64 - PG_FRAMEBITS); \
+ dsrl reg, reg, (64 - PG_FRAMEBITS)
+#endif
+
/* entryhi values */
#ifndef CPU_R8000
#endif
/* software pte bits - not put in entrylo */
-#ifdef CPU_R8000
+#if defined(CPU_R8000)
#define PG_WIRED 0x00000010
#define PG_RO 0x00000020
-#else
+#elif defined(CPU_R4000)
#define PG_WIRED (1ULL << (PG_FRAMEBITS + 2))
#define PG_RO (1ULL << (PG_FRAMEBITS + 1))
#define PG_SP (1ULL << (PG_FRAMEBITS + 0)) /* ``special'' bit */
+#else
+#define PG_WIRED (1ULL << (PG_FRAMEBITS + 2))
+ /* 1ULL << (PG_FRAMEBITS + 1) is PG_XI. */
+#define PG_RO (1ULL << (PG_FRAMEBITS + 0))
+#endif
+
+#ifdef CPU_MIPS64R2
+#define PG_XI (1ULL << (PTE_BITS - 2))
+#else
+#define PG_XI 0x00000000
#endif
#define PG_NV 0x00000000
-/* $OpenBSD: context.S,v 1.54 2015/09/29 17:07:53 miod Exp $ */
+/* $OpenBSD: context.S,v 1.55 2016/08/14 08:23:52 visa Exp $ */
/*
* Copyright (c) 2002-2003 Opsycon AB (www.opsycon.se / www.opsycon.com)
dmtc0 v0, COP_0_TLB_HI
PTE_LOAD ta0, 0(t1)
PTE_LOAD ta1, PTE_OFFS(t1)
- dsll ta0, ta0, (64 - PG_FRAMEBITS) # clear bits left of PG_FRAME
- dsrl ta0, ta0, (64 - PG_FRAMEBITS)
- dsll ta1, ta1, (64 - PG_FRAMEBITS)
- dsrl ta1, ta1, (64 - PG_FRAMEBITS)
+ PTE_CLEAR_SWBITS(ta0)
+ PTE_CLEAR_SWBITS(ta1)
dmtc0 ta0, COP_0_TLB_LO0
dmtc0 ta1, COP_0_TLB_LO1
PTR_ADDU v0, 2*PAGE_SIZE
dmtc0 v0, COP_0_TLB_HI # init high entry (tlbid)
PTE_LOAD ta0, (2*PTE_OFFS)(t1)
PTE_LOAD ta1, (3*PTE_OFFS)(t1)
- dsll ta0, ta0, (64 - PG_FRAMEBITS) # clear bits left of PG_FRAME
- dsrl ta0, ta0, (64 - PG_FRAMEBITS)
+ PTE_CLEAR_SWBITS(ta0)
TLB_HAZARD
tlbp
TLB_HAZARD # necessary?
- dsll ta1, ta1, (64 - PG_FRAMEBITS)
- dsrl ta1, ta1, (64 - PG_FRAMEBITS)
+ PTE_CLEAR_SWBITS(ta1)
mfc0 t0, COP_0_TLB_INDEX
nop
bltz t0, ctx2 # not in tlb
-/* $OpenBSD: db_machdep.c,v 1.45 2016/03/06 19:42:27 mpi Exp $ */
+/* $OpenBSD: db_machdep.c,v 1.46 2016/08/14 08:23:52 visa Exp $ */
/*
* Copyright (c) 1998-2003 Opsycon AB (www.opsycon.se)
#endif
if (tlblo & PG_V) {
db_printf("%016lx ", pa);
+#ifdef CPU_MIPS64R2
+ db_printf("%c", tlblo & PG_XI ? 'X' : ' ');
+#endif
db_printf("%c", tlblo & PG_M ? 'M' : ' ');
#ifndef CPU_R8000
db_printf("%c", tlblo & PG_G ? 'G' : ' ');
-/* $OpenBSD: mips64r2.S,v 1.2 2012/10/03 11:18:23 miod Exp $ */
+/* $OpenBSD: mips64r2.S,v 1.3 2016/08/14 08:23:52 visa Exp $ */
/*
* Copyright (c) 2011 Miodrag Vallat.
j ra
mfc0 v0, COP_0_CONFIG, 3
END(cp0_get_config_3)
+
+LEAF(cp0_get_pagegrain, 0)
+ j ra
+ mfc0 v0, COP_0_TLB_PG_GRAIN
+END(cp0_get_pagegrain)
+
+LEAF(cp0_set_pagegrain, 0)
+ mtc0 a0, COP_0_TLB_PG_GRAIN
+ jr.hb ra
+ nop
+END(cp0_set_pagegrain)
-/* $OpenBSD: pmap.c,v 1.90 2016/05/11 15:50:29 visa Exp $ */
+/* $OpenBSD: pmap.c,v 1.91 2016/08/14 08:23:52 visa Exp $ */
/*
* Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
#include <sys/atomic.h>
#include <mips64/cache.h>
+#include <mips64/mips_cpu.h>
#include <machine/autoconf.h>
#include <machine/cpu.h>
#include <machine/vmparam.h>
int pmap_enter_pv(pmap_t, vaddr_t, vm_page_t, pt_entry_t *);
void pmap_remove_pv(pmap_t, vaddr_t, paddr_t);
void pmap_page_remove(struct vm_page *);
-void pmap_page_wrprotect(struct vm_page *);
+void pmap_page_wrprotect(struct vm_page *, vm_prot_t);
void *pmap_pg_alloc(struct pool *, int, int *);
void pmap_pg_free(struct pool *, void *);
u_int Sysmapsize; /* number of pte's in Sysmap */
const vaddr_t Sysmapbase = VM_MIN_KERNEL_ADDRESS; /* for libkvm */
+pt_entry_t pg_xi;
+
void
pmap_invalidate_user_page(pmap_t pmap, vaddr_t va)
{
pmap_asid_info[i].pma_asidgen = 1;
pmap_asid_info[i].pma_asid = MIN_USER_ASID + 1;
}
+
+#ifdef CPU_MIPS64R2
+ if (cp0_get_pagegrain() & PGRAIN_XIE)
+ pg_xi = PG_XI;
+#endif
}
/*
* Makes all mappings to a given page read-only.
*/
void
-pmap_page_wrprotect(struct vm_page *pg)
+pmap_page_wrprotect(struct vm_page *pg, vm_prot_t prot)
{
struct cpu_info *ci = curcpu();
- pt_entry_t *pte, entry;
+ pt_entry_t *pte, entry, p;
pv_entry_t pv;
+ p = PG_RO;
+ if (!(prot & PROT_EXEC))
+ p |= pg_xi;
+
mtx_enter(&pg->mdpage.pv_mtx);
for (pv = pg_to_pvh(pg); pv != NULL; pv = pv->pv_next) {
if (pv->pv_pmap == pmap_kernel()) {
(entry & PG_CACHEMODE) == PG_CACHED)
Mips_HitSyncDCachePage(ci, pv->pv_va,
pfn_to_pad(entry));
- entry = (entry & ~PG_M) | PG_RO;
+ entry = (entry & ~(PG_M | PG_XI)) | p;
*pte = entry;
pmap_update_kernel_page(pv->pv_va, entry);
pmap_shootdown_page(pmap_kernel(), pv->pv_va);
(entry & PG_CACHEMODE) == PG_CACHED)
Mips_SyncDCachePage(ci, pv->pv_va,
pfn_to_pad(entry));
- entry = (entry & ~PG_M) | PG_RO;
+ entry = (entry & ~(PG_M | PG_XI)) | p;
*pte = entry;
pmap_update_user_page(pv->pv_pmap, pv->pv_va, entry);
pmap_shootdown_page(pv->pv_pmap, pv->pv_va);
/* copy_on_write */
case PROT_READ:
case PROT_READ | PROT_EXEC:
- pmap_page_wrprotect(pg);
+ pmap_page_wrprotect(pg, prot);
break;
/* remove_all */
}
p = (prot & PROT_WRITE) ? PG_M : PG_RO;
+ if (!(prot & PROT_EXEC))
+ p |= pg_xi;
pmap_lock(pmap);
if ((entry & PG_CACHEMODE) == PG_CACHED)
Mips_HitSyncDCachePage(ci, sva,
pfn_to_pad(entry));
- entry = (entry & ~(PG_M | PG_RO)) | p;
+ entry = (entry & ~(PG_M | PG_RO | PG_XI)) | p;
*pte = entry;
/*
* Update the TLB if the given address is in the cache.
Mips_SyncDCachePage(ci, sva,
pfn_to_pad(entry));
}
- entry = (entry & ~(PG_M | PG_RO)) | p;
+ entry = (entry & ~(PG_M | PG_RO | PG_XI)) | p;
*pte = entry;
pmap_update_user_page(pmap, sva, entry);
pmap_shootdown_page(pmap, sva);
}
}
+ if (!(prot & PROT_EXEC))
+ npte |= pg_xi;
+
if (pmap == pmap_kernel()) {
if (pg != NULL) {
if (pmap_enter_pv(pmap, va, pg, &npte) != 0) {
npte |= PG_RWPAGE;
else
npte |= PG_ROPAGE;
+ if (!(prot & PROT_EXEC))
+ npte |= pg_xi;
pte = kvtopte(va);
if ((*pte & PG_V) == 0) {
atomic_inc_long(&pmap_kernel()->pm_stats.resident_count);
-/* $OpenBSD: tlbhandler.S,v 1.44 2014/08/12 19:33:59 miod Exp $ */
+/* $OpenBSD: tlbhandler.S,v 1.45 2016/08/14 08:23:52 visa Exp $ */
/*
* Copyright (c) 1995-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
bltz k1, _inv_seg
dsll k0, k0, 1
dsll k1, k1, 1
-#else
- dsll k0, k0, (64 - PG_FRAMEBITS) # clear bits left of PG_FRAME
- dsll k1, k1, (64 - PG_FRAMEBITS)
-#endif
dsrl k0, k0, (64 - PG_FRAMEBITS)
dsrl k1, k1, (64 - PG_FRAMEBITS)
+#else
+ PTE_CLEAR_SWBITS(k0)
+ PTE_CLEAR_SWBITS(k1)
+#endif
dmtc0 k0, COP_0_TLB_LO0
dmtc0 k1, COP_0_TLB_LO1
TLB_HAZARD
*/
NLEAF(k_tlb_inv, 0)
.set noat
- LA k1, (VM_MIN_KERNEL_ADDRESS) # compute index
+#ifdef CPU_OCTEON
+ /* Check if the fault was caused by an instruction fetch. */
+ dmfc0 k0, COP_0_CAUSE_REG
+ /* XXX bbit0 k0, CR_BR_DELAY_BIT, 1f */
+ li k1, CR_BR_DELAY
+ and k0, k0, k1
+ beq k0, zero, 1f # fault in a branch delay slot?
+ dmfc0 k1, COP_0_EXC_PC
+ daddu k1, k1, 4 # adjust for the slot
+1: dmfc0 k0, COP_0_BAD_VADDR
+ beq k0, k1, go_k_general
+#else
dmfc0 k0, COP_0_BAD_VADDR # get the fault address
+#endif
+ LA k1, (VM_MIN_KERNEL_ADDRESS) # compute index
PTR_SUBU k0, k0, k1
lw k1, Sysmapsize # index within range?
PTR_SRL k0, k0, PGSHIFT
bltz k0, sys_stk_chk # probe fail
PTE_LOAD k0, 0(k1) # get PTE entry
- dsll k0, k0, (64 - PG_FRAMEBITS) # clear bits left of PG_FRAME
- dsrl k0, k0, (64 - PG_FRAMEBITS)
+ PTE_CLEAR_SWBITS(k0)
dmtc0 k0, COP_0_TLB_LO0 # load PTE entry
and k0, k0, PG_V # check for valid entry
beq k0, zero, go_k_general # PTE invalid
PTE_LOAD k0, PTE_OFFS(k1) # get odd PTE entry
- dsll k0, k0, (64 - PG_FRAMEBITS)
- dsrl k0, k0, (64 - PG_FRAMEBITS)
+ PTE_CLEAR_SWBITS(k0)
dmtc0 k0, COP_0_TLB_LO1 # load PTE entry
TLB_HAZARD
tlbwi # write TLB
bltz k0, sys_stk_chk # probe fail
PTE_LOAD k0, 0(k1) # get PTE entry
- dsll k0, k0, (64 - PG_FRAMEBITS) # clear bits left of PG_FRAME
- dsrl k0, k0, (64 - PG_FRAMEBITS)
+ PTE_CLEAR_SWBITS(k0)
dmtc0 k0, COP_0_TLB_LO1 # save PTE entry
and k0, k0, PG_V # check for valid entry
beq k0, zero, go_k_general # PTE invalid
PTE_LOAD k0, -PTE_OFFS(k1) # get even PTE entry
- dsll k0, k0, (64 - PG_FRAMEBITS)
- dsrl k0, k0, (64 - PG_FRAMEBITS)
+ PTE_CLEAR_SWBITS(k0)
dmtc0 k0, COP_0_TLB_LO0 # save PTE entry
TLB_HAZARD
tlbwi # update TLB
PTR_ADDU k1, k1, k0
PTE_LOAD k0, 0(k1) # get PTE entry
PTE_LOAD k1, PTE_OFFS(k1) # get odd PTE entry
- dsll k0, k0, (64 - PG_FRAMEBITS) # clear bits left of PG_FRAME
- dsrl k0, k0, (64 - PG_FRAMEBITS)
+ PTE_CLEAR_SWBITS(k0)
dmtc0 k0, COP_0_TLB_LO0 # load PTE entry
- dsll k1, k1, (64 - PG_FRAMEBITS)
- dsrl k1, k1, (64 - PG_FRAMEBITS)
+ PTE_CLEAR_SWBITS(k1)
dmtc0 k1, COP_0_TLB_LO1 # load PTE entry
TLB_HAZARD
tlbwr # write TLB
TLB_HAZARD
tlbp # Probe for the entry.
TLB_HAZARD # necessary?
- dsll a1, a1, (64 - PG_FRAMEBITS) # clear bits left of PG_FRAME
+ PTE_CLEAR_SWBITS(a1)
mfc0 v0, COP_0_TLB_INDEX # See what we got
bne ta1, zero, 2f # Decide even odd
- dsrl a1, a1, (64 - PG_FRAMEBITS)
+ nop
# EVEN
bltz v0, 1f # index < 0 => !found
nop
mtc0 ta1, COP_0_TLB_PG_MASK # init mask
dmtc0 a0, COP_0_TLB_HI # init high reg.
- dsll a1, a1, (64 - PG_FRAMEBITS) # clear bits left of PG_FRAME
- dsrl a1, a1, (64 - PG_FRAMEBITS)
+ PTE_CLEAR_SWBITS(a1)
dmtc0 a1, COP_0_TLB_LO0 # init low reg0.
- dsll a2, a2, (64 - PG_FRAMEBITS) # clear bits left of PG_FRAME
- dsrl a2, a2, (64 - PG_FRAMEBITS)
+ PTE_CLEAR_SWBITS(a2)
dmtc0 a2, COP_0_TLB_LO1 # init low reg1.
TLB_HAZARD
-/* $OpenBSD: trap.c,v 1.116 2016/03/06 19:42:27 mpi Exp $ */
+/* $OpenBSD: trap.c,v 1.117 2016/08/14 08:23:52 visa Exp $ */
/*
* Copyright (c) 1988 University of Utah.
case T_TLB_LD_MISS:
case T_TLB_ST_MISS:
- ftype = (type == T_TLB_ST_MISS) ? PROT_WRITE : PROT_READ;
+ if (type == T_TLB_LD_MISS) {
+#ifdef CPU_OCTEON
+ vaddr_t pc;
+
+ /*
+ * Check if the fault was caused by
+ * an instruction fetch.
+ */
+ pc = trapframe->pc;
+ if (trapframe->cause & CR_BR_DELAY)
+ pc += 4;
+ if (pc == trapframe->badvaddr)
+ ftype = PROT_EXEC;
+ else
+#endif
+ ftype = PROT_READ;
+ } else
+ ftype = PROT_WRITE;
+
pcb = &p->p_addr->u_pcb;
/* check for kernel address */
if (trapframe->badvaddr < 0) {
goto err;
}
- case T_TLB_LD_MISS+T_USER:
+ case T_TLB_LD_MISS+T_USER: {
+#ifdef CPU_OCTEON
+ vaddr_t pc;
+
+ /* Check if the fault was caused by an instruction fetch. */
+ pc = trapframe->pc;
+ if (trapframe->cause & CR_BR_DELAY)
+ pc += 4;
+ if (pc == trapframe->badvaddr)
+ ftype = PROT_EXEC;
+ else
+#endif
ftype = PROT_READ;
pcb = &p->p_addr->u_pcb;
goto fault_common;
+ }
case T_TLB_ST_MISS+T_USER:
ftype = PROT_WRITE;
-/* $OpenBSD: locore.S,v 1.9 2016/08/06 09:32:05 visa Exp $ */
+/* $OpenBSD: locore.S,v 1.10 2016/08/14 08:23:52 visa Exp $ */
/*
* Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
#endif
dmtc0 t0, COP_0_CVMMEMCTL
-/* initialize pagegrain */
- dli t0, PGRAIN_ELPA
- dmtc0 t0, COP_0_TLB_PG_GRAIN
-
mfc0 v0, COP_0_STATUS_REG
li v1, ~(SR_INT_ENAB | SR_ERL | SR_EXL)
and v0, v1
-/* $OpenBSD: machdep.c,v 1.74 2016/07/01 15:12:37 visa Exp $ */
+/* $OpenBSD: machdep.c,v 1.75 2016/08/14 08:23:52 visa Exp $ */
/*
* Copyright (c) 2009, 2010 Miodrag Vallat.
boolean_t is_memory_range(paddr_t, psize_t, psize_t);
void octeon_memory_init(struct boot_info *);
int octeon_cpuspeed(int *);
+void octeon_tlb_init(void);
static void process_bootargs(void);
static uint64_t get_ncpusfound(void);
Octeon_ConfigCache(curcpu());
Octeon_SyncCache(curcpu());
- tlb_init(bootcpu_hwinfo.tlbsize);
+ octeon_tlb_init();
/*
* Save the the boot information for future reference since we can't
}
}
+void
+octeon_tlb_init(void)
+{
+ uint32_t pgrain = 0;
+
+#ifdef MIPS_PTE64
+ pgrain |= PGRAIN_ELPA;
+#endif
+ if (cp0_get_config_3() & CONFIG3_RXI)
+ pgrain |= PGRAIN_XIE;
+ cp0_set_pagegrain(pgrain);
+
+ tlb_init(bootcpu_hwinfo.tlbsize);
+}
+
static u_int64_t
get_ncpusfound(void)
{
*/
setsr(getsr() | SR_KX | SR_UX);
- tlb_init(64);
+ octeon_tlb_init();
tlb_set_pid(0);
/*