ps3mmu.c revision 256281
13062Sjlahoda/*-
23290Srfield * Copyright (C) 2010 Nathan Whitehorn
33062Sjlahoda * All rights reserved.
43062Sjlahoda *
53062Sjlahoda * Redistribution and use in source and binary forms, with or without
63062Sjlahoda * modification, are permitted provided that the following conditions
73062Sjlahoda * are met:
83062Sjlahoda * 1. Redistributions of source code must retain the above copyright
93062Sjlahoda *    notice, this list of conditions and the following disclaimer.
103062Sjlahoda * 2. Redistributions in binary form must reproduce the above copyright
113062Sjlahoda *    notice, this list of conditions and the following disclaimer in the
123062Sjlahoda *    documentation and/or other materials provided with the distribution.
133062Sjlahoda *
143062Sjlahoda * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
153062Sjlahoda * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
163062Sjlahoda * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
173062Sjlahoda * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
183062Sjlahoda * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
193062Sjlahoda * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
203062Sjlahoda * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
213062Sjlahoda * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
223062Sjlahoda * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
233062Sjlahoda * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
243062Sjlahoda */
253316Srfield
263062Sjlahoda#include <sys/cdefs.h>
273062Sjlahoda__FBSDID("$FreeBSD: stable/10/sys/boot/powerpc/ps3/ps3mmu.c 230140 2012-01-15 16:58:44Z nwhitehorn $");
283062Sjlahoda
293062Sjlahoda#include <stand.h>
303062Sjlahoda#include <stdint.h>
313569Srfield
323569Srfield#define _KERNEL
333062Sjlahoda#include <machine/cpufunc.h>
343062Sjlahoda#include <machine/psl.h>
353062Sjlahoda#include <machine/pte.h>
363062Sjlahoda#include <machine/slb.h>
373062Sjlahoda#include <machine/param.h>
383062Sjlahoda
393569Srfield#include "bootstrap.h"
403062Sjlahoda#include "lv1call.h"
413062Sjlahoda#include "ps3.h"
423062Sjlahoda
433062Sjlahodaregister_t pteg_count, pteg_mask;
443062Sjlahodauint64_t as_id;
453062Sjlahodauint64_t virtual_avail;
463062Sjlahoda
473062Sjlahodaint
483062Sjlahodaps3mmu_map(uint64_t va, uint64_t pa)
493062Sjlahoda{
503062Sjlahoda	struct lpte pt;
513062Sjlahoda	int shift;
523062Sjlahoda	uint64_t vsid, ptegidx;
533062Sjlahoda
543062Sjlahoda	if (pa < 0x8000000) { /* Phys mem? */
553062Sjlahoda		pt.pte_hi = LPTE_BIG;
563062Sjlahoda		pt.pte_lo = LPTE_M;
573062Sjlahoda		shift = 24;
583062Sjlahoda		vsid = 0;
593062Sjlahoda	} else {
603062Sjlahoda		pt.pte_hi = 0;
613062Sjlahoda		pt.pte_lo = LPTE_I | LPTE_G | LPTE_M | LPTE_NOEXEC;
623062Sjlahoda		shift = ADDR_PIDX_SHFT;
633062Sjlahoda		vsid = 1;
643062Sjlahoda	}
653062Sjlahoda
663062Sjlahoda	pt.pte_hi |= (vsid << LPTE_VSID_SHIFT) |
673062Sjlahoda            (((uint64_t)(va & ADDR_PIDX) >> ADDR_API_SHFT64) & LPTE_API);
683062Sjlahoda	pt.pte_lo |= pa;
693062Sjlahoda	ptegidx = vsid ^ (((uint64_t)va & ADDR_PIDX) >> shift);
703062Sjlahoda
713062Sjlahoda	pt.pte_hi |= LPTE_LOCKED | LPTE_VALID;
723062Sjlahoda	ptegidx &= pteg_mask;
733062Sjlahoda
743062Sjlahoda	return (lv1_insert_pte(ptegidx, &pt, LPTE_LOCKED));
753062Sjlahoda}
763062Sjlahoda
773062Sjlahodavoid *
783062Sjlahodaps3mmu_mapdev(uint64_t pa, size_t length)
793062Sjlahoda{
803062Sjlahoda	uint64_t spa;
813062Sjlahoda	void *mapstart;
823062Sjlahoda	int err;
833062Sjlahoda
843062Sjlahoda	mapstart = (void *)(uintptr_t)virtual_avail;
853062Sjlahoda
863062Sjlahoda	for (spa = pa; spa < pa + length; spa += PAGE_SIZE) {
873062Sjlahoda		err = ps3mmu_map(virtual_avail, spa);
883569Srfield		virtual_avail += PAGE_SIZE;
893569Srfield		if (err != 0)
903569Srfield			return (NULL);
913569Srfield	}
923569Srfield
933569Srfield	return (mapstart);
943569Srfield}
953062Sjlahoda
963062Sjlahodaint
973569Srfieldps3mmu_init(int maxmem)
983062Sjlahoda{
993062Sjlahoda	uint64_t ptsize;
1003062Sjlahoda	int i;
1013062Sjlahoda
1023357Srfield	i = lv1_setup_address_space(&as_id, &ptsize);
1033569Srfield	pteg_count = ptsize / sizeof(struct lpteg);
1043062Sjlahoda	pteg_mask = pteg_count - 1;
1053062Sjlahoda
1063062Sjlahoda	for (i = 0; i < maxmem; i += 16*1024*1024)
1073062Sjlahoda		ps3mmu_map(i,i);
1083062Sjlahoda
1093062Sjlahoda	virtual_avail = 0x10000000;
1103062Sjlahoda
1113062Sjlahoda	__asm __volatile ("slbia; slbmte %0, %1; slbmte %2,%3" ::
1123062Sjlahoda	    "r"((0 << SLBV_VSID_SHIFT) | SLBV_L), "r"(0 | SLBE_VALID),
1133062Sjlahoda	    "r"(1 << SLBV_VSID_SHIFT),
1143062Sjlahoda	    "r"((1 << SLBE_ESID_SHIFT) | SLBE_VALID | 1));
1153062Sjlahoda
1163062Sjlahoda	mtmsr(PSL_IR | PSL_DR | PSL_RI | PSL_ME);
1173357Srfield
1183062Sjlahoda	return (0);
1193062Sjlahoda}
1203062Sjlahoda
1213062Sjlahoda