2007-07-09 01:14:14 +04:00
|
|
|
/* $NetBSD: xen_machdep.c,v 1.19 2007/07/08 21:14:14 bouyer Exp $ */
|
2006-01-16 01:09:51 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2006 Manuel Bouyer.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. 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.
|
|
|
|
* 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
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
2004-03-12 00:44:08 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Copyright (c) 2004 Christian Limpach.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. 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.
|
|
|
|
* 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
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <sys/cdefs.h>
|
2007-07-09 01:14:14 +04:00
|
|
|
__KERNEL_RCSID(0, "$NetBSD: xen_machdep.c,v 1.19 2007/07/08 21:14:14 bouyer Exp $");
|
2004-03-12 00:44:08 +03:00
|
|
|
|
|
|
|
#include "opt_xen.h"
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
2005-08-21 17:15:43 +04:00
|
|
|
#include <sys/boot_flag.h>
|
2004-03-12 00:44:08 +03:00
|
|
|
#include <sys/mount.h>
|
2005-06-16 02:08:08 +04:00
|
|
|
#include <sys/reboot.h>
|
2004-03-12 00:44:08 +03:00
|
|
|
|
|
|
|
#include <uvm/uvm.h>
|
|
|
|
|
|
|
|
#include <machine/gdt.h>
|
|
|
|
#include <machine/xenfunc.h>
|
|
|
|
|
2006-01-16 01:09:51 +03:00
|
|
|
#undef XENDEBUG
|
|
|
|
/* #define XENDEBUG_SYNC */
|
2004-03-12 00:44:08 +03:00
|
|
|
/* #define XENDEBUG_LOW */
|
|
|
|
|
|
|
|
#ifdef XENDEBUG
|
|
|
|
#define XENPRINTF(x) printf x
|
|
|
|
#define XENPRINTK(x) printk x
|
|
|
|
#define XENPRINTK2(x) /* printk x */
|
|
|
|
|
|
|
|
static char XBUF[256];
|
|
|
|
#else
|
|
|
|
#define XENPRINTF(x)
|
|
|
|
#define XENPRINTK(x)
|
|
|
|
#define XENPRINTK2(x)
|
|
|
|
#endif
|
|
|
|
#define PRINTF(x) printf x
|
|
|
|
#define PRINTK(x) printk x
|
|
|
|
|
2005-03-10 01:39:19 +03:00
|
|
|
volatile shared_info_t *HYPERVISOR_shared_info;
|
2004-03-12 00:44:08 +03:00
|
|
|
union start_info_union start_info_union;
|
|
|
|
|
|
|
|
void xen_failsafe_handler(void);
|
|
|
|
|
2006-01-16 01:09:51 +03:00
|
|
|
#ifdef XEN3
|
|
|
|
#define HYPERVISOR_mmu_update_self(req, count, success_count) \
|
|
|
|
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
|
|
|
|
|
2004-03-12 00:44:08 +03:00
|
|
|
void
|
|
|
|
xen_failsafe_handler(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
panic("xen_failsafe_handler called!\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
xen_update_descriptor(union descriptor *table, union descriptor *entry)
|
|
|
|
{
|
|
|
|
paddr_t pa;
|
|
|
|
pt_entry_t *ptp;
|
|
|
|
|
|
|
|
ptp = kvtopte((vaddr_t)table);
|
|
|
|
pa = (*ptp & PG_FRAME) | ((vaddr_t)table & ~PG_FRAME);
|
|
|
|
if (HYPERVISOR_update_descriptor(pa, entry->raw[0], entry->raw[1]))
|
|
|
|
panic("HYPERVISOR_update_descriptor failed\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xen_set_ldt(vaddr_t base, uint32_t entries)
|
|
|
|
{
|
|
|
|
vaddr_t va;
|
2005-03-10 01:39:19 +03:00
|
|
|
pt_entry_t *ptp, *maptp;
|
2005-05-26 17:54:43 +04:00
|
|
|
int s;
|
2004-03-12 00:44:08 +03:00
|
|
|
|
|
|
|
for (va = base; va < base + entries * sizeof(union descriptor);
|
|
|
|
va += PAGE_SIZE) {
|
|
|
|
KASSERT(va >= VM_MIN_KERNEL_ADDRESS);
|
|
|
|
ptp = kvtopte(va);
|
2005-03-10 01:39:19 +03:00
|
|
|
maptp = (pt_entry_t *)vtomach((vaddr_t)ptp);
|
|
|
|
XENPRINTF(("xen_set_ldt %p %d %p %p\n", (void *)base,
|
|
|
|
entries, ptp, maptp));
|
|
|
|
PTE_CLEARBITS(ptp, maptp, PG_RW);
|
2004-03-12 00:44:08 +03:00
|
|
|
}
|
2005-05-26 17:54:43 +04:00
|
|
|
s = splvm();
|
2004-03-12 00:44:08 +03:00
|
|
|
PTE_UPDATES_FLUSH();
|
|
|
|
|
|
|
|
xpq_queue_set_ldt(base, entries);
|
|
|
|
xpq_flush_queue();
|
2005-05-26 17:54:43 +04:00
|
|
|
splx(s);
|
2004-03-12 00:44:08 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
lgdt(struct region_descriptor *rdp)
|
|
|
|
{
|
|
|
|
|
|
|
|
panic("lgdt %p %08x\n", (void *)rdp->rd_base, rdp->rd_limit);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2004-04-24 22:55:02 +04:00
|
|
|
xen_parse_cmdline(int what, union xen_cmdline_parseinfo *xcp)
|
2004-03-12 00:44:08 +03:00
|
|
|
{
|
2007-07-09 01:14:14 +04:00
|
|
|
char _cmd_line[256], *cmd_line, *opt, *s;
|
2004-03-12 00:44:08 +03:00
|
|
|
int b, i, ipidx = 0;
|
|
|
|
uint32_t xi_ip[5];
|
2007-07-09 01:14:14 +04:00
|
|
|
size_t len;
|
2004-03-12 00:44:08 +03:00
|
|
|
|
2007-07-09 01:14:14 +04:00
|
|
|
len = strlcpy(_cmd_line, xen_start_info.cmd_line, sizeof(_cmd_line));
|
|
|
|
if (len > sizeof(_cmd_line)) {
|
|
|
|
printf("command line exceeded limit of 255 chars. Truncated.\n");
|
|
|
|
}
|
|
|
|
cmd_line = _cmd_line;
|
2004-03-12 00:44:08 +03:00
|
|
|
|
2004-04-24 22:55:02 +04:00
|
|
|
switch (what) {
|
|
|
|
case XEN_PARSE_BOOTDEV:
|
|
|
|
xcp->xcp_bootdev[0] = 0;
|
|
|
|
break;
|
|
|
|
case XEN_PARSE_CONSOLE:
|
|
|
|
xcp->xcp_console[0] = 0;
|
|
|
|
break;
|
|
|
|
}
|
2004-04-11 03:33:50 +04:00
|
|
|
|
2004-03-12 00:44:08 +03:00
|
|
|
while (cmd_line && *cmd_line) {
|
|
|
|
opt = cmd_line;
|
|
|
|
cmd_line = strchr(opt, ' ');
|
2004-04-11 03:33:50 +04:00
|
|
|
if (cmd_line)
|
|
|
|
*cmd_line = 0;
|
|
|
|
|
2004-04-24 22:55:02 +04:00
|
|
|
switch (what) {
|
|
|
|
case XEN_PARSE_BOOTDEV:
|
2007-06-29 00:54:47 +04:00
|
|
|
if (strncasecmp(opt, "bootdev=", 8) == 0) {
|
2004-04-24 22:55:02 +04:00
|
|
|
strncpy(xcp->xcp_bootdev, opt + 8,
|
2006-01-22 23:15:51 +03:00
|
|
|
sizeof(xcp->xcp_bootdev));
|
2007-06-29 00:54:47 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (strncasecmp(opt, "root=", 5) == 0) {
|
|
|
|
strncpy(xcp->xcp_bootdev, opt + 5,
|
|
|
|
sizeof(xcp->xcp_bootdev));
|
|
|
|
break;
|
|
|
|
}
|
2004-04-24 22:55:02 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case XEN_PARSE_NETINFO:
|
|
|
|
if (xcp->xcp_netinfo.xi_root &&
|
|
|
|
strncasecmp(opt, "nfsroot=", 8) == 0)
|
|
|
|
strncpy(xcp->xcp_netinfo.xi_root, opt + 8,
|
|
|
|
MNAMELEN);
|
|
|
|
|
|
|
|
if (strncasecmp(opt, "ip=", 3) == 0) {
|
|
|
|
memset(xi_ip, 0, sizeof(xi_ip));
|
|
|
|
opt += 3;
|
|
|
|
ipidx = 0;
|
|
|
|
while (opt && *opt) {
|
|
|
|
s = opt;
|
|
|
|
opt = strchr(opt, ':');
|
|
|
|
if (opt)
|
|
|
|
*opt = 0;
|
|
|
|
|
|
|
|
switch (ipidx) {
|
|
|
|
case 0: /* ip */
|
|
|
|
case 1: /* nfs server */
|
|
|
|
case 2: /* gw */
|
|
|
|
case 3: /* mask */
|
|
|
|
case 4: /* host */
|
|
|
|
if (*s == 0)
|
|
|
|
break;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
b = strtoul(s, &s, 10);
|
|
|
|
xi_ip[ipidx] = b + 256
|
|
|
|
* xi_ip[ipidx];
|
|
|
|
if (*s != '.')
|
|
|
|
break;
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
if (i < 3)
|
|
|
|
xi_ip[ipidx] = 0;
|
2004-03-12 00:44:08 +03:00
|
|
|
break;
|
2004-04-24 22:55:02 +04:00
|
|
|
case 5: /* interface */
|
|
|
|
if (!strncmp(s, "xennet", 6))
|
|
|
|
s += 6;
|
|
|
|
else if (!strncmp(s, "eth", 3))
|
|
|
|
s += 3;
|
|
|
|
else
|
2004-03-12 00:44:08 +03:00
|
|
|
break;
|
2004-04-24 22:55:02 +04:00
|
|
|
if (xcp->xcp_netinfo.xi_ifno
|
|
|
|
== strtoul(s, NULL, 10))
|
|
|
|
memcpy(xcp->
|
|
|
|
xcp_netinfo.xi_ip,
|
|
|
|
xi_ip,
|
|
|
|
sizeof(xi_ip));
|
2004-03-12 00:44:08 +03:00
|
|
|
break;
|
2004-04-24 22:55:02 +04:00
|
|
|
}
|
|
|
|
ipidx++;
|
2004-03-12 00:44:08 +03:00
|
|
|
|
2004-04-24 22:55:02 +04:00
|
|
|
if (opt)
|
|
|
|
*opt++ = ':';
|
|
|
|
}
|
2004-03-12 00:44:08 +03:00
|
|
|
}
|
2004-05-03 00:38:35 +04:00
|
|
|
break;
|
2004-04-24 22:55:02 +04:00
|
|
|
|
|
|
|
case XEN_PARSE_CONSOLE:
|
|
|
|
if (strncasecmp(opt, "console=", 8) == 0)
|
|
|
|
strncpy(xcp->xcp_console, opt + 8,
|
|
|
|
sizeof(xcp->xcp_console));
|
|
|
|
break;
|
|
|
|
|
2005-06-16 02:08:08 +04:00
|
|
|
case XEN_PARSE_BOOTFLAGS:
|
|
|
|
if (*opt == '-') {
|
|
|
|
opt++;
|
|
|
|
while(*opt != '\0') {
|
2005-08-21 17:15:43 +04:00
|
|
|
BOOT_FLAG(*opt, boothowto);
|
2005-06-16 02:08:08 +04:00
|
|
|
opt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2004-03-12 00:44:08 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cmd_line)
|
|
|
|
*cmd_line++ = ' ';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static pd_entry_t
|
|
|
|
xpmap_get_bootpde(paddr_t va)
|
|
|
|
{
|
|
|
|
|
|
|
|
return ((pd_entry_t *)xen_start_info.pt_base)[va >> PDSHIFT];
|
|
|
|
}
|
|
|
|
|
|
|
|
static pd_entry_t
|
|
|
|
xpmap_get_vbootpde(paddr_t va)
|
|
|
|
{
|
|
|
|
pd_entry_t pde;
|
|
|
|
|
|
|
|
pde = xpmap_get_bootpde(va);
|
|
|
|
if ((pde & PG_V) == 0)
|
|
|
|
return (pde & ~PG_FRAME);
|
|
|
|
return (pde & ~PG_FRAME) |
|
2004-04-27 02:05:04 +04:00
|
|
|
(xpmap_mtop(pde & PG_FRAME) + KERNBASE);
|
2004-03-12 00:44:08 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static pt_entry_t *
|
|
|
|
xpmap_get_bootptep(paddr_t va)
|
|
|
|
{
|
|
|
|
pd_entry_t pde;
|
|
|
|
|
|
|
|
pde = xpmap_get_vbootpde(va);
|
|
|
|
if ((pde & PG_V) == 0)
|
|
|
|
return (void *)-1;
|
|
|
|
return &(((pt_entry_t *)(pde & PG_FRAME))[(va & PT_MASK) >> PAGE_SHIFT]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static pt_entry_t
|
|
|
|
xpmap_get_bootpte(paddr_t va)
|
|
|
|
{
|
|
|
|
|
|
|
|
return xpmap_get_bootptep(va)[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(XENDEBUG)
|
|
|
|
static void
|
|
|
|
xpmap_dump_pt(pt_entry_t *ptp, int p)
|
|
|
|
{
|
|
|
|
pt_entry_t pte;
|
|
|
|
int j;
|
|
|
|
int bufpos;
|
|
|
|
|
2004-04-27 02:05:04 +04:00
|
|
|
pte = xpmap_ptom((uint32_t)ptp - KERNBASE);
|
2004-03-12 00:44:08 +03:00
|
|
|
PRINTK(("%03x: %p(%p) %08x\n", p, ptp, (void *)pte, p << PDSHIFT));
|
|
|
|
|
|
|
|
bufpos = 0;
|
|
|
|
for (j = 0; j < PTES_PER_PTP; j++) {
|
|
|
|
if ((ptp[j] & PG_V) == 0)
|
|
|
|
continue;
|
|
|
|
pte = ptp[j] /* & PG_FRAME */;
|
|
|
|
bufpos += sprintf(XBUF + bufpos, "%x:%03x:%08x ",
|
|
|
|
p, j, pte);
|
|
|
|
if (bufpos > 70) {
|
|
|
|
int k;
|
|
|
|
sprintf(XBUF + bufpos, "\n");
|
|
|
|
PRINTK((XBUF));
|
|
|
|
bufpos = 0;
|
|
|
|
for (k = 0; k < 1000000; k++);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bufpos) {
|
|
|
|
PRINTK((XBUF));
|
2005-03-10 01:39:19 +03:00
|
|
|
PRINTK(("\n"));
|
2004-03-12 00:44:08 +03:00
|
|
|
bufpos = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void
|
2004-04-27 02:05:04 +04:00
|
|
|
xpmap_init(void)
|
2004-03-12 00:44:08 +03:00
|
|
|
{
|
|
|
|
pd_entry_t *xen_pdp;
|
|
|
|
pt_entry_t *ptp, *sysptp;
|
|
|
|
pt_entry_t pte;
|
|
|
|
uint32_t i, j;
|
|
|
|
int bufpos;
|
|
|
|
#if defined(XENDEBUG_LOW)
|
|
|
|
extern char kernel_text, _etext, __bss_start, end, *esym;
|
|
|
|
#endif
|
|
|
|
|
2005-03-10 01:39:19 +03:00
|
|
|
xpmap_phys_to_machine_mapping = (void *)xen_start_info.mfn_list;
|
2004-03-12 00:44:08 +03:00
|
|
|
|
|
|
|
xen_pdp = (pd_entry_t *)xen_start_info.pt_base;
|
|
|
|
|
2006-01-16 01:09:51 +03:00
|
|
|
/*XENPRINTK(("text %p data %p bss %p end %p esym %p\n", &kernel_text,
|
|
|
|
&_etext, &__bss_start, &end, esym));*/
|
2005-03-10 01:39:19 +03:00
|
|
|
XENPRINTK(("xpmap_init PDP %p nkpde %d upages %d xen_PDP %p p2m-map %p\n",
|
|
|
|
(void *)PDPpaddr, nkpde, UPAGES, xen_pdp,
|
|
|
|
xpmap_phys_to_machine_mapping));
|
2004-03-12 00:44:08 +03:00
|
|
|
|
|
|
|
bufpos = 0;
|
|
|
|
|
|
|
|
XENPRINTK(("shared_inf %08x\n", (paddr_t)xen_start_info.shared_info));
|
|
|
|
XENPRINTK(("c0100000: %08x\n",
|
|
|
|
xpmap_get_bootpte(0xc0100000)));
|
|
|
|
|
|
|
|
/* Map kernel. */
|
|
|
|
|
|
|
|
/* Map kernel data/bss/tables. */
|
|
|
|
|
|
|
|
/* Map ISA I/O memory. */
|
|
|
|
|
|
|
|
/* Map kernel PDEs. */
|
|
|
|
|
|
|
|
/* Install a PDE recursively mapping page directory as a page table! */
|
|
|
|
|
2005-03-10 01:39:19 +03:00
|
|
|
sysptp = (pt_entry_t *)(PDPpaddr + ((1 + UPAGES) << PAGE_SHIFT));
|
|
|
|
|
|
|
|
/* make xen's PDE and PTE pages read-only in our pagetable */
|
|
|
|
for (i = 0; i < xen_start_info.nr_pt_frames; i++) {
|
|
|
|
/* mark PTE page read-only in our table */
|
|
|
|
sysptp[((xen_start_info.pt_base +
|
2005-11-07 14:42:34 +03:00
|
|
|
(i << PAGE_SHIFT) - KERNBASE) &
|
2005-03-10 01:39:19 +03:00
|
|
|
(PD_MASK | PT_MASK)) >> PAGE_SHIFT] &= ~PG_RW;
|
|
|
|
}
|
|
|
|
|
|
|
|
xpq_flush_queue();
|
|
|
|
|
2004-03-12 00:44:08 +03:00
|
|
|
for (i = 0; i < 1 + UPAGES + nkpde; i++) {
|
|
|
|
/* mark PTE page read-only in xen's table */
|
2005-03-10 01:39:19 +03:00
|
|
|
ptp = xpmap_get_bootptep(PDPpaddr + (i << PAGE_SHIFT));
|
|
|
|
xpq_queue_pte_update(
|
|
|
|
(void *)xpmap_ptom((unsigned long)ptp - KERNBASE), *ptp & ~PG_RW);
|
|
|
|
XENPRINTK(("%03x: %p(%p) -> %08x\n", i, ptp,
|
|
|
|
(unsigned long)ptp - KERNTEXTOFF, *ptp));
|
2004-03-12 00:44:08 +03:00
|
|
|
|
|
|
|
/* mark PTE page read-only in our table */
|
2005-11-07 14:42:34 +03:00
|
|
|
sysptp[((PDPpaddr + (i << PAGE_SHIFT) - KERNBASE) &
|
2004-03-12 00:44:08 +03:00
|
|
|
(PD_MASK | PT_MASK)) >> PAGE_SHIFT] &= ~PG_RW;
|
|
|
|
|
|
|
|
/* update our pte's */
|
2005-03-10 01:39:19 +03:00
|
|
|
ptp = (pt_entry_t *)(PDPpaddr + (i << PAGE_SHIFT));
|
2004-03-12 00:44:08 +03:00
|
|
|
#if 0
|
2004-04-27 02:05:04 +04:00
|
|
|
pte = xpmap_ptom((uint32_t)ptp - KERNBASE);
|
2004-03-12 00:44:08 +03:00
|
|
|
XENPRINTK(("%03x: %p(%p) %08x\n", i, ptp, pte, i << PDSHIFT));
|
|
|
|
#endif
|
|
|
|
for (j = 0; j < PTES_PER_PTP; j++) {
|
|
|
|
if ((ptp[j] & PG_V) == 0)
|
|
|
|
continue;
|
|
|
|
if (ptp[j] >= KERNTEXTOFF) {
|
|
|
|
pte = ptp[j];
|
|
|
|
ptp[j] = (pte & ~PG_FRAME) |
|
|
|
|
(xpmap_get_bootpte(pte & PG_FRAME) &
|
|
|
|
PG_FRAME);
|
|
|
|
}
|
|
|
|
#if defined(XENDEBUG) && 0
|
|
|
|
pte = ptp[j] /* & PG_FRAME */;
|
|
|
|
bufpos += sprintf(XBUF + bufpos, "%x:%03x:%08x ",
|
|
|
|
i, j, pte);
|
|
|
|
if (bufpos > 70) {
|
|
|
|
int k;
|
|
|
|
sprintf(XBUF + bufpos, "\n");
|
|
|
|
XENPRINTK((XBUF));
|
|
|
|
bufpos = 0;
|
|
|
|
for (k = 0; k < 1000000; k++);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bufpos) {
|
|
|
|
XENPRINTK((XBUF));
|
|
|
|
bufpos = 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
if (i == 0)
|
|
|
|
i = 1 + UPAGES - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
for (i = 0x300; i < 0x305; i++)
|
2005-03-10 01:39:19 +03:00
|
|
|
if (((pt_entry_t *)xen_start_info.pt_base)[i] & PG_V)
|
|
|
|
xpmap_dump_pt((pt_entry_t *)
|
|
|
|
(xpmap_mtop(((pt_entry_t *)xen_start_info.pt_base)[i] &
|
|
|
|
PG_FRAME) + KERNBASE), i);
|
2004-03-12 00:44:08 +03:00
|
|
|
xpmap_dump_pt((pt_entry_t *)xen_start_info.pt_base, 0);
|
|
|
|
#endif
|
|
|
|
|
2005-03-10 01:39:19 +03:00
|
|
|
XENPRINTK(("switching pdp: %p, %08lx, %p, %p, %p\n", (void *)PDPpaddr,
|
|
|
|
PDPpaddr - KERNBASE,
|
|
|
|
(void *)xpmap_ptom(PDPpaddr - KERNBASE),
|
|
|
|
(void *)xpmap_get_bootpte(PDPpaddr),
|
|
|
|
(void *)xpmap_mtop(xpmap_ptom(PDPpaddr - KERNBASE))));
|
2004-03-12 00:44:08 +03:00
|
|
|
|
|
|
|
#if defined(XENDEBUG)
|
2005-03-10 01:39:19 +03:00
|
|
|
xpmap_dump_pt((pt_entry_t *)PDPpaddr, 0);
|
2004-03-12 00:44:08 +03:00
|
|
|
#endif
|
|
|
|
|
2005-03-10 01:39:19 +03:00
|
|
|
xpq_flush_queue();
|
|
|
|
|
|
|
|
xpq_queue_pin_table(xpmap_get_bootpte(PDPpaddr) & PG_FRAME,
|
2004-03-12 00:44:08 +03:00
|
|
|
XPQ_PIN_L2_TABLE);
|
2005-03-10 01:39:19 +03:00
|
|
|
xpq_queue_pt_switch(xpmap_get_bootpte(PDPpaddr) & PG_FRAME);
|
2004-03-12 00:44:08 +03:00
|
|
|
xpq_queue_unpin_table(
|
|
|
|
xpmap_get_bootpte(xen_start_info.pt_base) & PG_FRAME);
|
|
|
|
|
2005-03-10 01:39:19 +03:00
|
|
|
/* make xen's PDE and PTE pages writable in our pagetable */
|
|
|
|
for (i = 0; i < xen_start_info.nr_pt_frames; i++) {
|
|
|
|
/* mark PTE page writable in our table */
|
|
|
|
ptp = &sysptp[((xen_start_info.pt_base +
|
2005-11-07 14:42:34 +03:00
|
|
|
(i << PAGE_SHIFT) - KERNBASE) &
|
2005-03-10 01:39:19 +03:00
|
|
|
(PD_MASK | PT_MASK)) >> PAGE_SHIFT];
|
|
|
|
xpq_queue_pte_update(
|
|
|
|
(void *)xpmap_ptom((unsigned long)ptp - KERNBASE), *ptp |
|
|
|
|
PG_RW);
|
|
|
|
}
|
|
|
|
|
2004-03-12 00:44:08 +03:00
|
|
|
xpq_flush_queue();
|
|
|
|
XENPRINTK(("pt_switch done!\n"));
|
|
|
|
}
|
|
|
|
|
2004-04-27 02:05:04 +04:00
|
|
|
/*
|
|
|
|
* Do a binary search to find out where physical memory ends on the
|
|
|
|
* real hardware. Xen will fail our updates if they are beyond the
|
|
|
|
* last available page (max_page in xen/common/memory.c).
|
|
|
|
*/
|
|
|
|
paddr_t
|
|
|
|
find_pmap_mem_end(vaddr_t va)
|
|
|
|
{
|
|
|
|
mmu_update_t r;
|
2005-03-10 01:39:19 +03:00
|
|
|
int start, end, ok;
|
2004-04-27 02:05:04 +04:00
|
|
|
pt_entry_t old;
|
|
|
|
|
|
|
|
start = xen_start_info.nr_pages;
|
|
|
|
end = HYPERVISOR_VIRT_START >> PAGE_SHIFT;
|
|
|
|
|
|
|
|
r.ptr = (unsigned long)&PTE_BASE[x86_btop(va)];
|
|
|
|
old = PTE_BASE[x86_btop(va)];
|
|
|
|
|
|
|
|
while (start + 1 < end) {
|
|
|
|
r.val = (((start + end) / 2) << PAGE_SHIFT) | PG_V;
|
|
|
|
|
2006-01-16 01:09:51 +03:00
|
|
|
if (HYPERVISOR_mmu_update_self(&r, 1, &ok) < 0)
|
2004-04-27 02:05:04 +04:00
|
|
|
end = (start + end) / 2;
|
|
|
|
else
|
|
|
|
start = (start + end) / 2;
|
|
|
|
}
|
|
|
|
r.val = old;
|
2006-01-16 01:09:51 +03:00
|
|
|
if (HYPERVISOR_mmu_update_self(&r, 1, &ok) < 0)
|
2004-04-27 02:05:04 +04:00
|
|
|
printf("pmap_mem_end find: old update failed %08x\n",
|
|
|
|
old);
|
|
|
|
|
|
|
|
return end << PAGE_SHIFT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-12 00:44:08 +03:00
|
|
|
#if 0
|
|
|
|
void xpmap_find_memory(paddr_t);
|
|
|
|
void
|
|
|
|
xpmap_find_memory(paddr_t first_avail)
|
|
|
|
{
|
|
|
|
char buf[256];
|
|
|
|
uint32_t i;
|
|
|
|
int bufpos;
|
|
|
|
paddr_t p;
|
|
|
|
|
|
|
|
bufpos = 0;
|
|
|
|
for (i = ((first_avail - KERNTEXTOFF) >> PAGE_SHIFT);
|
|
|
|
i < xen_start_info.nr_pages; i++) {
|
|
|
|
/* if (xpmap_phys_to_machine_mapping[i] */
|
|
|
|
bufpos += sprintf(buf + bufpos, "%03x:%08x:%08x ",
|
|
|
|
i, (uint32_t)xpmap_phys_to_machine_mapping[i],
|
|
|
|
(uint32_t)xpmap_mtop(xpmap_phys_to_machine_mapping[i] <<
|
|
|
|
PAGE_SHIFT));
|
|
|
|
p = xpmap_phys_to_machine_mapping[i];
|
|
|
|
uvm_page_physload(p, p + 1, p, p + 1, VM_FREELIST_DEFAULT);
|
|
|
|
|
|
|
|
if (bufpos > 70) {
|
|
|
|
int k;
|
|
|
|
sprintf(buf + bufpos, "\n");
|
|
|
|
XENPRINTK((buf));
|
|
|
|
bufpos = 0;
|
|
|
|
for (k = 0; k < 1000000; k++);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bufpos) {
|
|
|
|
XENPRINTK((buf));
|
|
|
|
bufpos = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef XENDEBUG
|
|
|
|
void xpq_debug_dump(void);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define XPQUEUE_SIZE 2048
|
2006-01-16 01:09:51 +03:00
|
|
|
static mmu_update_t xpq_queue[XPQUEUE_SIZE];
|
2004-03-12 00:44:08 +03:00
|
|
|
static int xpq_idx = 0;
|
|
|
|
|
|
|
|
void
|
|
|
|
xpq_flush_queue()
|
|
|
|
{
|
2005-03-10 01:39:19 +03:00
|
|
|
int i, ok;
|
2004-03-12 00:44:08 +03:00
|
|
|
|
|
|
|
XENPRINTK2(("flush queue %p entries %d\n", xpq_queue, xpq_idx));
|
|
|
|
for (i = 0; i < xpq_idx; i++)
|
2006-01-16 01:09:51 +03:00
|
|
|
XENPRINTK2(("%d: %p %08x\n", i, (u_int)xpq_queue[i].ptr,
|
|
|
|
(u_int)xpq_queue[i].val));
|
2005-03-10 01:39:19 +03:00
|
|
|
if (xpq_idx != 0 &&
|
2006-01-16 01:09:51 +03:00
|
|
|
HYPERVISOR_mmu_update_self(xpq_queue, xpq_idx, &ok) < 0)
|
2005-03-10 01:39:19 +03:00
|
|
|
panic("HYPERVISOR_mmu_update failed\n");
|
2004-03-12 00:44:08 +03:00
|
|
|
xpq_idx = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
xpq_increment_idx(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
xpq_idx++;
|
|
|
|
if (__predict_false(xpq_idx == XPQUEUE_SIZE))
|
|
|
|
xpq_flush_queue();
|
|
|
|
}
|
|
|
|
|
2005-08-20 23:20:54 +04:00
|
|
|
void
|
|
|
|
xpq_queue_machphys_update(paddr_t ma, paddr_t pa)
|
|
|
|
{
|
|
|
|
XENPRINTK2(("xpq_queue_machphys_update ma=%p pa=%p\n", (void *)ma, (void *)pa));
|
2006-01-16 01:09:51 +03:00
|
|
|
xpq_queue[xpq_idx].ptr = ma | MMU_MACHPHYS_UPDATE;
|
|
|
|
xpq_queue[xpq_idx].val = (pa - XPMAP_OFFSET) >> PAGE_SHIFT;
|
2005-08-20 23:20:54 +04:00
|
|
|
xpq_increment_idx();
|
2006-01-16 01:09:51 +03:00
|
|
|
#ifdef XENDEBUG_SYNC
|
|
|
|
xpq_flush_queue();
|
|
|
|
#endif
|
2005-08-20 23:20:54 +04:00
|
|
|
}
|
|
|
|
|
2004-03-12 00:44:08 +03:00
|
|
|
void
|
2006-01-16 01:09:51 +03:00
|
|
|
xpq_queue_pde_update(pd_entry_t *ptr, pd_entry_t val)
|
2004-03-12 00:44:08 +03:00
|
|
|
{
|
|
|
|
|
2006-01-16 01:09:51 +03:00
|
|
|
xpq_queue[xpq_idx].ptr = (paddr_t)ptr;
|
|
|
|
xpq_queue[xpq_idx].val = val;
|
2004-03-12 00:44:08 +03:00
|
|
|
xpq_increment_idx();
|
2006-01-16 01:09:51 +03:00
|
|
|
#ifdef XENDEBUG_SYNC
|
|
|
|
xpq_flush_queue();
|
|
|
|
#endif
|
2004-03-12 00:44:08 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-01-16 01:09:51 +03:00
|
|
|
xpq_queue_pte_update(pt_entry_t *ptr, pt_entry_t val)
|
2004-03-12 00:44:08 +03:00
|
|
|
{
|
|
|
|
|
2006-01-16 01:09:51 +03:00
|
|
|
xpq_queue[xpq_idx].ptr = (paddr_t)ptr;
|
|
|
|
xpq_queue[xpq_idx].val = val;
|
2004-03-12 00:44:08 +03:00
|
|
|
xpq_increment_idx();
|
2006-01-16 01:09:51 +03:00
|
|
|
#ifdef XENDEBUG_SYNC
|
|
|
|
xpq_flush_queue();
|
|
|
|
#endif
|
2004-03-12 00:44:08 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2006-01-16 01:09:51 +03:00
|
|
|
xpq_queue_unchecked_pte_update(pt_entry_t *ptr, pt_entry_t val)
|
2004-03-12 00:44:08 +03:00
|
|
|
{
|
|
|
|
|
2006-01-16 01:09:51 +03:00
|
|
|
xpq_queue[xpq_idx].ptr = (paddr_t)ptr | MMU_NORMAL_PT_UPDATE;
|
|
|
|
/* XXXcl UNCHECKED_PT_UPDATE */
|
|
|
|
xpq_queue[xpq_idx].val = val;
|
2004-03-12 00:44:08 +03:00
|
|
|
xpq_increment_idx();
|
2006-01-16 01:09:51 +03:00
|
|
|
#ifdef XENDEBUG_SYNC
|
|
|
|
xpq_flush_queue();
|
|
|
|
#endif
|
2004-03-12 00:44:08 +03:00
|
|
|
}
|
|
|
|
|
2006-01-16 01:09:51 +03:00
|
|
|
#ifdef XEN3
|
|
|
|
void
|
|
|
|
xpq_queue_pt_switch(paddr_t pa)
|
2005-03-10 01:39:19 +03:00
|
|
|
{
|
2006-01-16 01:09:51 +03:00
|
|
|
struct mmuext_op op;
|
|
|
|
xpq_flush_queue();
|
2005-03-10 01:39:19 +03:00
|
|
|
|
2006-01-16 01:09:51 +03:00
|
|
|
XENPRINTK2(("xpq_queue_pt_switch: %p %p\n", (void *)pa, (void *)pa));
|
|
|
|
op.cmd = MMUEXT_NEW_BASEPTR;
|
|
|
|
op.arg1.mfn = pa >> PAGE_SHIFT;
|
|
|
|
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0)
|
|
|
|
panic("xpq_queue_pt_switch");
|
2005-03-10 01:39:19 +03:00
|
|
|
}
|
|
|
|
|
2004-04-27 02:05:04 +04:00
|
|
|
void
|
2006-01-16 01:09:51 +03:00
|
|
|
xpq_queue_pin_table(paddr_t pa, int type)
|
2004-04-27 02:05:04 +04:00
|
|
|
{
|
2006-01-16 01:09:51 +03:00
|
|
|
struct mmuext_op op;
|
|
|
|
xpq_flush_queue();
|
2004-04-27 02:05:04 +04:00
|
|
|
|
2006-01-16 01:09:51 +03:00
|
|
|
XENPRINTK2(("xpq_queue_pin_table: %p %p\n", (void *)pa, (void *)pa));
|
|
|
|
op.arg1.mfn = pa >> PAGE_SHIFT;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case XPQ_PIN_L1_TABLE:
|
|
|
|
op.cmd = MMUEXT_PIN_L1_TABLE;
|
|
|
|
break;
|
|
|
|
case XPQ_PIN_L2_TABLE:
|
|
|
|
op.cmd = MMUEXT_PIN_L2_TABLE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0)
|
|
|
|
panic("xpq_queue_pin_table");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xpq_queue_unpin_table(paddr_t pa)
|
|
|
|
{
|
|
|
|
struct mmuext_op op;
|
|
|
|
xpq_flush_queue();
|
|
|
|
|
|
|
|
XENPRINTK2(("xpq_queue_unpin_table: %p %p\n", (void *)pa, (void *)pa));
|
|
|
|
op.arg1.mfn = pa >> PAGE_SHIFT;
|
|
|
|
op.cmd = MMUEXT_UNPIN_TABLE;
|
|
|
|
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0)
|
|
|
|
panic("xpq_queue_unpin_table");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xpq_queue_set_ldt(vaddr_t va, uint32_t entries)
|
|
|
|
{
|
|
|
|
struct mmuext_op op;
|
|
|
|
xpq_flush_queue();
|
|
|
|
|
|
|
|
XENPRINTK2(("xpq_queue_set_ldt\n"));
|
|
|
|
KASSERT(va == (va & PG_FRAME));
|
|
|
|
op.cmd = MMUEXT_SET_LDT;
|
|
|
|
op.arg1.linear_addr = va;
|
|
|
|
op.arg2.nr_ents = entries;
|
|
|
|
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0)
|
|
|
|
panic("xpq_queue_set_ldt");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xpq_queue_tlb_flush()
|
|
|
|
{
|
|
|
|
struct mmuext_op op;
|
|
|
|
xpq_flush_queue();
|
|
|
|
|
|
|
|
XENPRINTK2(("xpq_queue_tlb_flush\n"));
|
|
|
|
op.cmd = MMUEXT_TLB_FLUSH_LOCAL;
|
|
|
|
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0)
|
|
|
|
panic("xpq_queue_tlb_flush");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xpq_flush_cache()
|
|
|
|
{
|
|
|
|
struct mmuext_op op;
|
|
|
|
int s = splvm();
|
|
|
|
xpq_flush_queue();
|
|
|
|
|
|
|
|
XENPRINTK2(("xpq_queue_flush_cache\n"));
|
|
|
|
op.cmd = MMUEXT_FLUSH_CACHE;
|
|
|
|
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0)
|
|
|
|
panic("xpq_flush_cache");
|
|
|
|
splx(s);
|
2004-04-27 02:05:04 +04:00
|
|
|
}
|
|
|
|
|
2006-01-16 01:09:51 +03:00
|
|
|
void
|
|
|
|
xpq_queue_invlpg(vaddr_t va)
|
|
|
|
{
|
|
|
|
struct mmuext_op op;
|
|
|
|
xpq_flush_queue();
|
|
|
|
|
|
|
|
XENPRINTK2(("xpq_queue_invlpg %p\n", (void *)va));
|
|
|
|
op.cmd = MMUEXT_INVLPG_LOCAL;
|
|
|
|
op.arg1.linear_addr = (va & PG_FRAME);
|
|
|
|
if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0)
|
|
|
|
panic("xpq_queue_invlpg");
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
xpq_update_foreign(pt_entry_t *ptr, pt_entry_t val, int dom)
|
|
|
|
{
|
|
|
|
mmu_update_t op;
|
|
|
|
int ok;
|
|
|
|
xpq_flush_queue();
|
|
|
|
|
|
|
|
op.ptr = (uint32_t)ptr;
|
|
|
|
op.val = val;
|
|
|
|
if (HYPERVISOR_mmu_update(&op, 1, &ok, dom) < 0)
|
|
|
|
return EFAULT;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
#else /* XEN3 */
|
2004-03-12 00:44:08 +03:00
|
|
|
void
|
|
|
|
xpq_queue_pt_switch(paddr_t pa)
|
|
|
|
{
|
|
|
|
|
|
|
|
XENPRINTK2(("xpq_queue_pt_switch: %p %p\n", (void *)pa, (void *)pa));
|
2006-01-16 01:09:51 +03:00
|
|
|
xpq_queue[xpq_idx].ptr = pa | MMU_EXTENDED_COMMAND;
|
|
|
|
xpq_queue[xpq_idx].val = MMUEXT_NEW_BASEPTR;
|
2004-03-12 00:44:08 +03:00
|
|
|
xpq_increment_idx();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xpq_queue_pin_table(paddr_t pa, int type)
|
|
|
|
{
|
|
|
|
|
|
|
|
XENPRINTK2(("xpq_queue_pin_table: %p %p\n", (void *)pa, (void *)pa));
|
2006-01-16 01:09:51 +03:00
|
|
|
xpq_queue[xpq_idx].ptr = pa | MMU_EXTENDED_COMMAND;
|
2004-03-12 00:44:08 +03:00
|
|
|
switch (type) {
|
|
|
|
case XPQ_PIN_L1_TABLE:
|
2006-01-16 01:09:51 +03:00
|
|
|
xpq_queue[xpq_idx].val = MMUEXT_PIN_L1_TABLE;
|
2004-03-12 00:44:08 +03:00
|
|
|
break;
|
|
|
|
case XPQ_PIN_L2_TABLE:
|
2006-01-16 01:09:51 +03:00
|
|
|
xpq_queue[xpq_idx].val = MMUEXT_PIN_L2_TABLE;
|
2004-03-12 00:44:08 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
xpq_increment_idx();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xpq_queue_unpin_table(paddr_t pa)
|
|
|
|
{
|
|
|
|
|
|
|
|
XENPRINTK2(("xpq_queue_unpin_table: %p %p\n", (void *)pa, (void *)pa));
|
2006-01-16 01:09:51 +03:00
|
|
|
xpq_queue[xpq_idx].ptr = pa | MMU_EXTENDED_COMMAND;
|
|
|
|
xpq_queue[xpq_idx].val = MMUEXT_UNPIN_TABLE;
|
2004-03-12 00:44:08 +03:00
|
|
|
xpq_increment_idx();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xpq_queue_set_ldt(vaddr_t va, uint32_t entries)
|
|
|
|
{
|
|
|
|
|
|
|
|
XENPRINTK2(("xpq_queue_set_ldt\n"));
|
|
|
|
KASSERT(va == (va & PG_FRAME));
|
2006-01-16 01:09:51 +03:00
|
|
|
xpq_queue[xpq_idx].ptr = MMU_EXTENDED_COMMAND | va;
|
|
|
|
xpq_queue[xpq_idx].val = MMUEXT_SET_LDT | (entries << MMUEXT_CMD_SHIFT);
|
2004-03-12 00:44:08 +03:00
|
|
|
xpq_increment_idx();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xpq_queue_tlb_flush()
|
|
|
|
{
|
|
|
|
|
|
|
|
XENPRINTK2(("xpq_queue_tlb_flush\n"));
|
2006-01-16 01:09:51 +03:00
|
|
|
xpq_queue[xpq_idx].ptr = MMU_EXTENDED_COMMAND;
|
|
|
|
xpq_queue[xpq_idx].val = MMUEXT_TLB_FLUSH;
|
2004-03-12 00:44:08 +03:00
|
|
|
xpq_increment_idx();
|
|
|
|
}
|
|
|
|
|
2005-03-10 01:39:19 +03:00
|
|
|
void
|
|
|
|
xpq_flush_cache()
|
|
|
|
{
|
2005-05-26 17:54:43 +04:00
|
|
|
int s = splvm();
|
2005-03-10 01:39:19 +03:00
|
|
|
|
|
|
|
XENPRINTK2(("xpq_queue_flush_cache\n"));
|
2006-01-16 01:09:51 +03:00
|
|
|
xpq_queue[xpq_idx].ptr = MMU_EXTENDED_COMMAND;
|
|
|
|
xpq_queue[xpq_idx].val = MMUEXT_FLUSH_CACHE;
|
2005-03-10 01:39:19 +03:00
|
|
|
xpq_increment_idx();
|
|
|
|
xpq_flush_queue();
|
2005-05-26 17:54:43 +04:00
|
|
|
splx(s);
|
2005-03-10 01:39:19 +03:00
|
|
|
}
|
|
|
|
|
2006-01-16 01:09:51 +03:00
|
|
|
void
|
|
|
|
xpq_queue_invlpg(vaddr_t va)
|
|
|
|
{
|
|
|
|
|
|
|
|
XENPRINTK2(("xpq_queue_invlpg %p\n", (void *)va));
|
|
|
|
xpq_queue[xpq_idx].ptr = (va & PG_FRAME) | MMU_EXTENDED_COMMAND;
|
|
|
|
xpq_queue[xpq_idx].val = MMUEXT_INVLPG;
|
|
|
|
xpq_increment_idx();
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
xpq_update_foreign(pt_entry_t *ptr, pt_entry_t val, int dom)
|
|
|
|
{
|
|
|
|
mmu_update_t xpq_up[3];
|
|
|
|
|
|
|
|
xpq_up[0].ptr = MMU_EXTENDED_COMMAND;
|
|
|
|
xpq_up[0].val = MMUEXT_SET_FOREIGNDOM | (dom << 16);
|
|
|
|
xpq_up[1].ptr = (paddr_t)ptr;
|
|
|
|
xpq_up[1].val = val;
|
|
|
|
if (HYPERVISOR_mmu_update_self(xpq_up, 2, NULL) < 0)
|
|
|
|
return EFAULT;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
#endif /* XEN3 */
|
2005-03-10 01:39:19 +03:00
|
|
|
|
2004-03-12 00:44:08 +03:00
|
|
|
#ifdef XENDEBUG
|
|
|
|
void
|
|
|
|
xpq_debug_dump()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
XENPRINTK2(("idx: %d\n", xpq_idx));
|
|
|
|
for (i = 0; i < xpq_idx; i++) {
|
2006-01-16 01:09:51 +03:00
|
|
|
sprintf(XBUF, "%x %08x ", (u_int)xpq_queue[i].ptr,
|
|
|
|
(u_int)xpq_queue[i].val);
|
2004-03-12 00:44:08 +03:00
|
|
|
if (++i < xpq_idx)
|
2006-01-16 01:09:51 +03:00
|
|
|
sprintf(XBUF + strlen(XBUF), "%x %08x ",
|
|
|
|
(u_int)xpq_queue[i].ptr, (u_int)xpq_queue[i].val);
|
2004-03-12 00:44:08 +03:00
|
|
|
if (++i < xpq_idx)
|
2006-01-16 01:09:51 +03:00
|
|
|
sprintf(XBUF + strlen(XBUF), "%x %08x ",
|
|
|
|
(u_int)xpq_queue[i].ptr, (u_int)xpq_queue[i].val);
|
2004-03-12 00:44:08 +03:00
|
|
|
if (++i < xpq_idx)
|
2006-01-16 01:09:51 +03:00
|
|
|
sprintf(XBUF + strlen(XBUF), "%x %08x ",
|
|
|
|
(u_int)xpq_queue[i].ptr, (u_int)xpq_queue[i].val);
|
2004-03-12 00:44:08 +03:00
|
|
|
XENPRINTK2(("%d: %s\n", xpq_idx, XBUF));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|