Attached is a patch to add ability to make read-only grants and ioremaps
of iomem pages. Apologies if I've done something wrong - this is my
first attempt at Xen devel and driving mercurial!
Signed-off-by: kmansley@xxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kjm@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Date 1155721361 -3600
# Node ID 0b37070e2efb0911d5bcfda5884089a64669e21e
# Parent 0e32095a7b4611d18a82052a9d5b23e474f91af9
Add ability to grant/map iomem pages read only as well as read write
diff -r 0e32095a7b46 -r 0b37070e2efb linux-2.6-xen-
sparse/arch/i386/mm/ioremap-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c Wed Aug 09
21:34:27 2006 +0100
+++ b/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c Wed Aug 16
10:42:41 2006 +0100
@@ -281,7 +281,7 @@ void __iomem * __ioremap(unsigned long p
return NULL;
area->phys_addr = phys_addr;
addr = (void __iomem *) area->addr;
- flags |= _PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED;
+ flags |= _PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED;
#ifdef __x86_64__
flags |= _PAGE_USER;
#endif
@@ -320,7 +320,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 0e32095a7b46 -r 0b37070e2efb 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 Wed Aug 09
21:34:27 2006 +0100
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/io.h Wed Aug 16
10:42:41 2006 +0100
@@ -49,6 +49,11 @@
#include <linux/vmalloc.h>
#include <asm/fixmap.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+
/*
* Convert a physical pointer to a virtual kernel pointer for /dev/mem
@@ -129,6 +134,12 @@ 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 0e32095a7b46 -r 0b37070e2efb 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 Wed Aug
09 21:34:27 2006 +0100
+++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/io.h Wed Aug
16 10:42:41 2006 +0100
@@ -105,6 +105,7 @@ __OUTS(l)
#if defined(__KERNEL__) && __x86_64__
#include <linux/vmalloc.h>
+#include <linux/init.h>
#ifndef __i386__
/*
@@ -143,10 +144,15 @@ static inline void * phys_to_virt(unsign
bvec_to_pseudophys((vec2))))
#include <asm-generic/iomap.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 0e32095a7b46 -r 0b37070e2efb xen/arch/ia64/xen/dom0_ops.c
--- a/xen/arch/ia64/xen/dom0_ops.c Wed Aug 09 21:34:27 2006 +0100
+++ b/xen/arch/ia64/xen/dom0_ops.c Wed Aug 16 10:42:41 2006 +0100
@@ -210,11 +210,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 0e32095a7b46 -r 0b37070e2efb xen/arch/ia64/xen/dom_fw.c
--- a/xen/arch/ia64/xen/dom_fw.c Wed Aug 09 21:34:27 2006 +0100
+++ b/xen/arch/ia64/xen/dom_fw.c Wed Aug 16 10:42:41 2006 +0100
@@ -496,7 +496,7 @@ dom_fw_dom0_passthrough(efi_memory_desc_
if (md->type == EFI_MEMORY_MAPPED_IO && (size > 0x100000000UL))
return 0;
- paddr = assign_domain_mmio_page(d, start, size);
+ paddr = assign_domain_mmio_page(d, start, size,
ASSIGN_writable);
} else
paddr = assign_domain_mach_page(d, start, size, arg->flags);
@@ -913,7 +913,8 @@ dom_fw_init (struct domain *d, struct ia
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);
}
}
for (i = 0 ; i < bp->efi_memmap_size/sizeof(efi_memory_desc_t) ; i++)
{
diff -r 0e32095a7b46 -r 0b37070e2efb xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c Wed Aug 09 21:34:27 2006 +0100
+++ b/xen/arch/ia64/xen/domain.c Wed Aug 16 10:42:41 2006 +0100
@@ -364,7 +364,7 @@ int arch_domain_create(struct domain *d)
goto fail_nomem;
d->arch.ioport_caps = rangeset_new(d, "I/O Ports",
- RANGESETF_prettyprint_hex);
+ RANGESETF_prettyprint_hex);
printf ("arch_domain_create: domain=%p\n", d);
return 0;
@@ -850,7 +850,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 0e32095a7b46 -r 0b37070e2efb xen/arch/ia64/xen/mm.c
--- a/xen/arch/ia64/xen/mm.c Wed Aug 09 21:34:27 2006 +0100
+++ b/xen/arch/ia64/xen/mm.c Wed Aug 16 10:42:41 2006 +0100
@@ -963,7 +963,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) {
DPRINTK("%s: domain %p mpaddr 0x%lx size = 0x%lx\n",
@@ -974,7 +975,7 @@ assign_domain_mmio_page(struct domain *d
__func__, __LINE__, d, mpaddr, size);
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 0e32095a7b46 -r 0b37070e2efb xen/arch/powerpc/domain_build.c
--- a/xen/arch/powerpc/domain_build.c Wed Aug 09 21:34:27 2006 +0100
+++ b/xen/arch/powerpc/domain_build.c Wed Aug 16 10:42:41 2006 +0100
@@ -276,7 +276,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 0e32095a7b46 -r 0b37070e2efb xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c Wed Aug 09 21:34:27 2006 +0100
+++ b/xen/arch/x86/domain_build.c Wed Aug 16 10:42:41 2006 +0100
@@ -815,7 +815,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 0e32095a7b46 -r 0b37070e2efb xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Wed Aug 09 21:34:27 2006 +0100
+++ b/xen/arch/x86/mm.c Wed Aug 16 10:42:41 2006 +0100
@@ -555,7 +555,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;
@@ -573,9 +573,17 @@ 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)
{
MEM_LOG("Non-privileged attempt to map I/O space %08lx",
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 0e32095a7b46 -r 0b37070e2efb xen/common/dom0_ops.c
--- a/xen/common/dom0_ops.c Wed Aug 09 21:34:27 2006 +0100
+++ b/xen/common/dom0_ops.c Wed Aug 16 10:42:41 2006 +0100
@@ -678,7 +678,8 @@ long do_dom0_op(XEN_GUEST_HANDLE(dom0_op
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 0e32095a7b46 -r 0b37070e2efb xen/common/domain.c
--- a/xen/common/domain.c Wed Aug 09 21:34:27 2006 +0100
+++ b/xen/common/domain.c Wed Aug 16 10:42:41 2006 +0100
@@ -147,9 +147,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 ( !is_idle_domain(d) )
diff -r 0e32095a7b46 -r 0b37070e2efb xen/include/asm-ia64/mm.h
--- a/xen/include/asm-ia64/mm.h Wed Aug 09 21:34:27 2006 +0100
+++ b/xen/include/asm-ia64/mm.h Wed Aug 16 10:42:41 2006 +0100
@@ -435,7 +435,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 0e32095a7b46 -r 0b37070e2efb xen/include/asm-x86/iocap.h
--- a/xen/include/asm-x86/iocap.h Wed Aug 09 21:34:27 2006 +0100
+++ b/xen/include/asm-x86/iocap.h Wed Aug 16 10:42:41 2006 +0100
@@ -14,7 +14,8 @@
#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 0e32095a7b46 -r 0b37070e2efb xen/include/public/dom0_ops.h
--- a/xen/include/public/dom0_ops.h Wed Aug 09 21:34:27 2006 +0100
+++ b/xen/include/public/dom0_ops.h Wed Aug 16 10:42:41 2006 +0100
@@ -19,7 +19,7 @@
* This makes sure that old versions of dom0 tools will stop working in
a
* well-defined way (rather than crashing the machine, for instance).
*/
-#define DOM0_INTERFACE_VERSION 0x03000001
+#define DOM0_INTERFACE_VERSION 0x03000002
/************************************************************************/
@@ -506,6 +506,11 @@ struct dom0_iomem_permission {
xen_pfn_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 dom0_iomem_permission dom0_iomem_permission_t;
DEFINE_XEN_GUEST_HANDLE(dom0_iomem_permission_t);
diff -r 0e32095a7b46 -r 0b37070e2efb xen/include/xen/iocap.h
--- a/xen/include/xen/iocap.h Wed Aug 09 21:34:27 2006 +0100
+++ b/xen/include/xen/iocap.h Wed Aug 16 10:42:41 2006 +0100
@@ -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,6 +41,7 @@
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)))
#endif /* __XEN_IOCAP_H__ */
diff -r 0e32095a7b46 -r 0b37070e2efb xen/include/xen/sched.h
--- a/xen/include/xen/sched.h Wed Aug 09 21:34:27 2006 +0100
+++ b/xen/include/xen/sched.h Wed Aug 16 10:42:41 2006 +0100
@@ -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@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|