bitkeeper revision 1.1159.79.2 (414c1134FG1zvS9xwv2yPDvyS7W3ig)

Linux scrubs memory before returnign it to Xen, or transferring it to
other domains (e.g., net backend driver). To avoid continual scrubbing during
network transfers, I allocate rx skbuffs from a dedicated slab cache. Pages
only neded to be scrubbed on entry to the cache, which should be ratehr more
occasional than allocs/frees.
Finally, scrubbing can be entirely disabled via a config option under the
'XEN' menu in the 2.4 and 2.6 kernel configurators.
This commit is contained in:
kaf24@freefall.cl.cam.ac.uk committed 2004-09-18 10:43:00 +00:00
1 parent 90d122ec63
commit 0bfc95f5b0
21 files changed
+163 -50

No files matched your search

+1
View File
@@ -176,6 +176,7 @@
412dfae9eA3_6e6bCGUtg1mj8b56fQ linux-2.6.8.1-xen-sparse/arch/xen/kernel/gnttab.c
40f56239sFcjHiIRmnObRIDF-zaeKQ linux-2.6.8.1-xen-sparse/arch/xen/kernel/process.c
40f562392LBhwmOxVPsYdkYXMxI_ZQ linux-2.6.8.1-xen-sparse/arch/xen/kernel/reboot.c
414c113396tK1HTVeUalm3u-1DF16g linux-2.6.8.1-xen-sparse/arch/xen/kernel/skbuff.c
3f68905c5eiA-lBMQSvXLMWS1ikDEA linux-2.6.8.1-xen-sparse/arch/xen/kernel/xen_proc.c
41261688yS8eAyy-7kzG4KBs0xbYCA linux-2.6.8.1-xen-sparse/drivers/Makefile
4108f5c1WfTIrs0HZFeV39sttekCTw linux-2.6.8.1-xen-sparse/drivers/char/mem.c
@@ -16,6 +16,7 @@ mainmenu_option next_comment
comment 'Xen'
bool 'Support for privileged operations (domain 0)' CONFIG_XEN_PRIVILEGED_GUEST
bool 'Device-driver domain (physical device access)' CONFIG_XEN_PHYSDEV_ACCESS
bool 'Scrub memory before freeing it to Xen' CONFIG_XEN_SCRUB_PAGES
endmenu
# The IBM S/390 patch needs this.
define_bool CONFIG_NO_IDLE_HZ y
@@ -12,6 +12,7 @@ CONFIG_UID16=y
#
CONFIG_XEN_PRIVILEGED_GUEST=y
CONFIG_XEN_PHYSDEV_ACCESS=y
CONFIG_XEN_SCRUB_PAGES=y
CONFIG_NO_IDLE_HZ=y
CONFIG_FOREIGN_PAGES=y
@@ -12,6 +12,7 @@ CONFIG_UID16=y
#
# CONFIG_XEN_PRIVILEGED_GUEST is not set
# CONFIG_XEN_PHYSDEV_ACCESS is not set
CONFIG_XEN_SCRUB_PAGES=y
CONFIG_NO_IDLE_HZ=y
# CONFIG_FOREIGN_PAGES is not set
CONFIG_NETDEVICES=y
@@ -104,8 +104,20 @@ static unsigned long inflate_balloon(unsigned long num_pages)
{
unsigned long mfn = phys_to_machine_mapping[*currp];
curraddr = (unsigned long)page_address(mem_map + *currp);
/* Blow away page contents for security, and also p.t. ref if any. */
if ( curraddr != 0 )
{
scrub_pages(curraddr, 1);
queue_l1_entry_update(get_ptep(curraddr), 0);
}
#ifdef CONFIG_XEN_SCRUB_PAGES
else
{
void *p = kmap(&mem_map[*currp]);
scrub_pages(p, 1);
kunmap(&mem_map[*currp]);
}
#endif
phys_to_machine_mapping[*currp] = DEAD;
*currp = mfn;
}
@@ -388,9 +400,9 @@ static int balloon_write(struct file *file, const char *buffer,
}
len = strnlen_user(buffer, count);
if (len==0) return -EBADMSG;
if (len==1) return 1; /* input starts with a NUL char */
if ( strncpy_from_user(memstring, buffer, len) < 0)
if ( len == 0 ) return -EBADMSG;
if ( len == 1 ) return 1; /* input starts with a NUL char */
if ( strncpy_from_user(memstring, buffer, len) < 0 )
return -EFAULT;
endchar = memstring;
@@ -6,12 +6,12 @@ all: kernel.o head.o init_task.o
O_TARGET := kernel.o
export-objs := i386_ksyms.o gnttab.o
export-objs := i386_ksyms.o gnttab.o skbuff.o
obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \
ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o \
i386_ksyms.o i387.o evtchn.o ctrl_if.o pci-dma.o \
reboot.o fixup.o gnttab.o
reboot.o fixup.o gnttab.o skbuff.o
ifdef CONFIG_PCI
obj-y += pci-i386.o pci-pc.o
@@ -10,9 +10,16 @@
#ifndef __ASSEMBLY__
#include <linux/config.h>
#include <linux/string.h>
#include <asm/types.h>
#include <asm/hypervisor-ifs/hypervisor-if.h>
#ifdef CONFIG_XEN_SCRUB_PAGES
#define scrub_pages(_p,_n) memset((void *)(_p), 0, (_n) << PAGE_SHIFT)
#else
#define scrub_pages(_p,_n) ((void)0)
#endif
#ifdef CONFIG_X86_USE_3DNOW
#include <asm/mmx.h>
@@ -1027,19 +1027,18 @@ static inline void __skb_queue_purge(struct sk_buff_head *list)
*
* %NULL is returned in there is no free memory.
*/
#ifndef CONFIG_XEN
static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
int gfp_mask)
{
struct sk_buff *skb;
#if defined(CONFIG_XEN)
length = (PAGE_SIZE/2)+1; /* force slab allocater to give us a page */
#endif
skb = alloc_skb(length+16, gfp_mask);
struct sk_buff *skb = alloc_skb(length+16, gfp_mask);
if (skb)
skb_reserve(skb,16);
return skb;
}
#else
extern struct sk_buff *__dev_alloc_skb(unsigned int length, int gfp_mask);
#endif
/**
* dev_alloc_skb - allocate an skbuff for sending
+1
View File
@@ -228,6 +228,7 @@ ln -sf ../../../${LINUX_26}/arch/xen/kernel/evtchn.c
ln -sf ../../../${LINUX_26}/arch/xen/kernel/fixup.c
ln -sf ../../../${LINUX_26}/arch/xen/kernel/gnttab.c
ln -sf ../../../${LINUX_26}/arch/xen/kernel/reboot.c
ln -sf ../../../${LINUX_26}/arch/xen/kernel/skbuff.c
ln -sf ../../../${LINUX_26}/arch/xen/i386/kernel/ioport.c
ln -sf ../../../${LINUX_26}/arch/xen/i386/kernel/pci-dma.c
+13 -3
View File
@@ -100,16 +100,26 @@ config XEN_WRITABLE_PAGETABLES
help
Use writable L1 pagetables
config XEN_SCRUB_PAGES
bool "Scrub memory before freeing it to Xen"
default y
help
Erase memory contents before freeing it back to Xen's global
pool. This ensures that any secrets contained within that
memory (e.g., private keys) cannot be found by other guests that
may be running on the machine. Most people will want to say Y here.
If security is not a concern then you may increase performance by
saying N.
endmenu
config FOREIGN_PAGES
bool
default y
config PAGESIZED_SKBS
config HAVE_ARCH_DEV_ALLOC_SKB
bool
default y if XEN_NETDEV_BACKEND
default n if !XEN_NETDEV_BACKEND
default y
#config VT
# bool
@@ -16,8 +16,9 @@ CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
CONFIG_XEN_WRITABLE_PAGETABLES=y
CONFIG_XEN_SCRUB_PAGES=y
CONFIG_FOREIGN_PAGES=y
CONFIG_PAGESIZED_SKBS=y
CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
CONFIG_X86=y
# CONFIG_X86_64 is not set
@@ -16,8 +16,9 @@ CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
CONFIG_XEN_WRITABLE_PAGETABLES=y
CONFIG_XEN_SCRUB_PAGES=y
CONFIG_FOREIGN_PAGES=y
# CONFIG_PAGESIZED_SKBS is not set
CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
CONFIG_X86=y
# CONFIG_X86_64 is not set
@@ -55,6 +55,7 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
pmd_t *pmd;
pte_t *pte;
unsigned long pfn, i;
scrub_pages(vstart, 1 << order);
/* 1. Zap current PTEs, giving away the underlying pages. */
for (i = 0; i < (1<<order); i++) {
pgd = pgd_offset_k( (vstart + (i*PAGE_SIZE)));
@@ -414,6 +414,8 @@ unsigned long allocate_empty_lowmem_region(unsigned long pages)
if ( vstart == 0 )
return 0UL;
scrub_pages(vstart, 1 << order);
pfn_array = vmalloc((1<<order) * sizeof(*pfn_array));
if ( pfn_array == NULL )
BUG();
@@ -10,4 +10,4 @@ $(obj)/vmlinux.lds.s:
extra-y += vmlinux.lds.s
obj-y := ctrl_if.o evtchn.o fixup.o process.o reboot.o xen_proc.o empty.o \
gnttab.o
gnttab.o skbuff.o
@@ -0,0 +1,68 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/inetdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/page.h>
EXPORT_SYMBOL(__dev_alloc_skb);
static kmem_cache_t *skbuff_cachep;
struct sk_buff *__dev_alloc_skb(unsigned int length, int gfp_mask)
{
struct sk_buff *skb;
u8 *new_data, *new_shinfo;
/*
* Yuk! There is no way to get a skbuff head without allocating the
* data area using kmalloc(). So we do that and then replace the default
* data area with our own.
*/
skb = alloc_skb(0, gfp_mask);
if ( unlikely(skb == NULL) )
return NULL;
new_data = kmem_cache_alloc(skbuff_cachep, gfp_mask);
if ( new_data == NULL )
{
dev_kfree_skb(skb);
return NULL;
}
new_shinfo =
new_data + PAGE_SIZE - sizeof(struct skb_shared_info);
memcpy(new_shinfo, skb_shinfo(skb), sizeof(struct skb_shared_info));
kfree(skb->head);
skb->head = new_data;
skb->data = skb->tail = new_data + 16; /* __dev_alloc_skb does this */
skb->end = new_shinfo;
skb->truesize = 1500; /* is this important? */
return skb;
}
static void skbuff_ctor(void *buf, kmem_cache_t *cachep, unsigned long unused)
{
scrub_pages(buf, 1);
}
static int __init skbuff_init(void)
{
skbuff_cachep = kmem_cache_create(
"xen-skb", PAGE_SIZE, PAGE_SIZE, 0, skbuff_ctor, NULL);
return 0;
}
__initcall(skbuff_init);
@@ -132,7 +132,7 @@ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
(((unsigned long)skb->end ^ (unsigned long)skb->head) & PAGE_MASK) ||
((skb->end - skb->head) < (PAGE_SIZE/2)) )
{
struct sk_buff *nskb = alloc_skb(PAGE_SIZE-1024, GFP_ATOMIC);
struct sk_buff *nskb = dev_alloc_skb(PAGE_SIZE);
int hlen = skb->data - skb->head;
if ( unlikely(nskb == NULL) )
goto drop;
@@ -39,6 +39,7 @@
#ifndef __GFP_NOWARN
#define __GFP_NOWARN 0
#endif
#define alloc_skb_page() __dev_alloc_skb(PAGE_SIZE, GFP_ATOMIC|__GFP_NOWARN)
/*
* If the backend driver is pipelining transmit requests then we can be very
@@ -193,35 +194,24 @@ static int netctrl_connected_count(void)
* @param dev device
* @return 0 on success, error code otherwise
*/
static int vif_wake(struct net_device *dev){
int err = 0;
static int vif_wake(struct net_device *dev)
{
struct sk_buff *skb;
u32 src_ip;
u32 dst_ip = INADDR_BROADCAST;
unsigned char dst_hw[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
u32 src_ip, dst_ip;
unsigned char dst_hw[ETH_ALEN];
memset(dst_hw, 0xff, ETH_ALEN);
dst_ip = INADDR_BROADCAST;
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;
}
if ( skb == NULL )
return -ENOMEM;
static inline struct sk_buff *alloc_skb_page(void)
{
struct sk_buff *skb;
skb = __dev_alloc_skb((PAGE_SIZE/2)+1, GFP_ATOMIC|__GFP_NOWARN);
#if 0
if ( skb && unlikely(((unsigned long)skb->head & (PAGE_SIZE-1)) != 0) )
panic("alloc_skb needs to provide us page-aligned buffers.");
#endif
return skb;
return dev_queue_xmit(skb);
}
static int network_open(struct net_device *dev)
@@ -13,9 +13,16 @@
#ifndef __ASSEMBLY__
#include <linux/config.h>
#include <linux/string.h>
#include <linux/types.h>
#include <asm/hypervisor-ifs/hypervisor-if.h>
#ifdef CONFIG_XEN_SCRUB_PAGES
#define scrub_pages(_p,_n) memset((void *)(_p), 0, (_n) << PAGE_SHIFT)
#else
#define scrub_pages(_p,_n) ((void)0)
#endif
#ifdef CONFIG_X86_USE_3DNOW
#include <asm/mmx.h>
@@ -936,18 +936,18 @@ static inline void __skb_queue_purge(struct sk_buff_head *list)
*
* %NULL is returned in there is no free memory.
*/
#ifndef CONFIG_HAVE_ARCH_DEV_ALLOC_SKB
static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
int gfp_mask)
{
struct sk_buff *skb;
#ifdef CONFIG_PAGESIZED_SKBS
length = max(length, (unsigned int)(PAGE_SIZE - 16));
#endif
skb = alloc_skb(length + 16, gfp_mask);
struct sk_buff *skb = alloc_skb(length + 16, gfp_mask);
if (likely(skb))
skb_reserve(skb, 16);
return skb;
}
#else
extern struct sk_buff *__dev_alloc_skb(unsigned int length, int gfp_mask);
#endif
/**
* dev_alloc_skb - allocate an skbuff for sending
+15 -5
View File
@@ -28,6 +28,7 @@
#include <xen/spinlock.h>
#include <xen/slab.h>
#include <xen/irq.h>
#include <asm/domain_page.h>
extern char opt_badpage[];
@@ -427,6 +428,7 @@ void free_domheap_pages(struct pfn_info *pg, int order)
{
int i, drop_dom_ref;
struct domain *d = pg->u.inuse.domain;
void *p;
if ( unlikely(IS_XEN_HEAP_FRAME(pg)) )
{
@@ -448,14 +450,22 @@ void free_domheap_pages(struct pfn_info *pg, int order)
for ( i = 0; i < (1 << order); i++ )
{
#ifndef NDEBUG
if ( pg[i].u.inuse.type_info & PGT_count_mask )
printk("ERROR: type count not zero on free %x\n",
pg[i].u.inuse.type_info );
#endif
ASSERT((pg[i].u.inuse.type_info & PGT_count_mask) == 0);
pg[i].tlbflush_timestamp = tlbflush_clock;
pg[i].u.free.cpu_mask = 1 << d->processor;
list_del(&pg[i].list);
/*
* Normally we expect a domain to clear pages before freeing them,
* if it cares about the secrecy of their contents. However, after
* a domain has died we assume responsibility for erasure.
*/
if ( unlikely(test_bit(DF_DYING, &d->flags)) )
{
p = map_domain_mem(page_to_phys(&pg[i]));
clear_page(p);
unmap_domain_mem(p);
}
}
d->tot_pages -= 1 << order;
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.