[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] merge?
# HG changeset patch # User cl349@xxxxxxxxxxxxxxxxxxxx # Node ID 291e816acbf46071a69b5d1b12ac3b5c46eaa49b # Parent edd1616cf8cb6f0d7ab32600a27d3a98ac8414b2 # Parent fc12b08bf4fe858b29317427cc0db82d29764c5f merge? diff -r edd1616cf8cb -r 291e816acbf4 extras/mini-os/README --- a/extras/mini-os/README Fri Sep 2 14:15:49 2005 +++ b/extras/mini-os/README Fri Sep 2 14:17:08 2005 @@ -23,13 +23,8 @@ - to build it just type make. -- copy image.final somewhere where dom0 can access it +- to start it do the following in domain0 (assuming xend is running) + # xm create domain_config -- in dom0 - # xi_create 16000 test - <domid> - # xi_build <domid> image.final 0 - # xi_start <domid> - -this prints out a bunch of stuff and then every 1000 timer interrupts the -system time. +this starts the kernel and prints out a bunch of stuff and then every +1000 timer interrupts the system time. diff -r edd1616cf8cb -r 291e816acbf4 extras/mini-os/include/hypervisor.h --- a/extras/mini-os/include/hypervisor.h Fri Sep 2 14:15:49 2005 +++ b/extras/mini-os/include/hypervisor.h Fri Sep 2 14:17:08 2005 @@ -329,7 +329,7 @@ int ret; __asm__ __volatile__ ( TRAP_INSTR - : "=a" (ret) : "0" (__HYPERVISOR_dom_mem_op), + : "=a" (ret) : "0" (__HYPERVISOR_memory_op), _a1 (dom_mem_op) : "memory" ); return ret; diff -r edd1616cf8cb -r 291e816acbf4 linux-2.6-xen-sparse/arch/xen/Kconfig --- a/linux-2.6-xen-sparse/arch/xen/Kconfig Fri Sep 2 14:15:49 2005 +++ b/linux-2.6-xen-sparse/arch/xen/Kconfig Fri Sep 2 14:17:08 2005 @@ -109,15 +109,8 @@ dedicated device-driver domain, or your master control domain (domain 0), then you almost certainly want to say Y here. -config XEN_NETDEV_GRANT_TX - bool "Grant table substrate for net drivers tx path (DANGEROUS)" - default n - help - This introduces the use of grant tables as a data exhange mechanism - between the frontend and backend network drivers. - -config XEN_NETDEV_GRANT_RX - bool "Grant table substrate for net drivers rx path (DANGEROUS)" +config XEN_NETDEV_GRANT + bool "Grant table substrate for network drivers (DANGEROUS)" default n help This introduces the use of grant tables as a data exhange mechanism diff -r edd1616cf8cb -r 291e816acbf4 linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 --- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 Fri Sep 2 14:15:49 2005 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 Fri Sep 2 14:17:08 2005 @@ -19,8 +19,7 @@ # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y -CONFIG_XEN_NETDEV_GRANT_TX=y -CONFIG_XEN_NETDEV_GRANT_RX=y +CONFIG_XEN_NETDEV_GRANT=y # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set # CONFIG_XEN_BLKDEV_TAP is not set # CONFIG_XEN_SHADOW_MODE is not set @@ -1124,7 +1123,7 @@ # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set +CONFIG_CRAMFS=y # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set diff -r edd1616cf8cb -r 291e816acbf4 linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 --- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 Fri Sep 2 14:15:49 2005 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 Fri Sep 2 14:17:08 2005 @@ -19,8 +19,7 @@ # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y -CONFIG_XEN_NETDEV_GRANT_TX=y -CONFIG_XEN_NETDEV_GRANT_RX=y +CONFIG_XEN_NETDEV_GRANT=y # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set # CONFIG_XEN_BLKDEV_TAP is not set # CONFIG_XEN_SHADOW_MODE is not set @@ -1033,7 +1032,7 @@ # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set +CONFIG_CRAMFS=y # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set diff -r edd1616cf8cb -r 291e816acbf4 linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 --- a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 Fri Sep 2 14:15:49 2005 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 Fri Sep 2 14:17:08 2005 @@ -16,8 +16,7 @@ # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y -CONFIG_XEN_NETDEV_GRANT_TX=y -CONFIG_XEN_NETDEV_GRANT_RX=y +CONFIG_XEN_NETDEV_GRANT=y # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set # CONFIG_XEN_BLKDEV_TAP is not set # CONFIG_XEN_SHADOW_MODE is not set diff -r edd1616cf8cb -r 291e816acbf4 linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64 --- a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64 Fri Sep 2 14:15:49 2005 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64 Fri Sep 2 14:17:08 2005 @@ -16,8 +16,7 @@ # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y -CONFIG_XEN_NETDEV_GRANT_TX=y -CONFIG_XEN_NETDEV_GRANT_RX=y +CONFIG_XEN_NETDEV_GRANT=y # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set # CONFIG_XEN_BLKDEV_TAP is not set # CONFIG_XEN_SHADOW_MODE is not set diff -r edd1616cf8cb -r 291e816acbf4 linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 --- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 Fri Sep 2 14:15:49 2005 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 Fri Sep 2 14:17:08 2005 @@ -19,8 +19,7 @@ # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y -CONFIG_XEN_NETDEV_GRANT_TX=y -CONFIG_XEN_NETDEV_GRANT_RX=y +CONFIG_XEN_NETDEV_GRANT=y # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set # CONFIG_XEN_BLKDEV_TAP is not set # CONFIG_XEN_SHADOW_MODE is not set diff -r edd1616cf8cb -r 291e816acbf4 linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 --- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 Fri Sep 2 14:15:49 2005 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 Fri Sep 2 14:17:08 2005 @@ -19,8 +19,7 @@ # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y -CONFIG_XEN_NETDEV_GRANT_TX=y -CONFIG_XEN_NETDEV_GRANT_RX=y +CONFIG_XEN_NETDEV_GRANT=y # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set # CONFIG_XEN_BLKDEV_TAP is not set # CONFIG_XEN_SHADOW_MODE is not set diff -r edd1616cf8cb -r 291e816acbf4 linux-2.6-xen-sparse/drivers/char/tpm/Kconfig.domU --- a/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig.domU Fri Sep 2 14:15:49 2005 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/Kconfig.domU Fri Sep 2 14:17:08 2005 @@ -19,7 +19,7 @@ config TCG_XEN tristate "XEN TPM Interface" - depends on TCG_TPM && ARCH_XEN + depends on TCG_TPM && ARCH_XEN && XEN_TPMDEV_FRONTEND ---help--- If you want to make TPM support available to a Xen user domain, say Yes and it will diff -r edd1616cf8cb -r 291e816acbf4 linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c --- a/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c Fri Sep 2 14:15:49 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c Fri Sep 2 14:17:08 2005 @@ -105,7 +105,7 @@ xen_start_info.console_evtchn, handle_input, 0, "xencons", inring()); if (err) { - xprintk(KERN_ERR "XEN console request irq failed %i\n", err); + xprintk("XEN console request irq failed %i\n", err); unbind_evtchn_from_irq(xen_start_info.console_evtchn); return err; } diff -r edd1616cf8cb -r 291e816acbf4 linux-2.6-xen-sparse/drivers/xen/netback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Fri Sep 2 14:15:49 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Fri Sep 2 14:17:08 2005 @@ -20,9 +20,12 @@ #include <asm/io.h> #include <asm/pgalloc.h> -#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX) +#ifdef CONFIG_XEN_NETDEV_GRANT #include <asm-xen/xen-public/grant_table.h> #include <asm-xen/gnttab.h> + +#define GRANT_INVALID_REF (0xFFFF) + #endif @@ -37,6 +40,11 @@ #define ASSERT(_p) ((void)0) #define DPRINTK(_f, _a...) ((void)0) #endif +#define IPRINTK(fmt, args...) \ + printk(KERN_INFO "xen_net: " fmt, ##args) +#define WPRINTK(fmt, args...) \ + printk(KERN_WARNING "xen_net: " fmt, ##args) + typedef struct netif_st { /* Unique identifier for this interface. */ @@ -47,13 +55,13 @@ /* Physical parameters of the comms window. */ unsigned long tx_shmem_frame; -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT u16 tx_shmem_handle; unsigned long tx_shmem_vaddr; grant_ref_t tx_shmem_ref; #endif unsigned long rx_shmem_frame; -#ifdef CONFIG_XEN_NETDEV_GRANT_RX +#ifdef CONFIG_XEN_NETDEV_GRANT u16 rx_shmem_handle; unsigned long rx_shmem_vaddr; grant_ref_t rx_shmem_ref; @@ -68,7 +76,7 @@ /* Private indexes into shared ring. */ NETIF_RING_IDX rx_req_cons; NETIF_RING_IDX rx_resp_prod; /* private version of shared variable */ -#ifdef CONFIG_XEN_NETDEV_GRANT_RX +#ifdef CONFIG_XEN_NETDEV_GRANT NETIF_RING_IDX rx_resp_prod_copy; /* private version of shared variable */ #endif NETIF_RING_IDX tx_req_cons; diff -r edd1616cf8cb -r 291e816acbf4 linux-2.6-xen-sparse/drivers/xen/netback/interface.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Fri Sep 2 14:15:49 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c Fri Sep 2 14:17:08 2005 @@ -111,91 +111,81 @@ return netif; } -static int map_frontend_page(netif_t *netif, unsigned long localaddr, - unsigned long tx_ring_ref, unsigned long rx_ring_ref) -{ -#if !defined(CONFIG_XEN_NETDEV_GRANT_TX)||!defined(CONFIG_XEN_NETDEV_GRANT_RX) +static int map_frontend_pages(netif_t *netif, unsigned long localaddr, + unsigned long tx_ring_ref, + unsigned long rx_ring_ref) +{ +#ifdef CONFIG_XEN_NETDEV_GRANT + struct gnttab_map_grant_ref op; + + /* Map: Use the Grant table reference */ + op.host_addr = localaddr; + op.flags = GNTMAP_host_map; + op.ref = tx_ring_ref; + op.dom = netif->domid; + + BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) ); + if (op.handle < 0) { + DPRINTK(" Grant table operation failure mapping tx_ring_ref!\n"); + return op.handle; + } + + netif->tx_shmem_ref = tx_ring_ref; + netif->tx_shmem_handle = op.handle; + netif->tx_shmem_vaddr = localaddr; + + /* Map: Use the Grant table reference */ + op.host_addr = localaddr + PAGE_SIZE; + op.flags = GNTMAP_host_map; + op.ref = rx_ring_ref; + op.dom = netif->domid; + + BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) ); + if (op.handle < 0) { + DPRINTK(" Grant table operation failure mapping rx_ring_ref!\n"); + return op.handle; + } + + netif->rx_shmem_ref = rx_ring_ref; + netif->rx_shmem_handle = op.handle; + netif->rx_shmem_vaddr = localaddr + PAGE_SIZE; + +#else pgprot_t prot = __pgprot(_KERNPG_TABLE); int err; -#endif -#if defined(CONFIG_XEN_NETDEV_GRANT_TX) - { - struct gnttab_map_grant_ref op; - - /* Map: Use the Grant table reference */ - op.host_addr = localaddr; - op.flags = GNTMAP_host_map; - op.ref = tx_ring_ref; - op.dom = netif->domid; - - BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) ); - if (op.handle < 0) { - DPRINTK(" Grant table operation failure !\n"); - return op.handle; - } - - netif->tx_shmem_ref = tx_ring_ref; - netif->tx_shmem_handle = op.handle; - netif->tx_shmem_vaddr = localaddr; - } -#else + err = direct_remap_area_pages(&init_mm, localaddr, tx_ring_ref<<PAGE_SHIFT, PAGE_SIZE, prot, netif->domid); + + err |= direct_remap_area_pages(&init_mm, localaddr + PAGE_SIZE, + rx_ring_ref<<PAGE_SHIFT, PAGE_SIZE, + prot, netif->domid); + if (err) return err; #endif -#if defined(CONFIG_XEN_NETDEV_GRANT_RX) - { - struct gnttab_map_grant_ref op; - - /* Map: Use the Grant table reference */ - op.host_addr = localaddr + PAGE_SIZE; - op.flags = GNTMAP_host_map; - op.ref = rx_ring_ref; - op.dom = netif->domid; - - BUG_ON( HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1) ); - if (op.handle < 0) { - DPRINTK(" Grant table operation failure !\n"); - return op.handle; - } - - netif->rx_shmem_ref = rx_ring_ref; - netif->rx_shmem_handle = op.handle; - netif->rx_shmem_vaddr = localaddr + PAGE_SIZE; - } -#else - err = direct_remap_area_pages(&init_mm, localaddr + PAGE_SIZE, - rx_ring_ref<<PAGE_SHIFT, PAGE_SIZE, - prot, netif->domid); - if (err) - return err; -#endif - return 0; } -static void unmap_frontend_page(netif_t *netif) -{ -#if defined(CONFIG_XEN_NETDEV_GRANT_RX) || defined(CONFIG_XEN_NETDEV_GRANT_TX) +static void unmap_frontend_pages(netif_t *netif) +{ +#ifdef CONFIG_XEN_NETDEV_GRANT struct gnttab_unmap_grant_ref op; -#endif - -#ifdef CONFIG_XEN_NETDEV_GRANT_TX + op.host_addr = netif->tx_shmem_vaddr; op.handle = netif->tx_shmem_handle; op.dev_bus_addr = 0; BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)); -#endif - -#ifdef CONFIG_XEN_NETDEV_GRANT_RX + op.host_addr = netif->rx_shmem_vaddr; op.handle = netif->rx_shmem_handle; op.dev_bus_addr = 0; BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)); #endif + + return; } int netif_map(netif_t *netif, unsigned long tx_ring_ref, @@ -209,8 +199,8 @@ if (vma == NULL) return -ENOMEM; - err = map_frontend_page(netif, (unsigned long)vma->addr, tx_ring_ref, - rx_ring_ref); + err = map_frontend_pages(netif, (unsigned long)vma->addr, tx_ring_ref, + rx_ring_ref); if (err) { vfree(vma->addr); return err; @@ -222,7 +212,7 @@ op.u.bind_interdomain.port2 = evtchn; err = HYPERVISOR_event_channel_op(&op); if (err) { - unmap_frontend_page(netif); + unmap_frontend_pages(netif); vfree(vma->addr); return err; } @@ -267,7 +257,7 @@ unregister_netdev(netif->dev); if (netif->tx) { - unmap_frontend_page(netif); + unmap_frontend_pages(netif); vfree(netif->tx); /* Frees netif->rx as well. */ } diff -r edd1616cf8cb -r 291e816acbf4 linux-2.6-xen-sparse/drivers/xen/netback/netback.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Fri Sep 2 14:15:49 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Fri Sep 2 14:17:08 2005 @@ -14,23 +14,6 @@ #include <asm-xen/balloon.h> #include <asm-xen/xen-public/memory.h> -#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX) -#include <asm-xen/xen-public/grant_table.h> -#include <asm-xen/gnttab.h> -#ifdef GRANT_DEBUG -static void -dump_packet(int tag, u32 addr, unsigned char *p) -{ - int i; - - printk(KERN_ALERT "#### rx_action %c %08x ", tag & 0xff, addr); - for (i = 0; i < 20; i++) { - printk("%02x", p[i]); - } - printk("\n"); -} -#endif -#endif static void netif_idx_release(u16 pending_idx); static void netif_page_release(struct page *page); @@ -57,7 +40,8 @@ static struct sk_buff_head rx_queue; static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE*2+1]; static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE]; -#ifdef CONFIG_XEN_NETDEV_GRANT_RX + +#ifdef CONFIG_XEN_NETDEV_GRANT static gnttab_donate_t grant_rx_op[MAX_PENDING_REQS]; #else static struct mmuext_op rx_mmuext[NETIF_RX_RING_SIZE]; @@ -88,16 +72,13 @@ static struct sk_buff_head tx_queue; -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT static u16 grant_tx_ref[MAX_PENDING_REQS]; static gnttab_unmap_grant_ref_t tx_unmap_ops[MAX_PENDING_REQS]; static gnttab_map_grant_ref_t tx_map_ops[MAX_PENDING_REQS]; + #else static multicall_entry_t tx_mcl[MAX_PENDING_REQS]; -#endif - -#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX) -#define GRANT_INVALID_REF (0xFFFF) #endif static struct list_head net_schedule_list; @@ -127,7 +108,7 @@ return mfn; } -#ifndef CONFIG_XEN_NETDEV_GRANT_RX +#ifndef CONFIG_XEN_NETDEV_GRANT static void free_mfn(unsigned long mfn) { unsigned long flags; @@ -200,7 +181,7 @@ dev_kfree_skb(skb); skb = nskb; } -#ifdef CONFIG_XEN_NETDEV_GRANT_RX +#ifdef CONFIG_XEN_NETDEV_GRANT #ifdef DEBUG_GRANT printk(KERN_ALERT "#### be_xmit: req_prod=%d req_cons=%d id=%04x gr=%04x\n", netif->rx->req_prod, @@ -246,12 +227,12 @@ static void net_rx_action(unsigned long unused) { - netif_t *netif; + netif_t *netif = NULL; s8 status; u16 size, id, evtchn; multicall_entry_t *mcl; mmu_update_t *mmu; -#ifdef CONFIG_XEN_NETDEV_GRANT_RX +#ifdef CONFIG_XEN_NETDEV_GRANT gnttab_donate_t *gop; #else struct mmuext_op *mmuext; @@ -266,7 +247,7 @@ mcl = rx_mcl; mmu = rx_mmu; -#ifdef CONFIG_XEN_NETDEV_GRANT_RX +#ifdef CONFIG_XEN_NETDEV_GRANT gop = grant_rx_op; #else mmuext = rx_mmuext; @@ -282,7 +263,7 @@ if ( (new_mfn = alloc_mfn()) == 0 ) { if ( net_ratelimit() ) - printk(KERN_WARNING "Memory squeeze in netback driver.\n"); + WPRINTK("Memory squeeze in netback driver.\n"); mod_timer(&net_timer, jiffies + HZ); skb_queue_head(&rx_queue, skb); break; @@ -297,7 +278,7 @@ pfn_pte_ma(new_mfn, PAGE_KERNEL), 0); mcl++; -#ifdef CONFIG_XEN_NETDEV_GRANT_RX +#ifdef CONFIG_XEN_NETDEV_GRANT gop->mfn = old_mfn; gop->domid = netif->domid; gop->handle = netif->rx->ring[ @@ -340,7 +321,7 @@ mcl->args[3] = DOMID_SELF; mcl++; -#ifdef CONFIG_XEN_NETDEV_GRANT_RX +#ifdef CONFIG_XEN_NETDEV_GRANT mcl[-2].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; #else mcl[-3].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; @@ -349,9 +330,17 @@ BUG(); mcl = rx_mcl; -#ifdef CONFIG_XEN_NETDEV_GRANT_RX - BUG_ON(HYPERVISOR_grant_table_op( - GNTTABOP_donate, grant_rx_op, gop - grant_rx_op)); +#ifdef CONFIG_XEN_NETDEV_GRANT + if(HYPERVISOR_grant_table_op(GNTTABOP_donate, grant_rx_op, + gop - grant_rx_op)) { + /* + ** The other side has given us a bad grant ref, or has no headroom, + ** or has gone away. Unfortunately the current grant table code + ** doesn't inform us which is the case, so not much we can do. + */ + DPRINTK("net_rx: donate to DOM%u failed; dropping (up to) %d " + "packets.\n", grant_rx_op[0].domid, gop - grant_rx_op); + } gop = grant_rx_op; #else mmuext = rx_mmuext; @@ -363,7 +352,7 @@ /* Rederive the machine addresses. */ new_mfn = mcl[0].args[1] >> PAGE_SHIFT; -#ifdef CONFIG_XEN_NETDEV_GRANT_RX +#ifdef CONFIG_XEN_NETDEV_GRANT old_mfn = 0; /* XXX Fix this so we can free_mfn() on error! */ #else old_mfn = mmuext[0].mfn; @@ -380,8 +369,13 @@ /* Check the reassignment error code. */ status = NETIF_RSP_OKAY; -#ifdef CONFIG_XEN_NETDEV_GRANT_RX - BUG_ON(gop->status != 0); /* XXX */ +#ifdef CONFIG_XEN_NETDEV_GRANT + if(gop->status != 0) { + DPRINTK("Bad status %d from grant donate to DOM%u\n", + gop->status, netif->domid); + /* XXX SMH: should free 'old_mfn' here */ + status = NETIF_RSP_ERROR; + } #else if ( unlikely(mcl[1].result != 0) ) { @@ -404,7 +398,7 @@ netif_put(netif); dev_kfree_skb(skb); -#ifdef CONFIG_XEN_NETDEV_GRANT_RX +#ifdef CONFIG_XEN_NETDEV_GRANT mcl++; gop++; #else @@ -420,6 +414,7 @@ notify_via_evtchn(evtchn); } + out: /* More work to do? */ if ( !skb_queue_empty(&rx_queue) && !timer_pending(&net_timer) ) tasklet_schedule(&net_rx_tasklet); @@ -496,7 +491,7 @@ inline static void net_tx_action_dealloc(void) { -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT gnttab_unmap_grant_ref_t *gop; #else multicall_entry_t *mcl; @@ -508,7 +503,7 @@ dc = dealloc_cons; dp = dealloc_prod; -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT /* * Free up any grants we have finished using */ @@ -542,7 +537,7 @@ #endif while ( dealloc_cons != dp ) { -#ifndef CONFIG_XEN_NETDEV_GRANT_TX +#ifndef CONFIG_XEN_NETDEV_GRANT /* The update_va_mapping() must not fail. */ BUG_ON(mcl[0].result != 0); #endif @@ -569,7 +564,7 @@ netif_put(netif); -#ifndef CONFIG_XEN_NETDEV_GRANT_TX +#ifndef CONFIG_XEN_NETDEV_GRANT mcl++; #endif } @@ -585,7 +580,7 @@ netif_tx_request_t txreq; u16 pending_idx; NETIF_RING_IDX i; -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT gnttab_map_grant_ref_t *mop; #else multicall_entry_t *mcl; @@ -595,7 +590,7 @@ if ( dealloc_cons != dealloc_prod ) net_tx_action_dealloc(); -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT mop = tx_map_ops; #else mcl = tx_mcl; @@ -696,7 +691,7 @@ /* Packets passed to netif_rx() must have some headroom. */ skb_reserve(skb, 16); -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT mop->host_addr = MMAP_VADDR(pending_idx); mop->dom = netif->domid; mop->ref = txreq.addr >> PAGE_SHIFT; @@ -719,7 +714,7 @@ pending_cons++; -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT if ( (mop - tx_map_ops) >= ARRAY_SIZE(tx_map_ops) ) break; #else @@ -729,7 +724,7 @@ #endif } -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT if ( mop == tx_map_ops ) return; @@ -752,7 +747,7 @@ memcpy(&txreq, &pending_tx_info[pending_idx].req, sizeof(txreq)); /* Check the remap error code. */ -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT /* XXX SMH: error returns from grant operations are pretty poorly specified/thought out, but the below at least conforms with @@ -826,7 +821,7 @@ netif_rx(skb); netif->dev->last_rx = jiffies; -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT mop++; #else mcl++; @@ -949,12 +944,9 @@ !(xen_start_info.flags & SIF_INITDOMAIN) ) return 0; - printk("Initialising Xen netif backend\n"); -#ifdef CONFIG_XEN_NETDEV_GRANT_TX - printk("#### netback tx using grant tables\n"); -#endif -#ifdef CONFIG_XEN_NETDEV_GRANT_RX - printk("#### netback rx using grant tables\n"); + IPRINTK("Initialising Xen netif backend.\n"); +#ifdef CONFIG_XEN_NETDEV_GRANT + IPRINTK("Using grant tables.\n"); #endif /* We can increase reservation by this much in net_rx_action(). */ diff -r edd1616cf8cb -r 291e816acbf4 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Fri Sep 2 14:15:49 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Fri Sep 2 14:17:08 2005 @@ -55,9 +55,18 @@ #include <asm/page.h> #include <asm/uaccess.h> -#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX) +#ifdef CONFIG_XEN_NETDEV_GRANT #include <asm-xen/xen-public/grant_table.h> #include <asm-xen/gnttab.h> + +static grant_ref_t gref_tx_head; +static grant_ref_t grant_tx_ref[NETIF_TX_RING_SIZE + 1]; + +static grant_ref_t gref_rx_head; +static grant_ref_t grant_rx_ref[NETIF_RX_RING_SIZE + 1]; + +#define GRANT_INVALID_REF (0xFFFF) + #ifdef GRANT_DEBUG static void dump_packet(int tag, void *addr, u32 ap) @@ -71,8 +80,17 @@ } printk("\n"); } -#endif -#endif + +#define GDPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \ + __FILE__ , __LINE__ , ## _a ) +#else +#define dump_packet(x,y,z) ((void)0) +#define GDPRINTK(_f, _a...) ((void)0) +#endif + +#endif + + #ifndef __GFP_NOWARN #define __GFP_NOWARN 0 @@ -102,22 +120,10 @@ #define TX_TEST_IDX req_cons /* conservative: not seen all our requests? */ #endif -#ifdef CONFIG_XEN_NETDEV_GRANT_TX -static grant_ref_t gref_tx_head; -static grant_ref_t grant_tx_ref[NETIF_TX_RING_SIZE + 1]; -#endif - -#ifdef CONFIG_XEN_NETDEV_GRANT_RX -static grant_ref_t gref_rx_head; -static grant_ref_t grant_rx_ref[NETIF_RX_RING_SIZE + 1]; -#endif - -#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX) -#define GRANT_INVALID_REF (0xFFFF) -#endif #define NETIF_STATE_DISCONNECTED 0 #define NETIF_STATE_CONNECTED 1 + static unsigned int netif_state = NETIF_STATE_DISCONNECTED; @@ -279,7 +285,7 @@ for (i = np->tx_resp_cons; i != prod; i++) { id = np->tx->ring[MASK_NETIF_TX_IDX(i)].resp.id; skb = np->tx_skbs[id]; -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT if (unlikely(gnttab_query_foreign_access(grant_tx_ref[id]) != 0)) { /* other domain is still using this grant - shouldn't happen but if it does, we'll try to reclaim the grant later */ @@ -310,7 +316,7 @@ mb(); } while (prod != np->tx->resp_prod); -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT out: #endif @@ -330,8 +336,8 @@ int i, batch_target; NETIF_RING_IDX req_prod = np->rx->req_prod; struct xen_memory_reservation reservation; -#ifdef CONFIG_XEN_NETDEV_GRANT_RX - int ref; +#ifdef CONFIG_XEN_NETDEV_GRANT + grant_ref_t ref; #endif if (unlikely(np->backend_state != BEST_CONNECTED)) @@ -365,9 +371,9 @@ np->rx_skbs[id] = skb; np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.id = id; -#ifdef CONFIG_XEN_NETDEV_GRANT_RX +#ifdef CONFIG_XEN_NETDEV_GRANT ref = gnttab_claim_grant_reference(&gref_rx_head); - if (unlikely(ref < 0)) { + if (unlikely((signed short)ref < 0)) { printk(KERN_ALERT "#### netfront can't claim rx reference\n"); BUG(); } @@ -426,8 +432,8 @@ struct net_private *np = netdev_priv(dev); netif_tx_request_t *tx; NETIF_RING_IDX i; -#ifdef CONFIG_XEN_NETDEV_GRANT_TX - unsigned int ref; +#ifdef CONFIG_XEN_NETDEV_GRANT + grant_ref_t ref; unsigned long mfn; #endif @@ -464,9 +470,9 @@ tx = &np->tx->ring[MASK_NETIF_TX_IDX(i)].req; tx->id = id; -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT ref = gnttab_claim_grant_reference(&gref_tx_head); - if (unlikely(ref < 0)) { + if (unlikely((signed short)ref < 0)) { printk(KERN_ALERT "#### netfront can't claim tx grant reference\n"); BUG(); } @@ -519,7 +525,7 @@ network_tx_buf_gc(dev); spin_unlock_irqrestore(&np->tx_lock, flags); - if ((np->rx_resp_cons != np->rx->resp_prod) && (np->user_state == UST_OPEN)) + if((np->rx_resp_cons != np->rx->resp_prod) && (np->user_state == UST_OPEN)) netif_rx_schedule(dev); return IRQ_HANDLED; @@ -537,7 +543,7 @@ int work_done, budget, more_to_do = 1; struct sk_buff_head rxq; unsigned long flags; -#ifdef CONFIG_XEN_NETDEV_GRANT_RX +#ifdef CONFIG_XEN_NETDEV_GRANT unsigned long mfn; grant_ref_t ref; #endif @@ -574,8 +580,19 @@ continue; } -#ifdef CONFIG_XEN_NETDEV_GRANT_RX - ref = grant_rx_ref[rx->id]; +#ifdef CONFIG_XEN_NETDEV_GRANT + ref = grant_rx_ref[rx->id]; + + if(ref == GRANT_INVALID_REF) { + printk(KERN_WARNING "Bad rx grant reference %d from dom %d.\n", + ref, np->backend_id); + np->rx->ring[MASK_NETIF_RX_IDX(np->rx->req_prod)].req.id = rx->id; + wmb(); + np->rx->req_prod++; + work_done--; + continue; + } + grant_rx_ref[rx->id] = GRANT_INVALID_REF; mfn = gnttab_end_foreign_transfer_ref(ref); gnttab_release_grant_reference(&gref_rx_head, ref); @@ -585,7 +602,7 @@ ADD_ID_TO_FREELIST(np->rx_skbs, rx->id); /* NB. We handle skb overflow later. */ -#ifdef CONFIG_XEN_NETDEV_GRANT_RX +#ifdef CONFIG_XEN_NETDEV_GRANT skb->data = skb->head + rx->addr; #else skb->data = skb->head + (rx->addr & ~PAGE_MASK); @@ -600,14 +617,14 @@ np->stats.rx_bytes += rx->status; /* Remap the page. */ -#ifdef CONFIG_XEN_NETDEV_GRANT_RX +#ifdef CONFIG_XEN_NETDEV_GRANT mmu->ptr = mfn << PAGE_SHIFT | MMU_MACHPHYS_UPDATE; #else mmu->ptr = (rx->addr & PAGE_MASK) | MMU_MACHPHYS_UPDATE; #endif mmu->val = __pa(skb->head) >> PAGE_SHIFT; mmu++; -#ifdef CONFIG_XEN_NETDEV_GRANT_RX +#ifdef CONFIG_XEN_NETDEV_GRANT MULTI_update_va_mapping(mcl, (unsigned long)skb->head, pfn_pte_ma(mfn, PAGE_KERNEL), 0); #else @@ -617,19 +634,19 @@ #endif mcl++; -#ifdef CONFIG_XEN_NETDEV_GRANT_RX +#ifdef CONFIG_XEN_NETDEV_GRANT phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = mfn; + GDPRINTK("#### rx_poll enqueue vdata=%p mfn=%lu ref=%x\n", + skb->data, mfn, ref); #else phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = rx->addr >> PAGE_SHIFT; -#endif - -#ifdef GRANT_DEBUG - printk(KERN_ALERT "#### rx_poll enqueue vdata=%p mfn=%lu ref=%x\n", - skb->data, mfn, ref); -#endif +#endif + + __skb_queue_tail(&rxq, skb); } + /* Some pages are no longer absent... */ balloon_update_driver_allowance(-work_done); @@ -646,9 +663,9 @@ } while ((skb = __skb_dequeue(&rxq)) != NULL) { -#ifdef GRANT_DEBUG - printk(KERN_ALERT "#### rx_poll dequeue vdata=%p mfn=%lu\n", - skb->data, virt_to_mfn(skb->data)); +#ifdef CONFIG_XEN_NETDEV_GRANT + GDPRINTK("#### rx_poll dequeue vdata=%p mfn=%lu\n", + skb->data, virt_to_mfn(skb->data)); dump_packet('d', skb->data, (unsigned long)skb->data); #endif /* @@ -747,7 +764,6 @@ return &np->stats; } - static void network_connect(struct net_device *dev) { struct net_private *np; @@ -787,8 +803,11 @@ tx = &np->tx->ring[requeue_idx++].req; tx->id = i; -#ifdef CONFIG_XEN_NETDEV_GRANT_TX - tx->addr = 0; /*(ref << PAGE_SHIFT) |*/ +#ifdef CONFIG_XEN_NETDEV_GRANT + gnttab_grant_foreign_access_ref(grant_tx_ref[i], np->backend_id, + virt_to_mfn(np->tx_skbs[i]->data), + GNTMAP_readonly); + tx->addr = grant_tx_ref[i] << PAGE_SHIFT; #else tx->addr = virt_to_mfn(skb->data) << PAGE_SHIFT; #endif @@ -803,9 +822,20 @@ np->tx->req_prod = requeue_idx; /* Rebuild the RX buffer freelist and the RX ring itself. */ - for (requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++) - if ((unsigned long)np->rx_skbs[i] >= __PAGE_OFFSET) - np->rx->ring[requeue_idx++].req.id = i; + for (requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++) { + if ((unsigned long)np->rx_skbs[i] >= __PAGE_OFFSET) { +#ifdef CONFIG_XEN_NETDEV_GRANT + /* Reinstate the grant ref so backend can 'donate' mfn to us. */ + gnttab_grant_foreign_transfer_ref(grant_rx_ref[i], np->backend_id, + virt_to_mfn(np->rx_skbs[i]->head) + ); + np->rx->ring[requeue_idx].req.gref = grant_rx_ref[i]; +#endif + np->rx->ring[requeue_idx].req.id = i; + requeue_idx++; + } + } + wmb(); np->rx->req_prod = requeue_idx; @@ -901,13 +931,14 @@ /* Initialise {tx,rx}_skbs to be a free chain containing every entry. */ for (i = 0; i <= NETIF_TX_RING_SIZE; i++) { np->tx_skbs[i] = (void *)((unsigned long) i+1); -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT grant_tx_ref[i] = GRANT_INVALID_REF; #endif } + for (i = 0; i <= NETIF_RX_RING_SIZE; i++) { np->rx_skbs[i] = (void *)((unsigned long) i+1); -#ifdef CONFIG_XEN_NETDEV_GRANT_RX +#ifdef CONFIG_XEN_NETDEV_GRANT grant_rx_ref[i] = GRANT_INVALID_REF; #endif } @@ -991,10 +1022,8 @@ evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound }; int err; -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT info->tx_ring_ref = GRANT_INVALID_REF; -#endif -#ifdef CONFIG_XEN_NETDEV_GRANT_RX info->rx_ring_ref = GRANT_INVALID_REF; #endif @@ -1014,7 +1043,7 @@ memset(info->rx, 0, PAGE_SIZE); info->backend_state = BEST_DISCONNECTED; -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT err = gnttab_grant_foreign_access(info->backend_id, virt_to_mfn(info->tx), 0); if (err < 0) { @@ -1022,11 +1051,7 @@ goto out; } info->tx_ring_ref = err; -#else - info->tx_ring_ref = virt_to_mfn(info->tx); -#endif - -#ifdef CONFIG_XEN_NETDEV_GRANT_RX + err = gnttab_grant_foreign_access(info->backend_id, virt_to_mfn(info->rx), 0); if (err < 0) { @@ -1034,7 +1059,9 @@ goto out; } info->rx_ring_ref = err; + #else + info->tx_ring_ref = virt_to_mfn(info->tx); info->rx_ring_ref = virt_to_mfn(info->rx); #endif @@ -1054,16 +1081,17 @@ if (info->rx) free_page((unsigned long)info->rx); info->rx = 0; -#ifdef CONFIG_XEN_NETDEV_GRANT_TX + +#ifdef CONFIG_XEN_NETDEV_GRANT if (info->tx_ring_ref != GRANT_INVALID_REF) gnttab_end_foreign_access(info->tx_ring_ref, 0); info->tx_ring_ref = GRANT_INVALID_REF; -#endif -#ifdef CONFIG_XEN_NETDEV_GRANT_RX + if (info->rx_ring_ref != GRANT_INVALID_REF) gnttab_end_foreign_access(info->rx_ring_ref, 0); info->rx_ring_ref = GRANT_INVALID_REF; #endif + return err; } @@ -1075,16 +1103,17 @@ if (info->rx) free_page((unsigned long)info->rx); info->rx = 0; -#ifdef CONFIG_XEN_NETDEV_GRANT_TX + +#ifdef CONFIG_XEN_NETDEV_GRANT if (info->tx_ring_ref != GRANT_INVALID_REF) gnttab_end_foreign_access(info->tx_ring_ref, 0); info->tx_ring_ref = GRANT_INVALID_REF; -#endif -#ifdef CONFIG_XEN_NETDEV_GRANT_RX + if (info->rx_ring_ref != GRANT_INVALID_REF) gnttab_end_foreign_access(info->rx_ring_ref, 0); info->rx_ring_ref = GRANT_INVALID_REF; #endif + unbind_evtchn_from_irqhandler(info->evtchn, info->netdev); info->evtchn = 0; } @@ -1294,6 +1323,7 @@ int err; err = talk_to_backend(dev, np); + return err; } @@ -1342,29 +1372,28 @@ if (xen_start_info.flags & SIF_INITDOMAIN) return 0; -#ifdef CONFIG_XEN_NETDEV_GRANT_TX - /* A grant for every ring slot */ + if ((err = xennet_proc_init()) != 0) + return err; + + IPRINTK("Initialising virtual ethernet driver.\n"); + +#ifdef CONFIG_XEN_NETDEV_GRANT + IPRINTK("Using grant tables.\n"); + + /* A grant for every tx ring slot */ if (gnttab_alloc_grant_references(NETIF_TX_RING_SIZE, &gref_tx_head) < 0) { printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n"); return 1; } - printk(KERN_ALERT "Netdev frontend (TX) is using grant tables.\n"); -#endif -#ifdef CONFIG_XEN_NETDEV_GRANT_RX - /* A grant for every ring slot */ + /* A grant for every rx ring slot */ if (gnttab_alloc_grant_references(NETIF_RX_RING_SIZE, &gref_rx_head) < 0) { printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n"); return 1; } - printk(KERN_ALERT "Netdev frontend (RX) is using grant tables.\n"); -#endif - - if ((err = xennet_proc_init()) != 0) - return err; - - IPRINTK("Initialising virtual ethernet driver.\n"); +#endif + (void)register_inetaddr_notifier(¬ifier_inetdev); @@ -1377,10 +1406,8 @@ static void netif_exit(void) { -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT gnttab_free_grant_references(gref_tx_head); -#endif -#ifdef CONFIG_XEN_NETDEV_GRANT_RX gnttab_free_grant_references(gref_rx_head); #endif } diff -r edd1616cf8cb -r 291e816acbf4 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Fri Sep 2 14:15:49 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Fri Sep 2 14:17:08 2005 @@ -212,7 +212,7 @@ xen_start_info.store_evtchn, wake_waiting, 0, "xenbus", &xb_waitq); if (err) { - printk(KERN_ERR "XENBUS request irq failed %i\n", err); + xprintk("XENBUS request irq failed %i\n", err); unbind_evtchn_from_irq(xen_start_info.store_evtchn); return err; } diff -r edd1616cf8cb -r 291e816acbf4 tools/check/check_brctl --- a/tools/check/check_brctl Fri Sep 2 14:15:49 2005 +++ b/tools/check/check_brctl Fri Sep 2 14:17:08 2005 @@ -2,8 +2,9 @@ # CHECK-INSTALL function error { - echo 'Check for the bridge control utils (brctl) failed.' + echo + echo ' *** Check for the bridge control utils (brctl) FAILED' exit 1 } -brctl show || error \ No newline at end of file +which brctl 1>/dev/null 2>&1 || error diff -r edd1616cf8cb -r 291e816acbf4 tools/check/check_iproute --- a/tools/check/check_iproute Fri Sep 2 14:15:49 2005 +++ b/tools/check/check_iproute Fri Sep 2 14:17:08 2005 @@ -2,9 +2,10 @@ # CHECK-INSTALL function error { - echo 'Check for iproute (ip addr) failed.' + echo + echo ' *** Check for iproute (ip addr) FAILED' exit 1 } -ip addr list || error +ip addr list 1>/dev/null 2>&1 || error diff -r edd1616cf8cb -r 291e816acbf4 tools/check/check_logging --- a/tools/check/check_logging Fri Sep 2 14:15:49 2005 +++ b/tools/check/check_logging Fri Sep 2 14:17:08 2005 @@ -18,11 +18,12 @@ import logging except ImportError: hline() - msg("Python logging is not installed.") - msg("Use 'make install-logging' at the xen root to install.") msg("") - msg("Alternatively download and install from") - msg("http://www.red-dove.com/python_logging.html") + msg(" *** Python logging is not installed.") + msg(" *** Use 'make install-logging' at the xen root to install.") + msg(" *** ") + msg(" *** Alternatively download and install from") + msg(" *** http://www.red-dove.com/python_logging.html") hline() sys.exit(1) diff -r edd1616cf8cb -r 291e816acbf4 tools/check/check_python --- a/tools/check/check_python Fri Sep 2 14:15:49 2005 +++ b/tools/check/check_python Fri Sep 2 14:17:08 2005 @@ -2,9 +2,9 @@ # CHECK-BUILD CHECK-INSTALL function error { - echo "Check for Python version 2.2 or higher failed." + echo + echo " *** Check for Python version >= 2.2 FAILED" exit 1 } -python -V python -V 2>&1 | cut -d ' ' -f 2 | grep -q -E '^2.2|^2.3|^2.4' || error diff -r edd1616cf8cb -r 291e816acbf4 tools/check/check_zlib_devel --- a/tools/check/check_zlib_devel Fri Sep 2 14:15:49 2005 +++ b/tools/check/check_zlib_devel Fri Sep 2 14:17:08 2005 @@ -2,9 +2,10 @@ # CHECK-BUILD function error { - echo 'Check for zlib includes failed.' + echo + echo " *** Check for zlib headers FAILED" exit 1 } set -e -[ -e /usr/include/zlib.h ] || error \ No newline at end of file +[ -e /usr/include/zlib.h ] || error diff -r edd1616cf8cb -r 291e816acbf4 tools/check/check_zlib_lib --- a/tools/check/check_zlib_lib Fri Sep 2 14:15:49 2005 +++ b/tools/check/check_zlib_lib Fri Sep 2 14:17:08 2005 @@ -2,9 +2,10 @@ # CHECK-BUILD CHECK-INSTALL function error { - echo 'Check for zlib library failed.' + echo + echo " *** Check for zlib library FAILED" exit 1 } set -e -ldconfig -p | grep libz.so || error \ No newline at end of file +ldconfig -p | grep -q libz.so || error diff -r edd1616cf8cb -r 291e816acbf4 tools/check/chk --- a/tools/check/chk Fri Sep 2 14:15:49 2005 +++ b/tools/check/chk Fri Sep 2 14:17:08 2005 @@ -17,14 +17,11 @@ case $1 in build) check="CHECK-BUILD" - info=".chkbuild" ;; install) check="CHECK-INSTALL" - info=".chkinstall" ;; clean) - rm -f .chkbuild .chkinstall exit 0 ;; *) @@ -34,7 +31,7 @@ failed=0 -echo "Xen ${check} " $(date) > ${info} +echo "Xen ${check} " $(date) for f in check_* ; do case $f in *~) @@ -49,24 +46,12 @@ if ! grep -q ${check} $f ; then continue fi - echo ' ' >> ${info} - echo "Checking $f" >> ${info} - if ./$f 1>>${info} 2>&1 ; then - echo OK >> ${info} + echo -n "Checking $f: " + if ./$f 2>&1 ; then + echo OK else failed=1 - echo "FAILED $f" - echo FAILED >> ${info} fi done -echo >> ${info} - -if [ "$failed" == "1" ] ; then - echo "Checks failed. See `pwd`/${info} for details." - echo "FAILED" >> ${info} - exit 1 -else - echo "OK" >> ${info} - exit 0 -fi +exit $failed diff -r edd1616cf8cb -r 291e816acbf4 tools/console/daemon/utils.c --- a/tools/console/daemon/utils.c Fri Sep 2 14:15:49 2005 +++ b/tools/console/daemon/utils.c Fri Sep 2 14:17:08 2005 @@ -234,7 +234,7 @@ } if (!xs_watch(xs, "/console", "console")) { - dolog(LOG_ERR, "xenstore watch on /console failes."); + dolog(LOG_ERR, "xenstore watch on /console fails."); goto out_close_data; } diff -r edd1616cf8cb -r 291e816acbf4 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Fri Sep 2 14:15:49 2005 +++ b/tools/python/xen/xend/XendDomainInfo.py Fri Sep 2 14:17:08 2005 @@ -1028,6 +1028,7 @@ """ try: + self.clear_shutdown() self.state = STATE_VM_OK self.shutdown_pending = None self.restart_check() diff -r edd1616cf8cb -r 291e816acbf4 tools/security/Makefile --- a/tools/security/Makefile Fri Sep 2 14:15:49 2005 +++ b/tools/security/Makefile Fri Sep 2 14:17:08 2005 @@ -45,6 +45,7 @@ $(MAKE) secpol_xml2bin chmod 700 ./setlabel.sh chmod 700 ./updategrub.sh + chmod 700 ./getlabel.sh secpol_tool : secpol_tool.c secpol_compat.h $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< diff -r edd1616cf8cb -r 291e816acbf4 tools/security/secpol_tool.c --- a/tools/security/secpol_tool.c Fri Sep 2 14:15:49 2005 +++ b/tools/security/secpol_tool.c Fri Sep 2 14:17:08 2005 @@ -25,6 +25,7 @@ #include <stdio.h> #include <errno.h> #include <fcntl.h> +#include <getopt.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> @@ -40,6 +41,17 @@ #define PERROR(_m, _a...) \ fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \ errno, strerror(errno)) + +void usage(char *progname) +{ + printf("Use: %s \n" + "\t getpolicy\n" + "\t dumpstats\n" + "\t loadpolicy <binary policy file>\n" + "\t getssid -d <domainid> [-f]\n" + "\t getssid -s <ssidref> [-f]\n", progname); + exit(-1); +} static inline int do_policycmd(int xc_handle, unsigned int cmd, unsigned long data) @@ -320,7 +332,7 @@ if (ret) printf - ("ERROR setting policy. Use 'xm dmesg' to see details.\n"); + ("ERROR setting policy. Try 'xm dmesg' to see details.\n"); else printf("Successfully changed policy.\n"); @@ -370,7 +382,7 @@ if (ret < 0) { - printf("ERROR dumping policy stats. Use 'xm dmesg' to see details.\n"); + printf("ERROR dumping policy stats. Try 'xm dmesg' to see details.\n"); return ret; } stats = (struct acm_stats_buffer *) stats_buffer; @@ -421,17 +433,121 @@ } return ret; } +/************************ get ssidref & types ******************************/ +/* + * the ssid (types) can be looked up either by domain id or by ssidref + */ +int acm_domain_getssid(int xc_handle, int argc, char * const argv[]) +{ + /* this includes header and a set of types */ + #define MAX_SSIDBUFFER 2000 + int ret, i; + acm_op_t op; + struct acm_ssid_buffer *hdr; + unsigned char *buf; + int nice_print = 1; + + op.cmd = ACM_GETSSID; + op.interface_version = ACM_INTERFACE_VERSION; + op.u.getssid.get_ssid_by = UNSET; + /* arguments + -d ... domain id to look up + -s ... ssidref number to look up + -f ... formatted print (scripts depend on this format) + */ + while (1) + { + int c = getopt(argc, argv, "d:s:f"); + if (c == -1) + break; + if (c == 'd') + { + if (op.u.getssid.get_ssid_by != UNSET) + usage(argv[0]); + op.u.getssid.get_ssid_by = DOMAINID; + op.u.getssid.id.domainid = strtoul(optarg, NULL, 0); + } + else if (c== 's') + { + if (op.u.getssid.get_ssid_by != UNSET) + usage(argv[0]); + op.u.getssid.get_ssid_by = SSIDREF; + op.u.getssid.id.ssidref = strtoul(optarg, NULL, 0); + } + else if (c== 'f') + { + nice_print = 0; + } + else + usage(argv[0]); + } + if (op.u.getssid.get_ssid_by == UNSET) + usage(argv[0]); + + buf = malloc(MAX_SSIDBUFFER); + if (!buf) + return -ENOMEM; + + /* dump it and then push it down into xen/acm */ + op.u.getssid.ssidbuf = buf; /* out */ + op.u.getssid.ssidbuf_size = MAX_SSIDBUFFER; + ret = do_acm_op(xc_handle, &op); + + if (ret) + { + printf("ERROR getting ssidref. Try 'xm dmesg' to see details.\n"); + goto out; + } + hdr = (struct acm_ssid_buffer *)buf; + if (hdr->len > MAX_SSIDBUFFER) + { + printf("ERROR: Buffer length inconsistent (ret=%d, hdr->len=%d)!\n", + ret, hdr->len); + return -EIO; + } + if (nice_print) + { + printf("SSID: ssidref = 0x%08x \n", hdr->ssidref); + printf(" P: %s, max_types = %d\n", + ACM_POLICY_NAME(hdr->primary_policy_code), hdr->primary_max_types); + printf(" Types: "); + for (i=0; i< hdr->primary_max_types; i++) + if (buf[hdr->primary_types_offset + i]) + printf("%02x ", i); + else + printf("-- "); + printf("\n"); + + printf(" S: %s, max_types = %d\n", + ACM_POLICY_NAME(hdr->secondary_policy_code), hdr->secondary_max_types); + printf(" Types: "); + for (i=0; i< hdr->secondary_max_types; i++) + if (buf[hdr->secondary_types_offset + i]) + printf("%02x ", i); + else + printf("-- "); + printf("\n"); + } + else + { + /* formatted print for use with scripts (.sh) + * update scripts when updating here (usually + * used in combination with -d to determine a + * running domain's label + */ + printf("SSID: ssidref = 0x%08x \n", hdr->ssidref); + } + + /* return ste ssidref */ + if (hdr->primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) + ret = (hdr->ssidref) & 0xffff; + else if (hdr->secondary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) + ret = (hdr->ssidref) >> 16; + out: + return ret; +} /***************************** main **************************************/ - -void usage(char *progname) -{ - printf("Use: %s \n" - "\t getpolicy\n" - "\t dumpstats\n" - "\t loadpolicy <binary policy file>\n", progname); - exit(-1); -} int main(int argc, char **argv) { @@ -459,6 +575,8 @@ if (argc != 2) usage(argv[0]); ret = acm_domain_dumpstats(acm_cmd_fd); + } else if (!strcmp(argv[1], "getssid")) { + ret = acm_domain_getssid(acm_cmd_fd, argc, argv); } else usage(argv[0]); diff -r edd1616cf8cb -r 291e816acbf4 tools/security/setlabel.sh --- a/tools/security/setlabel.sh Fri Sep 2 14:15:49 2005 +++ b/tools/security/setlabel.sh Fri Sep 2 14:17:08 2005 @@ -34,275 +34,27 @@ exec sh -c "bash $0 $*" fi +export PATH=$PATH:. +source labelfuncs.sh usage () { - echo "Usage: $0 [Option] <vmfile> <label> <policy name> " - echo " or $0 -l <policy name>" + echo "Usage: $0 [Option] <vmfile> <label> [<policy name>]" + echo " or $0 -l [<policy name>]" echo "" - echo "Valid Options are:" + echo "Valid options are:" echo "-r : to relabel a file without being prompted" echo "" echo "vmfile : XEN vm configuration file" - echo "label : the label to map" + echo "label : the label to map to an ssidref" echo "policy name : the name of the policy, i.e. 'chwall'" + echo " If the policy name is omitted, it is attempted" + echo " to find the current policy's name in grub.conf." echo "" - echo "-l <policy name> is used to show valid labels in the map file" + echo "-l [<policy name>] is used to show valid labels in the map file of" + echo " the given or current policy." echo "" } - - -findMapFile () -{ - mapfile="./$1.map" - if [ -r "$mapfile" ]; then - return 1 - fi - - mapfile="./policies/$1/$1.map" - if [ -r "$mapfile" ]; then - return 1 - fi - - return 0 -} - -showLabels () -{ - mapfile=$1 - if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then - echo "Cannot read from vm configuration file $vmfile." - return -1 - fi - - getPrimaryPolicy $mapfile - getSecondaryPolicy $mapfile - - echo "The following labels are available:" - let line=1 - while [ 1 ]; do - ITEM=`cat $mapfile | \ - awk -vline=$line \ - -vprimary=$primary \ - '{ \ - if ($1 == "LABEL->SSID" && \ - $2 == "VM" && \ - $3 == primary ) { \ - ctr++; \ - if (ctr == line) { \ - print $4; \ - } \ - } \ - } END { \ - }'` - - if [ "$ITEM" == "" ]; then - break - fi - if [ "$secondary" != "NULL" ]; then - LABEL=`cat $mapfile | \ - awk -vitem=$ITEM \ - '{ - if ($1 == "LABEL->SSID" && \ - $2 == "VM" && \ - $3 == "CHWALL" && \ - $4 == item ) { \ - result = item; \ - } \ - } END { \ - print result \ - }'` - else - LABEL=$ITEM - fi - - if [ "$LABEL" != "" ]; then - echo "$LABEL" - found=1 - fi - let line=line+1 - done - if [ "$found" != "1" ]; then - echo "No labels found." - fi -} - -getPrimaryPolicy () -{ - mapfile=$1 - primary=`cat $mapfile | \ - awk ' \ - { \ - if ( $1 == "PRIMARY" ) { \ - res=$2; \ - } \ - } END { \ - print res; \ - } '` -} - -getSecondaryPolicy () -{ - mapfile=$1 - secondary=`cat $mapfile | \ - awk ' \ - { \ - if ( $1 == "SECONDARY" ) { \ - res=$2; \ - } \ - } END { \ - print res; \ - } '` -} - - -getDefaultSsid () -{ - mapfile=$1 - pol=$2 - RES=`cat $mapfile \ - awk -vpol=$pol \ - { \ - if ($1 == "LABEL->SSID" && \ - $2 == "ANY" && \ - $3 == pol && \ - $4 == "DEFAULT" ) {\ - res=$5; \ - } \ - } END { \ - printf "%04x", strtonum(res) \ - }'` - echo "default NULL mapping is $RES" - defaultssid=$RES -} - -relabel () -{ - vmfile=$1 - label=$2 - mapfile=$3 - mode=$4 - - if [ ! -r "$vmfile" ]; then - echo "Cannot read from vm configuration file $vmfile." - return -1 - fi - - if [ ! -w "$vmfile" ]; then - echo "Cannot write to vm configuration file $vmfile." - return -1 - fi - - if [ ! -r "$mapfile" ] ; then - echo "Cannot read mapping file $mapfile." - return -1 - fi - - # Determine which policy is primary, which sec. - getPrimaryPolicy $mapfile - getSecondaryPolicy $mapfile - - # Calculate the primary policy's SSIDREF - if [ "$primary" == "NULL" ]; then - SSIDLO="0000" - else - SSIDLO=`cat $mapfile | \ - awk -vlabel=$label \ - -vprimary=$primary \ - '{ \ - if ( $1 == "LABEL->SSID" && \ - $2 == "VM" && \ - $3 == primary && \ - $4 == label ) { \ - result=$5 \ - } \ - } END { \ - if (result != "" ) \ - {printf "%04x", strtonum(result)}\ - }'` - fi - - # Calculate the secondary policy's SSIDREF - if [ "$secondary" == "NULL" ]; then - SSIDHI="0000" - else - SSIDHI=`cat $mapfile | \ - awk -vlabel=$label \ - -vsecondary=$secondary \ - '{ \ - if ( $1 == "LABEL->SSID" && \ - $2 == "VM" && \ - $3 == secondary && \ - $4 == label ) { \ - result=$5 \ - } \ - } END { \ - if (result != "" ) \ - {printf "%04x", strtonum(result)}\ - }'` - fi - - if [ "$SSIDLO" == "" -o \ - "$SSIDHI" == "" ]; then - echo "Could not map the given label '$label'." - return -1 - fi - - ACM_POLICY=`cat $mapfile | \ - awk ' { if ( $1 == "POLICY" ) { \ - result=$2 \ - } \ - } \ - END { \ - if (result != "") { \ - printf result \ - } \ - }'` - - if [ "$ACM_POLICY" == "" ]; then - echo "Could not find 'POLICY' entry in map file." - return -1 - fi - - SSIDREF="0x$SSIDHI$SSIDLO" - - if [ "$mode" != "relabel" ]; then - RES=`cat $vmfile | \ - awk '{ \ - if ( substr($1,0,7) == "ssidref" ) {\ - print $0; \ - } \ - }'` - if [ "$RES" != "" ]; then - echo "Do you want to overwrite the existing mapping ($RES)? (y/N)" - read user - if [ "$user" != "y" -a "$user" != "Y" ]; then - echo "Aborted." - return 0 - fi - fi - fi - - #Write the output - vmtmp1="/tmp/__setlabel.tmp1" - vmtmp2="/tmp/__setlabel.tmp2" - touch $vmtmp1 - touch $vmtmp2 - if [ ! -w "$vmtmp1" -o ! -w "$vmtmp2" ]; then - echo "Cannot create temporary files. Aborting." - return -1 - fi - RES=`sed -e '/^#ACM_POLICY/d' $vmfile > $vmtmp1` - RES=`sed -e '/^#ACM_LABEL/d' $vmtmp1 > $vmtmp2` - RES=`sed -e '/^ssidref/d' $vmtmp2 > $vmtmp1` - echo "#ACM_POLICY=$ACM_POLICY" >> $vmtmp1 - echo "#ACM_LABEL=$label" >> $vmtmp1 - echo "ssidref = $SSIDREF" >> $vmtmp1 - mv -f $vmtmp1 $vmfile - rm -rf $vmtmp1 $vmtmp2 - echo "Mapped label '$label' to ssidref '$SSIDREF'." -} - if [ "$1" == "-r" ]; then @@ -317,10 +69,25 @@ if [ "$mode" == "show" ]; then if [ "$1" == "" ]; then - usage - exit -1; + findGrubConf + ret=$? + if [ $ret -eq 0 ]; then + echo "Could not find grub.conf" + exit -1; + fi + findPolicyInGrub $grubconf + if [ "$policy" != "" ]; then + echo "Assuming policy to be '$policy'."; + else + echo "Could not find policy." + exit -1; + fi + else + policy=$3; fi - findMapFile $1 + + + findMapFile $policy res=$? if [ "$res" != "0" ]; then showLabels $mapfile @@ -330,11 +97,29 @@ elif [ "$mode" == "usage" ]; then usage else + if [ "$2" == "" ]; then + usage + exit -1 + fi if [ "$3" == "" ]; then - usage - exit -1; + findGrubConf + ret=$? + if [ $ret -eq 0 ]; then + echo "Could not find grub.conf" + exit -1; + fi + findPolicyInGrub $grubconf + if [ "$policy" != "" ]; then + echo "Assuming policy to be '$policy'."; + else + echo "Could not find policy." + exit -1; + fi + + else + policy=$3; fi - findMapFile $3 + findMapFile $policy res=$? if [ "$res" != "0" ]; then relabel $1 $2 $mapfile $mode diff -r edd1616cf8cb -r 291e816acbf4 xen/Rules.mk --- a/xen/Rules.mk Fri Sep 2 14:15:49 2005 +++ b/xen/Rules.mk Fri Sep 2 14:17:08 2005 @@ -7,7 +7,6 @@ perfc ?= n perfc_arrays?= n trace ?= n -optimize ?= y domu_debug ?= n crash_debug ?= n diff -r edd1616cf8cb -r 291e816acbf4 xen/acm/acm_chinesewall_hooks.c --- a/xen/acm/acm_chinesewall_hooks.c Fri Sep 2 14:15:49 2005 +++ b/xen/acm/acm_chinesewall_hooks.c Fri Sep 2 14:17:08 2005 @@ -310,6 +310,28 @@ return 0; } +static int +chwall_dump_ssid_types(ssidref_t ssidref, u8 *buf, u16 len) +{ + int i; + + /* fill in buffer */ + if (chwall_bin_pol.max_types > len) + return -EFAULT; + + if (ssidref >= chwall_bin_pol.max_ssidrefs) + return -EFAULT; + + /* read types for chwall ssidref */ + for(i=0; i< chwall_bin_pol.max_types; i++) { + if (chwall_bin_pol.ssidrefs[ssidref * chwall_bin_pol.max_types + i]) + buf[i] = 1; + else + buf[i] = 0; + } + return chwall_bin_pol.max_types; +} + /*************************** * Authorization functions ***************************/ @@ -492,6 +514,7 @@ .dump_binary_policy = chwall_dump_policy, .set_binary_policy = chwall_set_policy, .dump_statistics = chwall_dump_stats, + .dump_ssid_types = chwall_dump_ssid_types, /* domain management control hooks */ .pre_domain_create = chwall_pre_domain_create, .post_domain_create = chwall_post_domain_create, diff -r edd1616cf8cb -r 291e816acbf4 xen/acm/acm_core.c --- a/xen/acm/acm_core.c Fri Sep 2 14:15:49 2005 +++ b/xen/acm/acm_core.c Fri Sep 2 14:17:08 2005 @@ -64,16 +64,17 @@ void acm_set_endian(void) { u32 test = 1; - if (*((u8 *)&test) == 1) { + if (*((u8 *)&test) == 1) + { printk("ACM module running in LITTLE ENDIAN.\n"); - little_endian = 1; - } else { - printk("ACM module running in BIG ENDIAN.\n"); - little_endian = 0; - } -} - -#if (ACM_USE_SECURITY_POLICY != ACM_NULL_POLICY) + little_endian = 1; + } + else + { + printk("ACM module running in BIG ENDIAN.\n"); + little_endian = 0; + } +} /* initialize global security policy for Xen; policy write-locked already */ static void @@ -101,7 +102,8 @@ * Try all modules and see whichever could be the binary policy. * Adjust the initrdidx if module[1] is the binary policy. */ - for (i = mbi->mods_count-1; i >= 1; i--) { + for (i = mbi->mods_count-1; i >= 1; i--) + { struct acm_policy_buffer *pol; char *_policy_start; unsigned long _policy_len; @@ -117,23 +119,32 @@ continue; /* not a policy */ pol = (struct acm_policy_buffer *)_policy_start; - if (ntohl(pol->magic) == ACM_MAGIC) { + if (ntohl(pol->magic) == ACM_MAGIC) + { rc = acm_set_policy((void *)_policy_start, (u16)_policy_len, 0); - if (rc == ACM_OK) { + if (rc == ACM_OK) + { printf("Policy len 0x%lx, start at %p.\n",_policy_len,_policy_start); - if (i == 1) { - if (mbi->mods_count > 2) { + if (i == 1) + { + if (mbi->mods_count > 2) + { *initrdidx = 2; - } else { + } + else { *initrdidx = 0; } - } else { + } + else + { *initrdidx = 1; } break; - } else { + } + else + { printk("Invalid policy. %d.th module line.\n", i+1); } } /* end if a binary policy definition, i.e., (ntohl(pol->magic) == ACM_MAGIC ) */ @@ -147,56 +158,84 @@ const multiboot_info_t *mbi, unsigned long initial_images_start) { - int ret = -EINVAL; - - acm_set_endian(); + int ret = ACM_OK; + + acm_set_endian(); write_lock(&acm_bin_pol_rwlock); - - if (ACM_USE_SECURITY_POLICY == ACM_CHINESE_WALL_POLICY) { - acm_init_binary_policy(NULL, NULL); - acm_init_chwall_policy(); + acm_init_binary_policy(NULL, NULL); + + /* set primary policy component */ + switch ((ACM_USE_SECURITY_POLICY) & 0x0f) + { + + case ACM_CHINESE_WALL_POLICY: + acm_init_chwall_policy(); acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY; acm_primary_ops = &acm_chinesewall_ops; + break; + + case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY: + acm_init_ste_policy(); + acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY; + acm_primary_ops = &acm_simple_type_enforcement_ops; + break; + + default: + /* NULL or Unknown policy not allowed primary; + * NULL/NULL will not compile this code */ + ret = -EINVAL; + goto out; + } + + /* secondary policy component part */ + switch ((ACM_USE_SECURITY_POLICY) >> 4) { + case ACM_NULL_POLICY: acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY; acm_secondary_ops = &acm_null_ops; - ret = ACM_OK; - } else if (ACM_USE_SECURITY_POLICY == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) { - acm_init_binary_policy(NULL, NULL); + break; + + case ACM_CHINESE_WALL_POLICY: + if (acm_bin_pol.primary_policy_code == ACM_CHINESE_WALL_POLICY) + { /* not a valid combination */ + ret = -EINVAL; + goto out; + } + acm_init_chwall_policy(); + acm_bin_pol.secondary_policy_code = ACM_CHINESE_WALL_POLICY; + acm_secondary_ops = &acm_chinesewall_ops; + break; + + case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY: + if (acm_bin_pol.primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) + { /* not a valid combination */ + ret = -EINVAL; + goto out; + } acm_init_ste_policy(); - acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY; - acm_primary_ops = &acm_simple_type_enforcement_ops; - acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY; - acm_secondary_ops = &acm_null_ops; - ret = ACM_OK; - } else if (ACM_USE_SECURITY_POLICY == ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) { - acm_init_binary_policy(NULL, NULL); - acm_init_chwall_policy(); - acm_init_ste_policy(); - acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY; - acm_primary_ops = &acm_chinesewall_ops; acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY; acm_secondary_ops = &acm_simple_type_enforcement_ops; - ret = ACM_OK; - } else if (ACM_USE_SECURITY_POLICY == ACM_NULL_POLICY) { - acm_init_binary_policy(NULL, NULL); - acm_bin_pol.primary_policy_code = ACM_NULL_POLICY; - acm_primary_ops = &acm_null_ops; - acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY; - acm_secondary_ops = &acm_null_ops; - ret = ACM_OK; + break; + + default: + ret = -EINVAL; + goto out; + } + + out: + write_unlock(&acm_bin_pol_rwlock); + + if (ret != ACM_OK) + { + printk("%s: Error setting policies.\n", __func__); + /* here one could imagine a clean panic */ + return -EINVAL; } - write_unlock(&acm_bin_pol_rwlock); - - if (ret != ACM_OK) - return -EINVAL; acm_setup(initrdidx, mbi, initial_images_start); printk("%s: Enforcing Primary %s, Secondary %s.\n", __func__, - ACM_POLICY_NAME(acm_bin_pol.primary_policy_code), ACM_POLICY_NAME(acm_bin_pol.secondary_policy_code)); + ACM_POLICY_NAME(acm_bin_pol.primary_policy_code), + ACM_POLICY_NAME(acm_bin_pol.secondary_policy_code)); return ret; } - - -#endif int acm_init_domain_ssid(domid_t id, ssidref_t ssidref) @@ -205,7 +244,8 @@ struct domain *subj = find_domain_by_id(id); int ret1, ret2; - if (subj == NULL) { + if (subj == NULL) + { printk("%s: ACM_NULL_POINTER ERROR (id=%x).\n", __func__, id); return ACM_NULL_POINTER_ERROR; } @@ -235,14 +275,16 @@ else ret2 = ACM_OK; - if ((ret1 != ACM_OK) || (ret2 != ACM_OK)) { + if ((ret1 != ACM_OK) || (ret2 != ACM_OK)) + { printk("%s: ERROR instantiating individual ssids for domain 0x%02x.\n", __func__, subj->domain_id); acm_free_domain_ssid(ssid); put_domain(subj); return ACM_INIT_SSID_ERROR; } - printk("%s: assigned domain %x the ssidref=%x.\n", __func__, id, ssid->ssidref); + printk("%s: assigned domain %x the ssidref=%x.\n", + __func__, id, ssid->ssidref); put_domain(subj); return ACM_OK; } @@ -254,11 +296,12 @@ domid_t id; /* domain is already gone, just ssid is left */ - if (ssid == NULL) { + if (ssid == NULL) + { printk("%s: ACM_NULL_POINTER ERROR.\n", __func__); return ACM_NULL_POINTER_ERROR; } - id = ssid->domainid; + id = ssid->domainid; ssid->subject = NULL; if (acm_primary_ops->free_domain_ssid != NULL) /* null policy */ @@ -268,6 +311,7 @@ acm_secondary_ops->free_domain_ssid(ssid->secondary_ssid); ssid->secondary_ssid = NULL; xfree(ssid); - printkd("%s: Freed individual domain ssid (domain=%02x).\n",__func__, id); + printkd("%s: Freed individual domain ssid (domain=%02x).\n", + __func__, id); return ACM_OK; } diff -r edd1616cf8cb -r 291e816acbf4 xen/acm/acm_null_hooks.c --- a/xen/acm/acm_null_hooks.c Fri Sep 2 14:15:49 2005 +++ b/xen/acm/acm_null_hooks.c Fri Sep 2 14:17:08 2005 @@ -14,13 +14,13 @@ #include <acm/acm_hooks.h> static int -null_init_domain_ssid(void **chwall_ssid, ssidref_t ssidref) +null_init_domain_ssid(void **ssid, ssidref_t ssidref) { return ACM_OK; } static void -null_free_domain_ssid(void *chwall_ssid) +null_free_domain_ssid(void *ssid) { return; } @@ -44,6 +44,14 @@ return 0; } +static int +null_dump_ssid_types(ssidref_t ssidref, u8 *buffer, u16 buf_size) +{ + /* no types */ + return 0; +} + + /* now define the hook structure similarly to LSM */ struct acm_operations acm_null_ops = { .init_domain_ssid = null_init_domain_ssid, @@ -51,6 +59,7 @@ .dump_binary_policy = null_dump_binary_policy, .set_binary_policy = null_set_binary_policy, .dump_statistics = null_dump_stats, + .dump_ssid_types = null_dump_ssid_types, /* domain management control hooks */ .pre_domain_create = NULL, .post_domain_create = NULL, diff -r edd1616cf8cb -r 291e816acbf4 xen/acm/acm_policy.c --- a/xen/acm/acm_policy.c Fri Sep 2 14:15:49 2005 +++ b/xen/acm/acm_policy.c Fri Sep 2 14:17:08 2005 @@ -26,8 +26,8 @@ #include <xen/lib.h> #include <xen/delay.h> #include <xen/sched.h> +#include <acm/acm_core.h> #include <public/acm_ops.h> -#include <acm/acm_core.h> #include <acm/acm_hooks.h> #include <acm/acm_endian.h> @@ -37,14 +37,16 @@ u8 *policy_buffer = NULL; struct acm_policy_buffer *pol; - if (buf_size < sizeof(struct acm_policy_buffer)) + if (buf_size < sizeof(struct acm_policy_buffer)) return -EFAULT; /* 1. copy buffer from domain */ if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL) - goto error_free; + return -ENOMEM; + if (isuserbuffer) { - if (copy_from_user(policy_buffer, buf, buf_size)) { + if (copy_from_user(policy_buffer, buf, buf_size)) + { printk("%s: Error copying!\n",__func__); goto error_free; } @@ -57,11 +59,13 @@ if ((ntohl(pol->magic) != ACM_MAGIC) || (ntohl(pol->policy_version) != ACM_POLICY_VERSION) || (ntohl(pol->primary_policy_code) != acm_bin_pol.primary_policy_code) || - (ntohl(pol->secondary_policy_code) != acm_bin_pol.secondary_policy_code)) { + (ntohl(pol->secondary_policy_code) != acm_bin_pol.secondary_policy_code)) + { printkd("%s: Wrong policy magics or versions!\n", __func__); goto error_free; } - if (buf_size != ntohl(pol->len)) { + if (buf_size != ntohl(pol->len)) + { printk("%s: ERROR in buf size.\n", __func__); goto error_free; } @@ -72,27 +76,25 @@ /* 3. set primary policy data */ if (acm_primary_ops->set_binary_policy(buf + ntohl(pol->primary_buffer_offset), ntohl(pol->secondary_buffer_offset) - - ntohl(pol->primary_buffer_offset))) { + ntohl(pol->primary_buffer_offset))) goto error_lock_free; - } + /* 4. set secondary policy data */ if (acm_secondary_ops->set_binary_policy(buf + ntohl(pol->secondary_buffer_offset), ntohl(pol->len) - - ntohl(pol->secondary_buffer_offset))) { + ntohl(pol->secondary_buffer_offset))) goto error_lock_free; - } + write_unlock(&acm_bin_pol_rwlock); - if (policy_buffer != NULL) - xfree(policy_buffer); + xfree(policy_buffer); return ACM_OK; error_lock_free: write_unlock(&acm_bin_pol_rwlock); error_free: printk("%s: Error setting policy.\n", __func__); - if (policy_buffer != NULL) - xfree(policy_buffer); - return -ENOMEM; + xfree(policy_buffer); + return -EFAULT; } int @@ -102,11 +104,14 @@ int ret; struct acm_policy_buffer *bin_pol; + if (buf_size < sizeof(struct acm_policy_buffer)) + return -EFAULT; + if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL) return -ENOMEM; read_lock(&acm_bin_pol_rwlock); - /* future: read policy from file and set it */ + bin_pol = (struct acm_policy_buffer *)policy_buffer; bin_pol->magic = htonl(ACM_MAGIC); bin_pol->primary_policy_code = htonl(acm_bin_pol.primary_policy_code); @@ -118,27 +123,30 @@ ret = acm_primary_ops->dump_binary_policy (policy_buffer + ntohl(bin_pol->primary_buffer_offset), buf_size - ntohl(bin_pol->primary_buffer_offset)); - if (ret < 0) { - printk("%s: ERROR creating chwallpolicy buffer.\n", __func__); - read_unlock(&acm_bin_pol_rwlock); - return -1; - } + if (ret < 0) + goto error_free_unlock; + bin_pol->len = htonl(ntohl(bin_pol->len) + ret); bin_pol->secondary_buffer_offset = htonl(ntohl(bin_pol->len)); ret = acm_secondary_ops->dump_binary_policy(policy_buffer + ntohl(bin_pol->secondary_buffer_offset), buf_size - ntohl(bin_pol->secondary_buffer_offset)); - if (ret < 0) { - printk("%s: ERROR creating chwallpolicy buffer.\n", __func__); - read_unlock(&acm_bin_pol_rwlock); - return -1; - } + if (ret < 0) + goto error_free_unlock; + bin_pol->len = htonl(ntohl(bin_pol->len) + ret); - read_unlock(&acm_bin_pol_rwlock); if (copy_to_user(buf, policy_buffer, ntohl(bin_pol->len))) - return -EFAULT; + goto error_free_unlock; + + read_unlock(&acm_bin_pol_rwlock); xfree(policy_buffer); return ACM_OK; + + error_free_unlock: + read_unlock(&acm_bin_pol_rwlock); + printk("%s: Error getting policy.\n", __func__); + xfree(policy_buffer); + return -EFAULT; } int @@ -185,4 +193,62 @@ return -EFAULT; } + +int +acm_get_ssid(ssidref_t ssidref, u8 *buf, u16 buf_size) +{ + /* send stats to user space */ + u8 *ssid_buffer; + int ret; + struct acm_ssid_buffer *acm_ssid; + if (buf_size < sizeof(struct acm_ssid_buffer)) + return -EFAULT; + + if ((ssid_buffer = xmalloc_array(u8, buf_size)) == NULL) + return -ENOMEM; + + read_lock(&acm_bin_pol_rwlock); + + acm_ssid = (struct acm_ssid_buffer *)ssid_buffer; + acm_ssid->len = sizeof(struct acm_ssid_buffer); + acm_ssid->ssidref = ssidref; + acm_ssid->primary_policy_code = acm_bin_pol.primary_policy_code; + acm_ssid->secondary_policy_code = acm_bin_pol.secondary_policy_code; + acm_ssid->primary_types_offset = acm_ssid->len; + + /* ret >= 0 --> ret == max_types */ + ret = acm_primary_ops->dump_ssid_types(ACM_PRIMARY(ssidref), + ssid_buffer + acm_ssid->primary_types_offset, + buf_size - acm_ssid->primary_types_offset); + if (ret < 0) + goto error_free_unlock; + + acm_ssid->len += ret; + acm_ssid->primary_max_types = ret; + + acm_ssid->secondary_types_offset = acm_ssid->len; + + ret = acm_secondary_ops->dump_ssid_types(ACM_SECONDARY(ssidref), + ssid_buffer + acm_ssid->secondary_types_offset, + buf_size - acm_ssid->secondary_types_offset); + if (ret < 0) + goto error_free_unlock; + + acm_ssid->len += ret; + acm_ssid->secondary_max_types = ret; + + if (copy_to_user(buf, ssid_buffer, acm_ssid->len)) + goto error_free_unlock; + + read_unlock(&acm_bin_pol_rwlock); + xfree(ssid_buffer); + return ACM_OK; + + error_free_unlock: + read_unlock(&acm_bin_pol_rwlock); + printk("%s: Error getting ssid.\n", __func__); + xfree(ssid_buffer); + return -ENOMEM; +} + /*eof*/ diff -r edd1616cf8cb -r 291e816acbf4 xen/acm/acm_simple_type_enforcement_hooks.c --- a/xen/acm/acm_simple_type_enforcement_hooks.c Fri Sep 2 14:15:49 2005 +++ b/xen/acm/acm_simple_type_enforcement_hooks.c Fri Sep 2 14:17:08 2005 @@ -383,6 +383,27 @@ return sizeof(struct acm_ste_stats_buffer); } +static int +ste_dump_ssid_types(ssidref_t ssidref, u8 *buf, u16 len) +{ + int i; + + /* fill in buffer */ + if (ste_bin_pol.max_types > len) + return -EFAULT; + + if (ssidref >= ste_bin_pol.max_ssidrefs) + return -EFAULT; + + /* read types for chwall ssidref */ + for(i=0; i< ste_bin_pol.max_types; i++) { + if (ste_bin_pol.ssidrefs[ssidref * ste_bin_pol.max_types + i]) + buf[i] = 1; + else + buf[i] = 0; + } + return ste_bin_pol.max_types; +} /* we need to go through this before calling the hooks, * returns 1 == cache hit */ @@ -625,22 +646,23 @@ /* policy management services */ .init_domain_ssid = ste_init_domain_ssid, .free_domain_ssid = ste_free_domain_ssid, - .dump_binary_policy = ste_dump_policy, - .set_binary_policy = ste_set_policy, + .dump_binary_policy = ste_dump_policy, + .set_binary_policy = ste_set_policy, .dump_statistics = ste_dump_stats, + .dump_ssid_types = ste_dump_ssid_types, /* domain management control hooks */ .pre_domain_create = ste_pre_domain_create, - .post_domain_create = NULL, - .fail_domain_create = NULL, - .post_domain_destroy = ste_post_domain_destroy, + .post_domain_create = NULL, + .fail_domain_create = NULL, + .post_domain_destroy = ste_post_domain_destroy, /* event channel control hooks */ - .pre_eventchannel_unbound = ste_pre_eventchannel_unbound, + .pre_eventchannel_unbound = ste_pre_eventchannel_unbound, .fail_eventchannel_unbound = NULL, .pre_eventchannel_interdomain = ste_pre_eventchannel_interdomain, .fail_eventchannel_interdomain = NULL, /* grant table control hooks */ - .pre_grant_map_ref = ste_pre_grant_map_ref, - .fail_grant_map_ref = NULL, - .pre_grant_setup = ste_pre_grant_setup, - .fail_grant_setup = NULL, + .pre_grant_map_ref = ste_pre_grant_map_ref, + .fail_grant_map_ref = NULL, + .pre_grant_setup = ste_pre_grant_setup, + .fail_grant_setup = NULL, }; diff -r edd1616cf8cb -r 291e816acbf4 xen/arch/x86/Makefile --- a/xen/arch/x86/Makefile Fri Sep 2 14:15:49 2005 +++ b/xen/arch/x86/Makefile Fri Sep 2 14:17:08 2005 @@ -17,7 +17,7 @@ OBJS := $(patsubst shadow%.o,,$(OBJS)) # drop all ifeq ($(TARGET_SUBARCH),x86_64) - OBJS += shadow.o shadow_public.o # x86_64: new code + OBJS += shadow.o shadow_public.o shadow_guest32.o # x86_64: new code endif ifeq ($(TARGET_SUBARCH),x86_32) ifneq ($(pae),n) diff -r edd1616cf8cb -r 291e816acbf4 xen/arch/x86/Rules.mk --- a/xen/arch/x86/Rules.mk Fri Sep 2 14:15:49 2005 +++ b/xen/arch/x86/Rules.mk Fri Sep 2 14:17:08 2005 @@ -13,10 +13,8 @@ CFLAGS += -I$(BASEDIR)/include/asm-x86/mach-generic CFLAGS += -I$(BASEDIR)/include/asm-x86/mach-default -ifeq ($(optimize),y) +ifneq ($(debug),y) CFLAGS += -O3 -fomit-frame-pointer -else -x86_32/usercopy.o: CFLAGS += -O1 endif # Prevent floating-point variables from creeping into Xen. diff -r edd1616cf8cb -r 291e816acbf4 xen/arch/x86/boot/x86_32.S --- a/xen/arch/x86/boot/x86_32.S Fri Sep 2 14:15:49 2005 +++ b/xen/arch/x86/boot/x86_32.S Fri Sep 2 14:17:08 2005 @@ -9,6 +9,8 @@ .text ENTRY(start) +ENTRY(stext) +ENTRY(_stext) jmp __start .align 4 @@ -260,6 +262,3 @@ .org 0x2000 + STACK_SIZE + PAGE_SIZE #endif /* CONFIG_X86_PAE */ - -ENTRY(stext) -ENTRY(_stext) diff -r edd1616cf8cb -r 291e816acbf4 xen/arch/x86/boot/x86_64.S --- a/xen/arch/x86/boot/x86_64.S Fri Sep 2 14:15:49 2005 +++ b/xen/arch/x86/boot/x86_64.S Fri Sep 2 14:17:08 2005 @@ -10,6 +10,8 @@ .code32 ENTRY(start) +ENTRY(stext) +ENTRY(_stext) jmp __start .org 0x004 @@ -267,5 +269,3 @@ .org 0x4000 + STACK_SIZE + PAGE_SIZE .code64 -ENTRY(stext) -ENTRY(_stext) diff -r edd1616cf8cb -r 291e816acbf4 xen/arch/x86/shadow.c --- a/xen/arch/x86/shadow.c Fri Sep 2 14:15:49 2005 +++ b/xen/arch/x86/shadow.c Fri Sep 2 14:17:08 2005 @@ -53,6 +53,9 @@ struct domain *d, unsigned long gpfn, unsigned long gmfn); static void shadow_map_into_current(struct vcpu *v, unsigned long va, unsigned int from, unsigned int to); +static inline void validate_bl2e_change( struct domain *d, + guest_root_pgentry_t *new_gle_p, pgentry_64_t *shadow_l3, int index); + #endif /******** @@ -217,10 +220,38 @@ } else { - page = alloc_domheap_page(NULL); - void *l1 = map_domain_page(page_to_pfn(page)); - memset(l1, 0, PAGE_SIZE); - unmap_domain_page(l1); + if (d->arch.ops->guest_paging_levels == PAGING_L2) + { +#if CONFIG_PAGING_LEVELS >= 4 + /* For 32-bit VMX guest, 2 shadow L1s to simulate 1 guest L1 + * So need allocate 2 continues shadow L1 each time. + */ + page = alloc_domheap_pages(NULL, SL1_ORDER, 0); + if (!page) + domain_crash_synchronous(); + + void *l1_0 = map_domain_page(page_to_pfn(page)); + memset(l1_0,0,PAGE_SIZE); + unmap_domain_page(l1_0); + void *l1_1 = map_domain_page(page_to_pfn(page+1)); + memset(l1_1,0,PAGE_SIZE); + unmap_domain_page(l1_1); +#else + page = alloc_domheap_page(NULL); + if (!page) + domain_crash_synchronous(); + void *l1 = map_domain_page(page_to_pfn(page)); + memset(l1, 0, PAGE_SIZE); + unmap_domain_page(l1); +#endif + } + else + { + page = alloc_domheap_page(NULL); + void *l1 = map_domain_page(page_to_pfn(page)); + memset(l1, 0, PAGE_SIZE); + unmap_domain_page(l1); + } } } else { @@ -331,7 +362,21 @@ fail: FSH_LOG("promotion of pfn=%lx mfn=%lx failed! external gnttab refs?", gpfn, gmfn); - free_domheap_page(page); + if (psh_type == PGT_l1_shadow) + { + if (d->arch.ops->guest_paging_levels == PAGING_L2) + { +#if CONFIG_PAGING_LEVELS >=4 + free_domheap_pages(page, SL1_ORDER); +#else + free_domheap_page(page); +#endif + } + else + free_domheap_page(page); + } + else + free_domheap_page(page); return 0; } @@ -478,8 +523,10 @@ { struct vcpu *v = current; struct domain *d = v->domain; - l1_pgentry_t *gpl1e, *spl1e; - l2_pgentry_t gl2e, sl2e; + l1_pgentry_t *spl1e; + l2_pgentry_t sl2e; + guest_l1_pgentry_t *gpl1e; + guest_l2_pgentry_t gl2e; unsigned long gl1pfn, gl1mfn, sl1mfn; int i, init_table = 0; @@ -523,28 +570,49 @@ ASSERT( !(l2e_get_flags(old_sl2e) & _PAGE_PRESENT) ); #endif - if ( !get_shadow_ref(sl1mfn) ) - BUG(); - l2pde_general(d, &gl2e, &sl2e, sl1mfn); - __guest_set_l2e(v, va, &gl2e); - __shadow_set_l2e(v, va, &sl2e); +#if CONFIG_PAGING_LEVELS >=4 + if (d->arch.ops->guest_paging_levels == PAGING_L2) + { + /* for 32-bit VMX guest on 64-bit host, + * need update two L2 entries each time + */ + if ( !get_shadow_ref(sl1mfn)) + BUG(); + l2pde_general(d, &gl2e, &sl2e, sl1mfn); + __guest_set_l2e(v, va, &gl2e); + __shadow_set_l2e(v, va & ~((1<<L2_PAGETABLE_SHIFT_32) - 1), &sl2e); + if ( !get_shadow_ref(sl1mfn+1)) + BUG(); + sl2e = l2e_empty(); + l2pde_general(d, &gl2e, &sl2e, sl1mfn+1); + __shadow_set_l2e(v,((va & ~((1<<L2_PAGETABLE_SHIFT_32) - 1)) + (1 << L2_PAGETABLE_SHIFT)) , &sl2e); + } else +#endif + { + if ( !get_shadow_ref(sl1mfn) ) + BUG(); + l2pde_general(d, &gl2e, &sl2e, sl1mfn); + __guest_set_l2e(v, va, &gl2e); + __shadow_set_l2e(v, va , &sl2e); + } if ( init_table ) { l1_pgentry_t sl1e; - int index = l1_table_offset(va); + int index = guest_l1_table_offset(va); int min = 1, max = 0; unsigned long entries, pt_va; l1_pgentry_t tmp_sl1e; - l1_pgentry_t tmp_gl1e;//Prepare for double compile - - - entries = PAGE_SIZE / sizeof(l1_pgentry_t); + guest_l1_pgentry_t tmp_gl1e;//Prepare for double compile + + + entries = PAGE_SIZE / sizeof(guest_l1_pgentry_t); pt_va = ((va >> L1_PAGETABLE_SHIFT) & ~(entries - 1)) << L1_PAGETABLE_SHIFT; - gpl1e = (l1_pgentry_t *) __guest_get_l1e(v, pt_va, &tmp_gl1e); - - entries = PAGE_SIZE / sizeof(l1_pgentry_t); + gpl1e = (guest_l1_pgentry_t *) __guest_get_l1e(v, pt_va, &tmp_gl1e); + + /* If the PGT_l1_shadow has two continual pages */ + entries = PAGE_SIZE / sizeof(guest_l1_pgentry_t); //1024 entry!!! pt_va = ((va >> L1_PAGETABLE_SHIFT) & ~(entries - 1)) << L1_PAGETABLE_SHIFT; spl1e = (l1_pgentry_t *) __shadow_get_l1e(v, pt_va, &tmp_sl1e); @@ -555,7 +623,7 @@ spl1e = &(shadow_linear_pg_table[l1_linear_offset(va) & ~(L1_PAGETABLE_ENTRIES-1)]);*/ - for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ ) + for ( i = 0; i < GUEST_L1_PAGETABLE_ENTRIES; i++ ) { l1pte_propagate_from_guest(d, gpl1e[i], &sl1e); if ( (l1e_get_flags(sl1e) & _PAGE_PRESENT) && @@ -584,7 +652,7 @@ } } -static void +static void shadow_set_l1e(unsigned long va, l1_pgentry_t new_spte, int create_l1_shadow) { struct vcpu *v = current; @@ -616,7 +684,7 @@ perfc_incrc(shadow_set_l1e_unlinked); if ( !get_shadow_ref(sl1mfn) ) BUG(); - l2pde_general(d, &gpde, &sl2e, sl1mfn); + l2pde_general(d, (guest_l2_pgentry_t *)&gpde, &sl2e, sl1mfn); __guest_set_l2e(v, va, &gpde); __shadow_set_l2e(v, va, &sl2e); } @@ -651,6 +719,7 @@ shadow_update_min_max(l2e_get_pfn(sl2e), l1_table_offset(va)); } +#if CONFIG_PAGING_LEVELS <= 3 static void shadow_invlpg_32(struct vcpu *v, unsigned long va) { struct domain *d = v->domain; @@ -679,6 +748,7 @@ shadow_unlock(d); } +#endif static struct out_of_sync_entry * shadow_alloc_oos_entry(struct domain *d) @@ -759,8 +829,8 @@ length = max - min + 1; perfc_incr_histo(snapshot_copies, length, PT_UPDATES); - min *= sizeof(l1_pgentry_t); - length *= sizeof(l1_pgentry_t); + min *= sizeof(guest_l1_pgentry_t); + length *= sizeof(guest_l1_pgentry_t); original = map_domain_page(gmfn); snapshot = map_domain_page(smfn); @@ -841,7 +911,7 @@ __shadow_get_l4e(v, va, &sl4e); if ( !(l4e_get_flags(sl4e) & _PAGE_PRESENT)) { - shadow_map_into_current(v, va, L3, L4); + shadow_map_into_current(v, va, PAGING_L3, PAGING_L4); } if (!__shadow_get_l3e(v, va, &sl3e)) { @@ -849,7 +919,7 @@ } if ( !(l3e_get_flags(sl3e) & _PAGE_PRESENT)) { - shadow_map_into_current(v, va, L2, L3); + shadow_map_into_current(v, va, PAGING_L2, PAGING_L3); } } #endif @@ -887,11 +957,11 @@ * Returns 0 otherwise. */ static int snapshot_entry_matches( - struct domain *d, l1_pgentry_t *guest_pt, + struct domain *d, guest_l1_pgentry_t *guest_pt, unsigned long gpfn, unsigned index) { unsigned long smfn = __shadow_status(d, gpfn, PGT_snapshot); - l1_pgentry_t *snapshot, gpte; // could be L1s or L2s or ... + guest_l1_pgentry_t *snapshot, gpte; // could be L1s or L2s or ... int entries_match; perfc_incrc(snapshot_entry_matches_calls); @@ -908,7 +978,7 @@ // This could probably be smarter, but this is sufficent for // our current needs. // - entries_match = !l1e_has_changed(gpte, snapshot[index], + entries_match = !guest_l1e_has_changed(gpte, snapshot[index], PAGE_FLAG_MASK); unmap_domain_page(snapshot); @@ -936,10 +1006,10 @@ unsigned long l2mfn = pagetable_get_pfn(v->arch.guest_table); #endif unsigned long l2pfn = __mfn_to_gpfn(d, l2mfn); - l2_pgentry_t l2e; + guest_l2_pgentry_t l2e; unsigned long l1pfn, l1mfn; - l1_pgentry_t *guest_pt; - l1_pgentry_t tmp_gle; + guest_l1_pgentry_t *guest_pt; + guest_l1_pgentry_t tmp_gle; unsigned long pt_va; ASSERT(shadow_lock_is_acquired(d)); @@ -948,7 +1018,7 @@ perfc_incrc(shadow_out_of_sync_calls); #if CONFIG_PAGING_LEVELS >= 4 - if (d->arch.ops->guest_paging_levels == L4) { /* Mode F */ + if (d->arch.ops->guest_paging_levels == PAGING_L4) { /* Mode F */ pgentry_64_t le; unsigned long gmfn; unsigned long gpfn; @@ -956,9 +1026,9 @@ gmfn = l2mfn; gpfn = l2pfn; - guest_pt = (l1_pgentry_t *)v->arch.guest_vtable; - - for (i = L4; i >= L3; i--) { + guest_pt = (guest_l1_pgentry_t *)v->arch.guest_vtable; + + for (i = PAGING_L4; i >= PAGING_L3; i--) { if ( page_out_of_sync(&frame_table[gmfn]) && !snapshot_entry_matches( d, guest_pt, gpfn, table_offset_64(va, i)) ) @@ -972,7 +1042,7 @@ if ( !VALID_MFN(gmfn) ) return 0; /* Todo: check!*/ - guest_pt = (l1_pgentry_t *)map_domain_page(gmfn); + guest_pt = (guest_l1_pgentry_t *)map_domain_page(gmfn); } @@ -986,13 +1056,13 @@ #endif if ( page_out_of_sync(&frame_table[l2mfn]) && - !snapshot_entry_matches(d, (l1_pgentry_t *)v->arch.guest_vtable, - l2pfn, l2_table_offset(va)) ) + !snapshot_entry_matches(d, (guest_l1_pgentry_t *)v->arch.guest_vtable, + l2pfn, guest_l2_table_offset(va)) ) return 1; __guest_get_l2e(v, va, &l2e); - if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) || - (l2e_get_flags(l2e) & _PAGE_PSE)) + if ( !(guest_l2e_get_flags(l2e) & _PAGE_PRESENT) || + (guest_l2e_get_flags(l2e) & _PAGE_PSE)) return 0; l1pfn = l2e_get_pfn(l2e); @@ -1001,20 +1071,20 @@ // If the l1 pfn is invalid, it can't be out of sync... if ( !VALID_MFN(l1mfn) ) return 0; - - pt_va = ((va >> L1_PAGETABLE_SHIFT) & ~(L1_PAGETABLE_ENTRIES - 1)) + + pt_va = ((va >> L1_PAGETABLE_SHIFT) & ~(GUEST_L1_PAGETABLE_ENTRIES - 1)) << L1_PAGETABLE_SHIFT; - guest_pt = (l1_pgentry_t *) __guest_get_l1e(v, pt_va, &tmp_gle); + guest_pt = (guest_l1_pgentry_t *) __guest_get_l1e(v, pt_va, &tmp_gle); if ( page_out_of_sync(&frame_table[l1mfn]) && !snapshot_entry_matches( - d, guest_pt, l1pfn, l1_table_offset(va)) ) + d, guest_pt, l1pfn, guest_l1_table_offset(va)) ) return 1; return 0; } -#define GPFN_TO_GPTEPAGE(_gpfn) ((_gpfn) / (PAGE_SIZE / sizeof(l1_pgentry_t))) +#define GPFN_TO_GPTEPAGE(_gpfn) ((_gpfn) / (PAGE_SIZE / sizeof(guest_l1_pgentry_t))) static inline unsigned long predict_writable_pte_page(struct domain *d, unsigned long gpfn) { @@ -1108,7 +1178,7 @@ return (found == max_refs_to_find); } - i = readonly_gpfn & (L1_PAGETABLE_ENTRIES - 1); + i = readonly_gpfn & (GUEST_L1_PAGETABLE_ENTRIES - 1); if ( !l1e_has_changed(pt[i], match, flags) && fix_entry(i) ) { perfc_incrc(remove_write_fast_exit); @@ -1117,7 +1187,7 @@ return found; } - for (i = 0; i < L1_PAGETABLE_ENTRIES; i++) + for (i = 0; i < GUEST_L1_PAGETABLE_ENTRIES; i++) { if ( unlikely(!l1e_has_changed(pt[i], match, flags)) && fix_entry(i) ) break; @@ -1282,15 +1352,15 @@ switch ( stype ) { case PGT_l1_shadow: { - l1_pgentry_t *guest1 = guest; + guest_l1_pgentry_t *guest1 = guest; l1_pgentry_t *shadow1 = shadow; - l1_pgentry_t *snapshot1 = snapshot; + guest_l1_pgentry_t *snapshot1 = snapshot; ASSERT(VM_ASSIST(d, VMASST_TYPE_writable_pagetables) || shadow_mode_write_all(d)); if ( !shadow_mode_refcounts(d) ) - revalidate_l1(d, guest1, snapshot1); + revalidate_l1(d, (l1_pgentry_t *)guest1, (l1_pgentry_t *)snapshot1); if ( !smfn ) break; @@ -1301,7 +1371,7 @@ for ( i = min_shadow; i <= max_shadow; i++ ) { if ( (i < min_snapshot) || (i > max_snapshot) || - l1e_has_changed(guest1[i], snapshot1[i], PAGE_FLAG_MASK) ) + guest_l1e_has_changed(guest1[i], snapshot1[i], PAGE_FLAG_MASK) ) { need_flush |= validate_pte_change(d, guest1[i], &shadow1[i]); @@ -1431,32 +1501,36 @@ { int max = -1; - l4_pgentry_t *guest4 = guest; + guest_root_pgentry_t *guest_root = guest; l4_pgentry_t *shadow4 = shadow; - l4_pgentry_t *snapshot4 = snapshot; + guest_root_pgentry_t *snapshot_root = snapshot; changed = 0; - for ( i = 0; i < L4_PAGETABLE_ENTRIES; i++ ) + for ( i = 0; i < GUEST_ROOT_PAGETABLE_ENTRIES; i++ ) { if ( !is_guest_l4_slot(i) && !external ) continue; - l4_pgentry_t new_l4e = guest4[i]; - if ( l4e_has_changed(new_l4e, snapshot4[i], PAGE_FLAG_MASK)) + guest_root_pgentry_t new_root_e = guest_root[i]; + if ( root_entry_has_changed( + new_root_e, snapshot_root[i], PAGE_FLAG_MASK)) { - need_flush |= validate_entry_change( - d, (pgentry_64_t *)&new_l4e, - (pgentry_64_t *)&shadow4[i], shadow_type_to_level(stype)); - + if (d->arch.ops->guest_paging_levels == PAGING_L4) { + need_flush |= validate_entry_change( + d, (pgentry_64_t *)&new_root_e, + (pgentry_64_t *)&shadow4[i], shadow_type_to_level(stype)); + } else { + validate_bl2e_change(d, &new_root_e, shadow, i); + } changed++; ESH_LOG("%d: shadow4 mfn: %lx, shadow root: %lx\n", i, smfn, pagetable_get_paddr(current->arch.shadow_table)); } - if ( l4e_get_intpte(new_l4e) != 0 ) /* FIXME: check flags? */ + if ( guest_root_get_intpte(new_root_e) != 0 ) /* FIXME: check flags? */ max = i; // Need a better solution in the long term. - if ( !(l4e_get_flags(new_l4e) & _PAGE_PRESENT) && - unlikely(l4e_get_intpte(new_l4e) != 0) && + if ( !(guest_root_get_flags(new_root_e) & _PAGE_PRESENT) && + unlikely(guest_root_get_intpte(new_root_e) != 0) && !unshadow && (frame_table[smfn].u.inuse.type_info & PGT_pinned) ) unshadow = 1; @@ -1555,8 +1629,14 @@ if ( shadow_mode_translate(d) ) need_flush |= resync_all(d, PGT_hl2_shadow); #endif - need_flush |= resync_all(d, PGT_l2_shadow); - need_flush |= resync_all(d, PGT_l3_shadow); + + /* + * Fixme: for i386 host + */ + if (d->arch.ops->guest_paging_levels == PAGING_L4) { + need_flush |= resync_all(d, PGT_l2_shadow); + need_flush |= resync_all(d, PGT_l3_shadow); + } need_flush |= resync_all(d, PGT_l4_shadow); if ( need_flush && !unlikely(shadow_mode_external(d)) ) @@ -1566,11 +1646,11 @@ } static inline int l1pte_write_fault( - struct vcpu *v, l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p, + struct vcpu *v, guest_l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p, unsigned long va) { struct domain *d = v->domain; - l1_pgentry_t gpte = *gpte_p; + guest_l1_pgentry_t gpte = *gpte_p; l1_pgentry_t spte; unsigned long gpfn = l1e_get_pfn(gpte); unsigned long gmfn = __gpfn_to_mfn(d, gpfn); @@ -1585,8 +1665,8 @@ } ASSERT(l1e_get_flags(gpte) & _PAGE_RW); - l1e_add_flags(gpte, _PAGE_DIRTY | _PAGE_ACCESSED); - spte = l1e_from_pfn(gmfn, l1e_get_flags(gpte) & ~_PAGE_GLOBAL); + guest_l1e_add_flags(gpte, _PAGE_DIRTY | _PAGE_ACCESSED); + spte = l1e_from_pfn(gmfn, guest_l1e_get_flags(gpte) & ~_PAGE_GLOBAL); SH_VVLOG("l1pte_write_fault: updating spte=0x%" PRIpte " gpte=0x%" PRIpte, l1e_get_intpte(spte), l1e_get_intpte(gpte)); @@ -1604,9 +1684,9 @@ } static inline int l1pte_read_fault( - struct domain *d, l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p) + struct domain *d, guest_l1_pgentry_t *gpte_p, l1_pgentry_t *spte_p) { - l1_pgentry_t gpte = *gpte_p; + guest_l1_pgentry_t gpte = *gpte_p; l1_pgentry_t spte = *spte_p; unsigned long pfn = l1e_get_pfn(gpte); unsigned long mfn = __gpfn_to_mfn(d, pfn); @@ -1618,10 +1698,10 @@ return 0; } - l1e_add_flags(gpte, _PAGE_ACCESSED); - spte = l1e_from_pfn(mfn, l1e_get_flags(gpte) & ~_PAGE_GLOBAL); - - if ( shadow_mode_log_dirty(d) || !(l1e_get_flags(gpte) & _PAGE_DIRTY) || + guest_l1e_add_flags(gpte, _PAGE_ACCESSED); + spte = l1e_from_pfn(mfn, guest_l1e_get_flags(gpte) & ~_PAGE_GLOBAL); + + if ( shadow_mode_log_dirty(d) || !(guest_l1e_get_flags(gpte) & _PAGE_DIRTY) || mfn_is_page_table(mfn) ) { l1e_remove_flags(spte, _PAGE_RW); @@ -1634,7 +1714,7 @@ return 1; } - +#if CONFIG_PAGING_LEVELS <= 3 static int shadow_fault_32(unsigned long va, struct cpu_user_regs *regs) { l1_pgentry_t gpte, spte, orig_gpte; @@ -1768,6 +1848,7 @@ shadow_unlock(d); return 0; } +#endif static int do_update_va_mapping(unsigned long va, l1_pgentry_t val, @@ -1787,7 +1868,7 @@ // __shadow_sync_va(v, va); - l1pte_propagate_from_guest(d, val, &spte); + l1pte_propagate_from_guest(d, *(guest_l1_pgentry_t *)&val, &spte); shadow_set_l1e(va, spte, 0); /* @@ -1848,7 +1929,7 @@ #if CONFIG_PAGING_LEVELS == 2 unsigned long hl2mfn; #endif - + int max_mode = ( shadow_mode_external(d) ? SHM_external : shadow_mode_translate(d) ? SHM_translate : shadow_mode_enabled(d) ? SHM_enable @@ -1954,17 +2035,6 @@ #endif } -struct shadow_ops MODE_A_HANDLER = { - .guest_paging_levels = 2, - .invlpg = shadow_invlpg_32, - .fault = shadow_fault_32, - .update_pagetables = shadow_update_pagetables, - .sync_all = sync_all, - .remove_all_write_access = remove_all_write_access, - .do_update_va_mapping = do_update_va_mapping, - .mark_mfn_out_of_sync = mark_mfn_out_of_sync, - .is_out_of_sync = is_out_of_sync, -}; /************************************************************************/ /************************************************************************/ @@ -2445,12 +2515,90 @@ BUG(); /* not implemenated yet */ return 42; } +static unsigned long gva_to_gpa_pae(unsigned long gva) +{ + BUG(); + return 43; +} #endif #if CONFIG_PAGING_LEVELS >= 4 /****************************************************************************/ /* 64-bit shadow-mode code testing */ /****************************************************************************/ +/* + * validate_bl2e_change() + * The code is for 32-bit VMX gues on 64-bit host. + * To sync guest L2. + */ + +static inline void +validate_bl2e_change( + struct domain *d, + guest_root_pgentry_t *new_gle_p, + pgentry_64_t *shadow_l3, + int index) +{ + int sl3_idx, sl2_idx; + unsigned long sl2mfn, sl1mfn; + pgentry_64_t *sl2_p; + + /* Using guest l2 pte index to get shadow l3&l2 index + * index: 0 ~ 1023, PAGETABLE_ENTRIES: 512 + */ + sl3_idx = index / (PAGETABLE_ENTRIES / 2); + sl2_idx = (index % (PAGETABLE_ENTRIES / 2)) * 2; + + sl2mfn = entry_get_pfn(shadow_l3[sl3_idx]); + sl2_p = (pgentry_64_t *)map_domain_page(sl2mfn); + + validate_pde_change( + d, *(guest_l2_pgentry_t *)new_gle_p, (l2_pgentry_t *)&sl2_p[sl2_idx]); + + /* Mapping the second l1 shadow page */ + if (entry_get_flags(sl2_p[sl2_idx]) & _PAGE_PRESENT) { + sl1mfn = entry_get_pfn(sl2_p[sl2_idx]); + sl2_p[sl2_idx + 1] = + entry_from_pfn(sl1mfn + 1, entry_get_flags(sl2_p[sl2_idx])); + } + unmap_domain_page(sl2_p); + +} + +/* + * init_bl2() is for 32-bit VMX guest on 64-bit host + * Using 1 shadow L4(l3) and 4 shadow L2s to simulate guest L2 + */ +static inline unsigned long init_bl2(l4_pgentry_t *spl4e, unsigned long smfn) +{ + unsigned int count; + unsigned long sl2mfn; + struct pfn_info *page; + + memset(spl4e, 0, PAGE_SIZE); + + /* Map the self entry, L4&L3 share the same page */ + spl4e[PAE_SHADOW_SELF_ENTRY] = l4e_from_pfn(smfn, __PAGE_HYPERVISOR); + + /* Allocate 4 shadow L2s */ + page = alloc_domheap_pages(NULL, SL2_ORDER, 0); + if (!page) + domain_crash_synchronous(); + + for (count = 0; count < PDP_ENTRIES; count++) + { + sl2mfn = page_to_pfn(page+count); + void *l2 = map_domain_page(sl2mfn); + memset(l2, 0, PAGE_SIZE); + unmap_domain_page(l2); + spl4e[count] = l4e_from_pfn(sl2mfn, _PAGE_PRESENT); + } + + unmap_domain_page(spl4e); + return smfn; + + +} static unsigned long shadow_l4_table( struct domain *d, unsigned long gpfn, unsigned long gmfn) @@ -2464,11 +2612,16 @@ if ( unlikely(!(smfn = alloc_shadow_page(d, gpfn, gmfn, PGT_l4_shadow))) ) { - printk("Couldn't alloc an L2 shadow for pfn=%lx mfn=%lx\n", gpfn, gmfn); + printk("Couldn't alloc an L4 shadow for pfn=%lx mfn=%lx\n", gpfn, gmfn); BUG(); /* XXX Deal gracefully with failure. */ } spl4e = (l4_pgentry_t *)map_domain_page(smfn); + + if (d->arch.ops->guest_paging_levels == PAGING_L2) { + return init_bl2(spl4e, smfn); + } + /* Install hypervisor and 4x linear p.t. mapings. */ if ( (PGT_base_page_table == PGT_l4_page_table) && !shadow_mode_external(d) ) @@ -2576,7 +2729,7 @@ pgentry_64_t gle, sle; unsigned long gpfn, smfn; - if (from == L1 && to == L2) { + if (from == PAGING_L1 && to == PAGING_L2) { shadow_map_l1_into_current_l2(va); return; } @@ -2608,7 +2761,7 @@ if (!(l4e_get_flags(sl4e) & _PAGE_PRESENT)) { if (create_l2_shadow) { perfc_incrc(shadow_set_l3e_force_map); - shadow_map_into_current(v, va, L3, L4); + shadow_map_into_current(v, va, PAGING_L3, PAGING_L4); __shadow_get_l4e(v, va, &sl4e); } else { printk("For non VMX shadow, create_l1_shadow:%d\n", create_l2_shadow); @@ -2619,7 +2772,7 @@ if (!(l3e_get_flags(sl3e) & _PAGE_PRESENT)) { if (create_l2_shadow) { perfc_incrc(shadow_set_l2e_force_map); - shadow_map_into_current(v, va, L2, L3); + shadow_map_into_current(v, va, PAGING_L2, PAGING_L3); __shadow_get_l3e(v, va, &sl3e); } else { printk("For non VMX shadow, create_l1_shadow:%d\n", create_l2_shadow); @@ -2655,8 +2808,15 @@ l1_pgentry_t old_spte; l1_pgentry_t sl1e = *(l1_pgentry_t *)sl1e_p; int i; - - for (i = L4; i >= L2; i--) { + unsigned long orig_va = 0; + + if (d->arch.ops->guest_paging_levels == PAGING_L2) { + /* This is for 32-bit VMX guest on 64-bit host */ + orig_va = va; + va = va & (~((1<<L2_PAGETABLE_SHIFT_32)-1)); + } + + for (i = PAGING_L4; i >= PAGING_L2; i--) { if (!__rw_entry(v, va, &sle, SHADOW_ENTRY | GET_ENTRY | i)) { printk("<%s> i = %d\n", __func__, i); BUG(); @@ -2672,9 +2832,13 @@ #endif } } - if(i < L4) + if(i < PAGING_L4) shadow_update_min_max(entry_get_pfn(sle_up), table_offset_64(va, i)); sle_up = sle; + } + + if (d->arch.ops->guest_paging_levels == PAGING_L2) { + va = orig_va; } if ( shadow_mode_refcounts(d) ) @@ -2692,9 +2856,13 @@ } __shadow_set_l1e(v, va, &sl1e); - shadow_update_min_max(entry_get_pfn(sle_up), table_offset_64(va, L1)); -} - + + shadow_update_min_max(entry_get_pfn(sle_up), guest_l1_table_offset(va)); +} + +/* As 32-bit guest don't support 4M page yet, + * we don't concern double compile for this function + */ static inline int l2e_rw_fault( struct vcpu *v, l2_pgentry_t *gl2e_p, unsigned long va, int rw) { @@ -2825,12 +2993,120 @@ } +/* + * Check P, R/W, U/S bits in the guest page table. + * If the fault belongs to guest return 1, + * else return 0. + */ +#if defined( GUEST_PGENTRY_32 ) +static inline int guest_page_fault(struct vcpu *v, + unsigned long va, unsigned int error_code, + guest_l2_pgentry_t *gpl2e, guest_l1_pgentry_t *gpl1e) +{ + /* The following check for 32-bit guest on 64-bit host */ + + __guest_get_l2e(v, va, gpl2e); + + /* Check the guest L2 page-table entry first*/ + if (unlikely(!(guest_l2e_get_flags(*gpl2e) & _PAGE_PRESENT))) + return 1; + + if (error_code & ERROR_W) { + if (unlikely(!(guest_l2e_get_flags(*gpl2e) & _PAGE_RW))) + return 1; + } + if (error_code & ERROR_U) { + if (unlikely(!(guest_l2e_get_flags(*gpl2e) & _PAGE_USER))) + return 1; + } + + if (guest_l2e_get_flags(*gpl2e) & _PAGE_PSE) + return 0; + + __guest_get_l1e(v, va, gpl1e); + + /* Then check the guest L1 page-table entry */ + if (unlikely(!(guest_l1e_get_flags(*gpl1e) & _PAGE_PRESENT))) + return 1; + + if (error_code & ERROR_W) { + if (unlikely(!(guest_l1e_get_flags(*gpl1e) & _PAGE_RW))) + return 1; + } + if (error_code & ERROR_U) { + if (unlikely(!(guest_l1e_get_flags(*gpl1e) & _PAGE_USER))) + return 1; + } + + return 0; +} +#else +static inline int guest_page_fault(struct vcpu *v, + unsigned long va, unsigned int error_code, + guest_l2_pgentry_t *gpl2e, guest_l1_pgentry_t *gpl1e) +{ + struct domain *d = v->domain; + pgentry_64_t gle, *lva; + unsigned long mfn; + int i; + + __rw_entry(v, va, &gle, GUEST_ENTRY | GET_ENTRY | PAGING_L4); + if (unlikely(!(entry_get_flags(gle) & _PAGE_PRESENT))) + return 1; + + if (error_code & ERROR_W) { + if (unlikely(!(entry_get_flags(gle) & _PAGE_RW))) + return 1; + } + if (error_code & ERROR_U) { + if (unlikely(!(entry_get_flags(gle) & _PAGE_USER))) + return 1; + } + for (i = PAGING_L3; i >= PAGING_L1; i--) { + /* + * If it's not external mode, then mfn should be machine physical. + */ + mfn = __gpfn_to_mfn(d, (entry_get_value(gle) >> PAGE_SHIFT)); + + lva = (pgentry_64_t *) phys_to_virt( + mfn << PAGE_SHIFT); + gle = lva[table_offset_64(va, i)]; + + if (unlikely(!(entry_get_flags(gle) & _PAGE_PRESENT))) + return 1; + + if (error_code & ERROR_W) { + if (unlikely(!(entry_get_flags(gle) & _PAGE_RW))) + return 1; + } + if (error_code & ERROR_U) { + if (unlikely(!(entry_get_flags(gle) & _PAGE_USER))) + return 1; + } + + if (i == PAGING_L2) { + if (gpl2e) + gpl2e->l2 = gle.lo; + + if (likely(entry_get_flags(gle) & _PAGE_PSE)) + return 0; + + } + + if (i == PAGING_L1) + if (gpl1e) + gpl1e->l1 = gle.lo; + } + return 0; +} +#endif static int shadow_fault_64(unsigned long va, struct cpu_user_regs *regs) { struct vcpu *v = current; struct domain *d = v->domain; - l2_pgentry_t gl2e; - l1_pgentry_t sl1e, gl1e; + guest_l2_pgentry_t gl2e; + guest_l1_pgentry_t gl1e; + l1_pgentry_t sl1e; perfc_incrc(shadow_fault_calls); @@ -2853,12 +3129,11 @@ * STEP 2. Check if the fault belongs to guest */ if ( guest_page_fault( - v, va, regs->error_code, - (pgentry_64_t *)&gl2e, (pgentry_64_t *)&gl1e) ) { + v, va, regs->error_code, &gl2e, &gl1e) ) { goto fail; } - if ( unlikely(!(l2e_get_flags(gl2e) & _PAGE_PSE)) ) { + if ( unlikely(!(guest_l2e_get_flags(gl2e) & _PAGE_PSE)) ) { /* * Handle 4K pages here */ @@ -2892,11 +3167,11 @@ */ /* Write fault? */ if ( regs->error_code & 2 ) { - if ( !l2e_rw_fault(v, &gl2e, va, WRITE_FAULT) ) { + if ( !l2e_rw_fault(v, (l2_pgentry_t *)&gl2e, va, WRITE_FAULT) ) { goto fail; } } else { - l2e_rw_fault(v, &gl2e, va, READ_FAULT); + l2e_rw_fault(v, (l2_pgentry_t *)&gl2e, va, READ_FAULT); } /* @@ -2944,7 +3219,27 @@ shadow_unlock(d); } -#ifndef PGENTRY_32 +static unsigned long gva_to_gpa_64(unsigned long gva) +{ + struct vcpu *v = current; + guest_l1_pgentry_t gl1e = {0}; + guest_l2_pgentry_t gl2e = {0}; + unsigned long gpa; + + if (guest_page_fault(v, gva, 0, &gl2e, &gl1e)) + return 0; + + if (guest_l2e_get_flags(gl2e) & _PAGE_PSE) + gpa = guest_l2e_get_paddr(gl2e) + (gva & ((1 << GUEST_L2_PAGETABLE_SHIFT) - 1)); + else + gpa = guest_l1e_get_paddr(gl1e) + (gva & ~PAGE_MASK); + + return gpa; + +} + +#ifndef GUEST_PGENTRY_32 + struct shadow_ops MODE_F_HANDLER = { .guest_paging_levels = 4, .invlpg = shadow_invlpg_64, @@ -2955,10 +3250,42 @@ .do_update_va_mapping = do_update_va_mapping, .mark_mfn_out_of_sync = mark_mfn_out_of_sync, .is_out_of_sync = is_out_of_sync, + .gva_to_gpa = gva_to_gpa_64, }; #endif #endif + +#if CONFIG_PAGING_LEVELS == 2 +struct shadow_ops MODE_A_HANDLER = { + .guest_paging_levels = 2, + .invlpg = shadow_invlpg_32, + .fault = shadow_fault_32, + .update_pagetables = shadow_update_pagetables, + .sync_all = sync_all, + .remove_all_write_access = remove_all_write_access, + .do_update_va_mapping = do_update_va_mapping, + .mark_mfn_out_of_sync = mark_mfn_out_of_sync, + .is_out_of_sync = is_out_of_sync, + .gva_to_gpa = gva_to_gpa_64, +}; + +#elif CONFIG_PAGING_LEVELS == 3 +struct shadow_ops MODE_B_HANDLER = { + .guest_paging_levels = 3, + .invlpg = shadow_invlpg_32, + .fault = shadow_fault_32, + .update_pagetables = shadow_update_pagetables, + .sync_all = sync_all, + .remove_all_write_access = remove_all_write_access, + .do_update_va_mapping = do_update_va_mapping, + .mark_mfn_out_of_sync = mark_mfn_out_of_sync, + .is_out_of_sync = is_out_of_sync, + .gva_to_gpa = gva_to_gpa_pae, +}; + +#endif + /* * Local variables: diff -r edd1616cf8cb -r 291e816acbf4 xen/arch/x86/shadow_public.c --- a/xen/arch/x86/shadow_public.c Fri Sep 2 14:15:49 2005 +++ b/xen/arch/x86/shadow_public.c Fri Sep 2 14:17:08 2005 @@ -33,11 +33,15 @@ #if CONFIG_PAGING_LEVELS >= 3 #include <asm/shadow_64.h> +#endif +#if CONFIG_PAGING_LEVELS == 4 extern struct shadow_ops MODE_F_HANDLER; +extern struct shadow_ops MODE_D_HANDLER; #endif extern struct shadow_ops MODE_A_HANDLER; +#define SHADOW_MAX_GUEST32(_encoded) ((L1_PAGETABLE_ENTRIES_32 - 1) - ((_encoded) >> 16)) /****************************************************************************/ /************* export interface functions ***********************************/ /****************************************************************************/ @@ -48,7 +52,7 @@ shadow_lock(d); switch(levels) { -#if CONFIG_PAGING_LEVELS >= 4 +#if CONFIG_PAGING_LEVELS >= 4 case 4: if ( d->arch.ops != &MODE_F_HANDLER ) d->arch.ops = &MODE_F_HANDLER; @@ -56,9 +60,14 @@ return 1; #endif case 3: - case 2: + case 2: +#if CONFIG_PAGING_LEVELS == 2 if ( d->arch.ops != &MODE_A_HANDLER ) d->arch.ops = &MODE_A_HANDLER; +#elif CONFIG_PAGING_LEVELS == 4 + if ( d->arch.ops != &MODE_D_HANDLER ) + d->arch.ops = &MODE_D_HANDLER; +#endif shadow_unlock(d); return 1; default: @@ -122,13 +131,17 @@ return d->arch.ops->is_out_of_sync(v, va); } +unsigned long gva_to_gpa(unsigned long gva) +{ + struct domain *d = current->domain; + return d->arch.ops->gva_to_gpa(gva); +} /****************************************************************************/ /****************************************************************************/ #if CONFIG_PAGING_LEVELS >= 4 /* * Convert PAE 3-level page-table to 4-level page-table */ -#define PDP_ENTRIES 4 static pagetable_t page_table_convert(struct domain *d) { struct pfn_info *l4page, *l3page; @@ -203,19 +216,41 @@ /* * Free l2, l3, l4 shadow tables */ + +void free_fake_shadow_l2(struct domain *d,unsigned long smfn); + static void inline free_shadow_tables(struct domain *d, unsigned long smfn, u32 level) { pgentry_64_t *ple = map_domain_page(smfn); int i, external = shadow_mode_external(d); - - for ( i = 0; i < PAGETABLE_ENTRIES; i++ ) - if ( external || is_guest_l4_slot(i) ) - if ( entry_get_flags(ple[i]) & _PAGE_PRESENT ) - put_shadow_ref(entry_get_pfn(ple[i])); - - unmap_domain_page(ple); -} + struct pfn_info *page = &frame_table[smfn]; + + if (d->arch.ops->guest_paging_levels == PAGING_L2) + { +#if CONFIG_PAGING_LEVELS >=4 + for ( i = 0; i < PDP_ENTRIES; i++ ) + { + if (entry_get_flags(ple[i]) & _PAGE_PRESENT ) + free_fake_shadow_l2(d,entry_get_pfn(ple[i])); + } + + page = &frame_table[entry_get_pfn(ple[0])]; + free_domheap_pages(page, SL2_ORDER); + unmap_domain_page(ple); +#endif + } + else + { + for ( i = 0; i < PAGETABLE_ENTRIES; i++ ) + if ( external || is_guest_l4_slot(i) ) + if ( entry_get_flags(ple[i]) & _PAGE_PRESENT ) + put_shadow_ref(entry_get_pfn(ple[i])); + + unmap_domain_page(ple); + } +} + void free_monitor_pagetable(struct vcpu *v) { @@ -453,7 +488,12 @@ struct pfn_info *spage = pfn_to_page(smfn); u32 min_max = spage->tlbflush_timestamp; int min = SHADOW_MIN(min_max); - int max = SHADOW_MAX(min_max); + int max; + + if (d->arch.ops->guest_paging_levels == PAGING_L2) + max = SHADOW_MAX_GUEST32(min_max); + else + max = SHADOW_MAX(min_max); for ( i = min; i <= max; i++ ) { @@ -512,9 +552,24 @@ unmap_domain_page(pl2e); } +void free_fake_shadow_l2(struct domain *d, unsigned long smfn) +{ + pgentry_64_t *ple = map_domain_page(smfn); + int i; + + for ( i = 0; i < PAGETABLE_ENTRIES; i = i + 2 ) + { + if ( entry_get_flags(ple[i]) & _PAGE_PRESENT ) + put_shadow_ref(entry_get_pfn(ple[i])); + } + + unmap_domain_page(ple); +} + void free_shadow_page(unsigned long smfn) { struct pfn_info *page = &frame_table[smfn]; + unsigned long gmfn = page->u.inuse.type_info & PGT_mfn_mask; struct domain *d = page_get_owner(pfn_to_page(gmfn)); unsigned long gpfn = __mfn_to_gpfn(d, gmfn); @@ -531,6 +586,7 @@ gpfn |= (1UL << 63); } #endif + delete_shadow_status(d, gpfn, gmfn, type); switch ( type ) @@ -687,7 +743,7 @@ int i; struct shadow_status *x; struct vcpu *v; - + /* * WARNING! The shadow page table must not currently be in use! * e.g., You are expected to have paused the domain and synchronized CR3. @@ -794,7 +850,16 @@ perfc_decr(free_l1_pages); struct pfn_info *page = list_entry(list_ent, struct pfn_info, list); - free_domheap_page(page); + if (d->arch.ops->guest_paging_levels == PAGING_L2) + { +#if CONFIG_PAGING_LEVELS >=4 + free_domheap_pages(page, SL1_ORDER); +#else + free_domheap_page(page); +#endif + } + else + free_domheap_page(page); } shadow_audit(d, 0); @@ -1191,7 +1256,7 @@ { DPRINTK("Don't try to do a shadow op on yourself!\n"); return -EINVAL; - } + } domain_pause(d); diff -r edd1616cf8cb -r 291e816acbf4 xen/arch/x86/traps.c --- a/xen/arch/x86/traps.c Fri Sep 2 14:15:49 2005 +++ b/xen/arch/x86/traps.c Fri Sep 2 14:17:08 2005 @@ -100,7 +100,14 @@ static int debug_stack_lines = 20; integer_param("debug_stack_lines", debug_stack_lines); -#define stack_words_per_line (32 / BYTES_PER_LONG) + +#ifdef CONFIG_X86_32 +#define stack_words_per_line 8 +#define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)®s->esp) +#else +#define stack_words_per_line 4 +#define ESP_BEFORE_EXCEPTION(regs) ((unsigned long *)regs->esp) +#endif int is_kernel_text(unsigned long addr) { @@ -118,17 +125,16 @@ return (unsigned long) &_etext; } -void show_guest_stack(void) +static void show_guest_stack(struct cpu_user_regs *regs) { int i; - struct cpu_user_regs *regs = guest_cpu_user_regs(); unsigned long *stack = (unsigned long *)regs->esp, addr; printk("Guest stack trace from "__OP"sp=%p:\n ", stack); for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ ) { - if ( ((long)stack & (STACK_SIZE-1)) == 0 ) + if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 ) break; if ( get_user(addr, stack) ) { @@ -148,38 +154,98 @@ printk("\n"); } -void show_trace(unsigned long *esp) -{ - unsigned long *stack = esp, addr; - int i = 0; - - printk("Xen call trace from "__OP"sp=%p:\n ", stack); - - while ( ((long) stack & (STACK_SIZE-1)) != 0 ) +#ifdef NDEBUG + +static void show_trace(struct cpu_user_regs *regs) +{ + unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr; + + printk("Xen call trace:\n "); + + printk("[<%p>]", _p(regs->eip)); + print_symbol(" %s\n ", regs->eip); + + while ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) != 0 ) { addr = *stack++; if ( is_kernel_text(addr) ) { printk("[<%p>]", _p(addr)); print_symbol(" %s\n ", addr); - i++; - } - } - if ( i == 0 ) - printk("Trace empty."); + } + } + printk("\n"); } -void show_stack(unsigned long *esp) -{ - unsigned long *stack = esp, addr; +#else + +static void show_trace(struct cpu_user_regs *regs) +{ + unsigned long *frame, next, addr, low, high; + + printk("Xen call trace:\n "); + + printk("[<%p>]", _p(regs->eip)); + print_symbol(" %s\n ", regs->eip); + + /* Bounds for range of valid frame pointer. */ + low = (unsigned long)(ESP_BEFORE_EXCEPTION(regs) - 2); + high = (low & ~(STACK_SIZE - 1)) + (STACK_SIZE - sizeof(struct cpu_info)); + + /* The initial frame pointer. */ + next = regs->ebp; + + for ( ; ; ) + { + /* Valid frame pointer? */ + if ( (next < low) || (next > high) ) + { + /* + * Exception stack frames have a different layout, denoted by an + * inverted frame pointer. + */ + next = ~next; + if ( (next < low) || (next > high) ) + break; + frame = (unsigned long *)next; + next = frame[0]; + addr = frame[(offsetof(struct cpu_user_regs, eip) - + offsetof(struct cpu_user_regs, ebp)) + / BYTES_PER_LONG]; + } + else + { + /* Ordinary stack frame. */ + frame = (unsigned long *)next; + next = frame[0]; + addr = frame[1]; + } + + printk("[<%p>]", _p(addr)); + print_symbol(" %s\n ", addr); + + low = (unsigned long)&frame[2]; + } + + printk("\n"); +} + +#endif + +void show_stack(struct cpu_user_regs *regs) +{ + unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr; int i; + if ( GUEST_MODE(regs) ) + return show_guest_stack(regs); + printk("Xen stack trace from "__OP"sp=%p:\n ", stack); for ( i = 0; i < (debug_stack_lines*stack_words_per_line); i++ ) { - if ( ((long)stack & (STACK_SIZE-1)) == 0 ) + if ( ((long)stack & (STACK_SIZE-BYTES_PER_LONG)) == 0 ) break; if ( (i != 0) && ((i % stack_words_per_line) == 0) ) printk("\n "); @@ -190,7 +256,7 @@ printk("Stack empty."); printk("\n"); - show_trace(esp); + show_trace(regs); } /* diff -r edd1616cf8cb -r 291e816acbf4 xen/arch/x86/vmx.c --- a/xen/arch/x86/vmx.c Fri Sep 2 14:15:49 2005 +++ b/xen/arch/x86/vmx.c Fri Sep 2 14:17:08 2005 @@ -412,7 +412,7 @@ if ( !result ) { __vmread(GUEST_RIP, &eip); - printk("vmx pgfault to guest va=%p eip=%p\n", va, eip); + printk("vmx pgfault to guest va=%lx eip=%lx\n", va, eip); } #endif @@ -456,7 +456,16 @@ clear_bit(X86_FEATURE_PSE, &edx); clear_bit(X86_FEATURE_PAE, &edx); clear_bit(X86_FEATURE_PSE36, &edx); +#else + struct vcpu *d = current; + if (d->domain->arch.ops->guest_paging_levels == PAGING_L2) + { + clear_bit(X86_FEATURE_PSE, &edx); + clear_bit(X86_FEATURE_PAE, &edx); + clear_bit(X86_FEATURE_PSE36, &edx); + } #endif + } regs->eax = (unsigned long) eax; @@ -650,7 +659,7 @@ p->df = (eflags & X86_EFLAGS_DF) ? 1 : 0; if (test_bit(5, &exit_qualification)) /* "rep" prefix */ - p->count = vm86 ? regs->ecx & 0xFFFF : regs->ecx; + p->count = vm86 ? regs->ecx & 0xFFFF : regs->ecx; /* * Split up string I/O operations that cross page boundaries. Don't @@ -1006,6 +1015,15 @@ #if CONFIG_PAGING_LEVELS >= 4 if(!shadow_set_guest_paging_levels(d->domain, 4)) { + printk("Unsupported guest paging levels\n"); + domain_crash_synchronous(); /* need to take a clean path */ + } +#endif + } + else + { +#if CONFIG_PAGING_LEVELS >= 4 + if(!shadow_set_guest_paging_levels(d->domain, 2)) { printk("Unsupported guest paging levels\n"); domain_crash_synchronous(); /* need to take a clean path */ } diff -r edd1616cf8cb -r 291e816acbf4 xen/arch/x86/x86_32/traps.c --- a/xen/arch/x86/x86_32/traps.c Fri Sep 2 14:15:49 2005 +++ b/xen/arch/x86/x86_32/traps.c Fri Sep 2 14:17:08 2005 @@ -79,11 +79,8 @@ "ss: %04lx cs: %04lx\n", ds, es, fs, gs, ss, cs); - if ( GUEST_MODE(regs) ) - show_guest_stack(); - else - show_stack((unsigned long *)®s->esp); -} + show_stack(regs); +} void show_page_walk(unsigned long addr) { diff -r edd1616cf8cb -r 291e816acbf4 xen/arch/x86/x86_64/traps.c --- a/xen/arch/x86/x86_64/traps.c Fri Sep 2 14:15:49 2005 +++ b/xen/arch/x86/x86_64/traps.c Fri Sep 2 14:17:08 2005 @@ -32,10 +32,7 @@ regs->r12, regs->r13, regs->r14); printk("r15: %016lx\n", regs->r15); - if ( GUEST_MODE(regs) ) - show_guest_stack(); - else - show_stack((unsigned long *)regs->rsp); + show_stack(regs); } void show_page_walk(unsigned long addr) diff -r edd1616cf8cb -r 291e816acbf4 xen/common/acm_ops.c --- a/xen/common/acm_ops.c Fri Sep 2 14:15:49 2005 +++ b/xen/common/acm_ops.c Fri Sep 2 14:17:08 2005 @@ -19,6 +19,7 @@ #include <xen/types.h> #include <xen/lib.h> #include <xen/mm.h> +#include <public/acm.h> #include <public/acm_ops.h> #include <xen/sched.h> #include <xen/event.h> @@ -41,7 +42,8 @@ POLICY, /* access to policy interface (early drop) */ GETPOLICY, /* dump policy cache */ SETPOLICY, /* set policy cache (controls security) */ - DUMPSTATS /* dump policy statistics */ + DUMPSTATS, /* dump policy statistics */ + GETSSID /* retrieve ssidref for domain id */ } acm_operation_t; int acm_authorize_acm_ops(struct domain *d, acm_operation_t pops) @@ -117,6 +119,35 @@ } break; + case ACM_GETSSID: + { + ssidref_t ssidref; + + if (acm_authorize_acm_ops(current->domain, GETSSID)) + return -EACCES; + + if (op->u.getssid.get_ssid_by == SSIDREF) + ssidref = op->u.getssid.id.ssidref; + else if (op->u.getssid.get_ssid_by == DOMAINID) { + struct domain *subj = find_domain_by_id(op->u.getssid.id.domainid); + if (!subj) + return -ESRCH; /* domain not found */ + + ssidref = ((struct acm_ssid_domain *)(subj->ssid))->ssidref; + put_domain(subj); + } else + return -ESRCH; + + ret = acm_get_ssid(ssidref, + op->u.getssid.ssidbuf, + op->u.getssid.ssidbuf_size); + if (ret == ACM_OK) + ret = 0; + else + ret = -ESRCH; + } + break; + default: ret = -ESRCH; diff -r edd1616cf8cb -r 291e816acbf4 xen/common/domain.c --- a/xen/common/domain.c Fri Sep 2 14:15:49 2005 +++ b/xen/common/domain.c Fri Sep 2 14:17:08 2005 @@ -178,6 +178,9 @@ struct domain *d = current->domain; struct vcpu *v; + if(reason == SHUTDOWN_crash) + printk("Domain %d crash detected.\n", d->domain_id); + if ( d->domain_id == 0 ) { extern void machine_restart(char *); diff -r edd1616cf8cb -r 291e816acbf4 xen/common/grant_table.c --- a/xen/common/grant_table.c Fri Sep 2 14:15:49 2005 +++ b/xen/common/grant_table.c Fri Sep 2 14:17:08 2005 @@ -887,21 +887,21 @@ e->tot_pages, e->max_pages); spin_unlock(&e->page_alloc_lock); put_domain(e); - result = GNTST_general_error; + gop->status = result = GNTST_general_error; break; } if (unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags))) { printk("gnttab_donate: target domain is dying\n"); spin_unlock(&e->page_alloc_lock); put_domain(e); - result = GNTST_general_error; + gop->status = result = GNTST_general_error; break; } if (unlikely(!gnttab_prepare_for_transfer(e, d, gop->handle))) { - printk("gnttab_donate: gnttab_prepare_for_transfer fails\n"); + printk("gnttab_donate: gnttab_prepare_for_transfer fails.\n"); spin_unlock(&e->page_alloc_lock); put_domain(e); - result = GNTST_general_error; + gop->status = result = GNTST_general_error; break; } #else @@ -914,7 +914,8 @@ e->tot_pages, e->max_pages, gop->handle, e->d_flags); spin_unlock(&e->page_alloc_lock); put_domain(e); - result = GNTST_general_error; + /* XXX SMH: better error return here would be useful */ + gop->status = result = GNTST_general_error; break; } #endif @@ -1020,7 +1021,7 @@ lgt = ld->grant_table; #if GRANT_DEBUG_VERBOSE - if ( ld->domain_ id != 0 ) { + if ( ld->domain_id != 0 ) { DPRINTK("Foreign unref rd(%d) ld(%d) frm(%lx) flgs(%x).\n", rd->domain_id, ld->domain_id, frame, readonly); } diff -r edd1616cf8cb -r 291e816acbf4 xen/include/acm/acm_core.h --- a/xen/include/acm/acm_core.h Fri Sep 2 14:15:49 2005 +++ b/xen/include/acm/acm_core.h Fri Sep 2 14:17:08 2005 @@ -101,9 +101,15 @@ * primary ssidref = lower 16 bit * secondary ssidref = higher 16 bit */ +#define ACM_PRIMARY(ssidref) \ + ((ssidref) & 0xffff) + +#define ACM_SECONDARY(ssidref) \ + ((ssidref) >> 16) + #define GET_SSIDREF(POLICY, ssidref) \ ((POLICY) == acm_bin_pol.primary_policy_code) ? \ - ((ssidref) & 0xffff) : ((ssidref) >> 16) + ACM_PRIMARY(ssidref) : ACM_SECONDARY(ssidref) /* macros to access ssid pointer for primary / secondary policy */ #define GET_SSIDP(POLICY, ssid) \ @@ -116,6 +122,7 @@ int acm_set_policy(void *buf, u16 buf_size, int isuserbuffer); int acm_get_policy(void *buf, u16 buf_size); int acm_dump_statistics(void *buf, u16 buf_size); +int acm_get_ssid(ssidref_t ssidref, u8 *buf, u16 buf_size); #endif diff -r edd1616cf8cb -r 291e816acbf4 xen/include/acm/acm_hooks.h --- a/xen/include/acm/acm_hooks.h Fri Sep 2 14:15:49 2005 +++ b/xen/include/acm/acm_hooks.h Fri Sep 2 14:17:08 2005 @@ -92,6 +92,7 @@ int (*dump_binary_policy) (u8 *buffer, u16 buf_size); int (*set_binary_policy) (u8 *buffer, u16 buf_size); int (*dump_statistics) (u8 *buffer, u16 buf_size); + int (*dump_ssid_types) (ssidref_t ssidref, u8 *buffer, u16 buf_size); /* domain management control hooks (can be NULL) */ int (*pre_domain_create) (void *subject_ssid, ssidref_t ssidref); void (*post_domain_create) (domid_t domid, ssidref_t ssidref); diff -r edd1616cf8cb -r 291e816acbf4 xen/include/asm-x86/page-guest32.h --- a/xen/include/asm-x86/page-guest32.h Fri Sep 2 14:15:49 2005 +++ b/xen/include/asm-x86/page-guest32.h Fri Sep 2 14:17:08 2005 @@ -32,6 +32,11 @@ /* Get pte access flags (unsigned int). */ #define l1e_get_flags_32(x) (get_pte_flags_32((x).l1)) #define l2e_get_flags_32(x) (get_pte_flags_32((x).l2)) + +#define l1e_get_paddr_32(x) \ + ((physaddr_t)(((x).l1 & (PADDR_MASK&PAGE_MASK)))) +#define l2e_get_paddr_32(x) \ + ((physaddr_t)(((x).l2 & (PADDR_MASK&PAGE_MASK)))) /* Construct an empty pte. */ #define l1e_empty_32() ((l1_pgentry_32_t) { 0 }) diff -r edd1616cf8cb -r 291e816acbf4 xen/include/asm-x86/processor.h --- a/xen/include/asm-x86/processor.h Fri Sep 2 14:15:49 2005 +++ b/xen/include/asm-x86/processor.h Fri Sep 2 14:17:08 2005 @@ -496,9 +496,7 @@ #endif -void show_guest_stack(); -void show_trace(unsigned long *esp); -void show_stack(unsigned long *esp); +void show_stack(struct cpu_user_regs *regs); void show_registers(struct cpu_user_regs *regs); void show_page_walk(unsigned long addr); asmlinkage void fatal_trap(int trapnr, struct cpu_user_regs *regs); diff -r edd1616cf8cb -r 291e816acbf4 xen/include/asm-x86/shadow.h --- a/xen/include/asm-x86/shadow.h Fri Sep 2 14:15:49 2005 +++ b/xen/include/asm-x86/shadow.h Fri Sep 2 14:17:08 2005 @@ -34,6 +34,8 @@ #include <asm/vmx.h> #include <public/dom0_ops.h> #include <asm/shadow_public.h> +#include <asm/page-guest32.h> +#include <asm/shadow_ops.h> /* Shadow PT operation mode : shadow-mode variable in arch_domain. */ @@ -104,9 +106,9 @@ } while (0) #endif -#define SHADOW_ENCODE_MIN_MAX(_min, _max) ((((L1_PAGETABLE_ENTRIES - 1) - (_max)) << 16) | (_min)) +#define SHADOW_ENCODE_MIN_MAX(_min, _max) ((((GUEST_L1_PAGETABLE_ENTRIES - 1) - (_max)) << 16) | (_min)) #define SHADOW_MIN(_encoded) ((_encoded) & ((1u<<16) - 1)) -#define SHADOW_MAX(_encoded) ((L1_PAGETABLE_ENTRIES - 1) - ((_encoded) >> 16)) +#define SHADOW_MAX(_encoded) ((GUEST_L1_PAGETABLE_ENTRIES - 1) - ((_encoded) >> 16)) extern void shadow_mode_init(void); extern int shadow_mode_control(struct domain *p, dom0_shadow_control_t *sc); @@ -132,6 +134,7 @@ struct domain_mmap_cache *cache); #if CONFIG_PAGING_LEVELS >= 3 #include <asm/page-guest32.h> +extern unsigned long gva_to_gpa(unsigned long gva); extern void shadow_l3_normal_pt_update(struct domain *d, unsigned long pa, l3_pgentry_t l3e, struct domain_mmap_cache *cache); @@ -794,22 +797,22 @@ #endif static inline void l1pte_propagate_from_guest( - struct domain *d, l1_pgentry_t gpte, l1_pgentry_t *spte_p) + struct domain *d, guest_l1_pgentry_t gpte, l1_pgentry_t *spte_p) { unsigned long mfn; l1_pgentry_t spte; spte = l1e_empty(); - if ( ((l1e_get_flags(gpte) & (_PAGE_PRESENT|_PAGE_ACCESSED) ) == + if ( ((guest_l1e_get_flags(gpte) & (_PAGE_PRESENT|_PAGE_ACCESSED) ) == (_PAGE_PRESENT|_PAGE_ACCESSED)) && VALID_MFN(mfn = __gpfn_to_mfn(d, l1e_get_pfn(gpte))) ) { spte = l1e_from_pfn( - mfn, l1e_get_flags(gpte) & ~(_PAGE_GLOBAL | _PAGE_AVAIL)); + mfn, guest_l1e_get_flags(gpte) & ~(_PAGE_GLOBAL | _PAGE_AVAIL)); if ( shadow_mode_log_dirty(d) || - !(l1e_get_flags(gpte) & _PAGE_DIRTY) || + !(guest_l1e_get_flags(gpte) & _PAGE_DIRTY) || mfn_is_page_table(mfn) ) { l1e_remove_flags(spte, _PAGE_RW); @@ -859,22 +862,22 @@ static inline void l2pde_general( struct domain *d, - l2_pgentry_t *gpde_p, + guest_l2_pgentry_t *gpde_p, l2_pgentry_t *spde_p, unsigned long sl1mfn) { - l2_pgentry_t gpde = *gpde_p; + guest_l2_pgentry_t gpde = *gpde_p; l2_pgentry_t spde; spde = l2e_empty(); - if ( (l2e_get_flags(gpde) & _PAGE_PRESENT) && (sl1mfn != 0) ) + if ( (guest_l2e_get_flags(gpde) & _PAGE_PRESENT) && (sl1mfn != 0) ) { spde = l2e_from_pfn( - sl1mfn, - (l2e_get_flags(gpde) | _PAGE_RW | _PAGE_ACCESSED) & ~_PAGE_AVAIL); + sl1mfn, + (guest_l2e_get_flags(gpde) | _PAGE_RW | _PAGE_ACCESSED) & ~_PAGE_AVAIL); /* N.B. PDEs do not have a dirty bit. */ - l2e_add_flags(gpde, _PAGE_ACCESSED); + guest_l2e_add_flags(gpde, _PAGE_ACCESSED); *gpde_p = gpde; } @@ -887,12 +890,12 @@ } static inline void l2pde_propagate_from_guest( - struct domain *d, l2_pgentry_t *gpde_p, l2_pgentry_t *spde_p) -{ - l2_pgentry_t gpde = *gpde_p; + struct domain *d, guest_l2_pgentry_t *gpde_p, l2_pgentry_t *spde_p) +{ + guest_l2_pgentry_t gpde = *gpde_p; unsigned long sl1mfn = 0; - if ( l2e_get_flags(gpde) & _PAGE_PRESENT ) + if ( guest_l2e_get_flags(gpde) & _PAGE_PRESENT ) sl1mfn = __shadow_status(d, l2e_get_pfn(gpde), PGT_l1_shadow); l2pde_general(d, gpde_p, spde_p, sl1mfn); } @@ -904,7 +907,7 @@ static int inline validate_pte_change( struct domain *d, - l1_pgentry_t new_pte, + guest_l1_pgentry_t new_pte, l1_pgentry_t *shadow_pte_p) { l1_pgentry_t old_spte, new_spte; @@ -1004,7 +1007,7 @@ static int inline validate_pde_change( struct domain *d, - l2_pgentry_t new_gpde, + guest_l2_pgentry_t new_gpde, l2_pgentry_t *shadow_pde_p) { l2_pgentry_t old_spde, new_spde; diff -r edd1616cf8cb -r 291e816acbf4 xen/include/asm-x86/shadow_64.h --- a/xen/include/asm-x86/shadow_64.h Fri Sep 2 14:15:49 2005 +++ b/xen/include/asm-x86/shadow_64.h Fri Sep 2 14:17:08 2005 @@ -27,6 +27,7 @@ #ifndef _XEN_SHADOW_64_H #define _XEN_SHADOW_64_H #include <asm/shadow.h> +#include <asm/shadow_ops.h> #define READ_FAULT 0 #define WRITE_FAULT 1 @@ -42,14 +43,14 @@ #define ESH_LOG(_f, _a...) ((void)0) #endif -#define L4 4UL -#define L3 3UL -#define L2 2UL -#define L1 1UL +#define PAGING_L4 4UL +#define PAGING_L3 3UL +#define PAGING_L2 2UL +#define PAGING_L1 1UL #define L_MASK 0xff -#define ROOT_LEVEL_64 L4 -#define ROOT_LEVEL_32 L2 +#define ROOT_LEVEL_64 PAGING_L4 +#define ROOT_LEVEL_32 PAGING_L2 #define SHADOW_ENTRY (2UL << 16) #define GUEST_ENTRY (1UL << 16) @@ -58,6 +59,10 @@ #define SET_ENTRY (1UL << 8) #define PAGETABLE_ENTRIES (1<<PAGETABLE_ORDER) + +/* For 32-bit VMX guest to allocate shadow L1 & L2*/ +#define SL1_ORDER 1 +#define SL2_ORDER 2 typedef struct { intpte_t lo; } pgentry_64_t; #define shadow_level_to_type(l) (l << 29) @@ -76,6 +81,10 @@ #define entry_remove_flags(x, flags) ((x).lo &= ~put_pte_flags(flags)) #define entry_has_changed(x,y,flags) \ ( !!(((x).lo ^ (y).lo) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags(flags))) ) + +#define PAE_SHADOW_SELF_ENTRY 259 +#define PDP_ENTRIES 4 + static inline int table_offset_64(unsigned long va, int level) { switch(level) { @@ -86,8 +95,13 @@ case 3: return (((va) >> L3_PAGETABLE_SHIFT) & (L3_PAGETABLE_ENTRIES - 1)); #if CONFIG_PAGING_LEVELS >= 4 +#ifndef GUEST_PGENTRY_32 case 4: return (((va) >> L4_PAGETABLE_SHIFT) & (L4_PAGETABLE_ENTRIES - 1)); +#else + case 4: + return PAE_SHADOW_SELF_ENTRY; +#endif #endif default: //printk("<table_offset_64> level %d is too big\n", level); @@ -165,30 +179,30 @@ return le_e; } #define __shadow_set_l4e(v, va, value) \ - __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | L4) + __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | PAGING_L4) #define __shadow_get_l4e(v, va, sl4e) \ - __rw_entry(v, va, sl4e, SHADOW_ENTRY | GET_ENTRY | L4) + __rw_entry(v, va, sl4e, SHADOW_ENTRY | GET_ENTRY | PAGING_L4) #define __shadow_set_l3e(v, va, value) \ - __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | L3) + __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | PAGING_L3) #define __shadow_get_l3e(v, va, sl3e) \ - __rw_entry(v, va, sl3e, SHADOW_ENTRY | GET_ENTRY | L3) + __rw_entry(v, va, sl3e, SHADOW_ENTRY | GET_ENTRY | PAGING_L3) #define __shadow_set_l2e(v, va, value) \ - __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | L2) + __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | PAGING_L2) #define __shadow_get_l2e(v, va, sl2e) \ - __rw_entry(v, va, sl2e, SHADOW_ENTRY | GET_ENTRY | L2) + __rw_entry(v, va, sl2e, SHADOW_ENTRY | GET_ENTRY | PAGING_L2) #define __shadow_set_l1e(v, va, value) \ - __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | L1) + __rw_entry(v, va, value, SHADOW_ENTRY | SET_ENTRY | PAGING_L1) #define __shadow_get_l1e(v, va, sl1e) \ - __rw_entry(v, va, sl1e, SHADOW_ENTRY | GET_ENTRY | L1) + __rw_entry(v, va, sl1e, SHADOW_ENTRY | GET_ENTRY | PAGING_L1) #define __guest_set_l4e(v, va, value) \ - __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | L4) + __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | PAGING_L4) #define __guest_get_l4e(v, va, gl4e) \ - __rw_entry(v, va, gl4e, GUEST_ENTRY | GET_ENTRY | L4) + __rw_entry(v, va, gl4e, GUEST_ENTRY | GET_ENTRY | PAGING_L4) #define __guest_set_l3e(v, va, value) \ - __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | L3) + __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | PAGING_L3) #define __guest_get_l3e(v, va, sl3e) \ - __rw_entry(v, va, gl3e, GUEST_ENTRY | GET_ENTRY | L3) + __rw_entry(v, va, gl3e, GUEST_ENTRY | GET_ENTRY | PAGING_L3) static inline void * __guest_set_l2e( struct vcpu *v, u64 va, void *value, int size) @@ -205,7 +219,7 @@ return &l2va[l2_table_offset_32(va)]; } case 8: - return __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | L2); + return __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | PAGING_L2); default: BUG(); return NULL; @@ -230,7 +244,7 @@ return &l2va[l2_table_offset_32(va)]; } case 8: - return __rw_entry(v, va, gl2e, GUEST_ENTRY | GET_ENTRY | L2); + return __rw_entry(v, va, gl2e, GUEST_ENTRY | GET_ENTRY | PAGING_L2); default: BUG(); return NULL; @@ -269,7 +283,7 @@ } case 8: - return __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | L1); + return __rw_entry(v, va, value, GUEST_ENTRY | SET_ENTRY | PAGING_L1); default: BUG(); return NULL; @@ -310,7 +324,7 @@ } case 8: // 64-bit guest - return __rw_entry(v, va, gl1e, GUEST_ENTRY | GET_ENTRY | L1); + return __rw_entry(v, va, gl1e, GUEST_ENTRY | GET_ENTRY | PAGING_L1); default: BUG(); return NULL; @@ -334,7 +348,7 @@ sle = entry_empty(); if ( (entry_get_flags(gle) & _PAGE_PRESENT) && (smfn != 0) ) { - if ((entry_get_flags(gle) & _PAGE_PSE) && level == L2) { + if ((entry_get_flags(gle) & _PAGE_PSE) && level == PAGING_L2) { sle = entry_from_pfn(smfn, entry_get_flags(gle)); entry_remove_flags(sle, _PAGE_PSE); @@ -376,7 +390,7 @@ unsigned long smfn = 0; if ( entry_get_flags(gle) & _PAGE_PRESENT ) { - if ((entry_get_flags(gle) & _PAGE_PSE) && level == L2) { + if ((entry_get_flags(gle) & _PAGE_PSE) && level == PAGING_L2) { smfn = __shadow_status(d, entry_get_value(gle) >> PAGE_SHIFT, PGT_fl1_shadow); } else { smfn = __shadow_status(d, entry_get_pfn(gle), @@ -421,88 +435,6 @@ return 1; } -/* - * Check P, R/W, U/S bits in the guest page table. - * If the fault belongs to guest return 1, - * else return 0. - */ -static inline int guest_page_fault(struct vcpu *v, - unsigned long va, unsigned int error_code, pgentry_64_t *gpl2e, pgentry_64_t *gpl1e) -{ - struct domain *d = v->domain; - pgentry_64_t gle, *lva; - unsigned long mfn; - int i; - - __rw_entry(v, va, &gle, GUEST_ENTRY | GET_ENTRY | L4); - if (unlikely(!(entry_get_flags(gle) & _PAGE_PRESENT))) - return 1; - - if (error_code & ERROR_W) { - if (unlikely(!(entry_get_flags(gle) & _PAGE_RW))) - return 1; - } - if (error_code & ERROR_U) { - if (unlikely(!(entry_get_flags(gle) & _PAGE_USER))) - return 1; - } - for (i = L3; i >= L1; i--) { - /* - * If it's not external mode, then mfn should be machine physical. - */ - mfn = __gpfn_to_mfn(d, (entry_get_paddr(gle) >> PAGE_SHIFT)); - if (mfn == -1) - return 1; - - lva = (pgentry_64_t *) phys_to_virt( - mfn << PAGE_SHIFT); - gle = lva[table_offset_64(va, i)]; - - if (unlikely(!(entry_get_flags(gle) & _PAGE_PRESENT))) - return 1; - - if (error_code & ERROR_W) { - if (unlikely(!(entry_get_flags(gle) & _PAGE_RW))) - return 1; - } - if (error_code & ERROR_U) { - if (unlikely(!(entry_get_flags(gle) & _PAGE_USER))) - return 1; - } - - if (i == L2) { - if (gpl2e) - *gpl2e = gle; - - if (likely(entry_get_flags(gle) & _PAGE_PSE)) - return 0; - - } - - if (i == L1) - if (gpl1e) - *gpl1e = gle; - } - return 0; -} - -static inline unsigned long gva_to_gpa(unsigned long gva) -{ - struct vcpu *v = current; - pgentry_64_t gl1e = {0}; - pgentry_64_t gl2e = {0}; - unsigned long gpa; - - if (guest_page_fault(v, gva, 0, &gl2e, &gl1e)) - return 0; - if (entry_get_flags(gl2e) & _PAGE_PSE) - gpa = entry_get_paddr(gl2e) + (gva & ((1 << L2_PAGETABLE_SHIFT) - 1)); - else - gpa = entry_get_paddr(gl1e) + (gva & ~PAGE_MASK); - - return gpa; - -} #endif diff -r edd1616cf8cb -r 291e816acbf4 xen/include/asm-x86/shadow_public.h --- a/xen/include/asm-x86/shadow_public.h Fri Sep 2 14:15:49 2005 +++ b/xen/include/asm-x86/shadow_public.h Fri Sep 2 14:17:08 2005 @@ -49,6 +49,7 @@ (*mark_mfn_out_of_sync)(struct vcpu *v, unsigned long gpfn, unsigned long mfn); int (*is_out_of_sync)(struct vcpu *v, unsigned long va); + unsigned long (*gva_to_gpa)(unsigned long gva); }; #endif diff -r edd1616cf8cb -r 291e816acbf4 xen/include/asm-x86/x86_32/asm_defns.h --- a/xen/include/asm-x86/x86_32/asm_defns.h Fri Sep 2 14:15:49 2005 +++ b/xen/include/asm-x86/x86_32/asm_defns.h Fri Sep 2 14:17:08 2005 @@ -1,10 +1,20 @@ #ifndef __X86_32_ASM_DEFNS_H__ #define __X86_32_ASM_DEFNS_H__ + +#ifndef NDEBUG +/* Indicate special exception stack frame by inverting the frame pointer. */ +#define SETUP_EXCEPTION_FRAME_POINTER \ + movl %esp,%ebp; \ + notl %ebp +#else +#define SETUP_EXCEPTION_FRAME_POINTER +#endif #define __SAVE_ALL_PRE \ cld; \ pushl %eax; \ pushl %ebp; \ + SETUP_EXCEPTION_FRAME_POINTER; \ pushl %edi; \ pushl %esi; \ pushl %edx; \ diff -r edd1616cf8cb -r 291e816acbf4 xen/include/asm-x86/x86_64/asm_defns.h --- a/xen/include/asm-x86/x86_64/asm_defns.h Fri Sep 2 14:15:49 2005 +++ b/xen/include/asm-x86/x86_64/asm_defns.h Fri Sep 2 14:17:08 2005 @@ -1,5 +1,14 @@ #ifndef __X86_64_ASM_DEFNS_H__ #define __X86_64_ASM_DEFNS_H__ + +#ifndef NDEBUG +/* Indicate special exception stack frame by inverting the frame pointer. */ +#define SETUP_EXCEPTION_FRAME_POINTER \ + movq %rsp,%rbp; \ + notq %rbp +#else +#define SETUP_EXCEPTION_FRAME_POINTER +#endif #define SAVE_ALL \ cld; \ @@ -14,6 +23,7 @@ pushq %r11; \ pushq %rbx; \ pushq %rbp; \ + SETUP_EXCEPTION_FRAME_POINTER; \ pushq %r12; \ pushq %r13; \ pushq %r14; \ diff -r edd1616cf8cb -r 291e816acbf4 xen/include/public/acm.h --- a/xen/include/public/acm.h Fri Sep 2 14:15:49 2005 +++ b/xen/include/public/acm.h Fri Sep 2 14:17:08 2005 @@ -56,20 +56,22 @@ #define ACM_ACCESS_DENIED -111 #define ACM_NULL_POINTER_ERROR -200 -#define ACM_MAX_POLICY 3 - +/* primary policy in lower 4 bits */ #define ACM_NULL_POLICY 0 #define ACM_CHINESE_WALL_POLICY 1 #define ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY 2 -#define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY 3 + +/* combinations have secondary policy component in higher 4bit */ +#define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY \ + ((ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY << 4) | ACM_CHINESE_WALL_POLICY) /* policy: */ #define ACM_POLICY_NAME(X) \ - (X == ACM_NULL_POLICY) ? "NULL policy" : \ - (X == ACM_CHINESE_WALL_POLICY) ? "CHINESE WALL policy" : \ - (X == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "SIMPLE TYPE ENFORCEMENT policy" : \ - (X == ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY) ? "CHINESE WALL AND SIMPLE TYPE ENFORCEMENT policy" : \ - "UNDEFINED policy" + ((X) == (ACM_NULL_POLICY)) ? "NULL policy" : \ + ((X) == (ACM_CHINESE_WALL_POLICY)) ? "CHINESE WALL policy" : \ + ((X) == (ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)) ? "SIMPLE TYPE ENFORCEMENT policy" : \ + ((X) == (ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY)) ? "CHINESE WALL AND SIMPLE TYPE ENFORCEMENT policy" : \ + "UNDEFINED policy" /* the following policy versions must be increased * whenever the interpretation of the related @@ -122,7 +124,7 @@ */ struct acm_policy_buffer { u32 policy_version; /* ACM_POLICY_VERSION */ - u32 magic; + u32 magic; u32 len; u32 primary_policy_code; u32 primary_buffer_offset; @@ -151,7 +153,7 @@ }; struct acm_stats_buffer { - u32 magic; + u32 magic; u32 len; u32 primary_policy_code; u32 primary_stats_offset; @@ -168,5 +170,15 @@ u32 gt_cachehit_count; }; +struct acm_ssid_buffer { + u32 len; + ssidref_t ssidref; + u32 primary_policy_code; + u32 primary_max_types; + u32 primary_types_offset; + u32 secondary_policy_code; + u32 secondary_max_types; + u32 secondary_types_offset; +}; #endif diff -r edd1616cf8cb -r 291e816acbf4 xen/include/public/acm_ops.h --- a/xen/include/public/acm_ops.h Fri Sep 2 14:15:49 2005 +++ b/xen/include/public/acm_ops.h Fri Sep 2 14:17:08 2005 @@ -1,3 +1,4 @@ + /****************************************************************************** * acm_ops.h * @@ -27,7 +28,7 @@ * This makes sure that old versions of acm tools will stop working in a * well-defined way (rather than crashing the machine, for instance). */ -#define ACM_INTERFACE_VERSION 0xAAAA0003 +#define ACM_INTERFACE_VERSION 0xAAAA0004 /************************************************************************/ @@ -46,12 +47,25 @@ u16 pullcache_size; } acm_getpolicy_t; + #define ACM_DUMPSTATS 6 typedef struct acm_dumpstats { void *pullcache; u16 pullcache_size; } acm_dumpstats_t; + +#define ACM_GETSSID 7 +enum get_type {UNSET, SSIDREF, DOMAINID}; +typedef struct acm_getssid { + enum get_type get_ssid_by; + union { + domaintype_t domainid; + ssidref_t ssidref; + } id; + void *ssidbuf; + u16 ssidbuf_size; +} acm_getssid_t; typedef struct acm_op { u32 cmd; @@ -60,6 +74,7 @@ acm_setpolicy_t setpolicy; acm_getpolicy_t getpolicy; acm_dumpstats_t dumpstats; + acm_getssid_t getssid; } u; } acm_op_t; diff -r edd1616cf8cb -r 291e816acbf4 xen/include/public/io/netif.h --- a/xen/include/public/io/netif.h Fri Sep 2 14:15:49 2005 +++ b/xen/include/public/io/netif.h Fri Sep 2 14:17:08 2005 @@ -23,13 +23,13 @@ typedef struct { u16 id; /* Echoed in response message. */ -#ifdef CONFIG_XEN_NETDEV_GRANT_RX +#ifdef CONFIG_XEN_NETDEV_GRANT grant_ref_t gref; /* 2: Reference to incoming granted frame */ #endif } netif_rx_request_t; typedef struct { -#ifdef CONFIG_XEN_NETDEV_GRANT_TX +#ifdef CONFIG_XEN_NETDEV_GRANT u32 addr; /* 0: Offset in page of start of received packet */ #else unsigned long addr; /* Machine address of packet. */ diff -r edd1616cf8cb -r 291e816acbf4 extras/mini-os/domain_config --- /dev/null Fri Sep 2 14:15:49 2005 +++ b/extras/mini-os/domain_config Fri Sep 2 14:17:08 2005 @@ -0,0 +1,17 @@ +# -*- mode: python; -*- +#============================================================================ +# Python configuration setup for 'xm create'. +# This script sets the parameters used when a domain is created using 'xm create'. +# You use a separate script for each domain you want to create, or +# you can set the parameters for the domain on the xm command line. +#============================================================================ + +#---------------------------------------------------------------------------- +# Kernel image file. +kernel = "mini-os.elf" + +# Initial memory allocation (in megabytes) for the new domain. +memory = 32 + +# A name for your domain. All domains must have different names. +name = "Mini-OS" diff -r edd1616cf8cb -r 291e816acbf4 extras/mini-os/include/list.h --- /dev/null Fri Sep 2 14:15:49 2005 +++ b/extras/mini-os/include/list.h Fri Sep 2 14:17:08 2005 @@ -0,0 +1,184 @@ +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static __inline__ void __list_add(struct list_head * new, + struct list_head * prev, + struct list_head * next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static __inline__ void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static __inline__ void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static __inline__ void __list_del(struct list_head * prev, + struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is in an undefined state. + */ +static __inline__ void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static __inline__ void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static __inline__ int list_empty(struct list_head *head) +{ + return head->next == head; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static __inline__ void list_splice(struct list_head *list, struct list_head *head) +{ + struct list_head *first = list->next; + + if (first != list) { + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) +#endif /* _LINUX_LIST_H */ + diff -r edd1616cf8cb -r 291e816acbf4 tools/security/getlabel.sh --- /dev/null Fri Sep 2 14:15:49 2005 +++ b/tools/security/getlabel.sh Fri Sep 2 14:17:08 2005 @@ -0,0 +1,130 @@ +#!/bin/sh +# * +# * getlabel +# * +# * Copyright (C) 2005 IBM Corporation +# * +# * Authors: +# * Stefan Berger <stefanb@xxxxxxxxxx> +# * +# * This program is free software; you can redistribute it and/or +# * modify it under the terms of the GNU General Public License as +# * published by the Free Software Foundation, version 2 of the +# * License. +# * +# * 'getlabel' tries to find the labels corresponding to the ssidref +# * +# * 'getlabel -?' shows the usage of the program +# * +# * 'getlabel -sid <ssidref> [<policy name>]' lists the label corresponding +# * to the given ssidref. +# * +# * 'getlabel -dom <domain id> [<policy name>]' lists the label of the +# * domain with given id +# * +# + +if [ -z "$runbash" ]; then + runbash="1" + export runbash + exec sh -c "bash $0 $*" +fi + + +export PATH=$PATH:. +source labelfuncs.sh + +usage () +{ + echo "Usage: $0 -sid <ssidref> [<policy name>] or" + echo " $0 -dom <domid> [<policy name>] " + echo "" + echo "policy name : the name of the policy, i.e. 'chwall'" + echo " If the policy name is omitted, the grub.conf" + echo " entry of the running system is tried to be read" + echo " and the policy name determined from there." + echo "ssidref : an ssidref in hex or decimal format, i.e., '0x00010002'" + echo " or '65538'" + echo "domid : id of the domain, i.e., '1'; Use numbers from the 2nd" + echo " column shown when invoking 'xm list'" + echo "" +} + + + +if [ "$1" == "-?" ]; then + mode="usage" +elif [ "$1" == "-dom" ]; then + mode="domid" + shift +elif [ "$1" == "-sid" ]; then + mode="sid" + shift +elif [ "$1" == "" ]; then + usage + exit -1 +fi + + +if [ "$mode" == "usage" ]; then + usage +elif [ "$mode" == "domid" ]; then + if [ "$2" == "" ]; then + findGrubConf + ret=$? + if [ $ret -eq 0 ]; then + echo "Could not find grub.conf" + exit -1; + fi + findPolicyInGrub $grubconf + if [ "$policy" != "" ]; then + echo "Assuming policy to be '$policy'."; + else + echo "Could not find policy." + exit -1; + fi + else + policy=$2 + fi + findMapFile $policy + res=$? + if [ "$res" != "0" ]; then + getSSIDUsingSecpolTool $1 + res=$? + if [ "$res" != "0" ]; then + translateSSIDREF $ssid $mapfile + else + echo "Could not determine the SSID of the domain." + fi + else + echo "Could not find map file for policy '$policy'." + fi +elif [ "$mode" == "sid" ]; then + if [ "$2" == "" ]; then + findGrubConf + ret=$? + if [ $ret -eq 0 ]; then + echo "Could not find grub.conf" + exit -1; + fi + findPolicyInGrub $grubconf + if [ "$policy" != "" ]; then + echo "Assuming policy to be '$policy'."; + else + echo "Could not find policy." + exit -1; + fi + else + policy=$2 + fi + findMapFile $policy + res=$? + if [ "$res" != "0" ]; then + translateSSIDREF $1 $mapfile + else + echo "Could not find map file for policy '$policy'." + fi + +else + usage +fi diff -r edd1616cf8cb -r 291e816acbf4 tools/security/labelfuncs.sh --- /dev/null Fri Sep 2 14:15:49 2005 +++ b/tools/security/labelfuncs.sh Fri Sep 2 14:17:08 2005 @@ -0,0 +1,675 @@ +# * +# * labelfuncs.sh +# * +# * Copyright (C) 2005 IBM Corporation +# * +# * Authors: +# * Stefan Berger <stefanb@xxxxxxxxxx> +# * +# * This program is free software; you can redistribute it and/or +# * modify it under the terms of the GNU General Public License as +# * published by the Free Software Foundation, version 2 of the +# * License. +# * +# * +# * A collection of functions to handle polcies, mapfiles, +# * and ssidrefs. +# + + +# Find the mapfile given a policy nmame +# Parameters: +# 1st : the name of the policy whose map file is to be found, i.e., +# chwall +# Results: +# The variable mapfile will hold the realtive path to the mapfile +# for the given policy. +# In case the mapfile could be found, the functions returns a '1', +# a '0' otherwise. +findMapFile () +{ + mapfile="./$1.map" + if [ -r "$mapfile" ]; then + return 1 + fi + + mapfile="./policies/$1/$1.map" + if [ -r "$mapfile" ]; then + return 1 + fi + + return 0 +} + + +# Determine the name of the primary policy +# Parameters +# 1st : the path to the mapfile; the path may be relative +# to the current directory +# Results +# The variable primary will hold the name of the primary policy +getPrimaryPolicy () +{ + mapfile=$1 + primary=`cat $mapfile | \ + awk ' \ + { \ + if ( $1 == "PRIMARY" ) { \ + res=$2; \ + } \ + } END { \ + print res; \ + } '` +} + + +# Determine the name of the secondary policy +# Parameters +# 1st : the path to the mapfile; the path may be relative +# to the current directory +# Results +# The variable secondary will hold the name of the secondary policy +getSecondaryPolicy () +{ + mapfile=$1 + secondary=`cat $mapfile | \ + awk ' \ + { \ + if ( $1 == "SECONDARY" ) { \ + res=$2; \ + } \ + } END { \ + print res; \ + } '` +} + + +#Return where the grub.conf file is. +#I only know of one place it can be. +findGrubConf() +{ + grubconf="/boot/grub/grub.conf" + if [ -w $grubconf ]; then + return 1 + fi + if [ -r $grubconf ]; then + return 2 + fi + return 0 +} + + +# This function sets the global variable 'linux' +# to the name and version of the Linux kernel that was compiled +# for domain 0. +# If this variable could not be found, the variable 'linux' +# will hold a pattern +# Parameters: +# 1st: the path to reach the root directory of the XEN build tree +# where linux-*-xen0 is located at +# Results: +# The variable linux holds then name and version of the compiled +# kernel, i.e., 'vmlinuz-2.6.12-xen0' +getLinuxVersion () +{ + path=$1 + linux="" + for f in $path/linux-*-xen0 ; do + versionfile=$f/include/linux/version.h + if [ -r $versionfile ]; then + lnx=`cat $versionfile | \ + grep UTS_RELEASE | \ + awk '{ \ + len=length($3); \ + print substr($3,2,len-2) }'` + fi + if [ "$lnx" != "" ]; then + linux="[./0-9a-zA-z]*$lnx" + return; + fi + done + + #Last resort. + linux="vmlinuz-2.[45678].[0-9]*[.0-9]*-xen0$" +} + + +# Find out with which policy the hypervisor was booted with. +# Parameters +# 1st : The complete path to grub.conf, i.e., /boot/grub/grub.conf +# +findPolicyInGrub () +{ + grubconf=$1 + linux=`uname -r` + policy=`cat $grubconf | \ + awk -vlinux=$linux '{ \ + if ( $1 == "title" ) { \ + kernelfound = 0; \ + policymaycome = 0; \ + } \ + else if ( $1 == "kernel" ) { \ + if ( match($2,"xen.gz$") ) { \ + pathlen=RSTART; \ + kernelfound = 1; \ + } \ + } \ + else if ( $1 == "module" && \ + kernelfound == 1 && \ + match($2,linux) ) { \ + policymaycome = 1; \ + } \ + else if ( $1 == "module" && \ + kernelfound == 1 && \ + policymaycome == 1 && \ + match($2,"[0-9a-zA-Z_]*.bin$") ) { \ + policymaycome = 0; \ + kernelfound = 0; \ + polname = substr($2,pathlen); \ + len=length(polname); \ + polname = substr(polname,0,len-4); \ + } \ + } END { \ + print polname \ + }'` +} + + +# Get the SSID of a domain +# Parameters: +# 1st : domain ID, i.e. '1' +# Results +# If the ssid could be found, the variable 'ssid' will hold +# the currently used ssid in the hex format, i.e., '0x00010001'. +# The funtion returns '1' on success, '0' on failure +getSSIDUsingSecpolTool () +{ + domid=$1 + export PATH=$PATH:. + ssid=`secpol_tool getssid -d $domid -f | \ + grep -E "SSID:" | \ + awk '{ print $4 }'` + + if [ "$ssid" != "" ]; then + return 1 + fi + return 0 +} + + +# Break the ssid identifier into its high and low values, +# which are equal to the secondary and primary policy references. +# Parameters: +# 1st: ssid to break into high and low value, i.e., '0x00010002' +# Results: +# The variable ssidlo_int and ssidhi_int will hold the low and +# high ssid values as integers. +getSSIDLOHI () +{ + ssid=$1 + ssidlo_int=`echo $ssid | awk \ + '{ \ + len=length($0); \ + beg=substr($0,1,2); \ + if ( beg == "0x" ) { \ + dig = len - 2; \ + if (dig <= 0) { \ + exit; \ + } \ + if (dig > 4) { \ + dig=4; \ + } \ + lo=sprintf("0x%s",substr($0,len-dig+1,dig)); \ + print strtonum(lo);\ + } else { \ + lo=strtonum($0); \ + if (lo < 65536) { \ + print lo; \ + } else { \ + hi=lo; \ + hi2= (hi / 65536);\ + hi2_str=sprintf("%d",hi2); \ + hi2=strtonum(hi2_str);\ + lo=hi-(hi2*65536); \ + printf("%d",lo); \ + } \ + } \ + }'` + ssidhi_int=`echo $ssid | awk \ + '{ \ + len=length($0); \ + beg=substr($0,1,2); \ + if ( beg == "0x" ) { \ + dig = len - 2; \ + if (dig <= 0 || \ + dig > 8) { \ + exit; \ + } \ + if (dig < 4) { \ + print 0; \ + exit; \ + } \ + dig -= 4; \ + hi=sprintf("0x%s",substr($0,len-4-dig+1,dig)); \ + print strtonum(hi);\ + } else { \ + hi=strtonum($0); \ + if (hi >= 65536) { \ + hi = hi / 65536; \ + printf ("%d",hi);\ + } else { \ + printf ("0"); \ + } \ + } \ + }'` + if [ "$ssidhi_int" == "" -o \ + "$ssidlo_int" == "" ]; then + return 0; + fi + return 1 +} + + +#Update the grub configuration file. +#Search for existing entries and replace the current +#policy entry with the policy passed to this script +# +#Arguments passed to this function +# 1st : the grub configuration file with full path +# 2nd : the binary policy file name, i.e. chwall.bin +# 3rd : the name or pattern of the linux kernel name to match +# (this determines where the module entry will be made) +# +# The algorithm here is based on pattern matching +# and is working correctly if +# - under a title a line beginning with 'kernel' is found +# whose following item ends with "xen.gz" +# Example: kernel /xen.gz dom0_mem=.... +# - a module line matching the 3rd parameter is found +# +updateGrub () +{ + grubconf=$1 + policyfile=$2 + linux=$3 + + tmpfile="/tmp/new_grub.conf" + + cat $grubconf | \ + awk -vpolicy=$policyfile \ + -vlinux=$linux '{ \ + if ( $1 == "title" ) { \ + kernelfound = 0; \ + if ( policymaycome == 1 ){ \ + printf ("\tmodule %s%s\n", path, policy); \ + } \ + policymaycome = 0; \ + } \ + else if ( $1 == "kernel" ) { \ + if ( match($2,"xen.gz$") ) { \ + path=substr($2,1,RSTART-1); \ + kernelfound = 1; \ + } \ + } \ + else if ( $1 == "module" && \ + kernelfound == 1 && \ + match($2,linux) ) { \ + policymaycome = 1; \ + } \ + else if ( $1 == "module" && \ + kernelfound == 1 && \ + policymaycome == 1 && \ + match($2,"[0-9a-zA-Z]*.bin$") ) { \ + printf ("\tmodule %s%s\n", path, policy); \ + policymaycome = 0; \ + kernelfound = 0; \ + dontprint = 1; \ + } \ + else if ( $1 == "" && \ + kernelfound == 1 && \ + policymaycome == 1) { \ + dontprint = 1; \ + } \ + if (dontprint == 0) { \ + printf ("%s\n", $0); \ + } \ + dontprint = 0; \ + } END { \ + if ( policymaycome == 1 ) { \ + printf ("\tmodule %s%s\n", path, policy); \ + } \ + }' > $tmpfile + if [ ! -r $tmpfile ]; then + echo "Could not create temporary file! Aborting." + exit -1 + fi + mv -f $tmpfile $grubconf +} + + +# Display all the labels in a given mapfile +# Parameters +# 1st: Full or relative path to the policy's mapfile +showLabels () +{ + mapfile=$1 + if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then + echo "Cannot read from vm configuration file $vmfile." + return -1 + fi + + getPrimaryPolicy $mapfile + getSecondaryPolicy $mapfile + + echo "The following labels are available:" + let line=1 + while [ 1 ]; do + ITEM=`cat $mapfile | \ + awk -vline=$line \ + -vprimary=$primary \ + '{ \ + if ($1 == "LABEL->SSID" && \ + $2 == "VM" && \ + $3 == primary ) { \ + ctr++; \ + if (ctr == line) { \ + print $4; \ + } \ + } \ + } END { \ + }'` + + if [ "$ITEM" == "" ]; then + break + fi + if [ "$secondary" != "NULL" ]; then + LABEL=`cat $mapfile | \ + awk -vitem=$ITEM \ + '{ + if ($1 == "LABEL->SSID" && \ + $2 == "VM" && \ + $3 == "CHWALL" && \ + $4 == item ) { \ + result = item; \ + } \ + } END { \ + print result \ + }'` + else + LABEL=$ITEM + fi + + if [ "$LABEL" != "" ]; then + echo "$LABEL" + found=1 + fi + let line=line+1 + done + if [ "$found" != "1" ]; then + echo "No labels found." + fi +} + + +# Get the default SSID given a mapfile and the policy name +# Parameters +# 1st: Full or relative path to the policy's mapfile +# 2nd: the name of the policy +getDefaultSsid () +{ + mapfile=$1 + pol=$2 + RES=`cat $mapfile \ + awk -vpol=$pol \ + { \ + if ($1 == "LABEL->SSID" && \ + $2 == "ANY" && \ + $3 == pol && \ + $4 == "DEFAULT" ) {\ + res=$5; \ + } \ + } END { \ + printf "%04x", strtonum(res) \ + }'` + echo "default NULL mapping is $RES" + defaultssid=$RES +} + + +#Relabel a VM configuration file +# Parameters +# 1st: Full or relative path to the VM configuration file +# 2nd: The label to translate into an ssidref +# 3rd: Full or relative path to the policy's map file +# 4th: The mode this function is supposed to operate in: +# 'relabel' : Relabels the file without querying the user +# other : Prompts the user whether to proceed +relabel () +{ + vmfile=$1 + label=$2 + mapfile=$3 + mode=$4 + + if [ ! -r "$vmfile" ]; then + echo "Cannot read from vm configuration file $vmfile." + return -1 + fi + + if [ ! -w "$vmfile" ]; then + echo "Cannot write to vm configuration file $vmfile." + return -1 + fi + + if [ ! -r "$mapfile" ] ; then + echo "Cannot read mapping file $mapfile." + return -1 + fi + + # Determine which policy is primary, which sec. + getPrimaryPolicy $mapfile + getSecondaryPolicy $mapfile + + # Calculate the primary policy's SSIDREF + if [ "$primary" == "NULL" ]; then + SSIDLO="0001" + else + SSIDLO=`cat $mapfile | \ + awk -vlabel=$label \ + -vprimary=$primary \ + '{ \ + if ( $1 == "LABEL->SSID" && \ + $2 == "VM" && \ + $3 == primary && \ + $4 == label ) { \ + result=$5 \ + } \ + } END { \ + if (result != "" ) \ + {printf "%04x", strtonum(result)}\ + }'` + fi + + # Calculate the secondary policy's SSIDREF + if [ "$secondary" == "NULL" ]; then + if [ "$primary" == "NULL" ]; then + SSIDHI="0001" + else + SSIDHI="0000" + fi + else + SSIDHI=`cat $mapfile | \ + awk -vlabel=$label \ + -vsecondary=$secondary \ + '{ \ + if ( $1 == "LABEL->SSID" && \ + $2 == "VM" && \ + $3 == secondary && \ + $4 == label ) { \ + result=$5 \ + } \ + } END { \ + if (result != "" ) \ + {printf "%04x", strtonum(result)}\ + }'` + fi + + if [ "$SSIDLO" == "" -o \ + "$SSIDHI" == "" ]; then + echo "Could not map the given label '$label'." + return -1 + fi + + ACM_POLICY=`cat $mapfile | \ + awk ' { if ( $1 == "POLICY" ) { \ + result=$2 \ + } \ + } \ + END { \ + if (result != "") { \ + printf result \ + } \ + }'` + + if [ "$ACM_POLICY" == "" ]; then + echo "Could not find 'POLICY' entry in map file." + return -1 + fi + + SSIDREF="0x$SSIDHI$SSIDLO" + + if [ "$mode" != "relabel" ]; then + RES=`cat $vmfile | \ + awk '{ \ + if ( substr($1,0,7) == "ssidref" ) {\ + print $0; \ + } \ + }'` + if [ "$RES" != "" ]; then + echo "Do you want to overwrite the existing mapping ($RES)? (y/N)" + read user + if [ "$user" != "y" -a "$user" != "Y" ]; then + echo "Aborted." + return 0 + fi + fi + fi + + #Write the output + vmtmp1="/tmp/__setlabel.tmp1" + vmtmp2="/tmp/__setlabel.tmp2" + touch $vmtmp1 + touch $vmtmp2 + if [ ! -w "$vmtmp1" -o ! -w "$vmtmp2" ]; then + echo "Cannot create temporary files. Aborting." + return -1 + fi + RES=`sed -e '/^#ACM_POLICY/d' $vmfile > $vmtmp1` + RES=`sed -e '/^#ACM_LABEL/d' $vmtmp1 > $vmtmp2` + RES=`sed -e '/^ssidref/d' $vmtmp2 > $vmtmp1` + echo "#ACM_POLICY=$ACM_POLICY" >> $vmtmp1 + echo "#ACM_LABEL=$label" >> $vmtmp1 + echo "ssidref = $SSIDREF" >> $vmtmp1 + mv -f $vmtmp1 $vmfile + rm -rf $vmtmp1 $vmtmp2 + echo "Mapped label '$label' to ssidref '$SSIDREF'." +} + + +# Translate an ssidref into its label. This does the reverse lookup +# to the relabel function above. +# This function displays the results. +# Parameters: +# 1st: The ssidref to translate; must be in the form '0x00010002' +# 2nd: Full or relative path to the policy's mapfile +translateSSIDREF () +{ + ssidref=$1 + mapfile=$2 + + if [ ! -r "$mapfile" -o "$mapfile" == "" ]; then + echo "Cannot read from vm configuration file $vmfile." + return -1 + fi + + getPrimaryPolicy $mapfile + getSecondaryPolicy $mapfile + + if [ "$primary" == "NULL" -a "$secondary" == "NULL" ]; then + echo "There are no labels for the NULL policy." + return + fi + + getSSIDLOHI $ssidref + ret=$? + if [ $ret -ne 1 ]; then + echo "Error while parsing the ssid ref number '$ssidref'." + fi; + + let line1=0 + let line2=0 + while [ 1 ]; do + ITEM1=`cat $mapfile | \ + awk -vprimary=$primary \ + -vssidlo=$ssidlo_int \ + -vline=$line1 \ + '{ \ + if ( $1 == "LABEL->SSID" && \ + $3 == primary && \ + int($5) == ssidlo ) { \ + if (l == line) { \ + print $4; \ + exit; \ + } \ + l++; \ + } \ + }'` + + ITEM2=`cat $mapfile | \ + awk -vsecondary=$secondary \ + -vssidhi=$ssidhi_int \ + -vline=$line2 \ + '{ \ + if ( $1 == "LABEL->SSID" && \ + $3 == secondary && \ + int($5) == ssidhi ) { \ + if (l == line) { \ + print $4; \ + exit; \ + } \ + l++; \ + } \ + }'` + + if [ "$secondary" != "NULL" ]; then + if [ "$ITEM1" == "" ]; then + let line1=0 + let line2=line2+1 + else + let line1=line1+1 + fi + + if [ "$ITEM1" == "" -a \ + "$ITEM2" == "" ]; then + echo "Could not determine the referenced label." + break + fi + + if [ "$ITEM1" == "$ITEM2" ]; then + echo "Label: $ITEM1" + break + fi + else + if [ "$ITEM1" != "" ]; then + echo "Label: $ITEM1" + else + if [ "$found" == "0" ]; then + found=1 + else + break + fi + fi + let line1=line1+1 + fi + done +} diff -r edd1616cf8cb -r 291e816acbf4 xen/arch/x86/shadow_guest32.c --- /dev/null Fri Sep 2 14:15:49 2005 +++ b/xen/arch/x86/shadow_guest32.c Fri Sep 2 14:17:08 2005 @@ -0,0 +1,18 @@ +#define GUEST_PGENTRY_32 +#if defined (__x86_64__) + +#include "shadow.c" +struct shadow_ops MODE_D_HANDLER = { + .guest_paging_levels = 2, + .invlpg = shadow_invlpg_64, + .fault = shadow_fault_64, + .update_pagetables = shadow_update_pagetables, + .sync_all = sync_all, + .remove_all_write_access = remove_all_write_access, + .do_update_va_mapping = do_update_va_mapping, + .mark_mfn_out_of_sync = mark_mfn_out_of_sync, + .is_out_of_sync = is_out_of_sync, + .gva_to_gpa = gva_to_gpa_64, +}; + +#endif diff -r edd1616cf8cb -r 291e816acbf4 xen/include/asm-x86/shadow_ops.h --- /dev/null Fri Sep 2 14:15:49 2005 +++ b/xen/include/asm-x86/shadow_ops.h Fri Sep 2 14:17:08 2005 @@ -0,0 +1,130 @@ +/****************************************************************************** + * include/asm-x86/shadow_ops.h + * + * Copyright (c) 2005 Michael A Fetterman + * Based on an earlier implementation by Ian Pratt et al + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _XEN_SHADOW_OPS_H +#define _XEN_SHADOW_OPS_H + +#if defined( GUEST_PGENTRY_32 ) + +#define GUEST_L1_PAGETABLE_ENTRIES L1_PAGETABLE_ENTRIES_32 +#define GUEST_L2_PAGETABLE_ENTRIES L2_PAGETABLE_ENTRIES_32 +#define GUEST_ROOT_PAGETABLE_ENTRIES ROOT_PAGETABLE_ENTRIES_32 +#define GUEST_L2_PAGETABLE_SHIFT L2_PAGETABLE_SHIFT_32 + +#define guest_l1_pgentry_t l1_pgentry_32_t +#define guest_l2_pgentry_t l2_pgentry_32_t +#define guest_root_pgentry_t l2_pgentry_32_t + +#define guest_l1e_get_paddr l1e_get_paddr_32 +#define guest_l2e_get_paddr l2e_get_paddr_32 + +#define guest_get_pte_flags get_pte_flags_32 +#define guest_put_pte_flags put_pte_flags_32 + +#define guest_l1e_get_flags l1e_get_flags_32 +#define guest_l2e_get_flags l2e_get_flags_32 +#define guest_root_get_flags l2e_get_flags_32 +#define guest_root_get_intpte l2e_get_intpte + +#define guest_l1e_empty l1e_empty_32 +#define guest_l2e_empty l2e_empty_32 + +#define guest_l1e_from_pfn l1e_from_pfn_32 +#define guest_l2e_from_pfn l2e_from_pfn_32 + +#define guest_l1e_from_paddr l1e_from_paddr_32 +#define guest_l2e_from_paddr l2e_from_paddr_32 + +#define guest_l1e_from_page l1e_from_page_32 +#define guest_l2e_from_page l2e_from_page_32 + +#define guest_l1e_add_flags l1e_add_flags_32 +#define guest_l2e_add_flags l2e_add_flags_32 + +#define guest_l1e_remove_flag l1e_remove_flags_32 +#define guest_l2e_remove_flag l2e_remove_flags_32 + +#define guest_l1e_has_changed l1e_has_changed_32 +#define guest_l2e_has_changed l2e_has_changed_32 +#define root_entry_has_changed l2e_has_changed_32 + +#define guest_l1_table_offset l1_table_offset_32 +#define guest_l2_table_offset l2_table_offset_32 + +#define guest_linear_l1_table linear_pg_table_32 +#define guest_linear_l2_table linear_l2_table_32 + +#define guest_va_to_l1mfn va_to_l1mfn_32 + +#else + +#define GUEST_L1_PAGETABLE_ENTRIES L1_PAGETABLE_ENTRIES +#define GUEST_L2_PAGETABLE_ENTRIES L2_PAGETABLE_ENTRIES +#define GUEST_ROOT_PAGETABLE_ENTRIES ROOT_PAGETABLE_ENTRIES +#define GUEST_L2_PAGETABLE_SHIFT L2_PAGETABLE_SHIFT + +#define guest_l1_pgentry_t l1_pgentry_t +#define guest_l2_pgentry_t l2_pgentry_t +#define guest_root_pgentry_t l4_pgentry_t + +#define guest_l1e_get_paddr l1e_get_paddr +#define guest_l2e_get_paddr l2e_get_paddr + +#define guest_get_pte_flags get_pte_flags +#define guest_put_pte_flags put_pte_flags + +#define guest_l1e_get_flags l1e_get_flags +#define guest_l2e_get_flags l2e_get_flags +#define guest_root_get_flags l4e_get_flags +#define guest_root_get_intpte l4e_get_intpte + +#define guest_l1e_empty l1e_empty +#define guest_l2e_empty l2e_empty + +#define guest_l1e_from_pfn l1e_from_pfn +#define guest_l2e_from_pfn l2e_from_pfn + +#define guest_l1e_from_paddr l1e_from_paddr +#define guest_l2e_from_paddr l2e_from_paddr + +#define guest_l1e_from_page l1e_from_page +#define guest_l2e_from_page l2e_from_page + +#define guest_l1e_add_flags l1e_add_flags +#define guest_l2e_add_flags l2e_add_flags + +#define guest_l1e_remove_flag l1e_remove_flags +#define guest_l2e_remove_flag l2e_remove_flags + +#define guest_l1e_has_changed l1e_has_changed +#define guest_l2e_has_changed l2e_has_changed +#define root_entry_has_changed l4e_has_changed + +#define guest_l1_table_offset l1_table_offset +#define guest_l2_table_offset l2_table_offset + +#define guest_linear_l1_table linear_pg_table +#define guest_linear_l2_table linear_l2_table + +#define guest_va_to_l1mfn va_to_l1mfn +#endif + +#endif /* _XEN_SHADOW_OPS_H */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |