diff --git a/.rootkeys b/.rootkeys index 698764dd14..ed597156b3 100644 --- a/.rootkeys +++ b/.rootkeys @@ -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 diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 35d2bada8d..9332c02f2b 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -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 diff --git a/linux-2.4.27-xen-sparse/arch/xen/kernel/time.c b/linux-2.4.27-xen-sparse/arch/xen/kernel/time.c index a2ffce3039..924a4a8efe 100644 --- a/linux-2.4.27-xen-sparse/arch/xen/kernel/time.c +++ b/linux-2.4.27-xen-sparse/arch/xen/kernel/time.c @@ -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; diff --git a/linux-2.6.8.1-patches/agpgart.patch b/linux-2.6.8.1-patches/agpgart.patch new file mode 100644 index 0000000000..aba8b200b1 --- /dev/null +++ b/linux-2.6.8.1-patches/agpgart.patch @@ -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<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<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 + #include ++#include + + /* + * 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 diff --git a/linux-2.6.8.1-patches/drm.patch b/linux-2.6.8.1-patches/drm.patch new file mode 100644 index 0000000000..3412ce6203 --- /dev/null +++ b/linux-2.6.8.1-patches/drm.patch @@ -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 diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/Kconfig b/linux-2.6.8.1-xen-sparse/arch/xen/Kconfig index 9f4c1d8002..5beabc830d 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/Kconfig +++ b/linux-2.6.8.1-xen-sparse/arch/xen/Kconfig @@ -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) diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/Kconfig.drivers b/linux-2.6.8.1-xen-sparse/arch/xen/Kconfig.drivers index 508bc7a174..93db5f9df6 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/Kconfig.drivers +++ b/linux-2.6.8.1-xen-sparse/arch/xen/Kconfig.drivers @@ -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: - - 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/. 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 diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/configs/xen0_defconfig b/linux-2.6.8.1-xen-sparse/arch/xen/configs/xen0_defconfig index 960c332306..75fac7e487 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/configs/xen0_defconfig +++ b/linux-2.6.8.1-xen-sparse/arch/xen/configs/xen0_defconfig @@ -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 # diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/configs/xenU_defconfig b/linux-2.6.8.1-xen-sparse/arch/xen/configs/xenU_defconfig index 09bfb25851..70e8811692 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/configs/xenU_defconfig +++ b/linux-2.6.8.1-xen-sparse/arch/xen/configs/xenU_defconfig @@ -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 # diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/i386/kernel/cpu/common.c b/linux-2.6.8.1-xen-sparse/arch/xen/i386/kernel/cpu/common.c index 6620406951..07ced337a2 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/i386/kernel/cpu/common.c +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/kernel/cpu/common.c @@ -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)) diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/Makefile b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/Makefile index 55063591f0..50c97507c2 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/Makefile +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/Makefile @@ -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 diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c index 0b2706b055..2e80b31c76 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/init.c @@ -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), diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/ioremap.c b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/ioremap.c index eed6379821..1efdacd8c2 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/ioremap.c +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/ioremap.c @@ -17,6 +17,25 @@ #include #include +#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) diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pageattr.c b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pageattr.c new file mode 100644 index 0000000000..57341454ed --- /dev/null +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pageattr.c @@ -0,0 +1,215 @@ +/* + * Copyright 2002 Andi Kleen, SuSE Labs. + * Thanks to Ben LaHaise for precious feedback. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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); diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pgtable.c b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pgtable.c index b6182d9961..bebd04f92d 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pgtable.c +++ b/linux-2.6.8.1-xen-sparse/arch/xen/i386/mm/pgtable.c @@ -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) diff --git a/linux-2.6.8.1-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6.8.1-xen-sparse/drivers/xen/blkfront/blkfront.c index 930e469103..259275ebd1 100644 --- a/linux-2.6.8.1-xen-sparse/drivers/xen/blkfront/blkfront.c +++ b/linux-2.6.8.1-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -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); diff --git a/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c index 71105776b2..44aa8e9dde 100644 --- a/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c @@ -26,6 +26,9 @@ #include #include +#include +#include + #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: diff --git a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/io.h b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/io.h index 81de51c1b5..db076b4370 100644 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/io.h +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/io.h @@ -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 /* diff --git a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h index e4daac8ed3..68889ad832 100644 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h @@ -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); } diff --git a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgalloc.h b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgalloc.h index 0ba1e5a542..3d36223eca 100644 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgalloc.h +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgalloc.h @@ -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 diff --git a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgtable.h b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgtable.h index a84b1a2308..20dda455dc 100644 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgtable.h +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/pgtable.h @@ -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) diff --git a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/system.h b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/system.h index 822c57f29a..133f1eaf49 100644 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/system.h +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/asm-i386/system.h @@ -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) { diff --git a/linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h b/linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h index 4d7ddc55a7..e1ee44a014 100644 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/hypervisor.h @@ -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); diff --git a/tools/python/xen/xend/XendClient.py b/tools/python/xen/xend/XendClient.py index 5041e06cb7..01d6d3df3c 100644 --- a/tools/python/xen/xend/XendClient.py +++ b/tools/python/xen/xend/XendClient.py @@ -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()) diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 2111a166bd..afe2a4601b 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -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']: diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index b86167143b..f582a51145 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -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 diff --git a/tools/python/xen/xend/server/SrvDaemon.py b/tools/python/xen/xend/server/SrvDaemon.py index 851b72198b..20569c74b4 100644 --- a/tools/python/xen/xend/server/SrvDaemon.py +++ b/tools/python/xen/xend/server/SrvDaemon.py @@ -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): diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py index c3c3eb2de3..60708e24a9 100755 --- a/tools/python/xen/xend/server/blkif.py +++ b/tools/python/xen/xend/server/blkif.py @@ -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) diff --git a/tools/python/xen/xend/server/messages.py b/tools/python/xen/xend/server/messages.py index 8d68d95887..fb94214a64 100644 --- a/tools/python/xen/xend/server/messages.py +++ b/tools/python/xen/xend/server/messages.py @@ -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 diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py index 3b4dc25339..3c07333a84 100755 --- a/tools/python/xen/xend/server/netif.py +++ b/tools/python/xen/xend/server/netif.py @@ -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) diff --git a/tools/python/xen/xend/server/params.py b/tools/python/xen/xend/server/params.py index fa3cee9b14..bb5277aecd 100644 --- a/tools/python/xen/xend/server/params.py +++ b/tools/python/xen/xend/server/params.py @@ -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 diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py index 2d77bd5ca6..d8c70e75fe 100644 --- a/tools/python/xen/xm/main.py +++ b/tools/python/xen/xm/main.py @@ -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) diff --git a/tools/xfrd/xen_domain.c b/tools/xfrd/xen_domain.c index 5f4dcda506..fe63e73a3d 100644 --- a/tools/xfrd/xen_domain.c +++ b/tools/xfrd/xen_domain.c @@ -16,6 +16,7 @@ typedef unsigned long u32; #define MODULE_NAME "XFRD" #define DEBUG 1 +#undef DEBUG #include "debug.h" diff --git a/tools/xfrd/xfrd.c b/tools/xfrd/xfrd.c index 05c942f5a5..f84e29e6a2 100644 --- a/tools/xfrd/xfrd.c +++ b/tools/xfrd/xfrd.c @@ -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){ diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 3031d5de69..868a3c97ad 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -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))<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<> 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) { diff --git a/xen/arch/x86/shadow.c b/xen/arch/x86/shadow.c index 672f48ef9f..d909d64085 100644 --- a/xen/arch/x86/shadow.c +++ b/xen/arch/x86/shadow.c @@ -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)); diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 24f1d401d2..d488a252f2 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -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; diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index 5ae8924143..5d95cdf184 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -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); diff --git a/xen/common/dom_mem_ops.c b/xen/common/dom_mem_ops.c index ba570d91f7..a4ce55bbc0 100644 --- a/xen/common/dom_mem_ops.c +++ b/xen/common/dom_mem_ops.c @@ -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) ) diff --git a/xen/common/domain.c b/xen/common/domain.c index 314f875511..f64d21e711 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -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, ¤t->flags); diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index faa3b6ec3a..02a46bf1c3 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -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++ ) diff --git a/xen/common/schedule.c b/xen/common/schedule.c index cc06d3c085..a986ee06a1 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -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) diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index 147b5a6c71..894130d143 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -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)<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); } diff --git a/xen/include/hypervisor-ifs/dom0_ops.h b/xen/include/hypervisor-ifs/dom0_ops.h index 7dec0af739..2bae662d12 100644 --- a/xen/include/hypervisor-ifs/dom0_ops.h +++ b/xen/include/hypervisor-ifs/dom0_ops.h @@ -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 diff --git a/xen/include/hypervisor-ifs/hypervisor-if.h b/xen/include/hypervisor-ifs/hypervisor-if.h index 3a0189a655..c7874bd708 100644 --- a/xen/include/hypervisor-ifs/hypervisor-if.h +++ b/xen/include/hypervisor-ifs/hypervisor-if.h @@ -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 diff --git a/xen/include/hypervisor-ifs/io/domain_controller.h b/xen/include/hypervisor-ifs/io/domain_controller.h index 45090aca0f..5de3c2d673 100644 --- a/xen/include/hypervisor-ifs/io/domain_controller.h +++ b/xen/include/hypervisor-ifs/io/domain_controller.h @@ -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 */