Kieran Mansley
2006-Dec-01 17:20 UTC
[Xen-devel] [PATCH 2/10] Add support for netfront/netback acceleration drivers
This set of patches adds the support for acceleration plugins to the netfront/netback drivers. These plugins are intended to support virtualisable network hardware that can be directly accessed from the guest, bypassing dom0. This is in response to the RFC we posted to xen-devel with an outline of our approach at the end of September. To follow will be another set of patches to provide our hardware specific drivers and plugins. The above set are all hardware-agnostic and so of wider relevance. Signed-off-by: kmansley@solarflare.com The following describes each of the patches that are attached. readonlyiomem: - Add ability to grant and map iomem pages readonly Support mapping iomem readonly (as well as existing read/write) diff -r b58bcd6551e2 linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c --- a/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c Fri Dec 01 16:21:46 2006 +0000 +++ b/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c Fri Dec 01 16:22:40 2006 +0000 @@ -249,7 +249,9 @@ void __iomem * __ioremap(unsigned long p return NULL; area->phys_addr = phys_addr; addr = (void __iomem *) area->addr; - flags |= _KERNPG_TABLE; + /* This doesn''t mean the page will always be readonly - caller + could have passed in _PAGE_RW in flags */ + flags |= _KERNPG_TABLE_READONLY; if (__direct_remap_pfn_range(&init_mm, (unsigned long)addr, phys_addr>>PAGE_SHIFT, size, __pgprot(flags), domid)) { @@ -285,7 +287,7 @@ void __iomem *ioremap_nocache (unsigned void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size) { unsigned long last_addr; - void __iomem *p = __ioremap(phys_addr, size, _PAGE_PCD); + void __iomem *p = __ioremap(phys_addr, size, _PAGE_PCD | _PAGE_RW); if (!p) return p; diff -r b58bcd6551e2 linux-2.6-xen-sparse/include/asm-i386/mach- xen/asm/io.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/io.h Fri Dec 01 16:21:46 2006 +0000 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/io.h Fri Dec 01 16:53:16 2006 +0000 @@ -49,6 +49,8 @@ #include <linux/vmalloc.h> #include <asm/fixmap.h> +#include <linux/sched.h> /* Needed to get init_mm for asm/pgtable.h */ +#include <asm/pgtable.h> /* * Convert a physical pointer to a virtual kernel pointer for /dev/mem @@ -130,6 +132,11 @@ extern void __iomem * __ioremap(unsigned */ static inline void __iomem * ioremap(unsigned long offset, unsigned long size) +{ + return __ioremap(offset, size, _PAGE_RW); +} + +static inline void __iomem * ioremap_readonly(unsigned long offset, unsigned long size) { return __ioremap(offset, size, 0); } diff -r b58bcd6551e2 linux-2.6-xen-sparse/include/asm-i386/mach- xen/asm/pgtable.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable.h Fri Dec 01 16:21:46 2006 +0000 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable.h Fri Dec 01 16:22:40 2006 +0000 @@ -133,6 +133,7 @@ void paging_init(void); #define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) +#define _KERNPG_TABLE_READONLY (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY) #define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) #define PAGE_NONE \ diff -r b58bcd6551e2 linux-2.6-xen-sparse/include/asm-x86_64/mach- xen/asm/io.h --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/io.h Fri Dec 01 16:21:46 2006 +0000 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/io.h Fri Dec 01 16:53:42 2006 +0000 @@ -143,10 +143,17 @@ static inline void * phys_to_virt(unsign bvec_to_pseudophys((vec2)))) #include <asm-generic/iomap.h> +#include <linux/sched.h> /* Needed to get init_mm for asm/pgtable.h */ +#include <asm/pgtable.h> extern void __iomem *__ioremap(unsigned long offset, unsigned long size, unsigned long flags); static inline void __iomem * ioremap (unsigned long offset, unsigned long size) +{ + return __ioremap(offset, size, _PAGE_RW); +} + +static inline void __iomem * ioremap_readonly(unsigned long offset, unsigned long size) { return __ioremap(offset, size, 0); } diff -r b58bcd6551e2 linux-2.6-xen-sparse/include/xen/domctl.h --- a/linux-2.6-xen-sparse/include/xen/domctl.h Fri Dec 01 16:21:46 2006 +0000 +++ b/linux-2.6-xen-sparse/include/xen/domctl.h Fri Dec 01 16:22:41 2006 +0000 @@ -28,13 +28,9 @@ #ifndef __XEN_PUBLIC_DOMCTL_H__ #define __XEN_PUBLIC_DOMCTL_H__ -#if !defined(__XEN__) && !defined(__XEN_TOOLS__) -#error "domctl operations are intended for use by node control tools only" -#endif - #include "xen.h" -#define XEN_DOMCTL_INTERFACE_VERSION 0x00000004 +#define XEN_DOMCTL_INTERFACE_VERSION 0x00000005 struct xenctl_cpumap { XEN_GUEST_HANDLE(uint8_t) bitmap; @@ -341,6 +337,11 @@ struct xen_domctl_iomem_permission { uint64_t first_mfn; /* first page (physical page number) in range */ uint64_t nr_mfns; /* number of pages in range (>0) */ uint8_t allow_access; /* allow (!0) or deny (0) access to range? */ +#define IOMEM_ACCESS_NOACCESS 0 +#define IOMEM_ACCESS_READWRITE 1 +#define IOMEM_ACCESS_READONLY 2 + uint8_t rw; /* read/write permissions to allow. + Only relevant if allow_access != 0 */ }; typedef struct xen_domctl_iomem_permission xen_domctl_iomem_permission_t; DEFINE_XEN_GUEST_HANDLE(xen_domctl_iomem_permission_t); diff -r b58bcd6551e2 xen/arch/ia64/xen/dom0_ops.c --- a/xen/arch/ia64/xen/dom0_ops.c Fri Dec 01 16:21:46 2006 +0000 +++ b/xen/arch/ia64/xen/dom0_ops.c Fri Dec 01 16:22:41 2006 +0000 @@ -296,11 +296,18 @@ dom0vp_ioremap(struct domain *d, unsigne end = PAGE_ALIGN(mpaddr + size); - if (!iomem_access_permitted(d, mpaddr >> PAGE_SHIFT, - (end >> PAGE_SHIFT) - 1)) + switch(iomem_access_permitted(d, mpaddr >> PAGE_SHIFT, + (end >> PAGE_SHIFT) - 1)){ + case IOMEM_ACCESS_READWRITE: + return assign_domain_mmio_page(d, mpaddr, size, ASSIGN_writable); + break; + case IOMEM_ACCESS_READONLY: + return assign_domain_mmio_page(d, mpaddr, size, ASSIGN_readonly); + break; + case IOMEM_ACCESS_NOACCESS: return -EPERM; - - return assign_domain_mmio_page(d, mpaddr, size); + break; + } } unsigned long diff -r b58bcd6551e2 xen/arch/ia64/xen/dom_fw.c --- a/xen/arch/ia64/xen/dom_fw.c Fri Dec 01 16:21:46 2006 +0000 +++ b/xen/arch/ia64/xen/dom_fw.c Fri Dec 01 16:22:41 2006 +0000 @@ -533,7 +533,7 @@ complete_dom0_memmap(struct domain *d, case EFI_MEMORY_MAPPED_IO_PORT_SPACE: /* Map into dom0. */ - assign_domain_mmio_page(d, start, size); + assign_domain_mmio_page(d, start, size, ASSIGN_writable); /* Copy descriptor. */ *dom_md = *md; dom_md->virt_addr = 0; @@ -667,7 +667,7 @@ complete_dom0_memmap(struct domain *d, continue; if (efi_mmio(addr, PAGE_SIZE)) - assign_domain_mmio_page(d, addr, PAGE_SIZE); + assign_domain_mmio_page(d, addr, PAGE_SIZE, ASSIGN_writable); } return num_mds; } diff -r b58bcd6551e2 xen/arch/ia64/xen/domain.c --- a/xen/arch/ia64/xen/domain.c Fri Dec 01 16:21:46 2006 +0000 +++ b/xen/arch/ia64/xen/domain.c Fri Dec 01 16:22:41 2006 +0000 @@ -911,7 +911,7 @@ void alloc_dom0(void) */ static void physdev_init_dom0(struct domain *d) { - if (iomem_permit_access(d, 0UL, ~0UL)) + if (iomem_permit_access(d, 0UL, ~0UL, IOMEM_ACCESS_READWRITE)) BUG(); if (irqs_permit_access(d, 0, NR_IRQS-1)) BUG(); diff -r b58bcd6551e2 xen/arch/ia64/xen/mm.c --- a/xen/arch/ia64/xen/mm.c Fri Dec 01 16:21:46 2006 +0000 +++ b/xen/arch/ia64/xen/mm.c Fri Dec 01 16:22:41 2006 +0000 @@ -857,7 +857,8 @@ __assign_domain_page(struct domain *d, /* get_page() and map a physical address to the specified metaphysical addr */ void assign_domain_page(struct domain *d, - unsigned long mpaddr, unsigned long physaddr) + unsigned long mpaddr, unsigned long physaddr, + unsigned long flags) { struct page_info* page = mfn_to_page(physaddr >> PAGE_SHIFT); int ret; @@ -869,7 +870,7 @@ assign_domain_page(struct domain *d, // because __assign_domain_page() uses set_pte_rel() which has // release semantics, smp_mb() isn''t needed. (void)__assign_domain_page(d, mpaddr, physaddr, - ASSIGN_writable | ASSIGN_pgc_allocated); + flags | ASSIGN_pgc_allocated); } int @@ -1016,7 +1017,8 @@ efi_mmio(unsigned long physaddr, unsigne unsigned long assign_domain_mmio_page(struct domain *d, - unsigned long mpaddr, unsigned long size) + unsigned long mpaddr, unsigned long size, + unsigned long flags) { if (size == 0) { gdprintk(XENLOG_INFO, "%s: domain %p mpaddr 0x%lx size = 0x%lx \n", @@ -1029,7 +1031,7 @@ assign_domain_mmio_page(struct domain *d #endif return -EINVAL; } - assign_domain_same_page(d, mpaddr, size, ASSIGN_writable | ASSIGN_nocache); + assign_domain_same_page(d, mpaddr, size, flags | ASSIGN_nocache); return mpaddr; } diff -r b58bcd6551e2 xen/arch/powerpc/domain_build.c --- a/xen/arch/powerpc/domain_build.c Fri Dec 01 16:21:46 2006 +0000 +++ b/xen/arch/powerpc/domain_build.c Fri Dec 01 16:22:41 2006 +0000 @@ -306,7 +306,7 @@ int construct_dom0(struct domain *d, rc = 0; /* DOM0 is permitted full I/O capabilities. */ - rc |= iomem_permit_access(dom0, 0UL, ~0UL); + rc |= iomem_permit_access(dom0, 0UL, ~0UL, IOMEM_ACCESS_READWRITE); rc |= irqs_permit_access(dom0, 0, NR_IRQS-1); BUG_ON(rc != 0); diff -r b58bcd6551e2 xen/arch/x86/domain_build.c --- a/xen/arch/x86/domain_build.c Fri Dec 01 16:21:46 2006 +0000 +++ b/xen/arch/x86/domain_build.c Fri Dec 01 16:22:41 2006 +0000 @@ -849,7 +849,7 @@ int construct_dom0(struct domain *d, /* DOM0 is permitted full I/O capabilities. */ rc |= ioports_permit_access(dom0, 0, 0xFFFF); - rc |= iomem_permit_access(dom0, 0UL, ~0UL); + rc |= iomem_permit_access(dom0, 0UL, ~0UL, IOMEM_ACCESS_READWRITE); rc |= irqs_permit_access(dom0, 0, NR_IRQS-1); /* diff -r b58bcd6551e2 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Fri Dec 01 16:21:46 2006 +0000 +++ b/xen/arch/x86/mm.c Fri Dec 01 16:22:41 2006 +0000 @@ -552,7 +552,7 @@ get_page_from_l1e( { unsigned long mfn = l1e_get_pfn(l1e); struct page_info *page = mfn_to_page(mfn); - int okay; + int okay, access; if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) ) return 1; @@ -570,11 +570,19 @@ get_page_from_l1e( if ( d == dom_io ) d = current->domain; - if ( !iomem_access_permitted(d, mfn, mfn) ) + if ( (access = iomem_access_permitted(d, mfn, mfn)) + == IOMEM_ACCESS_NOACCESS ) { if ( mfn != (PADDR_MASK >> PAGE_SHIFT) ) /* INVALID_MFN? */ MEM_LOG("Non-privileged (%u) attempt to map I/O space % 08lx", d->domain_id, mfn); + return 0; + } + + /* If access is IOMEM_ACCESS_READONLY, the l1e_get_flags below + should not have _PAGE_RW set */ + if(access == IOMEM_ACCESS_READONLY && l1e_get_flags(l1e) & _PAGE_RW){ + MEM_LOG("Non-privileged attempt to map readonly I/O space % 08lx", mfn); return 0; } diff -r b58bcd6551e2 xen/common/domain.c --- a/xen/common/domain.c Fri Dec 01 16:21:46 2006 +0000 +++ b/xen/common/domain.c Fri Dec 01 16:22:41 2006 +0000 @@ -160,9 +160,14 @@ struct domain *domain_create(domid_t dom if ( arch_domain_create(d) != 0 ) goto fail3; - d->iomem_caps = rangeset_new(d, "I/O Memory", RANGESETF_prettyprint_hex); + d->iomem_caps_readwrite = rangeset_new(d, "I/O Memory RW", + RANGESETF_prettyprint_hex); + d->iomem_caps_readonly = rangeset_new(d, "I/O Memory RO", + RANGESETF_prettyprint_hex); d->irq_caps = rangeset_new(d, "Interrupts", 0); - if ( (d->iomem_caps == NULL) || (d->irq_caps == NULL) ) + if ( (d->iomem_caps_readwrite == NULL) || + (d->iomem_caps_readonly == NULL) || + (d->irq_caps == NULL) ) goto fail4; if ( sched_init_domain(d) != 0 ) diff -r b58bcd6551e2 xen/common/domctl.c --- a/xen/common/domctl.c Fri Dec 01 16:21:46 2006 +0000 +++ b/xen/common/domctl.c Fri Dec 01 16:22:41 2006 +0000 @@ -623,7 +623,8 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc break; if ( op->u.iomem_permission.allow_access ) - ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1); + ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1, + op->u.iomem_permission.rw); else ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1); diff -r b58bcd6551e2 xen/include/asm-ia64/grant_table.h --- a/xen/include/asm-ia64/grant_table.h Fri Dec 01 16:21:46 2006 +0000 +++ b/xen/include/asm-ia64/grant_table.h Fri Dec 01 16:22:41 2006 +0000 @@ -32,7 +32,7 @@ void guest_physmap_add_page(struct domai # define gnttab_shared_gmfn(d, t, i) \ ({ assign_domain_page((d), \ IA64_GRANT_TABLE_PADDR + ((i) << PAGE_SHIFT), \ - gnttab_shared_maddr((d), (t), (i))); \ + gnttab_shared_maddr((d), (t), (i), ASSIGN_writable)); \ (IA64_GRANT_TABLE_PADDR >> PAGE_SHIFT) + (i);}) #define gnttab_mark_dirty(d, f) ((void)f) diff -r b58bcd6551e2 xen/include/asm-ia64/mm.h --- a/xen/include/asm-ia64/mm.h Fri Dec 01 16:21:46 2006 +0000 +++ b/xen/include/asm-ia64/mm.h Fri Dec 01 16:22:41 2006 +0000 @@ -432,7 +432,7 @@ extern unsigned long lookup_domain_mpa(s extern unsigned long lookup_domain_mpa(struct domain *d, unsigned long mpaddr, struct p2m_entry* entry); extern void *domain_mpa_to_imva(struct domain *d, unsigned long mpaddr); extern volatile pte_t *lookup_noalloc_domain_pte(struct domain* d, unsigned long mpaddr); -extern unsigned long assign_domain_mmio_page(struct domain *d, unsigned long mpaddr, unsigned long size); +extern unsigned long assign_domain_mmio_page(struct domain *d, unsigned long mpaddr, unsigned long size, unsigned long flags); extern unsigned long assign_domain_mach_page(struct domain *d, unsigned long mpaddr, unsigned long size, unsigned long flags); int domain_page_mapped(struct domain *d, unsigned long mpaddr); int efi_mmio(unsigned long physaddr, unsigned long size); diff -r b58bcd6551e2 xen/include/asm-x86/iocap.h --- a/xen/include/asm-x86/iocap.h Fri Dec 01 16:21:46 2006 +0000 +++ b/xen/include/asm-x86/iocap.h Fri Dec 01 16:22:41 2006 +0000 @@ -14,7 +14,10 @@ #define ioports_access_permitted(d, s, e) \ rangeset_contains_range((d)->arch.ioport_caps, s, e) -#define cache_flush_permitted(d) \ - (!rangeset_is_empty((d)->iomem_caps)) +#define cache_flush_permitted(d) \ + (!(rangeset_is_empty((d)->iomem_caps_readwrite) && \ + rangeset_is_empty((d)->iomem_caps_readonly))) + + #endif /* __X86_IOCAP_H__ */ diff -r b58bcd6551e2 xen/include/public/domctl.h --- a/xen/include/public/domctl.h Fri Dec 01 16:21:46 2006 +0000 +++ b/xen/include/public/domctl.h Fri Dec 01 16:22:41 2006 +0000 @@ -34,7 +34,7 @@ #include "xen.h" -#define XEN_DOMCTL_INTERFACE_VERSION 0x00000004 +#define XEN_DOMCTL_INTERFACE_VERSION 0x00000005 struct xenctl_cpumap { XEN_GUEST_HANDLE(uint8_t) bitmap; @@ -341,6 +341,11 @@ struct xen_domctl_iomem_permission { uint64_t first_mfn; /* first page (physical page number) in range */ uint64_t nr_mfns; /* number of pages in range (>0) */ uint8_t allow_access; /* allow (!0) or deny (0) access to range? */ +#define IOMEM_ACCESS_NOACCESS 0 +#define IOMEM_ACCESS_READWRITE 1 +#define IOMEM_ACCESS_READONLY 2 + uint8_t rw; /* read/write permissions to allow. + Only relevant if allow_access != 0 */ }; typedef struct xen_domctl_iomem_permission xen_domctl_iomem_permission_t; DEFINE_XEN_GUEST_HANDLE(xen_domctl_iomem_permission_t); diff -r b58bcd6551e2 xen/include/xen/iocap.h --- a/xen/include/xen/iocap.h Fri Dec 01 16:21:46 2006 +0000 +++ b/xen/include/xen/iocap.h Fri Dec 01 16:22:41 2006 +0000 @@ -10,12 +10,24 @@ #include <xen/rangeset.h> #include <asm/iocap.h> -#define iomem_permit_access(d, s, e) \ - rangeset_add_range((d)->iomem_caps, s, e) -#define iomem_deny_access(d, s, e) \ - rangeset_remove_range((d)->iomem_caps, s, e) -#define iomem_access_permitted(d, s, e) \ - rangeset_contains_range((d)->iomem_caps, s, e) +#define IOMEM_ACCESS_NOACCESS 0 +#define IOMEM_ACCESS_READWRITE 1 +#define IOMEM_ACCESS_READONLY 2 + +#define iomem_permit_access(d, s, e, r) \ + ((r) == IOMEM_ACCESS_READWRITE ? \ + rangeset_add_range((d)->iomem_caps_readwrite, s, e) : \ + rangeset_add_range((d)->iomem_caps_readonly, s, e)) + +#define iomem_deny_access(d, s, e) \ + (rangeset_remove_range((d)->iomem_caps_readwrite, s, e) || \ + rangeset_remove_range((d)->iomem_caps_readonly, s, e)) + +#define iomem_access_permitted(d, s, e) \ + (rangeset_contains_range((d)->iomem_caps_readwrite, s, e) ? \ + IOMEM_ACCESS_READWRITE : \ + (rangeset_contains_range((d)->iomem_caps_readonly, s, e) ? \ + IOMEM_ACCESS_READONLY : IOMEM_ACCESS_NOACCESS)) #define irq_permit_access(d, i) \ rangeset_add_singleton((d)->irq_caps, i) @@ -29,7 +41,9 @@ rangeset_contains_singleton((d)->irq_caps, i) #define multipage_allocation_permitted(d) \ - (!rangeset_is_empty((d)->iomem_caps)) + (!(rangeset_is_empty((d)->iomem_caps_readwrite) && \ + rangeset_is_empty((d)->iomem_caps_readonly))) + /* * Until TLB flushing issues are sorted out we consider it unsafe for @@ -37,6 +51,7 @@ * operations. */ #define grant_operation_permitted(d) \ - (!rangeset_is_empty((d)->iomem_caps)) + (!(rangeset_is_empty((d)->iomem_caps_readwrite) && \ + rangeset_is_empty((d)->iomem_caps_readonly))) #endif /* __XEN_IOCAP_H__ */ diff -r b58bcd6551e2 xen/include/xen/sched.h --- a/xen/include/xen/sched.h Fri Dec 01 16:21:46 2006 +0000 +++ b/xen/include/xen/sched.h Fri Dec 01 16:22:41 2006 +0000 @@ -139,7 +139,8 @@ struct domain DECLARE_BITMAP(pirq_mask, NR_IRQS); /* I/O capabilities (access to IRQs and memory-mapped I/O). */ - struct rangeset *iomem_caps; + struct rangeset *iomem_caps_readwrite; + struct rangeset *iomem_caps_readonly; struct rangeset *irq_caps; unsigned long domain_flags; _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Kieran Mansley
2006-Dec-01 17:25 UTC
Re: [Xen-devel] [PATCH 2/10] Add support for netfront/netback acceleration drivers
On Fri, 2006-12-01 at 17:20 +0000, Kieran Mansley wrote:> readonlyiomem: > - Add ability to grant and map iomem pages readonlyApologies: I''ve sent patches 2 and 3 in the wrong order. To apply cleanly, that should have been #3, and the one labelled 3/10 should have been #2 Kieran _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel