Index: kernel/arch/ia64/src/mm/as.c
===================================================================
--- kernel/arch/ia64/src/mm/as.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/ia64/src/mm/as.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2006 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ /** @addtogroup ia64mm
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/mm/as.h>
+#include <arch/mm/asid.h>
+#include <arch/mm/page.h>
+#include <genarch/mm/as_ht.h>
+#include <genarch/mm/asid_fifo.h>
+#include <mm/asid.h>
+#include <arch.h>
+#include <arch/barrier.h>
+#include <synch/spinlock.h>
+
+/** Architecture dependent address space init. */
+void as_arch_init(void)
+{
+	as_operations = &as_ht_operations;
+	asid_fifo_init();
+}
+
+/** Prepare registers for switching to another address space.
+ *
+ * @param as Address space.
+ */
+void as_install_arch(as_t *as)
+{
+	ipl_t ipl;
+	region_register rr;
+	int i;
+	
+	ipl = interrupts_disable();
+	spinlock_lock(&as->lock);
+	
+	ASSERT(as->asid != ASID_INVALID);
+	
+	/*
+	 * Load respective ASID (7 consecutive RIDs) to
+	 * region registers.
+	 */
+	for (i = 0; i < REGION_REGISTERS; i++) {
+		if (i == VRN_KERNEL)
+			continue;
+		
+		rr.word = rr_read(i);
+		rr.map.ve = false;			/* disable VHPT walker */
+		rr.map.rid = ASID2RID(as->asid, i);
+		rr.map.ps = PAGE_WIDTH;
+		rr_write(i, rr.word);
+	}
+	srlz_d();
+	srlz_i();
+	
+	spinlock_unlock(&as->lock);
+	interrupts_restore(ipl);
+}
+
+ /** @}
+ */
+
Index: kernel/arch/ia64/src/mm/frame.c
===================================================================
--- kernel/arch/ia64/src/mm/frame.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/ia64/src/mm/frame.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2005 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ /** @addtogroup ia64mm	
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/mm/frame.h>
+#include <mm/frame.h>
+#include <config.h>
+#include <panic.h>
+
+/*
+ * This is Ski-specific and certainly not sufficient
+ * for real ia64 systems that provide memory map.
+ */
+#define ROM_BASE	0xa0000
+#define ROM_SIZE	(384*1024)
+
+void frame_arch_init(void)
+{
+	zone_create(0, config.memory_size >> FRAME_WIDTH, 1, 0);
+	
+	/*
+	 * Blacklist ROM regions.
+	 */
+	frame_mark_unavailable(ADDR2PFN(ROM_BASE), ROM_SIZE >> FRAME_WIDTH);
+}
+
+ /** @}
+ */
+
Index: kernel/arch/ia64/src/mm/page.c
===================================================================
--- kernel/arch/ia64/src/mm/page.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/ia64/src/mm/page.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2006 Jakub Jermar
+ * Copyright (C) 2006 Jakub Vana
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ /** @addtogroup ia64mm	
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/mm/page.h>
+#include <genarch/mm/page_ht.h>
+#include <mm/asid.h>
+#include <arch/mm/asid.h>
+#include <arch/mm/vhpt.h>
+#include <arch/types.h>
+#include <typedefs.h>
+#include <print.h>
+#include <mm/page.h>
+#include <mm/frame.h>
+#include <config.h>
+#include <panic.h>
+#include <arch/asm.h>
+#include <arch/barrier.h>
+#include <memstr.h>
+
+static void set_environment(void);
+
+/** Initialize ia64 virtual address translation subsystem. */
+void page_arch_init(void)
+{
+	page_mapping_operations = &ht_mapping_operations;
+	pk_disable();
+	set_environment();
+}
+
+/** Initialize VHPT and region registers. */
+void set_environment(void)
+{
+	region_register rr;
+	pta_register pta;	
+	int i;
+#ifdef CONFIG_VHPT	
+	uintptr_t vhpt_base;
+#endif
+
+	/*
+	 * First set up kernel region register.
+	 * This is redundant (see start.S) but we keep it here just for sure.
+	 */
+	rr.word = rr_read(VRN_KERNEL);
+	rr.map.ve = 0;                  /* disable VHPT walker */
+	rr.map.ps = PAGE_WIDTH;
+	rr.map.rid = ASID2RID(ASID_KERNEL, VRN_KERNEL);
+	rr_write(VRN_KERNEL, rr.word);
+	srlz_i();
+	srlz_d();
+
+	/*
+	 * And setup the rest of region register.
+	 */
+	for(i = 0; i < REGION_REGISTERS; i++) {
+		/* skip kernel rr */
+		if (i == VRN_KERNEL)
+			continue;
+	
+		rr.word = rr_read(i);
+		rr.map.ve = 0;		/* disable VHPT walker */
+		rr.map.rid = RID_KERNEL;
+		rr.map.ps = PAGE_WIDTH;
+		rr_write(i, rr.word);
+		srlz_i();
+		srlz_d();
+	}
+
+#ifdef CONFIG_VHPT	
+	vhpt_base = vhpt_set_up();
+#endif
+	/*
+	 * Set up PTA register.
+	 */
+	pta.word = pta_read();
+#ifndef CONFIG_VHPT
+	pta.map.ve = 0;                   /* disable VHPT walker */
+	pta.map.base = 0 >> PTA_BASE_SHIFT;
+#else
+	pta.map.ve = 1;                   /* enable VHPT walker */
+	pta.map.base = vhpt_base >> PTA_BASE_SHIFT;
+#endif
+	pta.map.vf = 1;                   /* large entry format */
+	pta.map.size = VHPT_WIDTH;
+	pta_write(pta.word);
+	srlz_i();
+	srlz_d();
+}
+
+/** Calculate address of collision chain from VPN and ASID.
+ *
+ * Interrupts must be disabled.
+ *
+ * @param page Address of virtual page including VRN bits.
+ * @param asid Address space identifier.
+ *
+ * @return VHPT entry address.
+ */
+vhpt_entry_t *vhpt_hash(uintptr_t page, asid_t asid)
+{
+	region_register rr_save, rr;
+	index_t vrn;
+	rid_t rid;
+	vhpt_entry_t *v;
+
+	vrn = page >> VRN_SHIFT;
+	rid = ASID2RID(asid, vrn);
+	
+	rr_save.word = rr_read(vrn);
+	if (rr_save.map.rid == rid) {
+		/*
+		 * The RID is already in place, compute thash and return.
+		 */
+		v = (vhpt_entry_t *) thash(page);
+		return v;
+	}
+	
+	/*
+	 * The RID must be written to some region register.
+	 * To speed things up, register indexed by vrn is used.
+	 */
+	rr.word = rr_save.word;
+	rr.map.rid = rid;
+	rr_write(vrn, rr.word);
+	srlz_i();
+	v = (vhpt_entry_t *) thash(page);
+	rr_write(vrn, rr_save.word);
+	srlz_i();
+	srlz_d();
+
+	return v;
+}
+
+/** Compare ASID and VPN against PTE.
+ *
+ * Interrupts must be disabled.
+ *
+ * @param page Address of virtual page including VRN bits.
+ * @param asid Address space identifier.
+ *
+ * @return True if page and asid match the page and asid of t, false otherwise.
+ */
+bool vhpt_compare(uintptr_t page, asid_t asid, vhpt_entry_t *v)
+{
+	region_register rr_save, rr;	
+	index_t vrn;
+	rid_t rid;
+	bool match;
+
+	ASSERT(v);
+
+	vrn = page >> VRN_SHIFT;
+	rid = ASID2RID(asid, vrn);
+	
+	rr_save.word = rr_read(vrn);
+	if (rr_save.map.rid == rid) {
+		/*
+		 * The RID is already in place, compare ttag with t and return.
+		 */
+		return ttag(page) == v->present.tag.tag_word;
+	}
+	
+	/*
+	 * The RID must be written to some region register.
+	 * To speed things up, register indexed by vrn is used.
+	 */
+	rr.word = rr_save.word;
+	rr.map.rid = rid;
+	rr_write(vrn, rr.word);
+	srlz_i();
+	match = (ttag(page) == v->present.tag.tag_word);
+	rr_write(vrn, rr_save.word);
+	srlz_i();
+	srlz_d();
+
+	return match;		
+}
+
+/** Set up one VHPT entry.
+ *
+ * @param v VHPT entry to be set up.
+ * @param page Virtual address of the page mapped by the entry.
+ * @param asid Address space identifier of the address space to which page belongs.
+ * @param frame Physical address of the frame to wich page is mapped.
+ * @param flags Different flags for the mapping.
+ */
+void vhpt_set_record(vhpt_entry_t *v, uintptr_t page, asid_t asid, uintptr_t frame, int flags)
+{
+	region_register rr_save, rr;	
+	index_t vrn;
+	rid_t rid;
+	uint64_t tag;
+
+	ASSERT(v);
+
+	vrn = page >> VRN_SHIFT;
+	rid = ASID2RID(asid, vrn);
+	
+	/*
+	 * Compute ttag.
+	 */
+	rr_save.word = rr_read(vrn);
+	rr.word = rr_save.word;
+	rr.map.rid = rid;
+	rr_write(vrn, rr.word);
+	srlz_i();
+	tag = ttag(page);
+	rr_write(vrn, rr_save.word);
+	srlz_i();
+	srlz_d();
+	
+	/*
+	 * Clear the entry.
+	 */
+	v->word[0] = 0;
+	v->word[1] = 0;
+	v->word[2] = 0;
+	v->word[3] = 0;
+	
+	v->present.p = true;
+	v->present.ma = (flags & PAGE_CACHEABLE) ? MA_WRITEBACK : MA_UNCACHEABLE;
+	v->present.a = false;	/* not accessed */
+	v->present.d = false;	/* not dirty */
+	v->present.pl = (flags & PAGE_USER) ? PL_USER : PL_KERNEL;
+	v->present.ar = (flags & PAGE_WRITE) ? AR_WRITE : AR_READ;
+	v->present.ar |= (flags & PAGE_EXEC) ? AR_EXECUTE : 0; 
+	v->present.ppn = frame >> PPN_SHIFT;
+	v->present.ed = false;	/* exception not deffered */
+	v->present.ps = PAGE_WIDTH;
+	v->present.key = 0;
+	v->present.tag.tag_word = tag;
+}
+
+ /** @}
+ */
+
Index: kernel/arch/ia64/src/mm/tlb.c
===================================================================
--- kernel/arch/ia64/src/mm/tlb.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/ia64/src/mm/tlb.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,690 @@
+/*
+ * Copyright (C) 2006 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ /** @addtogroup ia64mm	
+ * @{
+ */
+/** @file
+ */
+
+/*
+ * TLB management.
+ */
+
+#include <mm/tlb.h>
+#include <mm/asid.h>
+#include <mm/page.h>
+#include <mm/as.h>
+#include <arch/mm/tlb.h>
+#include <arch/mm/page.h>
+#include <arch/mm/vhpt.h>
+#include <arch/barrier.h>
+#include <arch/interrupt.h>
+#include <arch/pal/pal.h>
+#include <arch/asm.h>
+#include <typedefs.h>
+#include <panic.h>
+#include <print.h>
+#include <arch.h>
+#include <interrupt.h>
+
+/** Invalidate all TLB entries. */
+void tlb_invalidate_all(void)
+{
+		ipl_t ipl;
+		uintptr_t adr;
+		uint32_t count1, count2, stride1, stride2;
+		
+		int i,j;
+		
+		adr = PAL_PTCE_INFO_BASE();
+		count1 = PAL_PTCE_INFO_COUNT1();
+		count2 = PAL_PTCE_INFO_COUNT2();
+		stride1 = PAL_PTCE_INFO_STRIDE1();
+		stride2 = PAL_PTCE_INFO_STRIDE2();
+		
+		ipl = interrupts_disable();
+
+		for(i = 0; i < count1; i++) {
+			for(j = 0; j < count2; j++) {
+				__asm__ volatile (
+					"ptc.e %0 ;;"
+					:
+					: "r" (adr)
+				);
+				adr += stride2;
+			}
+			adr += stride1;
+		}
+
+		interrupts_restore(ipl);
+
+		srlz_d();
+		srlz_i();
+#ifdef CONFIG_VHPT
+		vhpt_invalidate_all();
+#endif	
+}
+
+/** Invalidate entries belonging to an address space.
+ *
+ * @param asid Address space identifier.
+ */
+void tlb_invalidate_asid(asid_t asid)
+{
+	tlb_invalidate_all();
+}
+
+
+void tlb_invalidate_pages(asid_t asid, uintptr_t page, count_t cnt)
+{
+	region_register rr;
+	bool restore_rr = false;
+	int b = 0;
+	int c = cnt;
+
+	uintptr_t va;
+	va = page;
+
+	rr.word = rr_read(VA2VRN(va));
+	if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN(va))))) {
+		/*
+		 * The selected region register does not contain required RID.
+		 * Save the old content of the register and replace the RID.
+		 */
+		region_register rr0;
+
+		rr0 = rr;
+		rr0.map.rid = ASID2RID(asid, VA2VRN(va));
+		rr_write(VA2VRN(va), rr0.word);
+		srlz_d();
+		srlz_i();
+	}
+	
+	while(c >>= 1)
+		b++;
+	b >>= 1;
+	uint64_t ps;
+	
+	switch (b) {
+		case 0: /*cnt 1-3*/
+			ps = PAGE_WIDTH;
+			break;
+		case 1: /*cnt 4-15*/
+			/*cnt=((cnt-1)/4)+1;*/
+			ps = PAGE_WIDTH+2;
+			va &= ~((1<<ps)-1);
+			break;
+		case 2: /*cnt 16-63*/
+			/*cnt=((cnt-1)/16)+1;*/
+			ps = PAGE_WIDTH+4;
+			va &= ~((1<<ps)-1);
+			break;
+		case 3: /*cnt 64-255*/
+			/*cnt=((cnt-1)/64)+1;*/
+			ps = PAGE_WIDTH+6;
+			va &= ~((1<<ps)-1);
+			break;
+		case 4: /*cnt 256-1023*/
+			/*cnt=((cnt-1)/256)+1;*/
+			ps = PAGE_WIDTH+8;
+			va &= ~((1<<ps)-1);
+			break;
+		case 5: /*cnt 1024-4095*/
+			/*cnt=((cnt-1)/1024)+1;*/
+			ps = PAGE_WIDTH+10;
+			va &= ~((1<<ps)-1);
+			break;
+		case 6: /*cnt 4096-16383*/
+			/*cnt=((cnt-1)/4096)+1;*/
+			ps = PAGE_WIDTH+12;
+			va &= ~((1<<ps)-1);
+			break;
+		case 7: /*cnt 16384-65535*/
+		case 8: /*cnt 65536-(256K-1)*/
+			/*cnt=((cnt-1)/16384)+1;*/
+			ps = PAGE_WIDTH+14;
+			va &= ~((1<<ps)-1);
+			break;
+		default:
+			/*cnt=((cnt-1)/(16384*16))+1;*/
+			ps=PAGE_WIDTH+18;
+			va&=~((1<<ps)-1);
+			break;
+	}
+	/*cnt+=(page!=va);*/
+	for(; va<(page+cnt*(PAGE_SIZE)); va += (1<<ps))	{
+		__asm__ volatile (
+			"ptc.l %0,%1;;"
+			:
+			: "r" (va), "r" (ps<<2)
+		);
+	}
+	srlz_d();
+	srlz_i();
+	
+	if (restore_rr) {
+		rr_write(VA2VRN(va), rr.word);
+		srlz_d();
+		srlz_i();
+	}
+}
+
+/** Insert data into data translation cache.
+ *
+ * @param va Virtual page address.
+ * @param asid Address space identifier.
+ * @param entry The rest of TLB entry as required by TLB insertion format.
+ */
+void dtc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry)
+{
+	tc_mapping_insert(va, asid, entry, true);
+}
+
+/** Insert data into instruction translation cache.
+ *
+ * @param va Virtual page address.
+ * @param asid Address space identifier.
+ * @param entry The rest of TLB entry as required by TLB insertion format.
+ */
+void itc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry)
+{
+	tc_mapping_insert(va, asid, entry, false);
+}
+
+/** Insert data into instruction or data translation cache.
+ *
+ * @param va Virtual page address.
+ * @param asid Address space identifier.
+ * @param entry The rest of TLB entry as required by TLB insertion format.
+ * @param dtc If true, insert into data translation cache, use instruction translation cache otherwise.
+ */
+void tc_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtc)
+{
+	region_register rr;
+	bool restore_rr = false;
+
+	rr.word = rr_read(VA2VRN(va));
+	if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN(va))))) {
+		/*
+		 * The selected region register does not contain required RID.
+		 * Save the old content of the register and replace the RID.
+		 */
+		region_register rr0;
+
+		rr0 = rr;
+		rr0.map.rid = ASID2RID(asid, VA2VRN(va));
+		rr_write(VA2VRN(va), rr0.word);
+		srlz_d();
+		srlz_i();
+	}
+	
+	__asm__ volatile (
+		"mov r8=psr;;\n"
+		"rsm %0;;\n"   			/* PSR_IC_MASK */
+		"srlz.d;;\n"
+		"srlz.i;;\n"
+		"mov cr.ifa=%1\n"		/* va */
+		"mov cr.itir=%2;;\n"		/* entry.word[1] */
+		"cmp.eq p6,p7 = %4,r0;;\n"	/* decide between itc and dtc */ 
+		"(p6) itc.i %3;;\n"
+		"(p7) itc.d %3;;\n"
+		"mov psr.l=r8;;\n"
+		"srlz.d;;\n"
+		:
+		: "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (dtc)
+		: "p6", "p7", "r8"
+	);
+	
+	if (restore_rr) {
+		rr_write(VA2VRN(va), rr.word);
+		srlz_d();
+		srlz_i();
+	}
+}
+
+/** Insert data into instruction translation register.
+ *
+ * @param va Virtual page address.
+ * @param asid Address space identifier.
+ * @param entry The rest of TLB entry as required by TLB insertion format.
+ * @param tr Translation register.
+ */
+void itr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr)
+{
+	tr_mapping_insert(va, asid, entry, false, tr);
+}
+
+/** Insert data into data translation register.
+ *
+ * @param va Virtual page address.
+ * @param asid Address space identifier.
+ * @param entry The rest of TLB entry as required by TLB insertion format.
+ * @param tr Translation register.
+ */
+void dtr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, index_t tr)
+{
+	tr_mapping_insert(va, asid, entry, true, tr);
+}
+
+/** Insert data into instruction or data translation register.
+ *
+ * @param va Virtual page address.
+ * @param asid Address space identifier.
+ * @param entry The rest of TLB entry as required by TLB insertion format.
+ * @param dtr If true, insert into data translation register, use instruction translation register otherwise.
+ * @param tr Translation register.
+ */
+void tr_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry, bool dtr, index_t tr)
+{
+	region_register rr;
+	bool restore_rr = false;
+
+	rr.word = rr_read(VA2VRN(va));
+	if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN(va))))) {
+		/*
+		 * The selected region register does not contain required RID.
+		 * Save the old content of the register and replace the RID.
+		 */
+		region_register rr0;
+
+		rr0 = rr;
+		rr0.map.rid = ASID2RID(asid, VA2VRN(va));
+		rr_write(VA2VRN(va), rr0.word);
+		srlz_d();
+		srlz_i();
+	}
+
+	__asm__ volatile (
+		"mov r8=psr;;\n"
+		"rsm %0;;\n"			/* PSR_IC_MASK */
+		"srlz.d;;\n"
+		"srlz.i;;\n"
+		"mov cr.ifa=%1\n"        	/* va */		 
+		"mov cr.itir=%2;;\n"		/* entry.word[1] */ 
+		"cmp.eq p6,p7=%5,r0;;\n"	/* decide between itr and dtr */
+		"(p6) itr.i itr[%4]=%3;;\n"
+		"(p7) itr.d dtr[%4]=%3;;\n"
+		"mov psr.l=r8;;\n"
+		"srlz.d;;\n"
+		:
+		: "i" (PSR_IC_MASK), "r" (va), "r" (entry.word[1]), "r" (entry.word[0]), "r" (tr), "r" (dtr)
+		: "p6", "p7", "r8"
+	);
+	
+	if (restore_rr) {
+		rr_write(VA2VRN(va), rr.word);
+		srlz_d();
+		srlz_i();
+	}
+}
+
+/** Insert data into DTLB.
+ *
+ * @param page Virtual page address including VRN bits.
+ * @param frame Physical frame address.
+ * @param dtr If true, insert into data translation register, use data translation cache otherwise.
+ * @param tr Translation register if dtr is true, ignored otherwise.
+ */
+void dtlb_kernel_mapping_insert(uintptr_t page, uintptr_t frame, bool dtr, index_t tr)
+{
+	tlb_entry_t entry;
+	
+	entry.word[0] = 0;
+	entry.word[1] = 0;
+	
+	entry.p = true;			/* present */
+	entry.ma = MA_WRITEBACK;
+	entry.a = true;			/* already accessed */
+	entry.d = true;			/* already dirty */
+	entry.pl = PL_KERNEL;
+	entry.ar = AR_READ | AR_WRITE;
+	entry.ppn = frame >> PPN_SHIFT;
+	entry.ps = PAGE_WIDTH;
+	
+	if (dtr)
+		dtr_mapping_insert(page, ASID_KERNEL, entry, tr);
+	else
+		dtc_mapping_insert(page, ASID_KERNEL, entry);
+}
+
+/** Purge kernel entries from DTR.
+ *
+ * Purge DTR entries used by the kernel.
+ *
+ * @param page Virtual page address including VRN bits.
+ * @param width Width of the purge in bits.
+ */
+void dtr_purge(uintptr_t page, count_t width)
+{
+	__asm__ volatile ("ptr.d %0, %1\n" : : "r" (page), "r" (width<<2));
+}
+
+
+/** Copy content of PTE into data translation cache.
+ *
+ * @param t PTE.
+ */
+void dtc_pte_copy(pte_t *t)
+{
+	tlb_entry_t entry;
+
+	entry.word[0] = 0;
+	entry.word[1] = 0;
+	
+	entry.p = t->p;
+	entry.ma = t->c ? MA_WRITEBACK : MA_UNCACHEABLE;
+	entry.a = t->a;
+	entry.d = t->d;
+	entry.pl = t->k ? PL_KERNEL : PL_USER;
+	entry.ar = t->w ? AR_WRITE : AR_READ;
+	entry.ppn = t->frame >> PPN_SHIFT;
+	entry.ps = PAGE_WIDTH;
+	
+	dtc_mapping_insert(t->page, t->as->asid, entry);
+#ifdef CONFIG_VHPT
+	vhpt_mapping_insert(t->page, t->as->asid, entry);
+#endif	
+}
+
+/** Copy content of PTE into instruction translation cache.
+ *
+ * @param t PTE.
+ */
+void itc_pte_copy(pte_t *t)
+{
+	tlb_entry_t entry;
+
+	entry.word[0] = 0;
+	entry.word[1] = 0;
+	
+	ASSERT(t->x);
+	
+	entry.p = t->p;
+	entry.ma = t->c ? MA_WRITEBACK : MA_UNCACHEABLE;
+	entry.a = t->a;
+	entry.pl = t->k ? PL_KERNEL : PL_USER;
+	entry.ar = t->x ? (AR_EXECUTE | AR_READ) : AR_READ;
+	entry.ppn = t->frame >> PPN_SHIFT;
+	entry.ps = PAGE_WIDTH;
+	
+	itc_mapping_insert(t->page, t->as->asid, entry);
+#ifdef CONFIG_VHPT
+	vhpt_mapping_insert(t->page, t->as->asid, entry);
+#endif	
+}
+
+/** Instruction TLB fault handler for faults with VHPT turned off.
+ *
+ * @param vector Interruption vector.
+ * @param istate Structure with saved interruption state.
+ */
+void alternate_instruction_tlb_fault(uint64_t vector, istate_t *istate)
+{
+	region_register rr;
+	rid_t rid;
+	uintptr_t va;
+	pte_t *t;
+	
+	va = istate->cr_ifa;	/* faulting address */
+	rr.word = rr_read(VA2VRN(va));
+	rid = rr.map.rid;
+
+	page_table_lock(AS, true);
+	t = page_mapping_find(AS, va);
+	if (t) {
+		/*
+		 * The mapping was found in software page hash table.
+		 * Insert it into data translation cache.
+		 */
+		itc_pte_copy(t);
+		page_table_unlock(AS, true);
+	} else {
+		/*
+		 * Forward the page fault to address space page fault handler.
+		 */
+		page_table_unlock(AS, true);
+		if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) {
+			fault_if_from_uspace(istate,"Page fault at %p",va);
+			panic("%s: va=%p, rid=%d, iip=%p\n", __FUNCTION__, va, rid, istate->cr_iip);
+		}
+	}
+}
+
+/** Data TLB fault handler for faults with VHPT turned off.
+ *
+ * @param vector Interruption vector.
+ * @param istate Structure with saved interruption state.
+ */
+void alternate_data_tlb_fault(uint64_t vector, istate_t *istate)
+{
+	region_register rr;
+	rid_t rid;
+	uintptr_t va;
+	pte_t *t;
+	
+	va = istate->cr_ifa;	/* faulting address */
+	rr.word = rr_read(VA2VRN(va));
+	rid = rr.map.rid;
+	if (RID2ASID(rid) == ASID_KERNEL) {
+		if (VA2VRN(va) == VRN_KERNEL) {
+			/*
+			 * Provide KA2PA(identity) mapping for faulting piece of
+			 * kernel address space.
+			 */
+			dtlb_kernel_mapping_insert(va, KA2PA(va), false, 0);
+			return;
+		}
+	}
+
+	page_table_lock(AS, true);
+	t = page_mapping_find(AS, va);
+	if (t) {
+		/*
+		 * The mapping was found in software page hash table.
+		 * Insert it into data translation cache.
+		 */
+		dtc_pte_copy(t);
+		page_table_unlock(AS, true);
+	} else {
+		/*
+		 * Forward the page fault to address space page fault handler.
+		 */
+		page_table_unlock(AS, true);
+		if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
+			fault_if_from_uspace(istate,"Page fault at %p",va);
+			panic("%s: va=%p, rid=%d, iip=%p\n", __FUNCTION__, va, rid, istate->cr_iip);
+		}
+	}
+}
+
+/** Data nested TLB fault handler.
+ *
+ * This fault should not occur.
+ *
+ * @param vector Interruption vector.
+ * @param istate Structure with saved interruption state.
+ */
+void data_nested_tlb_fault(uint64_t vector, istate_t *istate)
+{
+	panic("%s\n", __FUNCTION__);
+}
+
+/** Data Dirty bit fault handler.
+ *
+ * @param vector Interruption vector.
+ * @param istate Structure with saved interruption state.
+ */
+void data_dirty_bit_fault(uint64_t vector, istate_t *istate)
+{
+	region_register rr;
+	rid_t rid;
+	uintptr_t va;
+	pte_t *t;
+	
+	va = istate->cr_ifa;	/* faulting address */
+	rr.word = rr_read(VA2VRN(va));
+	rid = rr.map.rid;
+
+	page_table_lock(AS, true);
+	t = page_mapping_find(AS, va);
+	ASSERT(t && t->p);
+	if (t && t->p && t->w) {
+		/*
+		 * Update the Dirty bit in page tables and reinsert
+		 * the mapping into DTC.
+		 */
+		t->d = true;
+		dtc_pte_copy(t);
+	} else {
+		if (as_page_fault(va, PF_ACCESS_WRITE, istate) == AS_PF_FAULT) {
+			fault_if_from_uspace(istate,"Page fault at %p",va);
+			panic("%s: va=%p, rid=%d, iip=%p\n", __FUNCTION__, va, rid, istate->cr_iip);
+			t->d = true;
+			dtc_pte_copy(t);
+		}
+	}
+	page_table_unlock(AS, true);
+}
+
+/** Instruction access bit fault handler.
+ *
+ * @param vector Interruption vector.
+ * @param istate Structure with saved interruption state.
+ */
+void instruction_access_bit_fault(uint64_t vector, istate_t *istate)
+{
+	region_register rr;
+	rid_t rid;
+	uintptr_t va;
+	pte_t *t;	
+
+	va = istate->cr_ifa;	/* faulting address */
+	rr.word = rr_read(VA2VRN(va));
+	rid = rr.map.rid;
+
+	page_table_lock(AS, true);
+	t = page_mapping_find(AS, va);
+	ASSERT(t && t->p);
+	if (t && t->p && t->x) {
+		/*
+		 * Update the Accessed bit in page tables and reinsert
+		 * the mapping into ITC.
+		 */
+		t->a = true;
+		itc_pte_copy(t);
+	} else {
+		if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) {
+			fault_if_from_uspace(istate,"Page fault at %p",va);
+			panic("%s: va=%p, rid=%d, iip=%p\n", __FUNCTION__, va, rid, istate->cr_iip);
+			t->a = true;
+			itc_pte_copy(t);
+		}
+	}
+	page_table_unlock(AS, true);
+}
+
+/** Data access bit fault handler.
+ *
+ * @param vector Interruption vector.
+ * @param istate Structure with saved interruption state.
+ */
+void data_access_bit_fault(uint64_t vector, istate_t *istate)
+{
+	region_register rr;
+	rid_t rid;
+	uintptr_t va;
+	pte_t *t;
+
+	va = istate->cr_ifa;	/* faulting address */
+	rr.word = rr_read(VA2VRN(va));
+	rid = rr.map.rid;
+
+	page_table_lock(AS, true);
+	t = page_mapping_find(AS, va);
+	ASSERT(t && t->p);
+	if (t && t->p) {
+		/*
+		 * Update the Accessed bit in page tables and reinsert
+		 * the mapping into DTC.
+		 */
+		t->a = true;
+		dtc_pte_copy(t);
+	} else {
+		if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
+			fault_if_from_uspace(istate,"Page fault at %p",va);
+			panic("%s: va=%p, rid=%d, iip=%p\n", __FUNCTION__, va, rid, istate->cr_iip);
+			t->a = true;
+			itc_pte_copy(t);
+		}
+	}
+	page_table_unlock(AS, true);
+}
+
+/** Page not present fault handler.
+ *
+ * @param vector Interruption vector.
+ * @param istate Structure with saved interruption state.
+ */
+void page_not_present(uint64_t vector, istate_t *istate)
+{
+	region_register rr;
+	rid_t rid;
+	uintptr_t va;
+	pte_t *t;
+	
+	va = istate->cr_ifa;	/* faulting address */
+	rr.word = rr_read(VA2VRN(va));
+	rid = rr.map.rid;
+
+	page_table_lock(AS, true);
+	t = page_mapping_find(AS, va);
+	ASSERT(t);
+	
+	if (t->p) {
+		/*
+		 * If the Present bit is set in page hash table, just copy it
+		 * and update ITC/DTC.
+		 */
+		if (t->x)
+			itc_pte_copy(t);
+		else
+			dtc_pte_copy(t);
+		page_table_unlock(AS, true);
+	} else {
+		page_table_unlock(AS, true);
+		if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
+			fault_if_from_uspace(istate,"Page fault at %p",va);
+			panic("%s: va=%p, rid=%d\n", __FUNCTION__, va, rid);
+		}
+	}
+}
+
+ /** @}
+ */
+
Index: kernel/arch/ia64/src/mm/vhpt.c
===================================================================
--- kernel/arch/ia64/src/mm/vhpt.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
+++ kernel/arch/ia64/src/mm/vhpt.c	(revision 1167520724b9b526c27b67f2d4bc447ef626240c)
@@ -0,0 +1,99 @@
+/*
+* Copyright (C) 2006 Jakub Vana
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* - Redistributions of source code must retain the above copyright
+*   notice, this list of conditions and the following disclaimer.
+* - Redistributions in binary form must reproduce the above copyright
+*   notice, this list of conditions and the following disclaimer in the
+*   documentation and/or other materials provided with the distribution.
+* - The name of the author may not be used to endorse or promote products
+*   derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ /** @addtogroup ia64mm	
+ * @{
+ */
+/** @file
+*/
+													
+
+#include <arch/mm/vhpt.h>
+#include <mm/frame.h>
+#include <print.h>
+
+
+static vhpt_entry_t* vhpt_base;
+
+uintptr_t vhpt_set_up(void)
+{
+	vhpt_base = frame_alloc(VHPT_WIDTH-FRAME_WIDTH,FRAME_KA | FRAME_ATOMIC);
+	if(!vhpt_base) 
+		panic("Kernel configured with VHPT but no memory for table.");
+	vhpt_invalidate_all();
+	return (uintptr_t) vhpt_base;
+}
+
+
+void vhpt_mapping_insert(uintptr_t va, asid_t asid, tlb_entry_t entry)
+{
+	region_register rr_save, rr;
+	index_t vrn;
+	rid_t rid;
+	uint64_t tag;
+
+	vhpt_entry_t *ventry;
+
+
+	vrn = va >> VRN_SHIFT;
+	rid = ASID2RID(asid, vrn);
+																												
+  rr_save.word = rr_read(vrn);
+  rr.word = rr_save.word;
+  rr.map.rid = rid;
+  rr_write(vrn, rr.word);
+  srlz_i();
+	
+	ventry = (vhpt_entry_t *) thash(va);
+  tag = ttag(va);
+  rr_write(vrn, rr_save.word);
+  srlz_i();
+  srlz_d();
+
+	ventry->word[0]=entry.word[0];
+	ventry->word[1]=entry.word[1];
+	ventry->present.tag.tag_word = tag;
+	
+
+}
+
+void vhpt_invalidate_all()
+{
+	memsetb((uintptr_t)vhpt_base,1<<VHPT_WIDTH,0);
+}
+
+void vhpt_invalidate_asid(asid_t asid)
+{
+	vhpt_invalidate_all();
+}
+
+
+
+ /** @}
+ */
+
