bitkeeper revision 1.1159.1.124 (413c80f8x6TVGW53WE2vlecpb4z_KA)

Avoid warning message when validating a linear pagedirectory mapping.
This commit is contained in:
cl349@freefall.cl.cam.ac.uk committed 2004-09-06 15:23:36 +00:00
commit ea5753a77c
47 files changed
+1372 -636

No files matched your search

+3
View File
@@ -126,6 +126,8 @@
409ba2e7akOFqQUg6Qyg2s28xcXiMg linux-2.4.27-xen-sparse/mm/page_alloc.c
3e5a4e683HKVU-sxtagrDasRB8eBVw linux-2.4.27-xen-sparse/mm/swapfile.c
41180721bNns9Na7w1nJ0ZVt8bhUNA linux-2.4.27-xen-sparse/mm/vmalloc.c
413aa1d0oNP8HXLvfPuMe6cSroUfSA linux-2.6.8.1-patches/agpgart.patch
413aa1d0ewvSv-ohnNnQQNGsbPTTNA linux-2.6.8.1-patches/drm.patch
40f562372u3A7_kfbYYixPHJJxYUxA linux-2.6.8.1-xen-sparse/arch/xen/Kconfig
40f56237utH41NPukqHksuNf29IC9A linux-2.6.8.1-xen-sparse/arch/xen/Kconfig.drivers
40f56237penAAlWVBVDpeQZNFIg8CA linux-2.6.8.1-xen-sparse/arch/xen/Makefile
@@ -161,6 +163,7 @@
40f562383SKvDStdtrvzr5fyCbW4rw linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/hypervisor.c
40f56239xcNylAxuGsQHwi1AyMLV8w linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c
41062ab7CjxC1UBaFhOMWWdhHkIUyg linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/ioremap.c
413b5ab8LIowAnQrEmaOJSdmqm96jQ linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pageattr.c
40f5623906UYHv1rsVUeRc0tFT0dWw linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pgtable.c
4107adf12ndy94MidCaivDibJ3pPAg linux-2.6.8.1-xen-sparse/arch/xen/i386/pci/Makefile
4107adf1WcCgkhsdLTRGX52cOG1vJg linux-2.6.8.1-xen-sparse/arch/xen/i386/pci/direct.c
+1
View File
@@ -19,6 +19,7 @@ iap10@striker.cl.cam.ac.uk
iap10@tetris.cl.cam.ac.uk
jws22@gauntlet.cl.cam.ac.uk
jws@cairnwell.research
kaf24@camelot.eng.3leafnetworks.com
kaf24@freefall.cl.cam.ac.uk
kaf24@labyrinth.cl.cam.ac.uk
kaf24@penguin.local
@@ -604,12 +604,15 @@ static struct irqaction dbg_time = {
void __init time_init(void)
{
unsigned long long alarm;
u64 __cpu_khz, cpu_freq, scale, scale2;
u64 __cpu_khz, __cpu_ghz, cpu_freq, scale, scale2;
unsigned int cpu_ghz;
__cpu_khz = HYPERVISOR_shared_info->cpu_freq;
do_div(__cpu_khz, 1000);
__cpu_khz = __cpu_ghz = cpu_freq = HYPERVISOR_shared_info->cpu_freq;
do_div(__cpu_khz, 1000UL);
cpu_khz = (u32)__cpu_khz;
do_div(__cpu_ghz, 1000000000UL);
cpu_ghz = (unsigned int)__cpu_ghz;
printk("Xen reported: %lu.%03lu MHz processor.\n",
cpu_khz / 1000, cpu_khz % 1000);
@@ -617,9 +620,6 @@ void __init time_init(void)
xtime.tv_usec = HYPERVISOR_shared_info->wc_usec;
processed_system_time = shadow_system_time;
cpu_freq = HYPERVISOR_shared_info->cpu_freq;
cpu_ghz = do_div(cpu_freq, 1000000000UL);
for ( rdtsc_bitshift = 0; cpu_ghz != 0; rdtsc_bitshift++, cpu_ghz >>= 1 )
continue;
+346
View File
@@ -0,0 +1,346 @@
--- linux-2.6.8.1/drivers/char/agp/ali-agp.c 2004-08-14 11:55:35.000000000 +0100
+++ linux-2.6.8.1-xen0/drivers/char/agp/ali-agp.c 2004-09-05 05:55:58.876495340 +0100
@@ -150,7 +150,7 @@
pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
- virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN ));
+ virt_to_bus(addr)) | ALI_CACHE_FLUSH_EN ));
return addr;
}
@@ -174,7 +174,7 @@
pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
- virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN));
+ virt_to_bus(addr)) | ALI_CACHE_FLUSH_EN));
agp_generic_destroy_page(addr);
}
--- linux-2.6.8.1/drivers/char/agp/amd-k7-agp.c 2004-08-14 11:56:24.000000000 +0100
+++ linux-2.6.8.1-xen0/drivers/char/agp/amd-k7-agp.c 2004-09-05 05:55:58.877495108 +0100
@@ -43,7 +43,7 @@
SetPageReserved(virt_to_page(page_map->real));
global_cache_flush();
- page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
+ page_map->remapped = ioremap_nocache(virt_to_bus(page_map->real),
PAGE_SIZE);
if (page_map->remapped == NULL) {
ClearPageReserved(virt_to_page(page_map->real));
@@ -152,7 +152,7 @@
agp_bridge->gatt_table_real = (u32 *)page_dir.real;
agp_bridge->gatt_table = (u32 *)page_dir.remapped;
- agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
+ agp_bridge->gatt_bus_addr = virt_to_bus(page_dir.real);
/* Get the address for the gart region.
* This is a bus address even on the alpha, b/c its
@@ -166,7 +166,7 @@
/* Calculate the agp offset */
for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
page_dir.remapped[GET_PAGE_DIR_OFF(addr)] =
- virt_to_phys(amd_irongate_private.gatt_pages[i]->real);
+ virt_to_bus(amd_irongate_private.gatt_pages[i]->real);
page_dir.remapped[GET_PAGE_DIR_OFF(addr)] |= 0x00000001;
}
--- linux-2.6.8.1/drivers/char/agp/amd64-agp.c 2004-08-14 11:55:47.000000000 +0100
+++ linux-2.6.8.1-xen0/drivers/char/agp/amd64-agp.c 2004-09-05 05:55:58.877495108 +0100
@@ -212,7 +212,7 @@
static int amd_8151_configure(void)
{
- unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real);
+ unsigned long gatt_bus = virt_to_bus(agp_bridge->gatt_table_real);
/* Configure AGP regs in each x86-64 host bridge. */
for_each_nb() {
@@ -521,7 +521,7 @@
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
- release_mem_region(virt_to_phys(bridge->gatt_table_real),
+ release_mem_region(virt_to_bus(bridge->gatt_table_real),
amd64_aperture_sizes[bridge->aperture_size_idx].size);
agp_remove_bridge(bridge);
agp_put_bridge(bridge);
--- linux-2.6.8.1/drivers/char/agp/ati-agp.c 2004-08-14 11:55:48.000000000 +0100
+++ linux-2.6.8.1-xen0/drivers/char/agp/ati-agp.c 2004-09-05 05:55:58.877495108 +0100
@@ -64,7 +64,7 @@
/* CACHE_FLUSH(); */
global_cache_flush();
- page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
+ page_map->remapped = ioremap_nocache(virt_to_bus(page_map->real),
PAGE_SIZE);
if (page_map->remapped == NULL || err) {
ClearPageReserved(virt_to_page(page_map->real));
--- linux-2.6.8.1/drivers/char/agp/backend.c 2004-08-14 11:55:47.000000000 +0100
+++ linux-2.6.8.1-xen0/drivers/char/agp/backend.c 2004-09-05 05:55:58.878494876 +0100
@@ -142,7 +142,7 @@
return -ENOMEM;
}
- bridge->scratch_page_real = virt_to_phys(addr);
+ bridge->scratch_page_real = virt_to_bus(addr);
bridge->scratch_page =
bridge->driver->mask_memory(bridge->scratch_page_real, 0);
}
@@ -186,7 +186,7 @@
err_out:
if (bridge->driver->needs_scratch_page)
bridge->driver->agp_destroy_page(
- phys_to_virt(bridge->scratch_page_real));
+ bus_to_virt(bridge->scratch_page_real));
if (got_gatt)
bridge->driver->free_gatt_table();
if (got_keylist) {
@@ -211,7 +211,7 @@
if (bridge->driver->agp_destroy_page &&
bridge->driver->needs_scratch_page)
bridge->driver->agp_destroy_page(
- phys_to_virt(bridge->scratch_page_real));
+ bus_to_virt(bridge->scratch_page_real));
}
static const drm_agp_t drm_agp = {
--- linux-2.6.8.1/drivers/char/agp/generic.c 2004-08-14 11:55:10.000000000 +0100
+++ linux-2.6.8.1-xen0/drivers/char/agp/generic.c 2004-09-05 05:55:58.879494644 +0100
@@ -127,7 +127,7 @@
}
if (curr->page_count != 0) {
for (i = 0; i < curr->page_count; i++) {
- agp_bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i]));
+ agp_bridge->driver->agp_destroy_page(bus_to_virt(curr->memory[i]));
}
}
agp_free_key(curr->key);
@@ -181,7 +181,7 @@
return NULL;
}
new->memory[i] =
- agp_bridge->driver->mask_memory(virt_to_phys(addr), type);
+ agp_bridge->driver->mask_memory(virt_to_bus(addr), type);
new->page_count++;
}
@@ -636,6 +636,7 @@
int i;
void *temp;
struct page *page;
+ dma_addr_t dma;
/* The generic routines can't handle 2 level gatt's */
if (agp_bridge->driver->size_type == LVL2_APER_SIZE)
@@ -674,8 +675,10 @@
break;
}
- table = (char *) __get_free_pages(GFP_KERNEL,
- page_order);
+ table = dma_alloc_coherent(
+ &agp_bridge->dev->dev,
+ PAGE_SIZE << page_order, &dma,
+ GFP_KERNEL);
if (table == NULL) {
i++;
@@ -706,7 +709,9 @@
size = ((struct aper_size_info_fixed *) temp)->size;
page_order = ((struct aper_size_info_fixed *) temp)->page_order;
num_entries = ((struct aper_size_info_fixed *) temp)->num_entries;
- table = (char *) __get_free_pages(GFP_KERNEL, page_order);
+ table = dma_alloc_coherent(
+ &agp_bridge->dev->dev,
+ PAGE_SIZE << page_order, &dma, GFP_KERNEL);
}
if (table == NULL)
@@ -721,7 +726,7 @@
agp_gatt_table = (void *)table;
agp_bridge->driver->cache_flush();
- agp_bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
+ agp_bridge->gatt_table = ioremap_nocache(virt_to_bus(table),
(PAGE_SIZE * (1 << page_order)));
agp_bridge->driver->cache_flush();
@@ -729,11 +734,12 @@
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
ClearPageReserved(page);
- free_pages((unsigned long) table, page_order);
+ dma_free_coherent(&agp_bridge->dev->dev, PAGE_SIZE<<page_order,
+ table, dma);
return -ENOMEM;
}
- agp_bridge->gatt_bus_addr = virt_to_phys(agp_bridge->gatt_table_real);
+ agp_bridge->gatt_bus_addr = virt_to_bus(table);
/* AK: bogus, should encode addresses > 4GB */
for (i = 0; i < num_entries; i++)
@@ -785,7 +791,8 @@
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
ClearPageReserved(page);
- free_pages((unsigned long) agp_bridge->gatt_table_real, page_order);
+ dma_free_coherent(&agp_bridge->dev->dev, PAGE_SIZE<<page_order,
+ agp_bridge->gatt_table_real, agp_bridge->gatt_bus_addr);
agp_gatt_table = NULL;
agp_bridge->gatt_table = NULL;
--- linux-2.6.8.1/drivers/char/agp/hp-agp.c 2004-08-14 11:55:59.000000000 +0100
+++ linux-2.6.8.1-xen0/drivers/char/agp/hp-agp.c 2004-09-05 05:55:58.879494644 +0100
@@ -110,7 +110,7 @@
hp->gart_size = HP_ZX1_GART_SIZE;
hp->gatt_entries = hp->gart_size / hp->io_page_size;
- hp->io_pdir = phys_to_virt(INREG64(hp->ioc_regs, HP_ZX1_PDIR_BASE));
+ hp->io_pdir = bus_to_virt(INREG64(hp->ioc_regs, HP_ZX1_PDIR_BASE));
hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)];
if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) {
@@ -248,7 +248,7 @@
agp_bridge->mode = INREG32(hp->lba_regs, hp->lba_cap_offset + PCI_AGP_STATUS);
if (hp->io_pdir_owner) {
- OUTREG64(hp->ioc_regs, HP_ZX1_PDIR_BASE, virt_to_phys(hp->io_pdir));
+ OUTREG64(hp->ioc_regs, HP_ZX1_PDIR_BASE, virt_to_bus(hp->io_pdir));
OUTREG64(hp->ioc_regs, HP_ZX1_TCNFG, hp->io_tlb_ps);
OUTREG64(hp->ioc_regs, HP_ZX1_IMASK, ~(HP_ZX1_IOVA_SIZE - 1));
OUTREG64(hp->ioc_regs, HP_ZX1_IBASE, hp->iova_base | 0x1);
--- linux-2.6.8.1/drivers/char/agp/i460-agp.c 2004-08-14 11:55:34.000000000 +0100
+++ linux-2.6.8.1-xen0/drivers/char/agp/i460-agp.c 2004-09-05 05:55:58.879494644 +0100
@@ -371,7 +371,7 @@
}
memset(lp->alloced_map, 0, map_size);
- lp->paddr = virt_to_phys(lpage);
+ lp->paddr = virt_to_bus(lpage);
lp->refcount = 0;
atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
return 0;
@@ -382,7 +382,7 @@
kfree(lp->alloced_map);
lp->alloced_map = NULL;
- free_pages((unsigned long) phys_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT);
+ free_pages((unsigned long) bus_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT);
atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
}
--- linux-2.6.8.1/drivers/char/agp/intel-agp.c 2004-08-14 11:55:32.000000000 +0100
+++ linux-2.6.8.1-xen0/drivers/char/agp/intel-agp.c 2004-09-05 05:55:58.880494412 +0100
@@ -285,7 +285,7 @@
if (new == NULL)
return NULL;
- new->memory[0] = virt_to_phys(addr);
+ new->memory[0] = virt_to_bus(addr);
if (pg_count == 4) {
/* kludge to get 4 physical pages for ARGB cursor */
new->memory[1] = new->memory[0] + PAGE_SIZE;
@@ -328,10 +328,10 @@
agp_free_key(curr->key);
if(curr->type == AGP_PHYS_MEMORY) {
if (curr->page_count == 4)
- i8xx_destroy_pages(phys_to_virt(curr->memory[0]));
+ i8xx_destroy_pages(bus_to_virt(curr->memory[0]));
else
agp_bridge->driver->agp_destroy_page(
- phys_to_virt(curr->memory[0]));
+ bus_to_virt(curr->memory[0]));
vfree(curr->memory);
}
kfree(curr);
--- linux-2.6.8.1/drivers/char/agp/intel-mch-agp.c 2004-08-14 11:54:49.000000000 +0100
+++ linux-2.6.8.1-xen0/drivers/char/agp/intel-mch-agp.c 2004-09-05 05:55:58.880494412 +0100
@@ -51,7 +51,7 @@
if (new == NULL)
return NULL;
- new->memory[0] = agp_bridge->driver->mask_memory(virt_to_phys(addr), type);
+ new->memory[0] = agp_bridge->driver->mask_memory(virt_to_bus(addr), type);
new->page_count = 1;
new->num_scratch_pages = 1;
new->type = AGP_PHYS_MEMORY;
@@ -63,7 +63,7 @@
{
agp_free_key(curr->key);
if(curr->type == AGP_PHYS_MEMORY) {
- agp_bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[0]));
+ agp_bridge->driver->agp_destroy_page(bus_to_virt(curr->memory[0]));
vfree(curr->memory);
}
kfree(curr);
--- linux-2.6.8.1/drivers/char/agp/sworks-agp.c 2004-08-14 11:55:10.000000000 +0100
+++ linux-2.6.8.1-xen0/drivers/char/agp/sworks-agp.c 2004-09-05 05:55:58.881494180 +0100
@@ -51,7 +51,7 @@
}
SetPageReserved(virt_to_page(page_map->real));
global_cache_flush();
- page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
+ page_map->remapped = ioremap_nocache(virt_to_bus(page_map->real),
PAGE_SIZE);
if (page_map->remapped == NULL) {
ClearPageReserved(virt_to_page(page_map->real));
@@ -164,7 +164,7 @@
for(i = 0; i < 1024; i++) {
serverworks_private.scratch_dir.remapped[i] = (unsigned long) agp_bridge->scratch_page;
page_dir.remapped[i] =
- virt_to_phys(serverworks_private.scratch_dir.real);
+ virt_to_bus(serverworks_private.scratch_dir.real);
page_dir.remapped[i] |= 0x00000001;
}
@@ -177,7 +177,7 @@
agp_bridge->gatt_table_real = (u32 *)page_dir.real;
agp_bridge->gatt_table = (u32 *)page_dir.remapped;
- agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
+ agp_bridge->gatt_bus_addr = virt_to_bus(page_dir.real);
/* Get the address for the gart region.
* This is a bus address even on the alpha, b/c its
@@ -191,7 +191,7 @@
for(i = 0; i < value->num_entries / 1024; i++) {
page_dir.remapped[i] =
- virt_to_phys(serverworks_private.gatt_pages[i]->real);
+ virt_to_bus(serverworks_private.gatt_pages[i]->real);
page_dir.remapped[i] |= 0x00000001;
}
--- linux-2.6.8.1/drivers/char/agp/uninorth-agp.c 2004-08-14 11:55:32.000000000 +0100
+++ linux-2.6.8.1-xen0/drivers/char/agp/uninorth-agp.c 2004-09-05 05:55:58.881494180 +0100
@@ -200,7 +200,7 @@
agp_bridge->gatt_table_real = (u32 *) table;
agp_bridge->gatt_table = (u32 *)table;
- agp_bridge->gatt_bus_addr = virt_to_phys(table);
+ agp_bridge->gatt_bus_addr = virt_to_bus(table);
for (i = 0; i < num_entries; i++) {
agp_bridge->gatt_table[i] =
--- linux-2.6.8.1/include/asm-i386/agp.h 2004-08-14 11:54:47.000000000 +0100
+++ linux-2.6.8.1-xen0/include/asm-i386/agp.h 2004-09-05 05:57:26.040268956 +0100
@@ -3,6 +3,7 @@
#include <asm/pgtable.h>
#include <asm/cacheflush.h>
+#include <asm/system.h>
/*
* Functions to keep the agpgart mappings coherent with the MMU.
@@ -19,6 +20,6 @@
/* Could use CLFLUSH here if the cpu supports it. But then it would
need to be called for each cacheline of the whole page so it may not be
worth it. Would need a page for it. */
-#define flush_agp_cache() asm volatile("wbinvd":::"memory")
+#define flush_agp_cache() wbinvd()
#endif
+11
View File
@@ -0,0 +1,11 @@
--- linux-2.6.8.1/drivers/char/drm/ati_pcigart.h 2004-08-14 11:56:14.000000000 +0100
+++ linux-2.6.8.1-xen0/drivers/char/drm/ati_pcigart.h 2004-09-05 06:14:51.751782846 +0100
@@ -158,7 +158,7 @@
ret = 1;
#if defined(__i386__) || defined(__x86_64__)
- asm volatile ( "wbinvd" ::: "memory" );
+ wbinvd();
#else
mb();
#endif
+1 -2
View File
@@ -26,13 +26,12 @@ menu "XEN"
config XEN_PRIVILEGED_GUEST
bool "Privileged Guest (domain 0)"
default n
select XEN_PHYSDEV_ACCESS
help
Support for privileged operation (domain 0)
config XEN_PHYSDEV_ACCESS
bool "Device-driver domain (physical device access)"
default y if XEN_PRIVILEGED_GUEST
default n
help
Device-driver domain (physical device access)
@@ -4,84 +4,52 @@ menu "Device Drivers"
source "drivers/base/Kconfig"
source "drivers/scsi/Kconfig"
source "drivers/block/Kconfig"
source "drivers/md/Kconfig"
if XEN_PHYSDEV_ACCESS
source "drivers/mtd/Kconfig"
source "drivers/parport/Kconfig"
source "drivers/pnp/Kconfig"
endif
# Always include scsi and block to enable iscsi, loop0 etc.
source "drivers/block/Kconfig"
if XEN_PHYSDEV_ACCESS
source "drivers/ide/Kconfig"
endif
source "drivers/scsi/Kconfig"
if XEN_PHYSDEV_ACCESS
source "drivers/cdrom/Kconfig"
endif
source "drivers/md/Kconfig"
if XEN_PHYSDEV_ACCESS
source "drivers/message/fusion/Kconfig"
source "drivers/ieee1394/Kconfig"
source "drivers/message/i2o/Kconfig"
endif
source "net/Kconfig"
if XEN_PRIVILEGED_GUEST
source "drivers/input/Kconfig"
endif
config INPUT
tristate "Input devices (needed for keyboard, mouse, ...)" if EMBEDDED
default y
---help---
Say Y here if you have any input device (mouse, keyboard, tablet,
joystick, steering wheel ...) connected to your system and want
it to be available to applications. This includes standard PS/2
keyboard and mouse.
Say N here if you have a headless (no monitor, no keyboard) system.
More information is available: <file:Documentation/input/input.txt>
If unsure, say Y.
To compile this driver as a module, choose M here: the
module will be called input.
if XEN_PRIVILEGED_GUEST
source "drivers/char/Kconfig"
endif
config UNIX98_PTYS
bool "Unix98 PTY support" if EMBEDDED
default y
---help---
A pseudo terminal (PTY) is a software device consisting of two
halves: a master and a slave. The slave device behaves identical to
a physical terminal; the master device is used by a process to
read data from and write data to the slave, thereby emulating a
terminal. Typical programs for the master side are telnet servers
and xterms.
Linux has traditionally used the BSD-like names /dev/ptyxx for
masters and /dev/ttyxx for slaves of pseudo terminals. This scheme
has a number of problems. The GNU C library glibc 2.1 and later,
however, supports the Unix98 naming standard: in order to acquire a
pseudo terminal, a process opens /dev/ptmx; the number of the pseudo
terminal is then made available to the process and the pseudo
terminal slave can be accessed as /dev/pts/<number>. What was
traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
All modern Linux systems use the Unix98 ptys. Say Y unless
you're on an embedded system and want to conserve memory.
if XEN_PHYSDEV_ACCESS
source "drivers/isdn/Kconfig"
source "drivers/telephony/Kconfig"
source "drivers/input/Kconfig"
source "drivers/char/Kconfig"
source "drivers/i2c/Kconfig"
source "drivers/w1/Kconfig"
source "drivers/misc/Kconfig"
source "drivers/media/Kconfig"
source "drivers/video/Kconfig"
source "sound/Kconfig"
source "drivers/usb/Kconfig"
endif
#config XEN_EVTCHN
# bool "Xen Event Channel"
# depends on XEN
# default Y
#
#config XEN_CONSOLE
# bool "Xen Console"
# depends on XEN && XEN_EVTCHN
# default Y
# help
# Say Y to build a console driver for Xen.
if !XEN_PHYSDEV_ACCESS
config UNIX98_PTYS
bool
default y
endif
endmenu
@@ -175,6 +175,105 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
# CONFIG_DEBUG_DRIVER is not set
#
# Memory Technology Devices (MTD)
#
# CONFIG_MTD is not set
#
# Parallel port support
#
# CONFIG_PARPORT is not set
#
# Plug and Play support
#
# CONFIG_PNP is not set
#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
CONFIG_BLK_DEV_NBD=y
# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
# CONFIG_LBD is not set
#
# ATA/ATAPI/MFM/RLL support
#
CONFIG_IDE=y
CONFIG_BLK_DEV_IDE=y
#
# Please see Documentation/ide.txt for help/info on IDE drives
#
# CONFIG_BLK_DEV_IDE_SATA is not set
# CONFIG_BLK_DEV_HD_IDE is not set
CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set
# CONFIG_BLK_DEV_IDECS is not set
CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
# CONFIG_IDE_TASKFILE_IO is not set
#
# IDE chipset support/bugfixes
#
CONFIG_IDE_GENERIC=y
# CONFIG_BLK_DEV_CMD640 is not set
CONFIG_BLK_DEV_IDEPCI=y
# CONFIG_IDEPCI_SHARE_IRQ is not set
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
# CONFIG_BLK_DEV_RZ1000 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_IDEDMA_ONLYDISK is not set
CONFIG_BLK_DEV_ADMA=y
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD74XX is not set
# CONFIG_BLK_DEV_ATIIXP is not set
# CONFIG_BLK_DEV_CMD64X is not set
# CONFIG_BLK_DEV_TRIFLEX is not set
# CONFIG_BLK_DEV_CY82C693 is not set
# CONFIG_BLK_DEV_CS5520 is not set
# CONFIG_BLK_DEV_CS5530 is not set
# CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_BLK_DEV_HPT366 is not set
# CONFIG_BLK_DEV_SC1200 is not set
CONFIG_BLK_DEV_PIIX=y
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_PDC202XX_OLD is not set
# CONFIG_BLK_DEV_PDC202XX_NEW is not set
CONFIG_BLK_DEV_SVWKS=y
# CONFIG_BLK_DEV_SIIMAGE is not set
# CONFIG_BLK_DEV_SIS5513 is not set
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
# CONFIG_IDE_ARM is not set
# CONFIG_IDE_CHIPSETS is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
CONFIG_IDEDMA_AUTO=y
# CONFIG_BLK_DEV_HD is not set
#
# SCSI device support
#
@@ -295,22 +394,9 @@ CONFIG_SCSI_QLA2XXX=y
# CONFIG_PCMCIA_SYM53C500 is not set
#
# Block devices
# Old CD-ROM drivers (not SCSI, not IDE)
#
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
CONFIG_BLK_DEV_LOOP=y
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
CONFIG_BLK_DEV_NBD=y
# CONFIG_BLK_DEV_SX8 is not set
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
# CONFIG_LBD is not set
# CONFIG_CD_NO_IDESCSI is not set
#
# Multi-device support (RAID and LVM)
@@ -330,75 +416,19 @@ CONFIG_DM_MIRROR=y
# CONFIG_DM_ZERO is not set
#
# ATA/ATAPI/MFM/RLL support
# Fusion MPT device support
#
CONFIG_IDE=y
CONFIG_BLK_DEV_IDE=y
# CONFIG_FUSION is not set
#
# Please see Documentation/ide.txt for help/info on IDE drives
# IEEE 1394 (FireWire) support
#
# CONFIG_BLK_DEV_IDE_SATA is not set
# CONFIG_BLK_DEV_HD_IDE is not set
CONFIG_BLK_DEV_IDEDISK=y
# CONFIG_IDEDISK_MULTI_MODE is not set
# CONFIG_BLK_DEV_IDECS is not set
CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_BLK_DEV_IDESCSI is not set
# CONFIG_IDE_TASK_IOCTL is not set
# CONFIG_IDE_TASKFILE_IO is not set
# CONFIG_IEEE1394 is not set
#
# IDE chipset support/bugfixes
# I2O device support
#
CONFIG_IDE_GENERIC=y
# CONFIG_BLK_DEV_CMD640 is not set
CONFIG_BLK_DEV_IDEPCI=y
# CONFIG_IDEPCI_SHARE_IRQ is not set
# CONFIG_BLK_DEV_OFFBOARD is not set
CONFIG_BLK_DEV_GENERIC=y
# CONFIG_BLK_DEV_OPTI621 is not set
# CONFIG_BLK_DEV_RZ1000 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_IDEDMA_ONLYDISK is not set
CONFIG_BLK_DEV_ADMA=y
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD74XX is not set
# CONFIG_BLK_DEV_ATIIXP is not set
# CONFIG_BLK_DEV_CMD64X is not set
# CONFIG_BLK_DEV_TRIFLEX is not set
# CONFIG_BLK_DEV_CY82C693 is not set
# CONFIG_BLK_DEV_CS5520 is not set
# CONFIG_BLK_DEV_CS5530 is not set
# CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_BLK_DEV_HPT366 is not set
# CONFIG_BLK_DEV_SC1200 is not set
CONFIG_BLK_DEV_PIIX=y
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_PDC202XX_OLD is not set
# CONFIG_BLK_DEV_PDC202XX_NEW is not set
CONFIG_BLK_DEV_SVWKS=y
# CONFIG_BLK_DEV_SIIMAGE is not set
# CONFIG_BLK_DEV_SIS5513 is not set
# CONFIG_BLK_DEV_SLC90E66 is not set
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
# CONFIG_IDE_ARM is not set
# CONFIG_IDE_CHIPSETS is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
CONFIG_IDEDMA_AUTO=y
# CONFIG_BLK_DEV_HD is not set
#
# Old CD-ROM drivers (not SCSI, not IDE)
#
# CONFIG_CD_NO_IDESCSI is not set
# CONFIG_I2O is not set
#
# Networking support
@@ -645,6 +675,16 @@ CONFIG_TIGON3=y
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
#
# ISDN subsystem
#
# CONFIG_ISDN is not set
#
# Telephony Support
#
# CONFIG_PHONE is not set
#
# Input device support
#
@@ -752,6 +792,26 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# CONFIG_I2C is not set
#
# Dallas's 1-wire bus
#
# CONFIG_W1 is not set
#
# Misc devices
#
# CONFIG_IBM_ASM is not set
#
# Multimedia devices
#
# CONFIG_VIDEO_DEV is not set
#
# Digital Video Broadcasting Devices
#
# CONFIG_DVB is not set
#
# Graphics support
#
@@ -765,6 +825,21 @@ CONFIG_VGA_CONSOLE=y
# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
#
# Sound
#
# CONFIG_SOUND is not set
#
# USB support
#
# CONFIG_USB is not set
#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
#
# File systems
#
@@ -131,6 +131,18 @@ CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_FW_LOADER is not set
#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
CONFIG_BLK_DEV_LOOP=m
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
# CONFIG_LBD is not set
#
# SCSI device support
#
@@ -167,18 +179,6 @@ CONFIG_BLK_DEV_SD=m
# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_DEBUG is not set
#
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
CONFIG_BLK_DEV_LOOP=m
# CONFIG_BLK_DEV_CRYPTOLOOP is not set
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=4096
CONFIG_BLK_DEV_INITRD=y
# CONFIG_LBD is not set
#
# Multi-device support (RAID and LVM)
#
@@ -283,7 +283,6 @@ CONFIG_NETDEVICES=y
# CONFIG_SLIP is not set
# CONFIG_SHAPER is not set
# CONFIG_NETCONSOLE is not set
CONFIG_INPUT=y
CONFIG_UNIX98_PTYS=y
#
@@ -20,6 +20,8 @@ struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
extern void mcheck_init(struct cpuinfo_x86 *c);
extern void machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c);
extern int disable_pse;
static void default_init(struct cpuinfo_x86 * c)
@@ -392,6 +394,8 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
c->x86_vendor, c->x86_model);
}
machine_specific_modify_cpu_capabilities(c);
/* Now the feature flags better reflect actual CPU features! */
printk(KERN_DEBUG "CPU: After all inits, caps: %08lx %08lx %08lx %08lx\n",
@@ -504,7 +508,7 @@ void __init cpu_gdt_init(struct Xgt_desc_struct *gdt_descr)
va < gdt_descr->address + gdt_descr->size;
va += PAGE_SIZE, f++) {
frames[f] = virt_to_machine(va) >> PAGE_SHIFT;
wrprotect_bootpt(swapper_pg_dir, (void *)va, 1);
protect_page(swapper_pg_dir, (void *)va, PROT_ON);
}
flush_page_update_queue();
if (HYPERVISOR_set_gdt(frames, gdt_descr->size / 8))
@@ -6,8 +6,8 @@ XENARCH := $(subst ",,$(CONFIG_XENARCH))
CFLAGS += -Iarch/$(XENARCH)/mm
obj-y := init.o fault.o ioremap.o pgtable.o hypervisor.o
c-obj-y := extable.o pageattr.o
obj-y := init.o fault.o ioremap.o pgtable.o hypervisor.o pageattr.o
c-obj-y := extable.o
c-obj-$(CONFIG_DISCONTIGMEM) += discontig.o
c-obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
@@ -76,11 +76,9 @@ static pte_t * __init one_page_table_init(pmd_t *pmd)
if (pmd_none(*pmd)) {
pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
flush_page_update_queue();
if (page_table != pte_offset_kernel(pmd, 0))
BUG();
wrprotect_bootpt((pgd_t *)start_info.pt_base, page_table, 1);
return page_table;
}
@@ -125,8 +123,7 @@ static void __init page_table_range_init (unsigned long start, unsigned long end
}
}
/* NOTE: caller must call flush_page_update_queue() */
void __init wrprotect_bootpt(pgd_t *pgd, void *page, int set)
void __init protect_page(pgd_t *pgd, void *page, int mode)
{
pmd_t *pmd;
pte_t *pte;
@@ -138,31 +135,25 @@ void __init wrprotect_bootpt(pgd_t *pgd, void *page, int set)
pte = pte_offset_kernel(pmd, addr);
if (!pte_present(*pte))
return;
queue_l1_entry_update(pte, set ? pte_val_ma(*pte) & ~_PAGE_RW :
pte_val_ma(*pte) | _PAGE_RW);
queue_l1_entry_update(pte, mode ? pte_val_ma(*pte) & ~_PAGE_RW :
pte_val_ma(*pte) | _PAGE_RW);
}
/* NOTE: caller must call flush_page_update_queue() */
static void __init protect_bootpt_entries(pgd_t *spgd, pgd_t *dpgd, int set,
int pmdupdate, int pmdset)
void __init protect_pagetable(pgd_t *dpgd, pgd_t *spgd, int mode)
{
pmd_t *pmd;
pte_t *pte;
int pgd_idx, pmd_idx;
protect_page(dpgd, spgd, mode);
for (pgd_idx = 0; pgd_idx < PTRS_PER_PGD_NO_HV; spgd++, pgd_idx++) {
pmd = pmd_offset(spgd, 0);
if (pmd_none(*pmd))
continue;
if (pmdupdate)
wrprotect_bootpt(dpgd, pmd, pmdset);
for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD; pmd++, pmd_idx++) {
if (cpu_has_pse) {
/* XXX */
} else {
pte = pte_offset_kernel(pmd, 0);
wrprotect_bootpt(dpgd, pte, set);
}
pte = pte_offset_kernel(pmd, 0);
protect_page(dpgd, pte, mode);
}
}
}
@@ -536,18 +527,6 @@ out:
#endif
/*
* - write protect new L1 pages in old pgd
* - write protect new pgd page in old pgd
* - write protect new pgd page in new pgd
* - write protect new L1 pages in new pgd
* - write protect old L1 pages in new pgd and write protect old pgd in
* new pgd
* - pin new pgd
* - switch to new pgd
* - unpin old pgd
* - make old L1 pages and old pgd page writeable in new pgd
*/
/*
* paging_init() sets up the page tables - note that the first 8MB are
* already mapped by head.S.
@@ -557,6 +536,8 @@ out:
*/
void __init paging_init(void)
{
pgd_t *old_pgd = (pgd_t *)start_info.pt_base;
pgd_t *new_pgd = swapper_pg_dir;
#ifdef CONFIG_XEN_PHYSDEV_ACCESS
int i;
#endif
@@ -569,21 +550,25 @@ void __init paging_init(void)
pagetable_init();
wrprotect_bootpt((pgd_t *)start_info.pt_base, swapper_pg_dir, 1);
wrprotect_bootpt(swapper_pg_dir, swapper_pg_dir, 1);
flush_page_update_queue();
protect_bootpt_entries(swapper_pg_dir, swapper_pg_dir, 1, 0, 0);
protect_bootpt_entries((pgd_t *)start_info.pt_base, swapper_pg_dir,
1, 1, 1);
queue_pgd_pin(__pa(swapper_pg_dir));
load_cr3(swapper_pg_dir);
/*
* Write-protect both page tables within both page tables.
* That's three ops, as the old p.t. is already protected
* within the old p.t. Then pin the new table, switch tables,
* and unprotect the old table.
*/
protect_pagetable(new_pgd, old_pgd, PROT_ON);
protect_pagetable(new_pgd, new_pgd, PROT_ON);
protect_pagetable(old_pgd, new_pgd, PROT_ON);
queue_pgd_pin(__pa(new_pgd));
load_cr3(new_pgd);
queue_pgd_unpin(__pa(old_pgd));
__flush_tlb_all(); /* implicit flush */
queue_pgd_unpin(__pa(start_info.pt_base));
protect_bootpt_entries((pgd_t *)start_info.pt_base, swapper_pg_dir,
0, 1, 0);
wrprotect_bootpt((pgd_t *)start_info.pt_base, swapper_pg_dir, 0);
protect_pagetable(new_pgd, old_pgd, PROT_OFF);
flush_page_update_queue();
/* Completely detached from old tables, so free them. */
free_bootmem(__pa(old_pgd), start_info.nr_pt_frames << PAGE_SHIFT);
#ifdef CONFIG_X86_PAE
/*
* We will bail out later - printk doesn't work right now so
@@ -741,9 +726,18 @@ void __init mem_init(void)
kmem_cache_t *pgd_cache;
kmem_cache_t *pmd_cache;
kmem_cache_t *pte_cache;
void __init pgtable_cache_init(void)
{
pte_cache = kmem_cache_create("pte",
PTRS_PER_PTE*sizeof(pte_t),
PTRS_PER_PTE*sizeof(pte_t),
0,
pte_ctor,
pte_dtor);
if (!pte_cache)
panic("pgtable_cache_init(): Cannot create pte cache");
if (PTRS_PER_PMD > 1) {
pmd_cache = kmem_cache_create("pmd",
PTRS_PER_PMD*sizeof(pmd_t),
@@ -17,6 +17,25 @@
#include <asm/tlbflush.h>
#include <asm/pgtable.h>
#ifndef CONFIG_XEN_PHYSDEV_ACCESS
void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
{ return NULL; }
void *ioremap_nocache (unsigned long phys_addr, unsigned long size)
{ return NULL; }
void iounmap(void *addr)
{ }
void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
{ return NULL; }
void __init bt_iounmap(void *addr, unsigned long size)
{ }
#else
static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
unsigned long phys_addr, unsigned long flags)
{
@@ -133,11 +152,11 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
/*
* Don't allow anybody to remap normal RAM that we're using..
*/
if (phys_addr < virt_to_phys(high_memory)) {
if (machine_to_phys(phys_addr) < virt_to_phys(high_memory)) {
char *t_addr, *t_end;
struct page *page;
t_addr = __va(phys_addr);
t_addr = bus_to_virt(phys_addr);
t_end = t_addr + (size - 1);
for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++)
@@ -200,8 +219,8 @@ void *ioremap_nocache (unsigned long phys_addr, unsigned long size)
/* Guaranteed to be > phys_addr, as per __ioremap() */
last_addr = phys_addr + size - 1;
if (last_addr < virt_to_phys(high_memory)) {
struct page *ppage = virt_to_page(__va(phys_addr));
if (machine_to_phys(last_addr) < virt_to_phys(high_memory)) {
struct page *ppage = virt_to_page(bus_to_virt(phys_addr));
unsigned long npages;
phys_addr &= PAGE_MASK;
@@ -237,8 +256,8 @@ void iounmap(void *addr)
return;
}
if (p->flags && p->phys_addr < virt_to_phys(high_memory)) {
change_page_attr(virt_to_page(__va(p->phys_addr)),
if (p->flags && machine_to_phys(p->phys_addr) < virt_to_phys(high_memory)) {
change_page_attr(virt_to_page(bus_to_virt(p->phys_addr)),
p->size >> PAGE_SHIFT,
PAGE_KERNEL);
global_flush_tlb();
@@ -316,6 +335,7 @@ void __init bt_iounmap(void *addr, unsigned long size)
}
}
#endif /* CONFIG_XEN_PHYSDEV_ACCESS */
#if defined(CONFIG_XEN_PRIVILEGED_GUEST)
@@ -0,0 +1,215 @@
/*
* Copyright 2002 Andi Kleen, SuSE Labs.
* Thanks to Ben LaHaise for precious feedback.
*/
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/highmem.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
#include <asm/tlbflush.h>
static spinlock_t cpa_lock = SPIN_LOCK_UNLOCKED;
static struct list_head df_list = LIST_HEAD_INIT(df_list);
pte_t *lookup_address(unsigned long address)
{
pgd_t *pgd = pgd_offset_k(address);
pmd_t *pmd;
if (pgd_none(*pgd))
return NULL;
pmd = pmd_offset(pgd, address);
if (pmd_none(*pmd))
return NULL;
if (pmd_large(*pmd))
return (pte_t *)pmd;
return pte_offset_kernel(pmd, address);
}
static struct page *split_large_page(unsigned long address, pgprot_t prot)
{
int i;
unsigned long addr;
struct page *base;
pte_t *pbase;
spin_unlock_irq(&cpa_lock);
base = alloc_pages(GFP_KERNEL, 0);
spin_lock_irq(&cpa_lock);
if (!base)
return NULL;
address = __pa(address);
addr = address & LARGE_PAGE_MASK;
pbase = (pte_t *)page_address(base);
for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) {
pbase[i] = pfn_pte(addr >> PAGE_SHIFT,
addr == address ? prot : PAGE_KERNEL);
}
return base;
}
static void flush_kernel_map(void *dummy)
{
/* Could use CLFLUSH here if the CPU supports it (Hammer,P4) */
if (boot_cpu_data.x86_model >= 4)
wbinvd();
/* Flush all to work around Errata in early athlons regarding
* large page flushing.
*/
__flush_tlb_all();
}
static void set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
{
struct page *page;
unsigned long flags;
set_pte_atomic(kpte, pte); /* change init_mm */
if (PTRS_PER_PMD > 1)
return;
spin_lock_irqsave(&pgd_lock, flags);
for (page = pgd_list; page; page = (struct page *)page->index) {
pgd_t *pgd;
pmd_t *pmd;
pgd = (pgd_t *)page_address(page) + pgd_index(address);
pmd = pmd_offset(pgd, address);
set_pte_atomic((pte_t *)pmd, pte);
}
spin_unlock_irqrestore(&pgd_lock, flags);
}
/*
* No more special protections in this 2/4MB area - revert to a
* large page again.
*/
static inline void revert_page(struct page *kpte_page, unsigned long address)
{
pte_t *linear = (pte_t *)
pmd_offset(pgd_offset(&init_mm, address), address);
set_pmd_pte(linear, address,
pfn_pte((__pa(address) & LARGE_PAGE_MASK) >> PAGE_SHIFT,
PAGE_KERNEL_LARGE));
}
static int
__change_page_attr(struct page *page, pgprot_t prot)
{
pte_t *kpte;
unsigned long address;
struct page *kpte_page;
#ifdef CONFIG_HIGHMEM
if (page >= highmem_start_page)
BUG();
#endif
address = (unsigned long)page_address(page);
kpte = lookup_address(address);
if (!kpte)
return -EINVAL;
kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK);
if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL)) {
if ((pte_val(*kpte) & _PAGE_PSE) == 0) {
pte_t old = *kpte;
pte_t standard = mk_pte(page, PAGE_KERNEL);
set_pte_atomic(kpte, mk_pte(page, prot));
if (pte_same(old,standard))
get_page(kpte_page);
} else {
struct page *split = split_large_page(address, prot);
if (!split)
return -ENOMEM;
get_page(kpte_page);
set_pmd_pte(kpte,address,mk_pte(split, PAGE_KERNEL));
}
} else if ((pte_val(*kpte) & _PAGE_PSE) == 0) {
set_pte_atomic(kpte, mk_pte(page, PAGE_KERNEL));
__put_page(kpte_page);
}
if (cpu_has_pse && (page_count(kpte_page) == 1)) {
list_add(&kpte_page->lru, &df_list);
revert_page(kpte_page, address);
}
return 0;
}
static inline void flush_map(void)
{
on_each_cpu(flush_kernel_map, NULL, 1, 1);
}
/*
* Change the page attributes of an page in the linear mapping.
*
* This should be used when a page is mapped with a different caching policy
* than write-back somewhere - some CPUs do not like it when mappings with
* different caching policies exist. This changes the page attributes of the
* in kernel linear mapping too.
*
* The caller needs to ensure that there are no conflicting mappings elsewhere.
* This function only deals with the kernel linear map.
*
* Caller must call global_flush_tlb() after this.
*/
int change_page_attr(struct page *page, int numpages, pgprot_t prot)
{
int err = 0;
int i;
unsigned long flags;
spin_lock_irqsave(&cpa_lock, flags);
for (i = 0; i < numpages; i++, page++) {
err = __change_page_attr(page, prot);
if (err)
break;
}
spin_unlock_irqrestore(&cpa_lock, flags);
return err;
}
void global_flush_tlb(void)
{
LIST_HEAD(l);
struct list_head* n;
BUG_ON(irqs_disabled());
spin_lock_irq(&cpa_lock);
list_splice_init(&df_list, &l);
spin_unlock_irq(&cpa_lock);
flush_map();
n = l.next;
while (n != &l) {
struct page *pg = list_entry(n, struct page, lru);
n = n->next;
__free_page(pg);
}
}
#ifdef CONFIG_DEBUG_PAGEALLOC
void kernel_map_pages(struct page *page, int numpages, int enable)
{
if (PageHighMem(page))
return;
/* the return value is ignored - the calls cannot fail,
* large pages are disabled at boot time.
*/
change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0));
/* we should perform an IPI and flush all tlbs,
* but that can deadlock->flush only current cpu.
*/
__flush_tlb_all();
}
EXPORT_SYMBOL(kernel_map_pages);
#endif
EXPORT_SYMBOL(change_page_attr);
EXPORT_SYMBOL(global_flush_tlb);
@@ -185,32 +185,44 @@ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
return pte;
}
void pte_ctor(void *pte, kmem_cache_t *cache, unsigned long unused)
{
clear_page(pte);
__make_page_readonly(pte);
queue_pte_pin(virt_to_phys(pte));
flush_page_update_queue();
}
void pte_dtor(void *pte, kmem_cache_t *cache, unsigned long unused)
{
queue_pte_unpin(virt_to_phys(pte));
__make_page_writable(pte);
flush_page_update_queue();
}
struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
{
struct page *pte;
pte_t *ptep;
#ifdef CONFIG_HIGHPTE
struct page *pte;
pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT, 0);
#else
pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0);
#endif
if (pte) {
#ifdef CONFIG_HIGHPTE
void *kaddr = kmap_atomic(pte, KM_USER0);
clear_page(kaddr);
kunmap_atomic_force(kaddr, KM_USER0);
#else
if (pte == NULL)
return pte;
if (pte >= highmem_start_page) {
clear_highpage(pte);
#endif
#ifdef CONFIG_HIGHPTE
if (pte < highmem_start_page)
#endif
{
__make_page_readonly(phys_to_virt(page_to_pseudophys(pte)));
flush_page_update_queue();
}
return pte;
}
return pte;
/* not a highmem page -- free page and grab one from the cache */
__free_page(pte);
#endif
ptep = kmem_cache_alloc(pte_cache, GFP_KERNEL);
if (ptep)
return virt_to_page(ptep);
return NULL;
}
void pmd_ctor(void *pmd, kmem_cache_t *cache, unsigned long flags)
@@ -1148,6 +1148,12 @@ static void blkif_status_change(blkif_fe_interface_status_changed_t *status)
break;
case BLKIF_INTERFACE_STATUS_CHANGED:
/* The domain controller is notifying us that a device has been
* added or removed.
*/
break;
default:
printk(KERN_WARNING "Status change to unknown value %d\n",
status->status);
@@ -26,6 +26,9 @@
#include <asm-xen/hypervisor-ifs/io/netif.h>
#include <asm/page.h>
#include <net/arp.h>
#include <net/route.h>
#if 0
#define DPRINTK(fmt, args...) \
printk(KERN_INFO "[XEN] %s" fmt, __FUNCTION__, ##args)
@@ -171,6 +174,32 @@ static int netctrl_connected_count(void)
return connected;
}
/** Send a packet on a net device to encourage switches to learn the
* MAC. We send a fake ARP request.
*
* @param dev device
* @return 0 on success, error code otherwise
*/
static int vif_wake(struct net_device *dev){
int err = 0;
struct sk_buff *skb;
u32 src_ip;
u32 dst_ip = INADDR_BROADCAST;
unsigned char dst_hw[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
src_ip = inet_select_addr(dev, dst_ip, RT_SCOPE_LINK);
skb = arp_create(ARPOP_REQUEST, ETH_P_ARP,
dst_ip, dev, src_ip,
dst_hw, dev->dev_addr, NULL);
if(skb == NULL){
err = -ENOMEM;
goto exit;
}
err = dev_queue_xmit(skb);
exit:
return err;
}
static inline struct sk_buff *alloc_skb_page(void)
{
struct sk_buff *skb;
@@ -739,6 +768,13 @@ static void netif_status_change(netif_fe_interface_status_changed_t *status)
(void)request_irq(np->irq, netif_int, SA_SAMPLE_RANDOM,
dev->name, dev);
netctrl_connected_count();
vif_wake(dev);
break;
case NETIF_INTERFACE_STATUS_CHANGED:
/* The domain controller is notifying us that a device has been
* added or removed.
*/
break;
default:
@@ -128,12 +128,12 @@ extern void bt_iounmap(void *addr, unsigned long size);
/*
* ISA I/O bus memory addresses are 1:1 with the physical address.
*/
#define isa_virt_to_bus(_x) BUG() // should be (void *)((FIX_ISAMAP_BEGIN - __virt_to_fix((_x))) << PAGE_SHIFT)
#define isa_page_to_bus(_x) BUG() // page_to_phys(_x)
#define isa_virt_to_bus(_x) isa_virt_to_bus_is_UNSUPPORTED->x
#define isa_page_to_bus(_x) isa_page_to_bus_is_UNSUPPORTED->x
#ifdef CONFIG_XEN_PRIVILEGED_GUEST
#define isa_bus_to_virt(_x) (void *)__fix_to_virt(FIX_ISAMAP_BEGIN - ((_x) >> PAGE_SHIFT))
#else
#define isa_bus_to_virt(_x) (void *)0L /* XXXcl */
#define isa_bus_to_virt(_x) isa_bus_to_virt_needs_PRIVILEGED_BUILD
#endif
/*
@@ -22,6 +22,17 @@ static char * __init machine_specific_memory_setup(void)
return who;
}
void __init machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c)
{
clear_bit(X86_FEATURE_VME, c->x86_capability);
clear_bit(X86_FEATURE_DE, c->x86_capability);
clear_bit(X86_FEATURE_PSE, c->x86_capability);
clear_bit(X86_FEATURE_TSC, c->x86_capability);
clear_bit(X86_FEATURE_PGE, c->x86_capability);
clear_bit(X86_FEATURE_MTRR, c->x86_capability);
clear_bit(X86_FEATURE_FXSR, c->x86_capability);
}
extern void hypervisor_callback(void);
extern void failsafe_callback(void);
@@ -31,11 +42,5 @@ static void __init machine_specific_arch_setup(void)
__KERNEL_CS, (unsigned long)hypervisor_callback,
__KERNEL_CS, (unsigned long)failsafe_callback);
clear_bit(X86_FEATURE_VME, boot_cpu_data.x86_capability);
clear_bit(X86_FEATURE_DE, boot_cpu_data.x86_capability);
clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability);
clear_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability);
clear_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability);
clear_bit(X86_FEATURE_FXSR, boot_cpu_data.x86_capability);
machine_specific_modify_cpu_capabilities(&boot_cpu_data);
}
@@ -41,19 +41,16 @@ static inline void pte_free(struct page *pte)
#ifdef CONFIG_HIGHPTE
if (pte < highmem_start_page)
#endif
{
__make_page_writable(phys_to_virt(page_to_pseudophys(pte)));
kmem_cache_free(pte_cache,
phys_to_virt(page_to_pseudophys(pte)));
#ifdef CONFIG_HIGHPTE
else
__free_page(pte);
flush_page_update_queue();
}
#endif
}
#define __pte_free_tlb(tlb,pte) do { \
tlb_remove_page((tlb),(pte)); \
flush_page_update_queue(); \
/* XXXcl queue */ \
} while (0)
#define __pte_free_tlb(tlb,pte) pte_free(pte)
/*
* allocating and freeing a pmd is trivial: the 1-entry pmd is
@@ -35,9 +35,12 @@ extern unsigned long empty_zero_page[1024];
extern pgd_t swapper_pg_dir[1024];
extern kmem_cache_t *pgd_cache;
extern kmem_cache_t *pmd_cache;
extern kmem_cache_t *pte_cache;
extern spinlock_t pgd_lock;
extern struct page *pgd_list;
void pte_ctor(void *, kmem_cache_t *, unsigned long);
void pte_dtor(void *, kmem_cache_t *, unsigned long);
void pmd_ctor(void *, kmem_cache_t *, unsigned long);
void pgd_ctor(void *, kmem_cache_t *, unsigned long);
void pgd_dtor(void *, kmem_cache_t *, unsigned long);
@@ -315,9 +318,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
#define pmd_clear(xp) do { \
pmd_t p = *(xp); \
set_pmd(xp, __pmd(0)); \
__make_page_writable((void *)pmd_page_kernel(p)); \
xen_flush_page_update_queue(); \
} while (0)
@@ -122,9 +122,13 @@ static inline unsigned long _get_base(char * addr)
#endif /* __KERNEL__ */
#define wbinvd() \
BUG();
// __asm__ __volatile__ ("wbinvd": : :"memory");
static inline void wbinvd(void)
{
mmu_update_t u;
u.ptr = MMU_EXTENDED_COMMAND;
u.val = MMUEXT_FLUSH_CACHE;
(void)HYPERVISOR_mmu_update(&u, 1, NULL);
}
static inline unsigned long get_limit(unsigned long segment)
{
@@ -34,7 +34,11 @@ void xen_cpu_idle (void);
void do_hypervisor_callback(struct pt_regs *regs);
/* arch/xen/i386/mm/init.c */
void wrprotect_bootpt(pgd_t *, void *, int);
/* NOTE: caller must call flush_page_update_queue() */
#define PROT_ON 1
#define PROT_OFF 0
void /* __init */ protect_page(pgd_t *dpgd, void *page, int mode);
void /* __init */ protect_pagetable(pgd_t *dpgd, pgd_t *spgd, int mode);
/* arch/xen/i386/kernel/head.S */
void lgdt_finish(void);
+1 -1
View File
@@ -548,7 +548,7 @@ class Xend:
return self.xendPost(self.domainurl(id),
{'op' : 'device_destroy',
'type' : type,
'index' : idx })
'idx' : idx })
def xend_consoles(self):
return self.xendGet(self.consoleurl())
+2 -2
View File
@@ -243,12 +243,12 @@ class XendDomain:
if d['shutdown']:
reason = XendDomainInfo.shutdown_reason(d['shutdown_reason'])
log.debug('XendDomain>reap> shutdown id=%s reason=%s', id, reason)
dominfo = self.domain_by_id.get(id)
name = (dominfo and dominfo.name) or '??'
if reason in ['suspend']:
dominfo = self.domain_by_id.get(id)
if dominfo.is_terminated():
log.debug('XendDomain>reap> Suspended domain died id=%s', id)
else:
name = (dominfo and dominfo.name) or '??'
eserver.inject('xend.domain.suspended', [name, id])
continue
if reason in ['poweroff', 'reboot']:
+20 -5
View File
@@ -576,6 +576,16 @@ class XendDomainInfo:
dl.append(dev)
self.devices[type] = dl
def remove_device(self, type, dev):
"""Remove a device from a virtual machine.
@param type: device type
@param dev: device
"""
dl = self.devices.get(type, [])
if dev in dl:
dl.remove(dev)
def get_devices(self, type):
"""Get a list of the devices of a given type.
@@ -812,7 +822,7 @@ class XendDomainInfo:
devs = self.get_devices(dev_name)
dev_index = len(devs)
self.config.append(['device', dev_config])
d = dev_handler(self, dev_config, dev_index)
d = dev_handler(self, dev_config, dev_index, change=1)
return d
def device_destroy(self, type, idx):
@@ -829,7 +839,8 @@ class XendDomainInfo:
dev_config = self.config_device(type, index)
if dev_config:
self.config.remove(['device', dev_config])
dev.destroy()
dev.destroy(change=1)
self.remove_device(type, dev)
def configure_memory(self):
"""Configure vm memory limit.
@@ -1053,7 +1064,7 @@ def vm_image_netbsd(vm, image):
return vm
def vm_dev_vif(vm, val, index):
def vm_dev_vif(vm, val, index, change=0):
"""Create a virtual network interface (vif).
@param vm: virtual machine
@@ -1069,11 +1080,13 @@ def vm_dev_vif(vm, val, index):
def cbok(dev):
dev.vifctl('up', vmname=vm.name)
vm.add_device('vif', dev)
if change:
dev.interfaceChanged()
return dev
defer.addCallback(cbok)
return defer
def vm_dev_vbd(vm, val, index):
def vm_dev_vbd(vm, val, index, change=0):
"""Create a virtual block device (vbd).
@param vm: virtual machine
@@ -1094,6 +1107,8 @@ def vm_dev_vbd(vm, val, index):
vbd.dev = dev
vbd.uname = uname
vm.add_device('vbd', vbd)
if change:
vbd.interfaceChanged()
return vbd
defer.addCallback(fn)
return defer
@@ -1110,7 +1125,7 @@ def parse_pci(val):
v = val
return v
def vm_dev_pci(vm, val, index):
def vm_dev_pci(vm, val, index, change=0):
"""Add a pci device.
@param vm: virtual machine
+102 -168
View File
@@ -23,7 +23,6 @@ from twisted.internet import reactor
from twisted.internet import protocol
from twisted.internet import abstract
from twisted.internet import defer
#defer.Deferred.debug = 1
from xen.lowlevel import xu
@@ -45,127 +44,6 @@ from params import *
DEBUG = 1
class MgmtProtocol(protocol.DatagramProtocol):
"""Handler for the management socket (unix-domain).
"""
def __init__(self, daemon):
#protocol.DatagramProtocol.__init__(self)
self.daemon = daemon
def write(self, data, addr):
return self.transport.write(data, addr)
def datagramReceived(self, data, addr):
if DEBUG: print 'datagramReceived> addr=', addr, 'data=', data
io = StringIO.StringIO(data)
try:
vals = sxp.parse(io)
res = self.dispatch(vals[0])
self.send_result(addr, res)
except SystemExit:
raise
except:
if DEBUG:
raise
else:
self.send_error(addr)
def send_reply(self, addr, sxpr):
io = StringIO.StringIO()
sxp.show(sxpr, out=io)
io.seek(0)
self.write(io.getvalue(), addr)
def send_result(self, addr, res):
def fn(res, self=self, addr=addr):
self.send_reply(addr, ['ok', res])
if isinstance(res, defer.Deferred):
res.addCallback(fn)
else:
fn(res)
def send_error(self, addr):
(extype, exval) = sys.exc_info()[:2]
self.send_reply(addr, ['err',
['type', str(extype) ],
['value', str(exval) ] ] )
def opname(self, name):
"""Get the name of the method for an operation.
"""
return 'op_' + name.replace('.', '_')
def operror(self, name, v):
"""Default operation handler - signals an error.
"""
raise NotImplementedError('Invalid operation: ' +name)
def dispatch(self, req):
"""Dispatch a request to its handler.
"""
op_name = sxp.name(req)
op_method_name = self.opname(op_name)
op_method = getattr(self, op_method_name, self.operror)
return op_method(op_name, req)
def op_console_create(self, name, req):
"""Create a new control interface - console for a domain.
"""
print name, req
dom = sxp.child_value(req, 'domain')
if not dom: raise XendError('Missing domain')
dom = int(dom)
console_port = sxp.child_value(req, 'console_port')
if console_port:
console_port = int(console_port)
resp = self.daemon.console_create(dom, console_port).sxpr()
print name, resp
return resp
def op_consoles(self, name, req):
"""Get a list of the consoles.
"""
return self.daemon.consoles()
def op_console_disconnect(self, name, req):
id = sxp.child_value(req, 'id')
if not id:
raise XendError('Missing console id')
id = int(id)
console = self.daemon.get_console(id)
if not console:
raise XendError('Invalid console id')
if console.conn:
console.conn.loseConnection()
return ['ok']
def op_blkifs(self, name, req):
pass
def op_blkif_devs(self, name, req):
pass
def op_blkif_create(self, name, req):
pass
def op_blkif_dev_create(self, name, req):
pass
def op_netifs(self, name, req):
pass
def op_netif_devs(self, name, req):
pass
def op_netif_create(self, name, req):
pass
def op_netif_dev_create(self, name, req):
pass
class NotifierProtocol(protocol.Protocol):
"""Asynchronous handler for i/o on the notifier (event channel).
"""
@@ -245,17 +123,14 @@ class NotifierPort(abstract.FileDescriptor):
del self.d
def doRead(self):
#print 'NotifierPort>doRead>', self
count = 0
while 1:
#print 'NotifierPort>doRead>', count
notification = self.notifier.read()
if not notification:
break
self.protocol.notificationReceived(notification)
self.notifier.unmask(notification)
count += 1
#print 'NotifierPort>doRead<'
class EventProtocol(protocol.Protocol):
"""Asynchronous handler for a connected event socket.
@@ -481,25 +356,69 @@ class Daemon:
err = 1
print "Daemon already running: ", pids
return err
def cleanup(self, kill=False):
# No cleanup to do if PID_FILE is empty.
if not os.path.isfile(PID_FILE) or not os.path.getsize(PID_FILE):
return 0
# Read the pid of the previous invocation and search active process list.
pid = open(PID_FILE, 'r').read()
lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
for line in lines:
if re.search('^ *' + pid + '.+xend', line):
if not kill:
print "Daemon is already running (pid %d)" % int(pid)
return 1
# Old daemon is still active: terminate it.
os.kill(int(pid), 1)
# Delete the stale PID_FILE.
os.remove(PID_FILE)
return 0
def read_pid(self, pidfile):
"""Read process id from a file.
@param pidfile: file to read
@return pid or 0
"""
pid = 0
if os.path.isfile(pidfile) and os.path.getsize(pidfile):
try:
pid = open(pidfile, 'r').read()
pid = int(pid)
except:
pid = 0
return pid
def find_process(self, pid, name):
"""Search for a process.
@param pid: process id
@param name: process name
@return: pid if found, 0 otherwise
"""
running = 0
if pid:
lines = os.popen('ps %d 2>/dev/null' % pid).readlines()
exp = '^ *%d.+%s' % (pid, name)
for line in lines:
if re.search(exp, line):
running = pid
break
return running
def cleanup_process(self, pidfile, name, kill):
"""Clean up the pidfile for a process.
If a running process is found, kills it if 'kill' is true.
@param pidfile: pid file
@param name: process name
@param kill: whether to kill the process
@return running process id or 0
"""
running = 0
pid = self.read_pid(pidfile)
if self.find_process(pid, name):
if kill:
os.kill(pid, 1)
else:
running = pid
if running == 0 and os.path.isfile(pidfile):
os.remove(pidfile)
return running
def cleanup_xend(self, kill=False):
return self.cleanup_process(XEND_PID_FILE, "xend", kill)
def cleanup_xfrd(self, kill=False):
return self.cleanup_process(XFRD_PID_FILE, "xfrd", kill)
def cleanup(self, kill=False):
self.cleanup_xend(kill=kill)
self.cleanup_xfrd(kill=kill)
def install_child_reaper(self):
#signal.signal(signal.SIGCHLD, self.onSIGCHLD)
# Ensure that zombie children are automatically reaped.
@@ -510,42 +429,65 @@ class Daemon:
while code > 0:
code = os.waitpid(-1, os.WNOHANG)
def fork_pid(self, pidfile):
"""Fork and write the pid of the child to 'pidfile'.
@param pidfile: pid file
@return: pid of child in parent, 0 in child
"""
pid = os.fork()
if pid:
# Parent
pidfile = open(pidfile, 'w')
pidfile.write(str(pid))
pidfile.close()
return pid
def start_xfrd(self):
"""Fork and exec xfrd, writing its pid to XFRD_PID_FILE.
"""
if self.fork_pid(XFRD_PID_FILE):
# Parent
pass
else:
# Child
self.set_user()
os.execl("/usr/sbin/xfrd", "xfrd")
def start(self, trace=0):
if self.cleanup(kill=False):
xend_pid = self.cleanup_xend()
xfrd_pid = self.cleanup_xfrd()
if xfrd_pid == 0:
self.start_xfrd()
if xend_pid > 0:
return 1
# Detach from TTY.
if not DEBUG:
os.setsid()
if self.set_user():
return 1
self.install_child_reaper()
# Fork -- parent writes PID_FILE and exits.
pid = os.fork()
if pid:
# Parent
pidfile = open(PID_FILE, 'w')
pidfile.write(str(pid))
pidfile.close()
return 0
# Child
self.tracing(trace)
self.run()
if self.fork_pid(XEND_PID_FILE):
#Parent
pass
else:
# Child
self.tracing(trace)
self.run()
return 0
def tracing(self, traceon):
"""Turn tracing on or off.
traceon tracing flag
@param traceon: tracing flag
"""
if traceon == self.traceon:
return
self.traceon = traceon
if traceon:
self.tracefile = open('/var/log/xend.trace', 'w+', 1)
self.tracefile = open(XEND_TRACE_FILE, 'w+', 1)
self.traceindent = 0
sys.settrace(self.trace)
try:
@@ -620,7 +562,6 @@ class Daemon:
xroot = XendRoot.instance()
log.info("Xend Daemon started")
self.createFactories()
self.listenMgmt()
self.listenEvent()
self.listenNotifier()
self.listenVirq()
@@ -634,13 +575,6 @@ class Daemon:
self.netifCF = netif.NetifControllerFactory()
self.consoleCF = console.ConsoleControllerFactory()
def listenMgmt(self):
protocol = MgmtProtocol(self)
s = os.path.join(CONTROL_DIR, MGMT_SOCK)
if os.path.exists(s):
os.unlink(s)
return reactor.listenUNIXDatagram(s, protocol)
def listenEvent(self):
protocol = EventFactory(self)
return reactor.listenTCP(EVENT_PORT, protocol)
@@ -656,7 +590,7 @@ class Daemon:
virqChan.registerClient(VirqClient(self))
def exit(self):
reactor.diconnectAll()
reactor.disconnectAll()
sys.exit(0)
def getDomChannel(self, dom):
+40 -17
View File
@@ -3,7 +3,6 @@
"""
from twisted.internet import defer
#defer.Deferred.debug = 1
from xen.xend import sxp
from xen.xend.XendLogging import log
@@ -88,14 +87,12 @@ class BlkifBackendInterface(controller.BackendInterface):
self.send_be_disconnect(response=d)
def send_be_disconnect(self, response=None):
log.debug('>BlkifBackendController>send_be_disconnect> %s', str(self))
msg = packMsg('blkif_be_disconnect_t',
{ 'domid' : self.controller.dom,
'blkif_handle' : self.handle })
self.writeRequest(msg, response=response)
def send_be_destroy(self, response=None):
log.debug('>BlkifBackendController>send_be_destroy> %s', str(self))
msg = packMsg('blkif_be_destroy_t',
{ 'domid' : self.controller.dom,
'blkif_handle' : self.handle })
@@ -127,9 +124,28 @@ class BlkifBackendInterface(controller.BackendInterface):
msg = packMsg('blkif_fe_interface_status_changed_t',
{ 'handle' : self.handle,
'status' : BLKIF_INTERFACE_STATUS_CONNECTED,
'domid' : 0, ## FIXME: should be domid of backend
'domid' : self.dom,
'evtchn' : self.evtchn['port2'] })
self.controller.writeRequest(msg, response=response)
def interfaceDisconnected(self):
msg = packMsg('blkif_fe_interface_status_changed_t',
{ 'handle' : self.handle,
'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED,
'domid' : self.dom,
'evtchn' : 0 })
self.controller.writeRequest(msg)
def interfaceChanged(self):
"""Notify the front-end that devices have been added or removed.
The front-end should then probe for devices.
"""
msg = packMsg('blkif_fe_interface_status_changed_t',
{ 'handle' : self.handle,
'status' : BLKIF_INTERFACE_STATUS_CHANGED,
'domid' : self.dom,
'evtchn' : 0 })
self.controller.writeRequest(msg)
class BlkifControllerFactory(controller.SplitControllerFactory):
"""Factory for creating block device interface controllers.
@@ -230,9 +246,21 @@ class BlkDev(controller.SplitDev):
val.append(['uname', self.uname])
return val
def destroy(self):
def destroy(self, change=0):
"""Destroy the device. If 'change' is true notify the front-end interface.
@param change: change flag
"""
log.debug("Destroying vbd domain=%d vdev=%d", self.controller.dom, self.vdev)
self.send_be_vbd_destroy()
d = self.send_be_vbd_destroy()
if change:
d.addCallback(lambda val: self.interfaceChanged())
def interfaceChanged(self):
"""Tell the back-end to notify the front-end that a device has been
added or removed.
"""
self.getBackendInterface().interfaceChanged()
def attach(self):
"""Attach the device to its controller.
@@ -295,16 +323,16 @@ class BlkDev(controller.SplitDev):
% (self.vdev, status))
return self
def send_be_vbd_destroy(self, response=None):
log.debug('>BlkDev>send_be_vbd_destroy> dom=%d vdev=%d',
self.controller.dom, self.vdev)
def send_be_vbd_destroy(self):
d = defer.Deferred()
backend = self.getBackendInterface()
msg = packMsg('blkif_be_vbd_destroy_t',
{ 'domid' : self.controller.dom,
'blkif_handle' : backend.handle,
'vdevice' : self.vdev })
self.controller.delDevice(self.vdev)
backend.writeRequest(msg, response=response)
backend.writeRequest(msg, response=d)
return d
class BlkifController(controller.SplitController):
@@ -399,13 +427,8 @@ class BlkifController(controller.SplitController):
def recv_fe_driver_status_changed(self, msg, req):
val = unpackMsg('blkif_fe_driver_status_changed_t', msg)
# For each backend?
msg = packMsg('blkif_fe_interface_status_changed_t',
{ 'handle' : 0,
'status' : BLKIF_INTERFACE_STATUS_DISCONNECTED,
'domid' : 0, ## FIXME: should be domid of backend
'evtchn' : 0 })
self.writeRequest(msg)
for backend in self.getBackendInterfaces():
backend.interfaceDisconnected()
def recv_fe_interface_connect(self, msg, req):
val = unpackMsg('blkif_fe_interface_connect_t', msg)
+2
View File
@@ -50,6 +50,7 @@ BLKIF_DRIVER_STATUS_UP = 1
BLKIF_INTERFACE_STATUS_DESTROYED = 0 #/* Interface doesn't exist. */
BLKIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
BLKIF_INTERFACE_STATUS_CONNECTED = 2 #/* Exists and is connected. */
BLKIF_INTERFACE_STATUS_CHANGED = 3 #/* A device has been added or removed. */
BLKIF_BE_STATUS_OKAY = 0
BLKIF_BE_STATUS_ERROR = 1
@@ -117,6 +118,7 @@ CMSG_NETIF_BE_DRIVER_STATUS_CHANGED = 32
NETIF_INTERFACE_STATUS_DESTROYED = 0 #/* Interface doesn't exist. */
NETIF_INTERFACE_STATUS_DISCONNECTED = 1 #/* Exists but is disconnected. */
NETIF_INTERFACE_STATUS_CONNECTED = 2 #/* Exists and is connected. */
NETIF_INTERFACE_STATUS_CHANGED = 3 #/* A device has been added or removed. */
NETIF_DRIVER_STATUS_DOWN = 0
NETIF_DRIVER_STATUS_UP = 1
+20 -5
View File
@@ -5,7 +5,6 @@
import random
from twisted.internet import defer
#defer.Deferred.debug = 1
from xen.xend import sxp
from xen.xend import Vifctl
@@ -208,13 +207,17 @@ class NetDev(controller.SplitDev):
val = unpackMsg('netif_be_create_t', msg)
return self
def destroy(self):
def destroy(self, change=0):
"""Destroy the device's resources and disconnect from the back-end
device controller.
device controller. If 'change' is true notify the front-end interface.
@param change: change flag
"""
def cb_destroy(val):
self.send_be_destroy()
self.getBackendInterface().close()
if change:
self.interfaceChanged()
log.debug("Destroying vif domain=%d vif=%d", self.controller.dom, self.vif)
self.vifctl('down')
d = self.send_be_disconnect()
@@ -256,7 +259,7 @@ class NetDev(controller.SplitDev):
{ 'handle' : self.vif,
'status' : NETIF_INTERFACE_STATUS_CONNECTED,
'evtchn' : self.evtchn['port2'],
'domid' : 0, ## FIXME: should be domid of backend
'domid' : self.backendDomain,
'mac' : self.mac })
self.controller.writeRequest(msg)
@@ -265,7 +268,19 @@ class NetDev(controller.SplitDev):
{ 'handle' : self.vif,
'status' : NETIF_INTERFACE_STATUS_DISCONNECTED,
'evtchn' : 0,
'domid' : 0, ## FIXME: should be domid of backend
'domid' : self.backendDomain,
'mac' : self.mac })
self.controller.writeRequest(msg)
def interfaceChanged(self):
"""Notify the font-end that a device has been added or removed.
The front-end should then probe the devices.
"""
msg = packMsg('netif_fe_interface_status_changed_t',
{ 'handle' : self.vif,
'status' : NETIF_INTERFACE_STATUS_CHANGED,
'evtchn' : 0,
'domid' : self.backendDomain,
'mac' : self.mac })
self.controller.writeRequest(msg)
+5 -3
View File
@@ -1,8 +1,10 @@
# The following parameters could be placed in a configuration file.
PID_FILE = '/var/run/xend.pid'
XEND_PID_FILE = '/var/run/xend.pid'
XFRD_PID_FILE = '/var/run/xfrd.pid'
XEND_TRACE_FILE = '/var/log/xend.trace'
USER = 'root'
CONTROL_DIR = '/var/run/xend'
MGMT_SOCK = 'xendsock' # relative to CONTROL_DIR
EVENT_PORT = 8001
CONSOLE_PORT_BASE = 9600
+14 -8
View File
@@ -737,22 +737,26 @@ class ProgVbdCreate(Prog):
info = """Create a new virtual block device for a domain"""
def help(self, args):
print args[0], "DOM UNAME DEV MODE"
print args[0], "DOM UNAME DEV MODE [BACKEND]"
print """
Create a virtual block device for a domain.
UNAME - device to export, e.g. phys:hda2
DEV - device name in the domain, e.g. xda1
MODE - access mode: r for read, w for read-write
UNAME - device to export, e.g. phy:hda2
DEV - device name in the domain, e.g. xda1
MODE - access mode: r for read, w for read-write
BACKEND - backend driver domain
"""
def main(self, args):
if len(args) != 5: self.err("%s: Invalid argument(s)" % args[0])
n = len(args)
if n < 5 or n > 6: self.err("%s: Invalid argument(s)" % args[0])
dom = args[1]
vbd = ['vbd',
['uname', args[2]],
['dev', args[3]],
['mode', args[4]]]
if n == 6:
vbd.append(['backend', args[5]])
server.xend_domain_device_create(dom, vbd)
xm.prog(ProgVbdCreate)
@@ -766,13 +770,15 @@ class ProgVbdDestroy(Prog):
print args[0], "DOM DEV"
print """
Destroy vbd DEV attached to domain DOM. Detaches the device
from the domain, but does not destroy the device contents."""
from the domain, but does not destroy the device contents.
The device indentifier DEV is the idx field in the device
information. This is visible in 'xm vbd-list'."""
def main(self, args):
if len(args!=3): self.err("%s: Invalid argument(s)" % args[0])
if len(args) != 3: self.err("%s: Invalid argument(s)" % args[0])
dom = args[1]
dev = args[2]
sever.xend_domain_device_destroy(dom, "vbd", dev)
server.xend_domain_device_destroy(dom, "vbd", dev)
xm.prog(ProgVbdDestroy)
+1
View File
@@ -16,6 +16,7 @@ typedef unsigned long u32;
#define MODULE_NAME "XFRD"
#define DEBUG 1
#undef DEBUG
#include "debug.h"
+5
View File
@@ -50,6 +50,7 @@
#define MODULE_NAME "XFRD"
#define DEBUG 0
#undef DEBUG
#include "debug.h"
/*
@@ -1142,7 +1143,11 @@ int main(int argc, char *argv[]){
int err = 0;
int key = 0;
int long_index = 0;
static const char * LOGFILE = "/var/log/xfrd.log";
freopen(LOGFILE, "w+", stdout);
fclose(stderr);
stderr = stdout;
dprintf(">\n");
set_defaults(args);
while(1){
+65 -46
View File
@@ -449,12 +449,68 @@ long do_iopl(domid_t domain, unsigned int new_io_pl)
#endif
void domain_relinquish_memory(struct domain *d)
static void relinquish_list(struct domain *d, struct list_head *list)
{
struct list_head *ent, *tmp;
struct list_head *ent;
struct pfn_info *page;
unsigned long x, y;
/* Use a recursive lock, as we may enter 'free_domheap_page'. */
spin_lock_recursive(&d->page_alloc_lock);
ent = list->next;
while ( ent != list )
{
page = list_entry(ent, struct pfn_info, list);
/* Grab a reference to the page so it won't disappear from under us. */
if ( unlikely(!get_page(page, d)) )
{
/* Couldn't get a reference -- someone is freeing this page. */
ent = ent->next;
continue;
}
if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
put_page_and_type(page);
if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
put_page(page);
/*
* Forcibly invalidate base page tables at this point to break circular
* 'linear page table' references. This is okay because MMU structures
* are not shared across domains and this domain is now dead. Thus base
* tables are not in use so a non-zero count means circular reference.
*/
y = page->u.inuse.type_info;
for ( ; ; )
{
x = y;
if ( likely((x & (PGT_type_mask|PGT_validated)) !=
(PGT_base_page_table|PGT_validated)) )
break;
y = cmpxchg(&page->u.inuse.type_info, x, x & ~PGT_validated);
if ( likely(y == x) )
{
free_page_type(page, PGT_base_page_table);
break;
}
}
/* Follow the list chain and /then/ potentially free the page. */
ent = ent->next;
put_page(page);
}
spin_unlock_recursive(&d->page_alloc_lock);
}
void domain_relinquish_memory(struct domain *d)
{
/* Ensure that noone is running over the dead domain's page tables. */
synchronise_pagetables(~0UL);
@@ -472,49 +528,9 @@ void domain_relinquish_memory(struct domain *d)
*/
destroy_gdt(d);
/* Use a recursive lock, as we may enter 'free_domheap_page'. */
spin_lock_recursive(&d->page_alloc_lock);
/* Relinquish Xen-heap pages. */
list_for_each_safe ( ent, tmp, &d->xenpage_list )
{
page = list_entry(ent, struct pfn_info, list);
if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
put_page(page);
}
/* Relinquish all pages on the domain's allocation list. */
list_for_each_safe ( ent, tmp, &d->page_list )
{
page = list_entry(ent, struct pfn_info, list);
if ( test_and_clear_bit(_PGC_guest_pinned, &page->count_info) )
put_page_and_type(page);
if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
put_page(page);
/*
* Forcibly invalidate base page tables at this point to break circular
* 'linear page table' references. This is okay because MMU structures
* are not shared across domains and this domain is now dead. Thus base
* tables are not in use so a non-zero count means circular reference.
*/
y = page->u.inuse.type_info;
do {
x = y;
if ( likely((x & (PGT_type_mask|PGT_validated)) !=
(PGT_base_page_table|PGT_validated)) )
break;
y = cmpxchg(&page->u.inuse.type_info, x, x & ~PGT_validated);
if ( likely(y == x) )
free_page_type(page, PGT_base_page_table);
}
while ( unlikely(y != x) );
}
spin_unlock_recursive(&d->page_alloc_lock);
/* Relinquish every page of memory. */
relinquish_list(d, &d->xenpage_list);
relinquish_list(d, &d->page_list);
}
@@ -739,12 +755,15 @@ int construct_dom0(struct domain *p,
/* Get another ref to L2 page so that it can be pinned. */
if ( !get_page_and_type(page, p, PGT_l2_page_table) )
BUG();
set_bit(_PGC_guest_pinned, &page->count_info);
set_bit(_PGT_pinned, &page->u.inuse.type_info);
}
else
{
page->u.inuse.type_info &= ~PGT_type_mask;
page->u.inuse.type_info |= PGT_l1_page_table;
page->u.inuse.type_info |=
((v_start>>L2_PAGETABLE_SHIFT)+(count-1))<<PGT_va_shift;
get_page(page, p); /* an extra ref because of readable mapping */
}
l1tab++;
+69 -75
View File
@@ -142,8 +142,6 @@ static struct domain *dom_xen, *dom_io;
void arch_init_memory(void)
{
static void ptwr_init_backpointers(void);
static void ptwr_disable(void);
unsigned long mfn;
/*
@@ -165,10 +163,15 @@ void arch_init_memory(void)
memset(percpu_info, 0, sizeof(percpu_info));
/* XXXX WRITEABLE PAGETABLES SHOULD BE A DOMAIN CREATION-TIME
DECISION, NOT SOMETHING THAT IS CHANGED ON A RUNNING DOMAIN
!!! FIX ME !!!!
*/
vm_assist_info[VMASST_TYPE_writable_pagetables].enable =
ptwr_init_backpointers;
NULL;
vm_assist_info[VMASST_TYPE_writable_pagetables].disable =
ptwr_disable;
NULL;
for ( mfn = 0; mfn < max_page; mfn++ )
frame_table[mfn].count_info |= PGC_always_set;
@@ -322,17 +325,6 @@ static int get_page_and_type_from_pagenr(unsigned long page_nr,
}
static inline void set_l1_page_va(unsigned long pfn,
unsigned long va_idx)
{
struct pfn_info *page;
page = &frame_table[pfn];
page->u.inuse.type_info &= ~PGT_va_mask;
page->u.inuse.type_info |= va_idx << PGT_va_shift;
}
/*
* We allow an L2 tables to map each other (a.k.a. linear page tables). It
* needs some special care with reference counst and access permissions:
@@ -466,8 +458,11 @@ get_page_from_l1e(
/* NB. Virtual address 'l2e' maps to a machine address within frame 'pfn'. */
static int
get_page_from_l2e(
l2_pgentry_t l2e, unsigned long pfn, struct domain *d)
l2_pgentry_t l2e, unsigned long pfn,
struct domain *d, unsigned long va_idx)
{
int rc;
if ( !(l2_pgentry_val(l2e) & _PAGE_PRESENT) )
return 1;
@@ -478,8 +473,11 @@ get_page_from_l2e(
return 0;
}
if ( unlikely(!get_page_and_type_from_pagenr(
l2_pgentry_to_pagenr(l2e), PGT_l1_page_table, d)) )
rc = get_page_and_type_from_pagenr(
l2_pgentry_to_pagenr(l2e),
PGT_l1_page_table | (va_idx<<PGT_va_shift), d);
if ( unlikely(!rc) )
return get_linear_pagetable(l2e, pfn, d);
return 1;
@@ -553,9 +551,8 @@ static int alloc_l2_table(struct pfn_info *page)
pl2e = map_domain_mem(page_nr << PAGE_SHIFT);
for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ ) {
if ( unlikely(!get_page_from_l2e(pl2e[i], page_nr, d)) )
if ( unlikely(!get_page_from_l2e(pl2e[i], page_nr, d, i)) )
goto fail;
set_l1_page_va(l2_pgentry_val(pl2e[i]) >> PAGE_SHIFT, i);
}
#if defined(__i386__)
@@ -677,11 +674,10 @@ static int mod_l2_entry(l2_pgentry_t *pl2e,
if ( ((l2_pgentry_val(ol2e) ^ l2_pgentry_val(nl2e)) & ~0xffe) == 0 )
return update_l2e(pl2e, ol2e, nl2e);
if ( unlikely(!get_page_from_l2e(nl2e, pfn, current)) )
if ( unlikely(!get_page_from_l2e(nl2e, pfn, current,
((unsigned long)pl2e &
~PAGE_MASK) >> 2)) )
return 0;
set_l1_page_va(l2_pgentry_val(nl2e) >> PAGE_SHIFT,
((unsigned long)pl2e & (PAGE_SIZE-1)) >> 2);
if ( unlikely(!update_l2e(pl2e, ol2e, nl2e)) )
{
@@ -836,10 +832,17 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
{
case MMUEXT_PIN_L1_TABLE:
case MMUEXT_PIN_L2_TABLE:
/*
* We insist that, if you pin an L1 page, it's the first thing that
* you do to it. This is because we require the backptr to still be
* mutable. This assumption seems safe.
*/
okay = get_page_and_type_from_pagenr(
pfn,
(cmd==MMUEXT_PIN_L2_TABLE) ? PGT_l2_page_table : PGT_l1_page_table,
((cmd==MMUEXT_PIN_L2_TABLE) ?
PGT_l2_page_table : (PGT_l1_page_table|PGT_va_mutable)),
FOREIGNDOM);
if ( unlikely(!okay) )
{
MEM_LOG("Error while pinning pfn %08lx", pfn);
@@ -847,8 +850,8 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
break;
}
if ( unlikely(test_and_set_bit(_PGC_guest_pinned,
&page->count_info)) )
if ( unlikely(test_and_set_bit(_PGT_pinned,
&page->u.inuse.type_info)) )
{
MEM_LOG("Pfn %08lx already pinned", pfn);
put_page_and_type(page);
@@ -864,8 +867,8 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
MEM_LOG("Page %08lx bad domain (dom=%p)",
ptr, page->u.inuse.domain);
}
else if ( likely(test_and_clear_bit(_PGC_guest_pinned,
&page->count_info)) )
else if ( likely(test_and_clear_bit(_PGT_pinned,
&page->u.inuse.type_info)) )
{
put_page_and_type(page);
put_page(page);
@@ -897,8 +900,7 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
/*
* Note that we tick the clock /after/ dropping the old base's
* reference count. If the page tables got freed then this will
* avoid unnecessary TLB flushes when the pages are reused.
*/
* avoid unnecessary TLB flushes when the pages are reused. */
tlb_clocktick();
}
else
@@ -915,6 +917,18 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
__flush_tlb_one(ptr);
break;
case MMUEXT_FLUSH_CACHE:
if ( unlikely(!IS_CAPABLE_PHYSDEV(d)) )
{
MEM_LOG("Non-physdev domain tried to FLUSH_CACHE.\n");
okay = 0;
}
else
{
wbinvd();
}
break;
case MMUEXT_SET_LDT:
{
unsigned long ents = val >> MMUEXT_CMD_SHIFT;
@@ -1040,13 +1054,18 @@ static int do_extended_command(unsigned long ptr, unsigned long val)
spin_lock(&e->page_alloc_lock);
/* Check that 'e' will accept the page and has reservation headroom. */
/*
* Check that 'e' will accept the page and has reservation headroom.
* Also, a domain mustn't have PGC_allocated pages when it is dying.
*/
ASSERT(e->tot_pages <= e->max_pages);
if ( unlikely(e->tot_pages == e->max_pages) ||
if ( unlikely(test_bit(DF_DYING, &e->flags)) ||
unlikely(e->tot_pages == e->max_pages) ||
unlikely(!gnttab_prepare_for_transfer(e, d, gntref)) )
{
MEM_LOG("Transferee has no reservation headroom (%d,%d), or "
"provided a bad grant ref.\n", e->tot_pages, e->max_pages);
"provided a bad grant ref, or is dying (%08lx).\n",
e->tot_pages, e->max_pages, e->flags);
spin_unlock(&e->page_alloc_lock);
put_domain(e);
okay = 0;
@@ -1182,6 +1201,7 @@ int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count)
unsigned long prev_spfn = 0;
l1_pgentry_t *prev_spl1e = 0;
struct domain *d = current;
u32 type_info;
perfc_incrc(calls_to_mmu_update);
perfc_addc(num_page_updates, count);
@@ -1230,10 +1250,11 @@ int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count)
}
page = &frame_table[pfn];
switch ( (page->u.inuse.type_info & PGT_type_mask) )
switch ( (type_info = page->u.inuse.type_info) & PGT_type_mask )
{
case PGT_l1_page_table:
if ( likely(get_page_type(page, PGT_l1_page_table)) )
if ( likely(get_page_type(
page, type_info & (PGT_type_mask|PGT_va_mask))) )
{
okay = mod_l1_entry((l1_pgentry_t *)va,
mk_l1_pgentry(req.val));
@@ -1483,11 +1504,11 @@ void ptwr_reconnect_disconnected(unsigned long addr)
[ptwr_info[cpu].writable_l1>>PAGE_SHIFT];
#ifdef PTWR_TRACK_DOMAIN
if (ptwr_domain[cpu] != get_current()->domain)
if (ptwr_domain[cpu] != current->domain)
printk("ptwr_reconnect_disconnected domain mismatch %d != %d\n",
ptwr_domain[cpu], get_current()->domain);
ptwr_domain[cpu], current->domain);
#endif
PTWR_PRINTK(("[A] page fault in disconnected space: addr %08lx space %08lx\n",
PTWR_PRINTK(("[A] page fault in disconn space: addr %08lx space %08lx\n",
addr, ptwr_info[cpu].disconnected << L2_PAGETABLE_SHIFT));
pl2e = &linear_l2_table[ptwr_info[cpu].disconnected];
@@ -1559,9 +1580,9 @@ void ptwr_flush_inactive(void)
int i, idx;
#ifdef PTWR_TRACK_DOMAIN
if (ptwr_info[cpu].domain != get_current()->domain)
if (ptwr_info[cpu].domain != current->domain)
printk("ptwr_flush_inactive domain mismatch %d != %d\n",
ptwr_info[cpu].domain, get_current()->domain);
ptwr_info[cpu].domain, current->domain);
#endif
#if 0
{
@@ -1626,9 +1647,11 @@ int ptwr_do_page_fault(unsigned long addr)
PTWR_PRINTK(("get user %p for va %08lx\n",
&linear_pg_table[addr>>PAGE_SHIFT], addr));
#endif
/* Testing for page_present in the L2 avoids lots of unncessary fixups */
if ( (l2_pgentry_val(linear_l2_table[addr >> L2_PAGETABLE_SHIFT]) &
_PAGE_PRESENT) &&
(__get_user(pte, (unsigned long *)
_PAGE_PRESENT) &&
(__get_user(pte, (unsigned long *)
&linear_pg_table[addr >> PAGE_SHIFT]) == 0) )
{
pfn = pte >> PAGE_SHIFT;
@@ -1640,9 +1663,9 @@ int ptwr_do_page_fault(unsigned long addr)
if ( (page->u.inuse.type_info & PGT_type_mask) == PGT_l1_page_table )
{
#ifdef PTWR_TRACK_DOMAIN
if ( ptwr_info[cpu].domain != get_current()->domain )
if ( ptwr_info[cpu].domain != current->domain )
printk("ptwr_do_page_fault domain mismatch %d != %d\n",
ptwr_info[cpu].domain, get_current()->domain);
ptwr_info[cpu].domain, current->domain);
#endif
pl2e = &linear_l2_table[(page->u.inuse.type_info &
PGT_va_mask) >> PGT_va_shift];
@@ -1653,6 +1676,7 @@ int ptwr_do_page_fault(unsigned long addr)
if ( l2_pgentry_val(*pl2e) >> PAGE_SHIFT != pfn )
{
/* this L1 is not in the current address space */
l1_pgentry_t *pl1e;
PTWR_PRINTK(("[I] freeing l1 page %p taf %08x/%08x\n", page,
page->u.inuse.type_info,
@@ -1718,36 +1742,6 @@ int ptwr_do_page_fault(unsigned long addr)
return 0;
}
static void ptwr_init_backpointers(void)
{
struct pfn_info *page;
unsigned long pde;
int va_idx;
for ( va_idx = 0; va_idx < DOMAIN_ENTRIES_PER_L2_PAGETABLE; va_idx++ )
{
/* check if entry valid */
pde = l2_pgentry_val(linear_l2_table[va_idx]);
if ( (pde & _PAGE_PRESENT) == 0 )
continue;
page = &frame_table[pde >> PAGE_SHIFT];
/* assert that page is an l1_page_table XXXcl maybe l2? */
if ( (page->u.inuse.type_info & PGT_type_mask) != PGT_l1_page_table ) {
MEM_LOG("ptwr: Inconsistent pagetable: pde %lx not an l1 page\n",
pde >> PAGE_SHIFT);
domain_crash();
}
page->u.inuse.type_info &= ~PGT_va_mask;
page->u.inuse.type_info |= va_idx << PGT_va_shift;
}
}
static void ptwr_disable(void)
{
__cleanup_writable_pagetable(PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
}
#ifndef NDEBUG
void ptwr_status(void)
{
+1 -1
View File
@@ -262,7 +262,7 @@ void __shadow_mode_disable(struct domain *d)
__free_shadow_table(m);
m->shadow_mode = 0;
SH_LOG("freed tables count=%d l1=%d l2=%d",
SH_VLOG("freed tables count=%d l1=%d l2=%d",
m->shadow_page_count, perfc_value(shadow_l1_pages),
perfc_value(shadow_l2_pages));
+2 -2
View File
@@ -330,9 +330,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs, long error_code)
return; /* successfully copied the mapping */
}
if ( unlikely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) )
{
if ( (addr >> L2_PAGETABLE_SHIFT) == ptwr_info[cpu].disconnected )
if ( unlikely((addr >> L2_PAGETABLE_SHIFT) == ptwr_info[cpu].disconnected ))
{
ptwr_reconnect_disconnected(addr);
return;
+1 -1
View File
@@ -628,7 +628,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
break;
}
if ( page->count_info & PGC_guest_pinned )
if ( page->u.inuse.type_info & PGT_pinned )
type |= LPINTAB;
l_arr[j] |= type;
put_page(page);
+1 -1
View File
@@ -82,7 +82,7 @@ static long free_dom_mem(struct domain *d,
return i;
}
if ( test_and_clear_bit(_PGC_guest_pinned, &page->count_info) )
if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
put_page_and_type(page);
if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
+3 -3
View File
@@ -65,7 +65,7 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu)
strncpy(d->name, buf, MAX_DOMAIN_NAME);
d->name[MAX_DOMAIN_NAME-1] = '\0';
arch_do_createdomain(d);
arch_do_createdomain(d);
sched_add_domain(d);
@@ -152,8 +152,8 @@ void domain_crash(void)
{
struct domain *d;
if (current->domain == 0)
BUG();
if ( current->domain == 0 )
BUG();
set_bit(DF_CRASHED, &current->flags);
+5 -1
View File
@@ -393,10 +393,13 @@ struct pfn_info *alloc_domheap_pages(struct domain *d, int order)
spin_lock(&d->page_alloc_lock);
if ( unlikely((d->tot_pages + (1 << order)) > d->max_pages) )
if ( unlikely(test_bit(DF_DYING, &d->flags)) ||
unlikely((d->tot_pages + (1 << order)) > d->max_pages) )
{
DPRINTK("Over-allocation for domain %u: %u > %u\n",
d->domain, d->tot_pages + (1 << order), d->max_pages);
DPRINTK("...or the domain is dying (%d)\n",
!!test_bit(DF_DYING, &d->flags));
spin_unlock(&d->page_alloc_lock);
free_heap_pages(MEMZONE_DOM, pg, order);
return NULL;
@@ -427,6 +430,7 @@ void free_domheap_pages(struct pfn_info *pg, int order)
if ( unlikely(IS_XEN_HEAP_FRAME(pg)) )
{
/* NB. May recursively lock from domain_relinquish_memory(). */
spin_lock_recursive(&d->page_alloc_lock);
for ( i = 0; i < (1 << order); i++ )
-14
View File
@@ -374,20 +374,6 @@ void __enter_scheduler(void)
cleanup_writable_pagetable(
prev, PTWR_CLEANUP_ACTIVE | PTWR_CLEANUP_INACTIVE);
#ifdef PTWR_TRACK_DOMAIN
{
extern domid_t ptwr_domain[];
int cpu = smp_processor_id();
if (ptwr_domain[cpu] != prev->domain)
printk("switch_to domain mismatch %d != %d\n",
ptwr_domain[cpu], prev->domain);
ptwr_domain[cpu] = next->domain;
if (ptwr_disconnected[cpu] != ENTRIES_PER_L2_PAGETABLE ||
ptwr_writable_idx[cpu])
printk("switch_to ptwr dirty!!!\n");
}
#endif
perfc_incrc(sched_ctx);
#if defined(WAKE_HISTO)
+46 -22
View File
@@ -71,26 +71,27 @@ struct pfn_info
/* Has this page been validated for use as its current type? */
#define _PGT_validated 28
#define PGT_validated (1<<_PGT_validated)
/* 10-bit most significant bits of va address if used as l1 page table */
#define PGT_va_shift 18
/* Owning guest has pinned this page to its current type? */
#define _PGT_pinned 27
#define PGT_pinned (1<<_PGT_pinned)
/* The 10 most significant bits of virt address if this is a page table. */
#define PGT_va_shift 17
#define PGT_va_mask (((1<<10)-1)<<PGT_va_shift)
/* 18-bit count of uses of this frame as its current type. */
#define PGT_count_mask ((1<<18)-1)
#define PGT_va_mutable PGT_va_mask /* va backpointer is mutable? */
/* 17-bit count of uses of this frame as its current type. */
#define PGT_count_mask ((1<<17)-1)
/* For safety, force a TLB flush when this page's type changes. */
#define _PGC_tlb_flush_on_type_change 31
#define PGC_tlb_flush_on_type_change (1<<_PGC_tlb_flush_on_type_change)
/* Owning guest has pinned this page to its current type? */
#define _PGC_guest_pinned 30
#define PGC_guest_pinned (1<<_PGC_guest_pinned)
/* Cleared when the owning guest 'frees' this page. */
#define _PGC_allocated 29
#define _PGC_allocated 30
#define PGC_allocated (1<<_PGC_allocated)
/* This bit is always set, guaranteeing that the count word is never zero. */
#define _PGC_always_set 28
#define _PGC_always_set 29
#define PGC_always_set (1<<_PGC_always_set)
/* 27-bit count of references to this frame. */
#define PGC_count_mask ((1<<28)-1)
/* 29-bit count of references to this frame. */
#define PGC_count_mask ((1<<29)-1)
/* We trust the slab allocator in slab.c, and our use of it. */
#define PageSlab(page) (1)
@@ -198,6 +199,12 @@ static inline void put_page_type(struct pfn_info *page)
nx &= ~PGT_validated;
}
}
else if ( unlikely((nx & (PGT_pinned | PGT_count_mask)) ==
(PGT_pinned | 1)) )
{
/* Page is now only pinned. Make the back pointer mutable again. */
nx |= PGT_va_mutable;
}
}
while ( unlikely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) != x) );
}
@@ -217,29 +224,45 @@ static inline int get_page_type(struct pfn_info *page, u32 type)
}
else if ( unlikely((x & PGT_count_mask) == 0) )
{
if ( (x & PGT_type_mask) != type )
if ( (x & (PGT_type_mask|PGT_va_mask)) != type )
{
nx &= ~(PGT_type_mask | PGT_validated);
nx &= ~(PGT_type_mask | PGT_va_mask | PGT_validated);
nx |= type;
/* No extra validation needed for writable pages. */
if ( type == PGT_writable_page )
nx |= PGT_validated;
}
}
else if ( unlikely((x & PGT_type_mask) != type) )
else if ( unlikely((x & (PGT_type_mask|PGT_va_mask)) != type) )
{
if ( unlikely((x & PGT_type_mask) != (type & PGT_type_mask) ) )
{
#ifdef VERBOSE
if ((x & PGT_type_mask) != PGT_l2_page_table &&
type != PGT_l1_page_table)
DPRINTK("Unexpected type (saw %08x != exp %08x) for pfn %08lx\n",
x & PGT_type_mask, type, page_to_pfn(page));
if ( ((x & PGT_type_mask) != PGT_l2_page_table) ||
((type & PGT_type_mask) != PGT_l1_page_table) )
DPRINTK("Bad type (saw %08x != exp %08x) for pfn %08lx\n",
x & PGT_type_mask, type, page_to_pfn(page));
#endif
return 0;
return 0;
}
else if ( (x & PGT_va_mask) == PGT_va_mutable )
{
/* The va backpointer is mutable, hence we update it. */
nx &= ~PGT_va_mask;
nx |= type; /* we know the actual type is correct */
}
else if ( unlikely((x & PGT_va_mask) != (type & PGT_va_mask)) )
{
/* The va backpointer wasn't mutable, and is different. */
DPRINTK("Unexpected va backpointer (saw %08x != exp %08x)"
" for pfn %08lx\n", x, type, page_to_pfn(page));
return 0;
}
}
else if ( unlikely(!(x & PGT_validated)) )
else if ( unlikely(!(x & PGT_validated)) )
{
/* Someone else is updating validation of this page. Wait... */
while ( (y = page->u.inuse.type_info) != x )
while ( (y = page->u.inuse.type_info) == x )
{
rep_nop();
barrier();
@@ -252,7 +275,7 @@ static inline int get_page_type(struct pfn_info *page, u32 type)
if ( unlikely(!(nx & PGT_validated)) )
{
/* Try to validate page type; drop the new reference on failure. */
if ( unlikely(!alloc_page_type(page, type)) )
if ( unlikely(!alloc_page_type(page, type & PGT_type_mask)) )
{
DPRINTK("Error while validating pfn %08lx for type %08x."
" caf=%08x taf=%08x\n",
@@ -262,6 +285,7 @@ static inline int get_page_type(struct pfn_info *page, u32 type)
put_page_type(page);
return 0;
}
set_bit(_PGT_validated, &page->u.inuse.type_info);
}
+1 -1
View File
@@ -19,7 +19,7 @@
* This makes sure that old versions of dom0 tools will stop working in a
* well-defined way (rather than crashing the machine, for instance).
*/
#define DOM0_INTERFACE_VERSION 0xAAAA0012
#define DOM0_INTERFACE_VERSION 0xAAAA0014
#define MAX_DOMAIN_NAME 16
+7 -3
View File
@@ -117,6 +117,9 @@
* val[7:0] == MMUEXT_INVLPG:
* ptr[:2] -- Linear address to be flushed from the TLB.
*
* val[7:0] == MMUEXT_FLUSH_CACHE:
* No additional arguments. Writes back and flushes cache contents.
*
* val[7:0] == MMUEXT_SET_LDT:
* ptr[:2] -- Linear address of LDT base (NB. must be page-aligned).
* val[:8] -- Number of entries in LDT.
@@ -150,11 +153,12 @@
#define MMUEXT_NEW_BASEPTR 5 /* ptr = MA of new pagetable base */
#define MMUEXT_TLB_FLUSH 6 /* ptr = NULL */
#define MMUEXT_INVLPG 7 /* ptr = VA to invalidate */
#define MMUEXT_SET_LDT 8 /* ptr = VA of table; val = # entries */
#define MMUEXT_TRANSFER_PAGE 9 /* ptr = MA of frame; val[31:16] = dom */
#define MMUEXT_FLUSH_CACHE 8
#define MMUEXT_SET_LDT 9 /* ptr = VA of table; val = # entries */
#define MMUEXT_SET_FOREIGNDOM 10 /* val[31:16] = dom */
#define MMUEXT_CLEAR_FOREIGNDOM 11
#define MMUEXT_REASSIGN_PAGE 12
#define MMUEXT_TRANSFER_PAGE 12 /* ptr = MA of frame; val[31:16] = dom */
#define MMUEXT_REASSIGN_PAGE 13
#define MMUEXT_CMD_MASK 255
#define MMUEXT_CMD_SHIFT 8
@@ -93,6 +93,7 @@ typedef struct {
#define BLKIF_INTERFACE_STATUS_DESTROYED 0 /* Interface doesn't exist. */
#define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
#define BLKIF_INTERFACE_STATUS_CONNECTED 2 /* Exists and is connected. */
#define BLKIF_INTERFACE_STATUS_CHANGED 3 /* A device has been added or removed. */
typedef struct {
u32 handle; /* 0 */
u32 status; /* 4 */
@@ -357,6 +358,7 @@ typedef struct {
#define NETIF_INTERFACE_STATUS_DESTROYED 0 /* Interface doesn't exist. */
#define NETIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
#define NETIF_INTERFACE_STATUS_CONNECTED 2 /* Exists and is connected. */
#define NETIF_INTERFACE_STATUS_CHANGED 3 /* A device has been added or removed. */
typedef struct {
u32 handle; /* 0 */
u32 status; /* 4 */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.