/*
 * Bolt the kernel addr space into the HPT
 */
static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr)
{
	unsigned long pa;
	unsigned long mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
	HPTE hpte;

	for (pa = saddr; pa < eaddr ;pa += PAGE_SIZE) {
		unsigned long ea = (unsigned long)__va(pa);
		unsigned long vsid = get_kernel_vsid(ea);
		unsigned long va = (vsid << 28) | (pa & 0xfffffff);
		unsigned long vpn = va >> PAGE_SHIFT;
		unsigned long slot = HvCallHpt_findValid(&hpte, vpn);

		/* Make non-kernel text non-executable */
		if (!in_kernel_text(ea))
			mode_rw |= HW_NO_EXEC;

		if (hpte.dw0.dw0.v) {
			/* HPTE exists, so just bolt it */
			HvCallHpt_setSwBits(slot, 0x10, 0);
			/* And make sure the pp bits are correct */
			HvCallHpt_setPp(slot, PP_RWXX);
		} else
			/* No HPTE exists, so create a new bolted one */
			iSeries_make_pte(va, phys_to_abs(pa), mode_rw);
	}
}
Example #2
0
/*
 * Functions used to find the PTE for a particular virtual address. 
 * Only used during boot when bolting pages.
 *
 * Input : vpn      : virtual page number
 * Output: PTE index within the page table of the entry
 *         -1 on failure
 */
static long iSeries_hpte_find(unsigned long vpn)
{
	HPTE hpte;
	long slot;

	/*
	 * The HvCallHpt_findValid interface is as follows:
	 * 0xffffffffffffffff : No entry found.
	 * 0x00000000xxxxxxxx : Entry found in primary group, slot x
	 * 0x80000000xxxxxxxx : Entry found in secondary group, slot x
	 */
	slot = HvCallHpt_findValid(&hpte, vpn); 
	if (hpte.dw0.dw0.v) {
		if (slot < 0) {
			slot &= 0x7fffffffffffffff;
			slot = -slot;
		}
	} else
		slot = -1;
	return slot;
}
Example #3
0
/*
 * Bolt the kernel addr space into the HPT
 */
static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr)
{
	unsigned long pa;
	unsigned long mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
	HPTE hpte;

	for (pa=saddr; pa < eaddr ;pa+=PAGE_SIZE) {
		unsigned long ea = (unsigned long)__va(pa);
		unsigned long vsid = get_kernel_vsid( ea );
		unsigned long va = ( vsid << 28 ) | ( pa & 0xfffffff );
		unsigned long vpn = va >> PAGE_SHIFT;
		unsigned long slot = HvCallHpt_findValid( &hpte, vpn );
		if (hpte.dw0.dw0.v) {
			/* HPTE exists, so just bolt it */
			HvCallHpt_setSwBits(slot, 0x10, 0);
		} else {
			/* No HPTE exists, so create a new bolted one */
			make_pte(NULL, va, (unsigned long)__v2a(ea), 
				 mode_rw, 0, 0);
		}
	}
}
Example #4
0
/*
 * Create a pte. Used during initialization only.
 */
static void iSeries_make_pte(unsigned long va, unsigned long pa,
			     int mode)
{
	HPTE local_hpte, rhpte;
	unsigned long hash, vpn;
	long slot;

	vpn = va >> PAGE_SHIFT;
	hash = hpt_hash(vpn, 0);

	local_hpte.dw1.dword1 = pa | mode;
	local_hpte.dw0.dword0 = 0;
	local_hpte.dw0.dw0.avpn = va >> 23;
	local_hpte.dw0.dw0.bolted = 1;		/* bolted */
	local_hpte.dw0.dw0.v = 1;

	slot = HvCallHpt_findValid(&rhpte, vpn);
	if (slot < 0) {
		/* Must find space in primary group */
		panic("hash_page: hpte already exists\n");
	}
	HvCallHpt_addValidate(slot, 0, (HPTE *)&local_hpte );
}