version 1.12, 2008/11/13 18:44:51 |
version 1.12.4.15, 2011/08/27 15:37:32 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
|
* must display the following acknowledgement: |
|
* This product includes software developed by Manuel Bouyer. |
|
* 4. 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 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
* 2. Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* documentation and/or other materials provided with the distribution. |
* 3. All advertising materials mentioning features or use of this software |
|
* must display the following acknowledgement: |
|
* This product includes software developed by Christian Limpach. |
|
* 4. 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 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
Line 87 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 77 __KERNEL_RCSID(0, "$NetBSD$"); |
|
|
|
#include <sys/param.h> |
#include <sys/param.h> |
#include <sys/systm.h> |
#include <sys/systm.h> |
|
#include <sys/simplelock.h> |
|
|
#include <uvm/uvm.h> |
#include <uvm/uvm.h> |
|
|
Line 129 unsigned long *xpmap_phys_to_machine_map |
|
Line 120 unsigned long *xpmap_phys_to_machine_map |
|
|
|
void xen_failsafe_handler(void); |
void xen_failsafe_handler(void); |
|
|
#ifdef XEN3 |
|
#define HYPERVISOR_mmu_update_self(req, count, success_count) \ |
#define HYPERVISOR_mmu_update_self(req, count, success_count) \ |
HYPERVISOR_mmu_update((req), (count), (success_count), DOMID_SELF) |
HYPERVISOR_mmu_update((req), (count), (success_count), DOMID_SELF) |
#else |
|
#define HYPERVISOR_mmu_update_self(req, count, success_count) \ |
|
HYPERVISOR_mmu_update((req), (count), (success_count)) |
|
#endif |
|
|
|
void |
void |
xen_failsafe_handler(void) |
xen_failsafe_handler(void) |
Line 162 xen_set_ldt(vaddr_t base, uint32_t entri |
|
Line 148 xen_set_ldt(vaddr_t base, uint32_t entri |
|
for (va = base; va < end; va += PAGE_SIZE) { |
for (va = base; va < end; va += PAGE_SIZE) { |
KASSERT(va >= VM_MIN_KERNEL_ADDRESS); |
KASSERT(va >= VM_MIN_KERNEL_ADDRESS); |
ptp = kvtopte(va); |
ptp = kvtopte(va); |
XENPRINTF(("xen_set_ldt %p %d %p\n", (void *)base, |
XENPRINTF(("xen_set_ldt %#" PRIxVADDR " %d %p\n", |
entries, ptp)); |
base, entries, ptp)); |
pmap_pte_clearbits(ptp, PG_RW); |
pmap_pte_clearbits(ptp, PG_RW); |
} |
} |
s = splvm(); |
s = splvm(); |
|
xpq_queue_lock(); |
xpq_queue_set_ldt(base, entries); |
xpq_queue_set_ldt(base, entries); |
xpq_flush_queue(); |
xpq_queue_unlock(); |
splx(s); |
splx(s); |
} |
} |
|
|
Line 180 void xpq_debug_dump(void); |
|
Line 167 void xpq_debug_dump(void); |
|
static mmu_update_t xpq_queue[XPQUEUE_SIZE]; |
static mmu_update_t xpq_queue[XPQUEUE_SIZE]; |
static int xpq_idx = 0; |
static int xpq_idx = 0; |
|
|
|
#ifdef MULTIPROCESSOR |
|
static struct simplelock xpq_lock = SIMPLELOCK_INITIALIZER; |
|
|
|
void |
|
xpq_queue_lock(void) |
|
{ |
|
simple_lock(&xpq_lock); |
|
} |
|
|
|
void |
|
xpq_queue_unlock(void) |
|
{ |
|
simple_unlock(&xpq_lock); |
|
} |
|
|
|
bool |
|
xpq_queue_locked(void) |
|
{ |
|
return simple_lock_held(&xpq_lock); |
|
} |
|
#endif /* MULTIPROCESSOR */ |
|
|
|
/* Must be called with xpq_lock held */ |
void |
void |
xpq_flush_queue(void) |
xpq_flush_queue(void) |
{ |
{ |
int i, ok; |
int i, ok, ret; |
|
|
|
KASSERT(xpq_queue_locked()); |
XENPRINTK2(("flush queue %p entries %d\n", xpq_queue, xpq_idx)); |
XENPRINTK2(("flush queue %p entries %d\n", xpq_queue, xpq_idx)); |
for (i = 0; i < xpq_idx; i++) |
for (i = 0; i < xpq_idx; i++) |
XENPRINTK2(("%d: %p %08" PRIx64 "\n", i, |
XENPRINTK2(("%d: 0x%08" PRIx64 " 0x%08" PRIx64 "\n", i, |
(uint64_t)xpq_queue[i].ptr, (uint64_t)xpq_queue[i].val)); |
xpq_queue[i].ptr, xpq_queue[i].val)); |
if (xpq_idx != 0 && |
|
HYPERVISOR_mmu_update_self(xpq_queue, xpq_idx, &ok) < 0) { |
ret = HYPERVISOR_mmu_update_self(xpq_queue, xpq_idx, &ok); |
printf("xpq_flush_queue: %d entries \n", xpq_idx); |
|
|
if (xpq_idx != 0 && ret < 0) { |
|
printf("xpq_flush_queue: %d entries (%d successful)\n", |
|
xpq_idx, ok); |
for (i = 0; i < xpq_idx; i++) |
for (i = 0; i < xpq_idx; i++) |
printf("0x%016" PRIx64 ": 0x%016" PRIx64 "\n", |
printf("0x%016" PRIx64 ": 0x%016" PRIx64 "\n", |
(uint64_t)xpq_queue[i].ptr, |
xpq_queue[i].ptr, xpq_queue[i].val); |
(uint64_t)xpq_queue[i].val); |
panic("HYPERVISOR_mmu_update failed, ret: %d\n", ret); |
panic("HYPERVISOR_mmu_update failed\n"); |
|
} |
} |
xpq_idx = 0; |
xpq_idx = 0; |
} |
} |
|
|
|
/* Must be called with xpq_lock held */ |
static inline void |
static inline void |
xpq_increment_idx(void) |
xpq_increment_idx(void) |
{ |
{ |
|
|
|
KASSERT(xpq_queue_locked()); |
xpq_idx++; |
xpq_idx++; |
if (__predict_false(xpq_idx == XPQUEUE_SIZE)) |
if (__predict_false(xpq_idx == XPQUEUE_SIZE)) |
xpq_flush_queue(); |
xpq_flush_queue(); |
Line 215 xpq_queue_machphys_update(paddr_t ma, pa |
|
Line 230 xpq_queue_machphys_update(paddr_t ma, pa |
|
{ |
{ |
XENPRINTK2(("xpq_queue_machphys_update ma=0x%" PRIx64 " pa=0x%" PRIx64 |
XENPRINTK2(("xpq_queue_machphys_update ma=0x%" PRIx64 " pa=0x%" PRIx64 |
"\n", (int64_t)ma, (int64_t)pa)); |
"\n", (int64_t)ma, (int64_t)pa)); |
|
KASSERT(xpq_queue_locked()); |
xpq_queue[xpq_idx].ptr = ma | MMU_MACHPHYS_UPDATE; |
xpq_queue[xpq_idx].ptr = ma | MMU_MACHPHYS_UPDATE; |
xpq_queue[xpq_idx].val = (pa - XPMAP_OFFSET) >> PAGE_SHIFT; |
xpq_queue[xpq_idx].val = (pa - XPMAP_OFFSET) >> PAGE_SHIFT; |
xpq_increment_idx(); |
xpq_increment_idx(); |
Line 228 xpq_queue_pte_update(paddr_t ptr, pt_ent |
|
Line 244 xpq_queue_pte_update(paddr_t ptr, pt_ent |
|
{ |
{ |
|
|
KASSERT((ptr & 3) == 0); |
KASSERT((ptr & 3) == 0); |
|
KASSERT(xpq_queue_locked()); |
xpq_queue[xpq_idx].ptr = (paddr_t)ptr | MMU_NORMAL_PT_UPDATE; |
xpq_queue[xpq_idx].ptr = (paddr_t)ptr | MMU_NORMAL_PT_UPDATE; |
xpq_queue[xpq_idx].val = val; |
xpq_queue[xpq_idx].val = val; |
xpq_increment_idx(); |
xpq_increment_idx(); |
Line 236 xpq_queue_pte_update(paddr_t ptr, pt_ent |
|
Line 253 xpq_queue_pte_update(paddr_t ptr, pt_ent |
|
#endif |
#endif |
} |
} |
|
|
#ifdef XEN3 |
|
void |
void |
xpq_queue_pt_switch(paddr_t pa) |
xpq_queue_pt_switch(paddr_t pa) |
{ |
{ |
struct mmuext_op op; |
struct mmuext_op op; |
|
KASSERT(xpq_queue_locked()); |
xpq_flush_queue(); |
xpq_flush_queue(); |
|
|
XENPRINTK2(("xpq_queue_pt_switch: 0x%" PRIx64 " 0x%" PRIx64 "\n", |
XENPRINTK2(("xpq_queue_pt_switch: 0x%" PRIx64 " 0x%" PRIx64 "\n", |
Line 252 xpq_queue_pt_switch(paddr_t pa) |
|
Line 269 xpq_queue_pt_switch(paddr_t pa) |
|
} |
} |
|
|
void |
void |
xpq_queue_pin_table(paddr_t pa) |
xpq_queue_pin_table(paddr_t pa, int lvl) |
{ |
{ |
struct mmuext_op op; |
struct mmuext_op op; |
xpq_flush_queue(); |
|
|
|
XENPRINTK2(("xpq_queue_pin_table: 0x%" PRIx64 " 0x%" PRIx64 "\n", |
|
(int64_t)pa, (int64_t)pa)); |
|
op.arg1.mfn = pa >> PAGE_SHIFT; |
|
|
|
#if defined(__x86_64__) |
|
op.cmd = MMUEXT_PIN_L4_TABLE; |
|
#else |
|
op.cmd = MMUEXT_PIN_L2_TABLE; |
|
#endif |
|
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) |
|
panic("xpq_queue_pin_table"); |
|
} |
|
|
|
#ifdef PAE |
KASSERT(xpq_queue_locked()); |
static void |
|
xpq_queue_pin_l3_table(paddr_t pa) |
|
{ |
|
struct mmuext_op op; |
|
xpq_flush_queue(); |
xpq_flush_queue(); |
|
|
XENPRINTK2(("xpq_queue_pin_l2_table: 0x%" PRIx64 " 0x%" PRIx64 "\n", |
XENPRINTK2(("xpq_queue_pin_l%d_table: %#" PRIxPADDR "\n", |
(int64_t)pa, (int64_t)pa)); |
lvl + 1, pa)); |
|
|
op.arg1.mfn = pa >> PAGE_SHIFT; |
op.arg1.mfn = pa >> PAGE_SHIFT; |
|
op.cmd = lvl; |
|
|
op.cmd = MMUEXT_PIN_L3_TABLE; |
|
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) |
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) |
panic("xpq_queue_pin_table"); |
panic("xpq_queue_pin_table"); |
} |
} |
#endif |
|
|
|
void |
void |
xpq_queue_unpin_table(paddr_t pa) |
xpq_queue_unpin_table(paddr_t pa) |
{ |
{ |
struct mmuext_op op; |
struct mmuext_op op; |
|
|
|
KASSERT(xpq_queue_locked()); |
xpq_flush_queue(); |
xpq_flush_queue(); |
|
|
XENPRINTK2(("xpq_queue_unpin_table: 0x%" PRIx64 " 0x%" PRIx64 "\n", |
XENPRINTK2(("xpq_queue_unpin_table: %#" PRIxPADDR "\n", pa)); |
(int64_t)pa, (int64_t)pa)); |
|
op.arg1.mfn = pa >> PAGE_SHIFT; |
op.arg1.mfn = pa >> PAGE_SHIFT; |
op.cmd = MMUEXT_UNPIN_TABLE; |
op.cmd = MMUEXT_UNPIN_TABLE; |
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) |
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) |
|
|
xpq_queue_set_ldt(vaddr_t va, uint32_t entries) |
xpq_queue_set_ldt(vaddr_t va, uint32_t entries) |
{ |
{ |
struct mmuext_op op; |
struct mmuext_op op; |
|
|
|
KASSERT(xpq_queue_locked()); |
xpq_flush_queue(); |
xpq_flush_queue(); |
|
|
XENPRINTK2(("xpq_queue_set_ldt\n")); |
XENPRINTK2(("xpq_queue_set_ldt\n")); |
|
|
xpq_queue_tlb_flush(void) |
xpq_queue_tlb_flush(void) |
{ |
{ |
struct mmuext_op op; |
struct mmuext_op op; |
|
|
|
KASSERT(xpq_queue_locked()); |
xpq_flush_queue(); |
xpq_flush_queue(); |
|
|
XENPRINTK2(("xpq_queue_tlb_flush\n")); |
XENPRINTK2(("xpq_queue_tlb_flush\n")); |
|
|
xpq_flush_cache(void) |
xpq_flush_cache(void) |
{ |
{ |
struct mmuext_op op; |
struct mmuext_op op; |
int s = splvm(); |
int s = splvm(), err; |
|
|
|
xpq_queue_lock(); |
xpq_flush_queue(); |
xpq_flush_queue(); |
|
|
XENPRINTK2(("xpq_queue_flush_cache\n")); |
XENPRINTK2(("xpq_queue_flush_cache\n")); |
op.cmd = MMUEXT_FLUSH_CACHE; |
op.cmd = MMUEXT_FLUSH_CACHE; |
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) |
if ((err = HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF)) < 0) { |
panic("xpq_flush_cache"); |
panic("xpq_flush_cache, err %d", err); |
splx(s); |
} |
|
xpq_queue_unlock(); |
|
splx(s); /* XXX: removeme */ |
} |
} |
|
|
void |
void |
xpq_queue_invlpg(vaddr_t va) |
xpq_queue_invlpg(vaddr_t va) |
{ |
{ |
struct mmuext_op op; |
struct mmuext_op op; |
|
KASSERT(xpq_queue_locked()); |
xpq_flush_queue(); |
xpq_flush_queue(); |
|
|
XENPRINTK2(("xpq_queue_invlpg %p\n", (void *)va)); |
XENPRINTK2(("xpq_queue_invlpg %#" PRIxVADDR "\n", va)); |
op.cmd = MMUEXT_INVLPG_LOCAL; |
op.cmd = MMUEXT_INVLPG_LOCAL; |
op.arg1.linear_addr = (va & ~PAGE_MASK); |
op.arg1.linear_addr = (va & ~PAGE_MASK); |
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) |
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) |
panic("xpq_queue_invlpg"); |
panic("xpq_queue_invlpg"); |
} |
} |
|
|
int |
void |
xpq_update_foreign(paddr_t ptr, pt_entry_t val, int dom) |
xen_mcast_invlpg(vaddr_t va, uint32_t cpumask) |
{ |
{ |
mmu_update_t op; |
mmuext_op_t op; |
int ok; |
|
|
KASSERT(xpq_queue_locked()); |
|
|
|
/* Flush pending page updates */ |
xpq_flush_queue(); |
xpq_flush_queue(); |
|
|
op.ptr = ptr; |
op.cmd = MMUEXT_INVLPG_MULTI; |
op.val = val; |
op.arg1.linear_addr = va; |
if (HYPERVISOR_mmu_update(&op, 1, &ok, dom) < 0) |
op.arg2.vcpumask = &cpumask; |
return EFAULT; |
|
return (0); |
|
} |
|
#else /* XEN3 */ |
|
void |
|
xpq_queue_pt_switch(paddr_t pa) |
|
{ |
|
|
|
XENPRINTK2(("xpq_queue_pt_switch: %p %p\n", (void *)pa, (void *)pa)); |
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) { |
xpq_queue[xpq_idx].ptr = pa | MMU_EXTENDED_COMMAND; |
panic("xpq_queue_invlpg_all"); |
xpq_queue[xpq_idx].val = MMUEXT_NEW_BASEPTR; |
} |
xpq_increment_idx(); |
|
|
return; |
} |
} |
|
|
void |
void |
xpq_queue_pin_table(paddr_t pa) |
xen_bcast_invlpg(vaddr_t va) |
{ |
{ |
|
mmuext_op_t op; |
|
|
XENPRINTK2(("xpq_queue_pin_table: %p %p\n", (void *)pa, (void *)pa)); |
/* Flush pending page updates */ |
xpq_queue[xpq_idx].ptr = pa | MMU_EXTENDED_COMMAND; |
KASSERT(xpq_queue_locked()); |
xpq_queue[xpq_idx].val = MMUEXT_PIN_L2_TABLE; |
xpq_flush_queue(); |
xpq_increment_idx(); |
|
} |
|
|
|
void |
op.cmd = MMUEXT_INVLPG_ALL; |
xpq_queue_unpin_table(paddr_t pa) |
op.arg1.linear_addr = va; |
{ |
|
|
|
XENPRINTK2(("xpq_queue_unpin_table: %p %p\n", (void *)pa, (void *)pa)); |
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) { |
xpq_queue[xpq_idx].ptr = pa | MMU_EXTENDED_COMMAND; |
panic("xpq_queue_invlpg_all"); |
xpq_queue[xpq_idx].val = MMUEXT_UNPIN_TABLE; |
} |
xpq_increment_idx(); |
|
|
return; |
} |
} |
|
|
|
/* This is a synchronous call. */ |
void |
void |
xpq_queue_set_ldt(vaddr_t va, uint32_t entries) |
xen_mcast_tlbflush(uint32_t cpumask) |
{ |
{ |
|
mmuext_op_t op; |
|
|
XENPRINTK2(("xpq_queue_set_ldt\n")); |
/* Flush pending page updates */ |
KASSERT(va == (va & ~PAGE_MASK)); |
KASSERT(xpq_queue_locked()); |
xpq_queue[xpq_idx].ptr = MMU_EXTENDED_COMMAND | va; |
xpq_flush_queue(); |
xpq_queue[xpq_idx].val = MMUEXT_SET_LDT | (entries << MMUEXT_CMD_SHIFT); |
|
xpq_increment_idx(); |
op.cmd = MMUEXT_TLB_FLUSH_MULTI; |
|
op.arg2.vcpumask = &cpumask; |
|
|
|
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) { |
|
panic("xpq_queue_invlpg_all"); |
|
} |
|
|
|
return; |
} |
} |
|
|
|
/* This is a synchronous call. */ |
void |
void |
xpq_queue_tlb_flush(void) |
xen_bcast_tlbflush(void) |
{ |
{ |
|
mmuext_op_t op; |
|
|
XENPRINTK2(("xpq_queue_tlb_flush\n")); |
/* Flush pending page updates */ |
xpq_queue[xpq_idx].ptr = MMU_EXTENDED_COMMAND; |
KASSERT(xpq_queue_locked()); |
xpq_queue[xpq_idx].val = MMUEXT_TLB_FLUSH; |
xpq_flush_queue(); |
xpq_increment_idx(); |
|
|
op.cmd = MMUEXT_TLB_FLUSH_ALL; |
|
|
|
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) { |
|
panic("xpq_queue_invlpg_all"); |
|
} |
|
|
|
return; |
} |
} |
|
|
|
/* This is a synchronous call. */ |
void |
void |
xpq_flush_cache(void) |
xen_vcpu_mcast_invlpg(vaddr_t sva, vaddr_t eva, uint32_t cpumask) |
{ |
{ |
int s = splvm(); |
KASSERT(eva > sva); |
|
|
XENPRINTK2(("xpq_queue_flush_cache\n")); |
/* Flush pending page updates */ |
xpq_queue[xpq_idx].ptr = MMU_EXTENDED_COMMAND; |
KASSERT(xpq_queue_locked()); |
xpq_queue[xpq_idx].val = MMUEXT_FLUSH_CACHE; |
|
xpq_increment_idx(); |
|
xpq_flush_queue(); |
xpq_flush_queue(); |
splx(s); |
|
|
/* Align to nearest page boundary */ |
|
sva &= ~PAGE_MASK; |
|
eva &= ~PAGE_MASK; |
|
|
|
for ( ; sva <= eva; sva += PAGE_SIZE) { |
|
xen_mcast_invlpg(sva, cpumask); |
|
} |
|
|
|
return; |
} |
} |
|
|
|
/* This is a synchronous call. */ |
void |
void |
xpq_queue_invlpg(vaddr_t va) |
xen_vcpu_bcast_invlpg(vaddr_t sva, vaddr_t eva) |
{ |
{ |
|
KASSERT(eva > sva); |
|
|
XENPRINTK2(("xpq_queue_invlpg %p\n", (void *)va)); |
/* Flush pending page updates */ |
xpq_queue[xpq_idx].ptr = (va & ~PAGE_MASK) | MMU_EXTENDED_COMMAND; |
KASSERT(xpq_queue_locked()); |
xpq_queue[xpq_idx].val = MMUEXT_INVLPG; |
xpq_flush_queue(); |
xpq_increment_idx(); |
|
|
/* Align to nearest page boundary */ |
|
sva &= ~PAGE_MASK; |
|
eva &= ~PAGE_MASK; |
|
|
|
for ( ; sva <= eva; sva += PAGE_SIZE) { |
|
xen_bcast_invlpg(sva); |
|
} |
|
|
|
return; |
} |
} |
|
|
int |
int |
xpq_update_foreign(paddr_t ptr, pt_entry_t val, int dom) |
xpq_update_foreign(paddr_t ptr, pt_entry_t val, int dom) |
{ |
{ |
mmu_update_t xpq_up[3]; |
mmu_update_t op; |
|
int ok; |
|
|
|
KASSERT(xpq_queue_locked()); |
|
xpq_flush_queue(); |
|
|
xpq_up[0].ptr = MMU_EXTENDED_COMMAND; |
op.ptr = ptr; |
xpq_up[0].val = MMUEXT_SET_FOREIGNDOM | (dom << 16); |
op.val = val; |
xpq_up[1].ptr = ptr; |
if (HYPERVISOR_mmu_update(&op, 1, &ok, dom) < 0) |
xpq_up[1].val = val; |
|
if (HYPERVISOR_mmu_update_self(xpq_up, 2, NULL) < 0) |
|
return EFAULT; |
return EFAULT; |
return (0); |
return (0); |
} |
} |
#endif /* XEN3 */ |
|
|
|
#ifdef XENDEBUG |
#ifdef XENDEBUG |
void |
void |
Line 466 xpq_debug_dump(void) |
|
Line 509 xpq_debug_dump(void) |
|
|
|
XENPRINTK2(("idx: %d\n", xpq_idx)); |
XENPRINTK2(("idx: %d\n", xpq_idx)); |
for (i = 0; i < xpq_idx; i++) { |
for (i = 0; i < xpq_idx; i++) { |
sprintf(XBUF, "%" PRIx64 " %08" PRIx64, |
snprintf(XBUF, sizeof(XBUF), "%" PRIx64 " %08" PRIx64, |
(uint64_t)xpq_queue[i].ptr, (uint64_t)xpq_queue[i].val); |
xpq_queue[i].ptr, xpq_queue[i].val); |
if (++i < xpq_idx) |
if (++i < xpq_idx) |
sprintf(XBUF + strlen(XBUF), "%" PRIx64 " %08" PRIx64, |
snprintf(XBUF + strlen(XBUF), |
(uint64_t)xpq_queue[i].ptr, (uint64_t)xpq_queue[i].val); |
sizeof(XBUF) - strlen(XBUF), |
|
"%" PRIx64 " %08" PRIx64, |
|
xpq_queue[i].ptr, xpq_queue[i].val); |
if (++i < xpq_idx) |
if (++i < xpq_idx) |
sprintf(XBUF + strlen(XBUF), "%" PRIx64 " %08" PRIx64, |
snprintf(XBUF + strlen(XBUF), |
(uint64_t)xpq_queue[i].ptr, (uint64_t)xpq_queue[i].val); |
sizeof(XBUF) - strlen(XBUF), |
|
"%" PRIx64 " %08" PRIx64, |
|
xpq_queue[i].ptr, xpq_queue[i].val); |
if (++i < xpq_idx) |
if (++i < xpq_idx) |
sprintf(XBUF + strlen(XBUF), "%" PRIx64 " %08" PRIx64, |
snprintf(XBUF + strlen(XBUF), |
(uint64_t)xpq_queue[i].ptr, (uint64_t)xpq_queue[i].val); |
sizeof(XBUF) - strlen(XBUF), |
|
"%" PRIx64 " %08" PRIx64, |
|
xpq_queue[i].ptr, xpq_queue[i].val); |
XENPRINTK2(("%d: %s\n", xpq_idx, XBUF)); |
XENPRINTK2(("%d: %s\n", xpq_idx, XBUF)); |
} |
} |
} |
} |
Line 617 bootstrap_again: |
|
Line 666 bootstrap_again: |
|
/* zero out free space after tables */ |
/* zero out free space after tables */ |
memset((void *)(init_tables + ((count + l2_4_count) * PAGE_SIZE)), 0, |
memset((void *)(init_tables + ((count + l2_4_count) * PAGE_SIZE)), 0, |
(UPAGES + 1) * NBPG); |
(UPAGES + 1) * NBPG); |
|
|
|
/* Finally, flush TLB. */ |
|
xpq_queue_lock(); |
|
xpq_queue_tlb_flush(); |
|
xpq_queue_unlock(); |
|
|
return (init_tables + ((count + l2_4_count) * PAGE_SIZE)); |
return (init_tables + ((count + l2_4_count) * PAGE_SIZE)); |
} |
} |
|
|
|
|
/* |
/* |
* Build a new table and switch to it |
* Build a new table and switch to it |
* old_count is # of old tables (including PGD, PDTPE and PDE) |
* old_count is # of old tables (including PGD, PDTPE and PDE) |
* new_count is # of new tables (PTE only) |
* new_count is # of new tables (PTE only) |
* we assume areas don't overlap |
* we assume areas don't overlap |
*/ |
*/ |
|
|
|
|
static void |
static void |
xen_bootstrap_tables (vaddr_t old_pgd, vaddr_t new_pgd, |
xen_bootstrap_tables (vaddr_t old_pgd, vaddr_t new_pgd, |
int old_count, int new_count, int final) |
int old_count, int new_count, int final) |
Line 640 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
Line 692 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
int i; |
int i; |
extern char __data_start; |
extern char __data_start; |
|
|
__PRINTK(("xen_bootstrap_tables(0x%lx, 0x%lx, %d, %d)\n", |
xpq_queue_lock(); |
|
|
|
__PRINTK(("xen_bootstrap_tables(%#" PRIxVADDR ", %#" PRIxVADDR "," |
|
" %d, %d)\n", |
old_pgd, new_pgd, old_count, new_count)); |
old_pgd, new_pgd, old_count, new_count)); |
text_end = ((vaddr_t)&__data_start) & ~PAGE_MASK; |
text_end = ((vaddr_t)&__data_start) & ~PAGE_MASK; |
/* |
/* |
Line 677 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
Line 732 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
|
|
__PRINTK(("xen_bootstrap_tables text_end 0x%lx map_end 0x%lx\n", |
__PRINTK(("xen_bootstrap_tables text_end 0x%lx map_end 0x%lx\n", |
text_end, map_end)); |
text_end, map_end)); |
__PRINTK(("console 0x%lx ", xen_start_info.console.domU.mfn)); |
__PRINTK(("console %#lx ", xen_start_info.console_mfn)); |
__PRINTK(("xenstore 0x%lx\n", xen_start_info.store_mfn)); |
__PRINTK(("xenstore %#" PRIx32 "\n", xen_start_info.store_mfn)); |
|
|
/* |
/* |
* Create bootstrap page tables |
* Create bootstrap page tables |
Line 703 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
Line 758 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
bt_pgd[pl4_pi(KERNTEXTOFF)] = |
bt_pgd[pl4_pi(KERNTEXTOFF)] = |
xpmap_ptom_masked(addr) | PG_k | PG_RW | PG_V; |
xpmap_ptom_masked(addr) | PG_k | PG_RW | PG_V; |
|
|
__PRINTK(("L3 va 0x%lx pa 0x%" PRIx64 " entry 0x%" PRIx64 " -> L4[0x%x]\n", |
__PRINTK(("L3 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR |
pdtpe, (uint64_t)addr, (uint64_t)bt_pgd[pl4_pi(KERNTEXTOFF)], |
" -> L4[%#x]\n", |
pl4_pi(KERNTEXTOFF))); |
pdtpe, addr, bt_pgd[pl4_pi(KERNTEXTOFF)], pl4_pi(KERNTEXTOFF))); |
#else |
#else |
pdtpe = bt_pgd; |
pdtpe = bt_pgd; |
#endif /* PTP_LEVELS > 3 */ |
#endif /* PTP_LEVELS > 3 */ |
Line 719 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
Line 774 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
addr = ((u_long) pde) - KERNBASE; |
addr = ((u_long) pde) - KERNBASE; |
pdtpe[pl3_pi(KERNTEXTOFF)] = |
pdtpe[pl3_pi(KERNTEXTOFF)] = |
xpmap_ptom_masked(addr) | PG_k | PG_V | PG_RW; |
xpmap_ptom_masked(addr) | PG_k | PG_V | PG_RW; |
__PRINTK(("L2 va 0x%lx pa 0x%" PRIx64 " entry 0x%" PRIx64 " -> L3[0x%x]\n", |
__PRINTK(("L2 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR |
pde, (int64_t)addr, (int64_t)pdtpe[pl3_pi(KERNTEXTOFF)], |
" -> L3[%#x]\n", |
pl3_pi(KERNTEXTOFF))); |
pde, addr, pdtpe[pl3_pi(KERNTEXTOFF)], pl3_pi(KERNTEXTOFF))); |
#elif defined(PAE) |
#elif defined(PAE) |
/* our PAE-style level 2: 5 contigous pages (4 L2 + 1 shadow) */ |
/* our PAE-style level 2: 5 contigous pages (4 L2 + 1 shadow) */ |
pde = (pd_entry_t *) avail; |
pde = (pd_entry_t *) avail; |
Line 735 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
Line 790 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
*/ |
*/ |
for (i = 0; i < 3; i++, addr += PAGE_SIZE) { |
for (i = 0; i < 3; i++, addr += PAGE_SIZE) { |
/* |
/* |
* Xen doens't want R/W mappings in L3 entries, it'll add it |
* Xen doesn't want R/W mappings in L3 entries, it'll add it |
* itself. |
* itself. |
*/ |
*/ |
pdtpe[i] = xpmap_ptom_masked(addr) | PG_k | PG_V; |
pdtpe[i] = xpmap_ptom_masked(addr) | PG_k | PG_V; |
__PRINTK(("L2 va 0x%lx pa 0x%" PRIx64 " entry 0x%" PRIx64 |
__PRINTK(("L2 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR |
" -> L3[0x%x]\n", (vaddr_t)pde + PAGE_SIZE * i, |
" -> L3[%#x]\n", |
(int64_t)addr, (int64_t)pdtpe[i], i)); |
(vaddr_t)pde + PAGE_SIZE * i, addr, pdtpe[i], i)); |
} |
} |
addr += PAGE_SIZE; |
addr += PAGE_SIZE; |
pdtpe[3] = xpmap_ptom_masked(addr) | PG_k | PG_V; |
pdtpe[3] = xpmap_ptom_masked(addr) | PG_k | PG_V; |
__PRINTK(("L2 va 0x%lx pa 0x%" PRIx64 " entry 0x%" PRIx64 |
__PRINTK(("L2 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR |
" -> L3[0x%x]\n", (vaddr_t)pde + PAGE_SIZE * 4, |
" -> L3[%#x]\n", |
(int64_t)addr, (int64_t)pdtpe[3], 3)); |
(vaddr_t)pde + PAGE_SIZE * 4, addr, pdtpe[3], 3)); |
|
|
#else /* PAE */ |
#else /* PAE */ |
pde = bt_pgd; |
pde = bt_pgd; |
Line 773 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
Line 828 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
if (page == (vaddr_t)HYPERVISOR_shared_info) { |
if (page == (vaddr_t)HYPERVISOR_shared_info) { |
pte[pl1_pi(page)] = xen_start_info.shared_info; |
pte[pl1_pi(page)] = xen_start_info.shared_info; |
__PRINTK(("HYPERVISOR_shared_info " |
__PRINTK(("HYPERVISOR_shared_info " |
"va 0x%lx pte 0x%" PRIx64 "\n", |
"va %#lx pte %#" PRIxPADDR "\n", |
HYPERVISOR_shared_info, (int64_t)pte[pl1_pi(page)])); |
HYPERVISOR_shared_info, pte[pl1_pi(page)])); |
} |
} |
#ifdef XEN3 |
|
if ((xpmap_ptom_masked(page - KERNBASE) >> PAGE_SHIFT) |
if ((xpmap_ptom_masked(page - KERNBASE) >> PAGE_SHIFT) |
== xen_start_info.console.domU.mfn) { |
== xen_start_info.console.domU.mfn) { |
xencons_interface = (void *)page; |
xencons_interface = (void *)page; |
pte[pl1_pi(page)] = xen_start_info.console.domU.mfn; |
pte[pl1_pi(page)] = xen_start_info.console_mfn; |
pte[pl1_pi(page)] <<= PAGE_SHIFT; |
pte[pl1_pi(page)] <<= PAGE_SHIFT; |
__PRINTK(("xencons_interface " |
__PRINTK(("xencons_interface " |
"va 0x%lx pte 0x%" PRIx64 "\n", |
"va %#lx pte %#" PRIxPADDR "\n", |
xencons_interface, (int64_t)pte[pl1_pi(page)])); |
xencons_interface, pte[pl1_pi(page)])); |
} |
} |
if ((xpmap_ptom_masked(page - KERNBASE) >> PAGE_SHIFT) |
if ((xpmap_ptom_masked(page - KERNBASE) >> PAGE_SHIFT) |
== xen_start_info.store_mfn) { |
== xen_start_info.store_mfn) { |
Line 792 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
Line 846 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
pte[pl1_pi(page)] = xen_start_info.store_mfn; |
pte[pl1_pi(page)] = xen_start_info.store_mfn; |
pte[pl1_pi(page)] <<= PAGE_SHIFT; |
pte[pl1_pi(page)] <<= PAGE_SHIFT; |
__PRINTK(("xenstore_interface " |
__PRINTK(("xenstore_interface " |
"va 0x%lx pte 0x%" PRIx64 "\n", |
"va %#lx pte %#" PRIxPADDR "\n", |
xenstore_interface, (int64_t)pte[pl1_pi(page)])); |
xenstore_interface, pte[pl1_pi(page)])); |
} |
} |
#endif /* XEN3 */ |
|
#ifdef DOM0OPS |
#ifdef DOM0OPS |
if (page >= (vaddr_t)atdevbase && |
if (page >= (vaddr_t)atdevbase && |
page < (vaddr_t)atdevbase + IOM_SIZE) { |
page < (vaddr_t)atdevbase + IOM_SIZE) { |
Line 822 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
Line 875 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
|
|
if ((page >= old_pgd && page < old_pgd + (old_count * PAGE_SIZE)) |
if ((page >= old_pgd && page < old_pgd + (old_count * PAGE_SIZE)) |
|| page >= new_pgd) { |
|| page >= new_pgd) { |
__PRINTK(("va 0x%lx pa 0x%lx " |
__PRINTK(("va %#lx pa %#lx " |
"entry 0x%" PRIx64 " -> L1[0x%x]\n", |
"entry 0x%" PRIxPADDR " -> L1[%#x]\n", |
page, page - KERNBASE, |
page, page - KERNBASE, |
(int64_t)pte[pl1_pi(page)], pl1_pi(page))); |
pte[pl1_pi(page)], pl1_pi(page))); |
} |
} |
page += PAGE_SIZE; |
page += PAGE_SIZE; |
} |
} |
Line 833 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
Line 886 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
addr = ((u_long) pte) - KERNBASE; |
addr = ((u_long) pte) - KERNBASE; |
pde[pl2_pi(cur_page)] = |
pde[pl2_pi(cur_page)] = |
xpmap_ptom_masked(addr) | PG_k | PG_RW | PG_V; |
xpmap_ptom_masked(addr) | PG_k | PG_RW | PG_V; |
__PRINTK(("L1 va 0x%lx pa 0x%" PRIx64 " entry 0x%" PRIx64 |
__PRINTK(("L1 va %#lx pa %#" PRIxPADDR " entry %#" PRIxPADDR |
" -> L2[0x%x]\n", pte, (int64_t)addr, |
" -> L2[%#x]\n", |
(int64_t)pde[pl2_pi(cur_page)], pl2_pi(cur_page))); |
pte, addr, pde[pl2_pi(cur_page)], pl2_pi(cur_page))); |
/* Mark readonly */ |
/* Mark readonly */ |
xen_bt_set_readonly((vaddr_t) pte); |
xen_bt_set_readonly((vaddr_t) pte); |
} |
} |
Line 860 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
Line 913 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
addr = (u_long)pde - KERNBASE; |
addr = (u_long)pde - KERNBASE; |
for (i = 0; i < 3; i++, addr += PAGE_SIZE) { |
for (i = 0; i < 3; i++, addr += PAGE_SIZE) { |
pde[PDIR_SLOT_PTE + i] = xpmap_ptom_masked(addr) | PG_k | PG_V; |
pde[PDIR_SLOT_PTE + i] = xpmap_ptom_masked(addr) | PG_k | PG_V; |
__PRINTK(("pde[%d] va 0x%lx pa 0x%lx entry 0x%" PRIx64 "\n", |
__PRINTK(("pde[%d] va %#" PRIxVADDR " pa %#" PRIxPADDR |
(int)(PDIR_SLOT_PTE + i), pde + PAGE_SIZE * i, (long)addr, |
" entry %#" PRIxPADDR "\n", |
(int64_t)pde[PDIR_SLOT_PTE + i])); |
(int)(PDIR_SLOT_PTE + i), pde + PAGE_SIZE * i, |
|
addr, pde[PDIR_SLOT_PTE + i])); |
} |
} |
#if 0 |
#if 0 |
addr += PAGE_SIZE; /* point to shadow L2 */ |
addr += PAGE_SIZE; /* point to shadow L2 */ |
Line 871 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
Line 925 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
(int)(PDIR_SLOT_PTE + 3), pde + PAGE_SIZE * 4, (long)addr, |
(int)(PDIR_SLOT_PTE + 3), pde + PAGE_SIZE * 4, (long)addr, |
(int64_t)pde[PDIR_SLOT_PTE + 3])); |
(int64_t)pde[PDIR_SLOT_PTE + 3])); |
#endif |
#endif |
/* Mark tables RO, and pin the kenrel's shadow as L2 */ |
/* Mark tables RO, and pin the kernel's shadow as L2 */ |
addr = (u_long)pde - KERNBASE; |
addr = (u_long)pde - KERNBASE; |
for (i = 0; i < 5; i++, addr += PAGE_SIZE) { |
for (i = 0; i < 5; i++, addr += PAGE_SIZE) { |
xen_bt_set_readonly(((vaddr_t)pde) + PAGE_SIZE * i); |
xen_bt_set_readonly(((vaddr_t)pde) + PAGE_SIZE * i); |
Line 879 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
Line 933 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
continue; |
continue; |
#if 0 |
#if 0 |
__PRINTK(("pin L2 %d addr 0x%" PRIx64 "\n", i, (int64_t)addr)); |
__PRINTK(("pin L2 %d addr 0x%" PRIx64 "\n", i, (int64_t)addr)); |
xpq_queue_pin_table(xpmap_ptom_masked(addr)); |
xpq_queue_pin_l2_table(xpmap_ptom_masked(addr)); |
#endif |
#endif |
} |
} |
if (final) { |
if (final) { |
addr = (u_long)pde - KERNBASE + 3 * PAGE_SIZE; |
addr = (u_long)pde - KERNBASE + 3 * PAGE_SIZE; |
__PRINTK(("pin L2 %d addr 0x%" PRIx64 "\n", 2, (int64_t)addr)); |
__PRINTK(("pin L2 %d addr %#" PRIxPADDR "\n", 2, addr)); |
xpq_queue_pin_table(xpmap_ptom_masked(addr)); |
xpq_queue_pin_l2_table(xpmap_ptom_masked(addr)); |
} |
} |
#if 0 |
#if 0 |
addr = (u_long)pde - KERNBASE + 2 * PAGE_SIZE; |
addr = (u_long)pde - KERNBASE + 2 * PAGE_SIZE; |
__PRINTK(("pin L2 %d addr 0x%" PRIx64 "\n", 2, (int64_t)addr)); |
__PRINTK(("pin L2 %d addr 0x%" PRIx64 "\n", 2, (int64_t)addr)); |
xpq_queue_pin_table(xpmap_ptom_masked(addr)); |
xpq_queue_pin_l2_table(xpmap_ptom_masked(addr)); |
#endif |
#endif |
#else /* PAE */ |
#else /* PAE */ |
/* recursive entry in higher-level PD */ |
/* recursive entry in higher-level PD */ |
bt_pgd[PDIR_SLOT_PTE] = |
bt_pgd[PDIR_SLOT_PTE] = |
xpmap_ptom_masked(new_pgd - KERNBASE) | PG_k | PG_V; |
xpmap_ptom_masked(new_pgd - KERNBASE) | PG_k | PG_V; |
__PRINTK(("bt_pgd[PDIR_SLOT_PTE] va 0x%lx pa 0x%" PRIx64 |
__PRINTK(("bt_pgd[PDIR_SLOT_PTE] va %#" PRIxVADDR " pa %#" PRIxPADDR |
" entry 0x%" PRIx64 "\n", new_pgd, (int64_t)new_pgd - KERNBASE, |
" entry %#" PRIxPADDR "\n", new_pgd, (paddr_t)new_pgd - KERNBASE, |
(int64_t)bt_pgd[PDIR_SLOT_PTE])); |
bt_pgd[PDIR_SLOT_PTE])); |
/* Mark tables RO */ |
/* Mark tables RO */ |
xen_bt_set_readonly((vaddr_t) pde); |
xen_bt_set_readonly((vaddr_t) pde); |
#endif |
#endif |
Line 909 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
Line 963 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
xen_bt_set_readonly(new_pgd); |
xen_bt_set_readonly(new_pgd); |
#endif |
#endif |
/* Pin the PGD */ |
/* Pin the PGD */ |
__PRINTK(("pin PDG\n")); |
__PRINTK(("pin PGD: %"PRIxVADDR"\n", new_pgd - KERNBASE)); |
#ifdef PAE |
#ifdef __x86_64__ |
|
xpq_queue_pin_l4_table(xpmap_ptom_masked(new_pgd - KERNBASE)); |
|
#elif PAE |
xpq_queue_pin_l3_table(xpmap_ptom_masked(new_pgd - KERNBASE)); |
xpq_queue_pin_l3_table(xpmap_ptom_masked(new_pgd - KERNBASE)); |
#else |
#else |
xpq_queue_pin_table(xpmap_ptom_masked(new_pgd - KERNBASE)); |
xpq_queue_pin_l2_table(xpmap_ptom_masked(new_pgd - KERNBASE)); |
#endif |
#endif |
#ifdef __i386__ |
|
/* Save phys. addr of PDP, for libkvm. */ |
/* Save phys. addr of PDP, for libkvm. */ |
PDPpaddr = (long)pde; |
|
#ifdef PAE |
#ifdef PAE |
/* also save the address of the L3 page */ |
PDPpaddr = (u_long)pde - KERNBASE; /* PDP is the L2 with PAE */ |
pmap_l3pd = pdtpe; |
#else |
pmap_l3paddr = (new_pgd - KERNBASE); |
PDPpaddr = (u_long)new_pgd - KERNBASE; |
#endif /* PAE */ |
#endif |
#endif /* i386 */ |
|
/* Switch to new tables */ |
/* Switch to new tables */ |
__PRINTK(("switch to PDG\n")); |
__PRINTK(("switch to PGD\n")); |
xpq_queue_pt_switch(xpmap_ptom_masked(new_pgd - KERNBASE)); |
xpq_queue_pt_switch(xpmap_ptom_masked(new_pgd - KERNBASE)); |
__PRINTK(("bt_pgd[PDIR_SLOT_PTE] now entry 0x%" PRIx64 "\n", |
__PRINTK(("bt_pgd[PDIR_SLOT_PTE] now entry %#" PRIxPADDR "\n", |
(int64_t)bt_pgd[PDIR_SLOT_PTE])); |
bt_pgd[PDIR_SLOT_PTE])); |
|
|
#ifdef PAE |
#ifdef PAE |
if (final) { |
if (final) { |
|
/* save the address of the L3 page */ |
|
cpu_info_primary.ci_pae_l3_pdir = pdtpe; |
|
cpu_info_primary.ci_pae_l3_pdirpa = (new_pgd - KERNBASE); |
|
|
/* now enter kernel's PTE mappings */ |
/* now enter kernel's PTE mappings */ |
addr = (u_long)pde - KERNBASE + PAGE_SIZE * 3; |
addr = (u_long)pde - KERNBASE + PAGE_SIZE * 3; |
xpq_queue_pte_update( |
xpq_queue_pte_update( |
Line 940 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
Line 1000 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
} |
} |
#endif |
#endif |
|
|
|
|
|
|
/* Now we can safely reclaim space taken by old tables */ |
/* Now we can safely reclaim space taken by old tables */ |
|
|
__PRINTK(("unpin old PDG\n")); |
__PRINTK(("unpin old PGD\n")); |
/* Unpin old PGD */ |
/* Unpin old PGD */ |
xpq_queue_unpin_table(xpmap_ptom_masked(old_pgd - KERNBASE)); |
xpq_queue_unpin_table(xpmap_ptom_masked(old_pgd - KERNBASE)); |
/* Mark old tables RW */ |
/* Mark old tables RW */ |
Line 953 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
Line 1011 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
addr = xpmap_mtop(addr); |
addr = xpmap_mtop(addr); |
pte = (pd_entry_t *) ((u_long)addr + KERNBASE); |
pte = (pd_entry_t *) ((u_long)addr + KERNBASE); |
pte += pl1_pi(page); |
pte += pl1_pi(page); |
__PRINTK(("*pde 0x%" PRIx64 " addr 0x%" PRIx64 " pte 0x%lx\n", |
__PRINTK(("*pde %#" PRIxPADDR " addr %#" PRIxPADDR " pte %#lx\n", |
(int64_t)pde[pl2_pi(page)], (int64_t)addr, (long)pte)); |
pde[pl2_pi(page)], addr, (long)pte)); |
while (page < old_pgd + (old_count * PAGE_SIZE) && page < map_end) { |
while (page < old_pgd + (old_count * PAGE_SIZE) && page < map_end) { |
addr = xpmap_ptom(((u_long) pte) - KERNBASE); |
addr = xpmap_ptom(((u_long) pte) - KERNBASE); |
XENPRINTK(("addr 0x%" PRIx64 " pte 0x%lx *pte 0x%" PRIx64 "\n", |
XENPRINTK(("addr %#" PRIxPADDR " pte %#lx " |
(int64_t)addr, (long)pte, (int64_t)*pte)); |
"*pte %#" PRIxPADDR "\n", |
|
addr, (long)pte, *pte)); |
xpq_queue_pte_update(addr, *pte | PG_RW); |
xpq_queue_pte_update(addr, *pte | PG_RW); |
page += PAGE_SIZE; |
page += PAGE_SIZE; |
/* |
/* |
Line 968 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
Line 1027 xen_bootstrap_tables (vaddr_t old_pgd, v |
|
pte++; |
pte++; |
} |
} |
xpq_flush_queue(); |
xpq_flush_queue(); |
|
xpq_queue_unlock(); |
} |
} |
|
|
|
|
Line 998 xen_set_user_pgd(paddr_t page) |
|
Line 1058 xen_set_user_pgd(paddr_t page) |
|
struct mmuext_op op; |
struct mmuext_op op; |
int s = splvm(); |
int s = splvm(); |
|
|
|
KASSERT(xpq_queue_locked()); |
xpq_flush_queue(); |
xpq_flush_queue(); |
op.cmd = MMUEXT_NEW_USER_BASEPTR; |
op.cmd = MMUEXT_NEW_USER_BASEPTR; |
op.arg1.mfn = xpmap_phys_to_machine_mapping[page >> PAGE_SHIFT]; |
op.arg1.mfn = pfn_to_mfn(page >> PAGE_SHIFT); |
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) |
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0) |
panic("xen_set_user_pgd: failed to install new user page" |
panic("xen_set_user_pgd: failed to install new user page" |
" directory %lx", page); |
" directory %#" PRIxPADDR, page); |
splx(s); |
splx(s); |
} |
} |
#endif /* __x86_64__ */ |
#endif /* __x86_64__ */ |