From a48212cb65e09669ed243581556529681cebba0a Mon Sep 17 00:00:00 2001 From: "iap10@labyrinth.cl.cam.ac.uk" Date: Mon, 24 Feb 2003 16:55:07 +0000 Subject: bitkeeper revision 1.93 (3e5a4e6bkPheUp3x1uufN2MS3LAB7A) Latest and Greatest version of XenoLinux based on the Linux-2.4.21-pre4 kernel. --- .../arch/xeno/mm/hypervisor.c | 168 +++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 old/xenolinux-2.4.16-sparse/arch/xeno/mm/hypervisor.c (limited to 'old/xenolinux-2.4.16-sparse/arch/xeno/mm/hypervisor.c') diff --git a/old/xenolinux-2.4.16-sparse/arch/xeno/mm/hypervisor.c b/old/xenolinux-2.4.16-sparse/arch/xeno/mm/hypervisor.c new file mode 100644 index 0000000000..b051684aa2 --- /dev/null +++ b/old/xenolinux-2.4.16-sparse/arch/xeno/mm/hypervisor.c @@ -0,0 +1,168 @@ +/****************************************************************************** + * xeno/mm/hypervisor.c + * + * Update page tables via the hypervisor. + * + * Copyright (c) 2002, K A Fraser + */ + +#include +#include +#include +#include +#include + +#define QUEUE_SIZE 2048 +static page_update_request_t update_queue[QUEUE_SIZE]; +unsigned int pt_update_queue_idx = 0; +#define idx pt_update_queue_idx + +#if PT_UPDATE_DEBUG > 0 +page_update_debug_t update_debug_queue[QUEUE_SIZE] = {{0}}; +#undef queue_l1_entry_update +#undef queue_l2_entry_update +static void DEBUG_allow_pt_reads(void) +{ + pte_t *pte; + page_update_request_t update; + int i; + for ( i = idx-1; i >= 0; i-- ) + { + pte = update_debug_queue[i].ptep; + if ( pte == NULL ) continue; + update_debug_queue[i].ptep = NULL; + update.ptr = phys_to_machine(__pa(pte)); + update.val = update_debug_queue[i].pteval; + HYPERVISOR_pt_update(&update, 1); + } +} +static void DEBUG_disallow_pt_read(unsigned long pa) +{ + pte_t *pte; + pmd_t *pmd; + pgd_t *pgd; + unsigned long pteval; + /* + * We may fault because of an already outstanding update. + * That's okay -- it'll get fixed up in the fault handler. + */ + page_update_request_t update; + unsigned long va = (unsigned long)__va(pa); + pgd = pgd_offset_k(va); + pmd = pmd_offset(pgd, va); + pte = pte_offset(pmd, va); + update.ptr = phys_to_machine(__pa(pte)); + pteval = *(unsigned long *)pte; + update.val = pteval & ~_PAGE_PRESENT; + HYPERVISOR_pt_update(&update, 1); + update_debug_queue[idx].ptep = pte; + update_debug_queue[idx].pteval = pteval; +} +#endif + +#if PT_UPDATE_DEBUG > 1 +#undef queue_pt_switch +#undef queue_tlb_flush +#undef queue_invlpg +#undef queue_pgd_pin +#undef queue_pgd_unpin +#undef queue_pte_pin +#undef queue_pte_unpin +#endif + + +/* + * This is the current pagetable base pointer, which is updated + * on context switch. + */ +unsigned long pt_baseptr; + +void _flush_page_update_queue(void) +{ + if ( idx == 0 ) return; +#if PT_UPDATE_DEBUG > 1 + printk("Flushing %d entries from pt update queue\n", idx); +#endif +#if PT_UPDATE_DEBUG > 0 + DEBUG_allow_pt_reads(); +#endif + HYPERVISOR_pt_update(update_queue, idx); + idx = 0; +} + +static void increment_index(void) +{ + if ( ++idx == QUEUE_SIZE ) _flush_page_update_queue(); +} + +void queue_l1_entry_update(unsigned long ptr, unsigned long val) +{ +#if PT_UPDATE_DEBUG > 0 + DEBUG_disallow_pt_read(ptr); +#endif + update_queue[idx].ptr = phys_to_machine(ptr); + update_queue[idx].val = val; + increment_index(); +} + +void queue_l2_entry_update(unsigned long ptr, unsigned long val) +{ + update_queue[idx].ptr = phys_to_machine(ptr); + update_queue[idx].val = val; + increment_index(); +} + +void queue_pt_switch(unsigned long ptr) +{ + update_queue[idx].ptr = phys_to_machine(ptr); + update_queue[idx].ptr |= PGREQ_EXTENDED_COMMAND; + update_queue[idx].val = PGEXT_NEW_BASEPTR; + increment_index(); +} + +void queue_tlb_flush(void) +{ + update_queue[idx].ptr = PGREQ_EXTENDED_COMMAND; + update_queue[idx].val = PGEXT_TLB_FLUSH; + increment_index(); +} + +void queue_invlpg(unsigned long ptr) +{ + update_queue[idx].ptr = PGREQ_EXTENDED_COMMAND; + update_queue[idx].val = ptr & PAGE_MASK; + update_queue[idx].val |= PGEXT_INVLPG; + increment_index(); +} + +void queue_pgd_pin(unsigned long ptr) +{ + update_queue[idx].ptr = phys_to_machine(ptr); + update_queue[idx].ptr |= PGREQ_EXTENDED_COMMAND; + update_queue[idx].val = PGEXT_PIN_L2_TABLE; + increment_index(); +} + +void queue_pgd_unpin(unsigned long ptr) +{ + update_queue[idx].ptr = phys_to_machine(ptr); + update_queue[idx].ptr |= PGREQ_EXTENDED_COMMAND; + update_queue[idx].val = PGEXT_UNPIN_TABLE; + increment_index(); +} + +void queue_pte_pin(unsigned long ptr) +{ + update_queue[idx].ptr = phys_to_machine(ptr); + update_queue[idx].ptr |= PGREQ_EXTENDED_COMMAND; + update_queue[idx].val = PGEXT_PIN_L1_TABLE; + increment_index(); +} + +void queue_pte_unpin(unsigned long ptr) +{ + update_queue[idx].ptr = phys_to_machine(ptr); + update_queue[idx].ptr |= PGREQ_EXTENDED_COMMAND; + update_queue[idx].val = PGEXT_UNPIN_TABLE; + increment_index(); +} -- cgit v1.2.3