# HG changeset patch # User gingold@virtu10 # Node ID d7bb72ade3d3adfca6dff3a43b04fd19fa3541d6 # Parent 1ffb1200700b08420a1656b817171798ff45bad4 IO ports for driver domains. Map/unmap IO ports. Signed-off-by: Tristan Gingold diff -r 1ffb1200700b -r d7bb72ade3d3 xen/arch/ia64/xen/dom0_ops.c --- a/xen/arch/ia64/xen/dom0_ops.c Thu Jul 27 09:46:31 2006 +0200 +++ b/xen/arch/ia64/xen/dom0_ops.c Thu Jul 27 12:49:06 2006 +0200 @@ -285,6 +285,7 @@ long arch_do_dom0_op(dom0_op_t *op, XEN_ struct domain *d; unsigned int fp = op->u.ioport_permission.first_port; unsigned int np = op->u.ioport_permission.nr_ports; + unsigned int lp = fp + np - 1; ret = -ESRCH; if ( unlikely((d = find_domain_by_id( @@ -295,9 +296,9 @@ long arch_do_dom0_op(dom0_op_t *op, XEN_ ret = 0; else { if ( op->u.ioport_permission.allow_access ) - ret = ioports_permit_access (d, fp, fp + np - 1); + ret = ioports_permit_access (d, fp, lp); else - ret = ioports_deny_access (d, fp, fp + np - 1); + ret = ioports_deny_access (d, fp, lp); } put_domain(d); diff -r 1ffb1200700b -r d7bb72ade3d3 xen/arch/ia64/xen/dom_fw.c --- a/xen/arch/ia64/xen/dom_fw.c Thu Jul 27 09:46:31 2006 +0200 +++ b/xen/arch/ia64/xen/dom_fw.c Thu Jul 27 12:49:06 2006 +0200 @@ -855,15 +855,17 @@ dom_fw_init (struct domain *d, struct ia } else { #ifndef CONFIG_XEN_IA64_DOM0_VP /* Dom0 maps legacy mmio in first MB. */ - MAKE_MD(EFI_LOADER_DATA,EFI_MEMORY_WB,0*MB,1*MB, 1); - MAKE_MD(EFI_CONVENTIONAL_MEMORY,EFI_MEMORY_WB,HYPERCALL_END,maxmem, 1); -#endif - /* hypercall patches live here, masquerade as reserved PAL memory */ - MAKE_MD(EFI_PAL_CODE,EFI_MEMORY_WB|EFI_MEMORY_RUNTIME,HYPERCALL_START,HYPERCALL_END, 1); - /* Create a dummy entry for IO ports, so that IO accesses are - trapped by Xen. */ - MAKE_MD(EFI_MEMORY_MAPPED_IO_PORT_SPACE,EFI_MEMORY_UC, - 0x00000ffffc000000, 0x00000fffffffffff, 1); + MAKE_MD(EFI_LOADER_DATA, EFI_MEMORY_WB, 0*MB, 1*MB, 1); + MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, + HYPERCALL_END, maxmem, 1); +#endif + /* hypercall patches live here, masquerade as reserved + PAL memory */ + MAKE_MD(EFI_PAL_CODE, EFI_MEMORY_WB|EFI_MEMORY_RUNTIME, + HYPERCALL_START, HYPERCALL_END, 1); + /* Create an entry for IO ports. */ + MAKE_MD(EFI_MEMORY_MAPPED_IO_PORT_SPACE, EFI_MEMORY_UC, + IO_PORTS_PADDR, IO_PORTS_PADDR + IO_PORTS_SIZE, 1); MAKE_MD(EFI_RESERVED_TYPE,0,0,0,0); } diff -r 1ffb1200700b -r d7bb72ade3d3 xen/arch/ia64/xen/mm.c --- a/xen/arch/ia64/xen/mm.c Thu Jul 27 09:46:31 2006 +0200 +++ b/xen/arch/ia64/xen/mm.c Thu Jul 27 12:49:06 2006 +0200 @@ -179,6 +179,8 @@ static void domain_page_flush(struct dom static void domain_page_flush(struct domain* d, unsigned long mpaddr, unsigned long old_mfn, unsigned long new_mfn); #endif + +extern unsigned long ia64_iobase; static struct domain *dom_xen, *dom_io; @@ -892,6 +894,60 @@ assign_domain_page(struct domain *d, // because __assign_domain_page() uses set_pte_rel() which has // release semantics, smp_mb() isn't needed. __assign_domain_page(d, mpaddr, physaddr, ASSIGN_writable); +} + +int +ioports_permit_access (struct domain *d, unsigned long fp, unsigned long lp) +{ + int ret; + unsigned long off; + unsigned long fp_offset; + unsigned long lp_offset; + + ret = rangeset_add_range(d->arch.ioport_caps, fp, lp); + if (ret != 0) + return ret; + + fp_offset = IO_SPACE_SPARSE_ENCODING (fp) & ~PAGE_MASK; + lp_offset = PAGE_ALIGN (IO_SPACE_SPARSE_ENCODING (lp)); + + for (off = fp_offset; off <= lp_offset; off += PAGE_SIZE) + __assign_domain_page + (d, IO_PORTS_PADDR + off, ia64_iobase + off, ASSIGN_nocache); + + return 0; +} + +int +ioports_deny_access (struct domain *d, unsigned long fp, unsigned long lp) +{ + int ret; + struct mm_struct *mm = &d->arch.mm; + unsigned long off; + unsigned long fp_offset; + unsigned long lp_offset; + + ret = rangeset_remove_range(d->arch.ioport_caps, fp, lp); + if (ret != 0) + return ret; + + fp_offset = IO_SPACE_SPARSE_ENCODING (fp) & ~PAGE_MASK; + lp_offset = PAGE_ALIGN (IO_SPACE_SPARSE_ENCODING (lp)); + + for (off = fp_offset; off <= lp_offset; off += PAGE_SIZE) { + unsigned long mpaddr = IO_PORTS_PADDR + off; + volatile pte_t *pte; + pte_t old_pte; + + pte = lookup_noalloc_domain_pte_none(d, mpaddr); + BUG_ON (pte == NULL); + BUG_ON (pte_none(*pte)); + + // clear pte + old_pte = ptep_get_and_clear(mm, mpaddr, pte); + } + domain_flush_vtlb_all (); + return 0; } #ifdef CONFIG_XEN_IA64_DOM0_VP diff -r 1ffb1200700b -r d7bb72ade3d3 xen/include/asm-ia64/domain.h --- a/xen/include/asm-ia64/domain.h Thu Jul 27 09:46:31 2006 +0200 +++ b/xen/include/asm-ia64/domain.h Thu Jul 27 12:49:06 2006 +0200 @@ -196,6 +196,10 @@ struct arch_vcpu { #include /* for KERNEL_DS */ #include +/* Guest physical address of IO ports space. */ +#define IO_PORTS_PADDR 0x00000ffffc000000UL +#define IO_PORTS_SIZE 0x0000000004000000UL + #endif /* __ASM_DOMAIN_H__ */ /* diff -r 1ffb1200700b -r d7bb72ade3d3 xen/include/asm-ia64/iocap.h --- a/xen/include/asm-ia64/iocap.h Thu Jul 27 09:46:31 2006 +0200 +++ b/xen/include/asm-ia64/iocap.h Thu Jul 27 12:49:06 2006 +0200 @@ -7,10 +7,9 @@ #ifndef __IA64_IOCAP_H__ #define __IA64_IOCAP_H__ -#define ioports_permit_access(d, s, e) \ - rangeset_add_range((d)->arch.ioport_caps, s, e) -#define ioports_deny_access(d, s, e) \ - rangeset_remove_range((d)->arch.ioport_caps, s, e) +extern int ioports_permit_access (struct domain *d, unsigned long s, unsigned long e); +extern int ioports_deny_access (struct domain *d, unsigned long s, unsigned long e); + #define ioports_access_permitted(d, s, e) \ rangeset_contains_range((d)->arch.ioport_caps, s, e)