[PATCH 00 of 24] More Xen updates - Kernel

This is a discussion on [PATCH 00 of 24] More Xen updates - Kernel ; Hi Ingo, More patches. There are three groups: - some code movements to make common code available to other architectures (namely, ia64) - Xen device driver updates, including a new xen paravirt framebuffer driver, - The Xen balloon driver (shrink ...

+ Reply to Thread
Page 1 of 2 1 2 LastLast
Results 1 to 20 of 23

Thread: [PATCH 00 of 24] More Xen updates

  1. [PATCH 00 of 24] More Xen updates

    Hi Ingo,

    More patches. There are three groups:

    - some code movements to make common code available to other
    architectures (namely, ia64)
    - Xen device driver updates, including a new xen paravirt framebuffer driver,
    - The Xen balloon driver (shrink only, so no dependency on memory hotplug yet)
    - some "using smp_processor_id while preemptable" warning fixes,
    mostly as a result of the core kernel's tendency to do tlb flushes
    and update init_mm while preemptable,
    - other little Xen cleanups

    Thanks,
    J


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  2. [PATCH 22 of 24] xen: fold xen_sysexit into xen_iret

    xen_sysexit and xen_iret were doing essentially the same thing. Rather
    than having a separate implementation for xen_sysexit, we can just strip
    the stack back to an iret frame and jump into xen_iret. This removes
    a lot of code and complexity - specifically, another critical region.

    Signed-off-by: Jeremy Fitzhardinge
    ---
    arch/x86/kernel/entry_32.S | 9 -----
    arch/x86/xen/xen-asm.S | 70 ++++++++------------------------------------
    2 files changed, 15 insertions(+), 64 deletions(-)

    diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
    --- a/arch/x86/kernel/entry_32.S
    +++ b/arch/x86/kernel/entry_32.S
    @@ -1044,15 +1044,8 @@

    jmp xen_iret_crit_fixup

    -1: cmpl $xen_sysexit_start_crit,%eax
    - jb 2f
    - cmpl $xen_sysexit_end_crit,%eax
    - jae 2f
    -
    - jmp xen_sysexit_crit_fixup
    -
    ENTRY(xen_do_upcall)
    -2: mov %esp, %eax
    +1: mov %esp, %eax
    call xen_evtchn_do_upcall
    jmp ret_from_intr
    CFI_ENDPROC
    diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S
    --- a/arch/x86/xen/xen-asm.S
    +++ b/arch/x86/xen/xen-asm.S
    @@ -106,6 +106,20 @@
    ret
    ENDPROC(xen_restore_fl_direct)
    RELOC(xen_restore_fl_direct, 2b+1)
    +
    +/*
    + We can't use sysexit directly, because we're not running in ring0.
    + But we can easily fake it up using iret. Assuming xen_sysexit
    + is jumped to with a standard stack frame, we can just strip it
    + back to a standard iret frame and use iret.
    + */
    +ENTRY(xen_sysexit)
    + movl PT_EAX(%esp), %eax /* Shouldn't be necessary? */
    + orl $X86_EFLAGS_IF, PT_EFLAGS(%esp)
    + lea PT_EIP(%esp), %esp
    +
    + jmp xen_iret
    +ENDPROC(xen_sysexit)

    /*
    This is run where a normal iret would be run, with the same stack setup:
    @@ -276,62 +290,6 @@
    2: jmp xen_do_upcall


    -ENTRY(xen_sysexit)
    - /* Store vcpu_info pointer for easy access. Do it this
    - way to avoid having to reload %fs */
    -#ifdef CONFIG_SMP
    - GET_THREAD_INFO(%eax)
    - movl TI_cpu(%eax),%eax
    - movl __per_cpu_offset(,%eax,4),%eax
    - mov per_cpu__xen_vcpu(%eax),%eax
    -#else
    - movl per_cpu__xen_vcpu, %eax
    -#endif
    -
    - /* We can't actually use sysexit in a pv guest,
    - so fake it up with iret */
    - pushl $__USER_DS /* user stack segment */
    - pushl %ecx /* user esp */
    - pushl PT_EFLAGS+2*4(%esp) /* user eflags */
    - pushl $__USER_CS /* user code segment */
    - pushl %edx /* user eip */
    -
    -xen_sysexit_start_crit:
    - /* Unmask events... */
    - movb $0, XEN_vcpu_info_mask(%eax)
    - /* ...and test for pending.
    - There's a preempt window here, but it doesn't
    - matter because we're within the critical section. */
    - testb $0xff, XEN_vcpu_info_pending(%eax)
    -
    - /* If there's something pending, mask events again so we
    - can directly inject it back into the kernel. */
    - jnz 1f
    -
    - movl PT_EAX+5*4(%esp),%eax
    -2: iret
    -1: movb $1, XEN_vcpu_info_mask(%eax)
    -xen_sysexit_end_crit:
    - addl $5*4, %esp /* remove iret frame */
    - /* no need to re-save regs, but need to restore kernel %fs */
    - mov $__KERNEL_PERCPU, %eax
    - mov %eax, %fs
    - jmp xen_do_upcall
    -.section __ex_table,"a"
    - .align 4
    - .long 2b,iret_exc
    -.previous
    -
    - .globl xen_sysexit_start_crit, xen_sysexit_end_crit
    -/*
    - sysexit fixup is easy, since the old frame is still sitting there
    - on the stack. We just need to remove the new recursive
    - interrupt and return.
    - */
    -ENTRY(xen_sysexit_crit_fixup)
    - addl $PT_OLDESP+5*4, %esp /* remove frame+iret */
    - jmp xen_do_upcall
    -
    /*
    Force an event check by making a hypercall,
    but preserve regs before making the call.


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  3. [PATCH 19 of 24] x86: fix build problem in pud_populate without CONFIG_PARAVIRT

    asm/paravirt.h ends up including linux/sched.h, which pud_populate needs
    for its reference to current. Specifically include linux/sched.h for it.

    In file included from /home/jeremy/hg/xen/paravirt/linux/arch/x86/mm/pgtable.c:3:
    include2/asm/pgalloc.h: In function ‘pud_populate’:
    include2/asm/pgalloc.h:93: error: dereferencing pointer to incomplete type
    make[3]: *** [arch/x86/mm/pgtable.o] Error 1
    make[2]: *** [arch/x86/mm/] Error 2
    make[1]: *** [sub-make] Error 2
    make: *** [all] Error 2

    Signed-off-by: Jeremy Fitzhardinge
    ---
    include/asm-x86/pgalloc.h | 1 +
    1 file changed, 1 insertion(+)

    diff --git a/include/asm-x86/pgalloc.h b/include/asm-x86/pgalloc.h
    --- a/include/asm-x86/pgalloc.h
    +++ b/include/asm-x86/pgalloc.h
    @@ -4,6 +4,7 @@
    #include
    #include /* for struct page */
    #include
    +#include

    #ifdef CONFIG_PARAVIRT
    #include


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  4. [PATCH 03 of 24] xen: add missing definitions for xen grant table which ia64/xen needs

    From: Isaku Yamahata

    Add xen handles realted definitions for grant table which ia64/xen
    needs.
    Pointer argumsnts for ia64/xen hypercall are passed in pseudo physical
    address (guest physical address) so that it is required to convert
    guest kernel virtual address into pseudo physical address right before
    issuing hypercall.
    The xen guest handle represents such arguments.
    Define necessary handles and helper functions.

    Signed-off-by: Isaku Yamahata
    Signed-off-by: Jeremy Fitzhardinge
    ---
    drivers/xen/grant-table.c | 2 +-
    include/asm-x86/xen/interface.h | 24 ++++++++++++++++++++++++
    include/xen/interface/grant_table.h | 12 ++++++++----
    3 files changed, 33 insertions(+), 5 deletions(-)

    diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
    --- a/drivers/xen/grant-table.c
    +++ b/drivers/xen/grant-table.c
    @@ -466,7 +466,7 @@

    setup.dom = DOMID_SELF;
    setup.nr_frames = nr_gframes;
    - setup.frame_list = frames;
    + set_xen_guest_handle(setup.frame_list, frames);

    rc = HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
    if (rc == -ENOSYS) {
    diff --git a/include/asm-x86/xen/interface.h b/include/asm-x86/xen/interface.h
    --- a/include/asm-x86/xen/interface.h
    +++ b/include/asm-x86/xen/interface.h
    @@ -21,6 +21,30 @@
    __DEFINE_GUEST_HANDLE(name, struct name)
    #define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name)
    #define GUEST_HANDLE(name) __guest_handle_ ## name
    +
    +#ifdef __XEN__
    +#if defined(__i386__)
    +#define set_xen_guest_handle(hnd, val) \
    + do { \
    + if (sizeof(hnd) == 8) \
    + *(uint64_t *)&(hnd) = 0; \
    + (hnd).p = val; \
    + } while (0)
    +#elif defined(__x86_64__)
    +#define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0)
    +#endif
    +#else
    +#if defined(__i386__)
    +#define set_xen_guest_handle(hnd, val) \
    + do { \
    + if (sizeof(hnd) == 8) \
    + *(uint64_t *)&(hnd) = 0; \
    + (hnd) = val; \
    + } while (0)
    +#elif defined(__x86_64__)
    +#define set_xen_guest_handle(hnd, val) do { (hnd) = val; } while (0)
    +#endif
    +#endif

    #ifndef __ASSEMBLY__
    /* Guest handles for primitive C types. */
    diff --git a/include/xen/interface/grant_table.h b/include/xen/interface/grant_table.h
    --- a/include/xen/interface/grant_table.h
    +++ b/include/xen/interface/grant_table.h
    @@ -185,6 +185,7 @@
    grant_handle_t handle;
    uint64_t dev_bus_addr;
    };
    +DEFINE_GUEST_HANDLE_STRUCT(gnttab_map_grant_ref);

    /*
    * GNTTABOP_unmap_grant_ref: Destroy one or more grant-reference mappings
    @@ -206,6 +207,7 @@
    /* OUT parameters. */
    int16_t status; /* GNTST_* */
    };
    +DEFINE_GUEST_HANDLE_STRUCT(gnttab_unmap_grant_ref );

    /*
    * GNTTABOP_setup_table: Set up a grant table for comprising at least
    @@ -223,8 +225,9 @@
    uint32_t nr_frames;
    /* OUT parameters. */
    int16_t status; /* GNTST_* */
    - ulong *frame_list;
    + GUEST_HANDLE(ulong) frame_list;
    };
    +DEFINE_GUEST_HANDLE_STRUCT(gnttab_setup_table);

    /*
    * GNTTABOP_dump_table: Dump the contents of the grant table to the
    @@ -237,6 +240,7 @@
    /* OUT parameters. */
    int16_t status; /* GNTST_* */
    };
    +DEFINE_GUEST_HANDLE_STRUCT(gnttab_dump_table);

    /*
    * GNTTABOP_transfer_grant_ref: Transfer to a foreign domain. The
    @@ -255,7 +259,7 @@
    /* OUT parameters. */
    int16_t status;
    };
    -
    +DEFINE_GUEST_HANDLE_STRUCT(gnttab_transfer);

    /*
    * GNTTABOP_copy: Hypervisor based copy
    @@ -296,6 +300,7 @@
    /* OUT parameters. */
    int16_t status;
    };
    +DEFINE_GUEST_HANDLE_STRUCT(gnttab_copy);

    /*
    * GNTTABOP_query_size: Query the current and maximum sizes of the shared
    @@ -313,7 +318,7 @@
    uint32_t max_nr_frames;
    int16_t status; /* GNTST_* */
    };
    -
    +DEFINE_GUEST_HANDLE_STRUCT(gnttab_query_size);

    /*
    * Bitfield values for update_pin_status.flags.


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  5. [PATCH 14 of 24] xen/blkfront: use bdget_disk

    info->dev is never initialized to anything, so bdget(info->dev) is
    meaningless. Get rid of info->dev, and use bdget_disk on the gendisk.

    Signed-off-by: Jeremy Fitzhardinge
    Cc: Al Viro
    ---
    drivers/block/xen-blkfront.c | 3 +--
    1 file changed, 1 insertion(+), 2 deletions(-)

    diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
    --- a/drivers/block/xen-blkfront.c
    +++ b/drivers/block/xen-blkfront.c
    @@ -75,7 +75,6 @@
    struct blkfront_info
    {
    struct xenbus_device *xbdev;
    - dev_t dev;
    struct gendisk *gd;
    int vdevice;
    blkif_vdev_t handle;
    @@ -903,7 +902,7 @@
    break;

    case XenbusStateClosing:
    - bd = bdget(info->dev);
    + bd = bdget_disk(info->gd, 0);
    if (bd == NULL)
    xenbus_dev_fatal(dev, -ENODEV, "bdget failed");



    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  6. [PATCH 04 of 24] xen: add missing definitions in include/xen/interface/vcpu.h which ia64/xen needs

    From: Isaku Yamahata

    Add xen handles realted definitions for xen vcpu which ia64/xen needs.
    Pointer argumsnts for ia64/xen hypercall are passed in pseudo physical
    address (guest physical address) so that it is required to convert
    guest kernel virtual address into pseudo physical address.
    The xen guest handle represents such arguments.

    Signed-off-by: Isaku Yamahata
    Signed-off-by: Jeremy Fitzhardinge
    ---
    include/xen/interface/vcpu.h | 6 +++++-
    1 file changed, 5 insertions(+), 1 deletion(-)

    diff --git a/include/xen/interface/vcpu.h b/include/xen/interface/vcpu.h
    --- a/include/xen/interface/vcpu.h
    +++ b/include/xen/interface/vcpu.h
    @@ -85,6 +85,7 @@
    */
    uint64_t time[4];
    };
    +DEFINE_GUEST_HANDLE_STRUCT(vcpu_runstate_info);

    /* VCPU is currently running on a physical CPU. */
    #define RUNSTATE_running 0
    @@ -119,6 +120,7 @@
    #define VCPUOP_register_runstate_memory_area 5
    struct vcpu_register_runstate_memory_area {
    union {
    + GUEST_HANDLE(vcpu_runstate_info) h;
    struct vcpu_runstate_info *v;
    uint64_t p;
    } addr;
    @@ -134,6 +136,7 @@
    struct vcpu_set_periodic_timer {
    uint64_t period_ns;
    };
    +DEFINE_GUEST_HANDLE_STRUCT(vcpu_set_periodic_time r);

    /*
    * Set or stop a VCPU's single-shot timer. Every VCPU has one single-shot
    @@ -145,6 +148,7 @@
    uint64_t timeout_abs_ns;
    uint32_t flags; /* VCPU_SSHOTTMR_??? */
    };
    +DEFINE_GUEST_HANDLE_STRUCT(vcpu_set_singleshot_ti mer);

    /* Flags to VCPUOP_set_singleshot_timer. */
    /* Require the timeout to be in the future (return -ETIME if it's passed). */
    @@ -164,5 +168,6 @@
    uint32_t offset; /* offset within page */
    uint32_t rsvd; /* unused */
    };
    +DEFINE_GUEST_HANDLE_STRUCT(vcpu_register_vcpu_inf o);

    #endif /* __XEN_PUBLIC_VCPU_H__ */


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  7. [PATCH 06 of 24] xen: Move events.c to drivers/xen for IA64/Xen support

    From: Isaku Yamahata

    move arch/x86/xen/events.c undedr drivers/xen to share codes
    with x86 and ia64. And minor adjustment to compile.
    ia64/xen also uses events.c

    Signed-off-by: Yaozu (Eddie) Dong
    Signed-off-by: Isaku Yamahata
    Signed-off-by: Jeremy Fitzhardinge
    ---
    arch/x86/xen/Makefile | 2 +-
    arch/x86/xen/xen-ops.h | 2 +-
    drivers/xen/Makefile | 2 +-
    drivers/xen/events.c | 3 +--
    include/xen/xen-ops.h | 9 ++++++++-
    5 files changed, 12 insertions(+), 6 deletions(-)

    diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
    --- a/arch/x86/xen/Makefile
    +++ b/arch/x86/xen/Makefile
    @@ -1,4 +1,4 @@
    obj-y := enlighten.o setup.o multicalls.o mmu.o \
    - events.o time.o manage.o xen-asm.o
    + time.o manage.o xen-asm.o

    obj-$(CONFIG_SMP) += smp.o
    diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
    --- a/arch/x86/xen/xen-ops.h
    +++ b/arch/x86/xen/xen-ops.h
    @@ -3,6 +3,7 @@

    #include
    #include
    +#include

    /* These are code, but not functions. Defined in entry.S */
    extern const char xen_hypervisor_callback[];
    @@ -10,7 +11,6 @@

    void xen_copy_trap_info(struct trap_info *traps);

    -DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
    DECLARE_PER_CPU(unsigned long, xen_cr3);
    DECLARE_PER_CPU(unsigned long, xen_current_cr3);

    diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
    --- a/drivers/xen/Makefile
    +++ b/drivers/xen/Makefile
    @@ -1,2 +1,2 @@
    -obj-y += grant-table.o features.o
    +obj-y += grant-table.o features.o events.o
    obj-y += xenbus/
    diff --git a/arch/x86/xen/events.c b/drivers/xen/events.c
    rename from arch/x86/xen/events.c
    rename to drivers/xen/events.c
    --- a/arch/x86/xen/events.c
    +++ b/drivers/xen/events.c
    @@ -33,11 +33,10 @@
    #include
    #include

    +#include
    #include
    #include
    #include
    -
    -#include "xen-ops.h"

    /*
    * This lock protects updates to the following mapping and reference-count
    diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
    new file mode 100644
    --- /dev/null
    +++ b/include/xen/xen-ops.h
    @@ -0,0 +1,8 @@
    +#ifndef INCLUDE_XEN_OPS_H
    +#define INCLUDE_XEN_OPS_H
    +
    +#include
    +
    +DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
    +
    +#endif /* INCLUDE_XEN_OPS_H */


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  8. [PATCH 02 of 24] xen: add missing VIRQ_ARCH_[0-7] definitions which ia64/xen needs

    From: Isaku Yamahata

    Add xen VIRQ numbers defined for arch specific use.
    ia64/xen domU uses VIRQ_ARCH_0 for virtual itc timer.
    Although all those constants aren't used yet by ia64
    at this moment, add all arch specific VIRQ numbers.

    Signed-off-by: Isaku Yamahata
    Signed-off-by: Jeremy Fitzhardinge
    ---
    include/xen/interface/xen.h | 13 +++++++++++--
    1 file changed, 11 insertions(+), 2 deletions(-)

    diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h
    --- a/include/xen/interface/xen.h
    +++ b/include/xen/interface/xen.h
    @@ -78,8 +78,18 @@
    #define VIRQ_CONSOLE 2 /* (DOM0) Bytes received on emergency console. */
    #define VIRQ_DOM_EXC 3 /* (DOM0) Exceptional event for some domain. */
    #define VIRQ_DEBUGGER 6 /* (DOM0) A domain has paused for debugging. */
    -#define NR_VIRQS 8

    +/* Architecture-specific VIRQ definitions. */
    +#define VIRQ_ARCH_0 16
    +#define VIRQ_ARCH_1 17
    +#define VIRQ_ARCH_2 18
    +#define VIRQ_ARCH_3 19
    +#define VIRQ_ARCH_4 20
    +#define VIRQ_ARCH_5 21
    +#define VIRQ_ARCH_6 22
    +#define VIRQ_ARCH_7 23
    +
    +#define NR_VIRQS 24
    /*
    * MMU-UPDATE REQUESTS
    *


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  9. [PATCH 09 of 24] xen: make include/xen/page.h portable moving those definitions under asm dir

    From: Isaku Yamahata

    The definitions in include/asm/xen/page.h are arch specific.
    ia64/xen wants to define its own version. So move them to arch specific
    directory and keep include/xen/page.h in order not to break compilation.

    Signed-off-by: Isaku Yamahata
    Signed-off-by: Jeremy Fitzhardinge
    ---
    include/asm-x86/xen/page.h | 168 +++++++++++++++++++++++++++++++++++++++++++
    include/xen/page.h | 169 --------------------------------------------
    2 files changed, 169 insertions(+), 168 deletions(-)

    diff --git a/include/asm-x86/xen/page.h b/include/asm-x86/xen/page.h
    new file mode 100644
    --- /dev/null
    +++ b/include/asm-x86/xen/page.h
    @@ -0,0 +1,168 @@
    +#ifndef __XEN_PAGE_H
    +#define __XEN_PAGE_H
    +
    +#include
    +
    +#include
    +#include
    +
    +#include
    +
    +/* Xen machine address */
    +typedef struct xmaddr {
    + phys_addr_t maddr;
    +} xmaddr_t;
    +
    +/* Xen pseudo-physical address */
    +typedef struct xpaddr {
    + phys_addr_t paddr;
    +} xpaddr_t;
    +
    +#define XMADDR(x) ((xmaddr_t) { .maddr = (x) })
    +#define XPADDR(x) ((xpaddr_t) { .paddr = (x) })
    +
    +/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
    +#define INVALID_P2M_ENTRY (~0UL)
    +#define FOREIGN_FRAME_BIT (1UL<<31)
    +#define FOREIGN_FRAME(m) ((m) | FOREIGN_FRAME_BIT)
    +
    +extern unsigned long *phys_to_machine_mapping;
    +
    +static inline unsigned long pfn_to_mfn(unsigned long pfn)
    +{
    + if (xen_feature(XENFEAT_auto_translated_physmap))
    + return pfn;
    +
    + return phys_to_machine_mapping[(unsigned int)(pfn)] &
    + ~FOREIGN_FRAME_BIT;
    +}
    +
    +static inline int phys_to_machine_mapping_valid(unsigned long pfn)
    +{
    + if (xen_feature(XENFEAT_auto_translated_physmap))
    + return 1;
    +
    + return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
    +}
    +
    +static inline unsigned long mfn_to_pfn(unsigned long mfn)
    +{
    + unsigned long pfn;
    +
    + if (xen_feature(XENFEAT_auto_translated_physmap))
    + return mfn;
    +
    +#if 0
    + if (unlikely((mfn >> machine_to_phys_order) != 0))
    + return max_mapnr;
    +#endif
    +
    + pfn = 0;
    + /*
    + * The array access can fail (e.g., device space beyond end of RAM).
    + * In such cases it doesn't matter what we return (we return garbage),
    + * but we must handle the fault without crashing!
    + */
    + __get_user(pfn, &machine_to_phys_mapping[mfn]);
    +
    + return pfn;
    +}
    +
    +static inline xmaddr_t phys_to_machine(xpaddr_t phys)
    +{
    + unsigned offset = phys.paddr & ~PAGE_MASK;
    + return XMADDR(PFN_PHYS((u64)pfn_to_mfn(PFN_DOWN(phys.padd r))) | offset);
    +}
    +
    +static inline xpaddr_t machine_to_phys(xmaddr_t machine)
    +{
    + unsigned offset = machine.maddr & ~PAGE_MASK;
    + return XPADDR(PFN_PHYS((u64)mfn_to_pfn(PFN_DOWN(machine.m addr))) | offset);
    +}
    +
    +/*
    + * We detect special mappings in one of two ways:
    + * 1. If the MFN is an I/O page then Xen will set the m2p entry
    + * to be outside our maximum possible pseudophys range.
    + * 2. If the MFN belongs to a different domain then we will certainly
    + * not have MFN in our p2m table. Conversely, if the page is ours,
    + * then we'll have p2m(m2p(MFN))==MFN.
    + * If we detect a special mapping then it doesn't have a 'struct page'.
    + * We force !pfn_valid() by returning an out-of-range pointer.
    + *
    + * NB. These checks require that, for any MFN that is not in our reservation,
    + * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
    + * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
    + * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
    + *
    + * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
    + * use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
    + * require. In all the cases we care about, the FOREIGN_FRAME bit is
    + * masked (e.g., pfn_to_mfn()) so behaviour there is correct.
    + */
    +static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
    +{
    + extern unsigned long max_mapnr;
    + unsigned long pfn = mfn_to_pfn(mfn);
    + if ((pfn < max_mapnr)
    + && !xen_feature(XENFEAT_auto_translated_physmap)
    + && (phys_to_machine_mapping[pfn] != mfn))
    + return max_mapnr; /* force !pfn_valid() */
    + return pfn;
    +}
    +
    +static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
    +{
    + if (xen_feature(XENFEAT_auto_translated_physmap)) {
    + BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
    + return;
    + }
    + phys_to_machine_mapping[pfn] = mfn;
    +}
    +
    +/* VIRT <-> MACHINE conversion */
    +#define virt_to_machine(v) (phys_to_machine(XPADDR(__pa(v))))
    +#define virt_to_mfn(v) (pfn_to_mfn(PFN_DOWN(__pa(v))))
    +#define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT))
    +
    +static inline unsigned long pte_mfn(pte_t pte)
    +{
    + return (pte.pte & ~_PAGE_NX) >> PAGE_SHIFT;
    +}
    +
    +static inline pte_t mfn_pte(unsigned long page_nr, pgprot_t pgprot)
    +{
    + pte_t pte;
    +
    + pte.pte = ((phys_addr_t)page_nr << PAGE_SHIFT) |
    + (pgprot_val(pgprot) & __supported_pte_mask);
    +
    + return pte;
    +}
    +
    +static inline pteval_t pte_val_ma(pte_t pte)
    +{
    + return pte.pte;
    +}
    +
    +static inline pte_t __pte_ma(pteval_t x)
    +{
    + return (pte_t) { .pte = x };
    +}
    +
    +#ifdef CONFIG_X86_PAE
    +#define pmd_val_ma(v) ((v).pmd)
    +#define pud_val_ma(v) ((v).pgd.pgd)
    +#define __pmd_ma(x) ((pmd_t) { (x) } )
    +#else /* !X86_PAE */
    +#define pmd_val_ma(v) ((v).pud.pgd.pgd)
    +#endif /* CONFIG_X86_PAE */
    +
    +#define pgd_val_ma(x) ((x).pgd)
    +
    +
    +xmaddr_t arbitrary_virt_to_machine(unsigned long address);
    +void make_lowmem_page_readonly(void *vaddr);
    +void make_lowmem_page_readwrite(void *vaddr);
    +
    +#endif /* __XEN_PAGE_H */
    diff --git a/include/xen/page.h b/include/xen/page.h
    --- a/include/xen/page.h
    +++ b/include/xen/page.h
    @@ -1,168 +1,1 @@
    -#ifndef __XEN_PAGE_H
    -#define __XEN_PAGE_H
    -
    -#include
    -
    -#include
    -#include
    -
    -#include
    -
    -/* Xen machine address */
    -typedef struct xmaddr {
    - phys_addr_t maddr;
    -} xmaddr_t;
    -
    -/* Xen pseudo-physical address */
    -typedef struct xpaddr {
    - phys_addr_t paddr;
    -} xpaddr_t;
    -
    -#define XMADDR(x) ((xmaddr_t) { .maddr = (x) })
    -#define XPADDR(x) ((xpaddr_t) { .paddr = (x) })
    -
    -/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
    -#define INVALID_P2M_ENTRY (~0UL)
    -#define FOREIGN_FRAME_BIT (1UL<<31)
    -#define FOREIGN_FRAME(m) ((m) | FOREIGN_FRAME_BIT)
    -
    -extern unsigned long *phys_to_machine_mapping;
    -
    -static inline unsigned long pfn_to_mfn(unsigned long pfn)
    -{
    - if (xen_feature(XENFEAT_auto_translated_physmap))
    - return pfn;
    -
    - return phys_to_machine_mapping[(unsigned int)(pfn)] &
    - ~FOREIGN_FRAME_BIT;
    -}
    -
    -static inline int phys_to_machine_mapping_valid(unsigned long pfn)
    -{
    - if (xen_feature(XENFEAT_auto_translated_physmap))
    - return 1;
    -
    - return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
    -}
    -
    -static inline unsigned long mfn_to_pfn(unsigned long mfn)
    -{
    - unsigned long pfn;
    -
    - if (xen_feature(XENFEAT_auto_translated_physmap))
    - return mfn;
    -
    -#if 0
    - if (unlikely((mfn >> machine_to_phys_order) != 0))
    - return max_mapnr;
    -#endif
    -
    - pfn = 0;
    - /*
    - * The array access can fail (e.g., device space beyond end of RAM).
    - * In such cases it doesn't matter what we return (we return garbage),
    - * but we must handle the fault without crashing!
    - */
    - __get_user(pfn, &machine_to_phys_mapping[mfn]);
    -
    - return pfn;
    -}
    -
    -static inline xmaddr_t phys_to_machine(xpaddr_t phys)
    -{
    - unsigned offset = phys.paddr & ~PAGE_MASK;
    - return XMADDR(PFN_PHYS((u64)pfn_to_mfn(PFN_DOWN(phys.padd r))) | offset);
    -}
    -
    -static inline xpaddr_t machine_to_phys(xmaddr_t machine)
    -{
    - unsigned offset = machine.maddr & ~PAGE_MASK;
    - return XPADDR(PFN_PHYS((u64)mfn_to_pfn(PFN_DOWN(machine.m addr))) | offset);
    -}
    -
    -/*
    - * We detect special mappings in one of two ways:
    - * 1. If the MFN is an I/O page then Xen will set the m2p entry
    - * to be outside our maximum possible pseudophys range.
    - * 2. If the MFN belongs to a different domain then we will certainly
    - * not have MFN in our p2m table. Conversely, if the page is ours,
    - * then we'll have p2m(m2p(MFN))==MFN.
    - * If we detect a special mapping then it doesn't have a 'struct page'.
    - * We force !pfn_valid() by returning an out-of-range pointer.
    - *
    - * NB. These checks require that, for any MFN that is not in our reservation,
    - * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
    - * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
    - * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
    - *
    - * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
    - * use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
    - * require. In all the cases we care about, the FOREIGN_FRAME bit is
    - * masked (e.g., pfn_to_mfn()) so behaviour there is correct.
    - */
    -static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
    -{
    - extern unsigned long max_mapnr;
    - unsigned long pfn = mfn_to_pfn(mfn);
    - if ((pfn < max_mapnr)
    - && !xen_feature(XENFEAT_auto_translated_physmap)
    - && (phys_to_machine_mapping[pfn] != mfn))
    - return max_mapnr; /* force !pfn_valid() */
    - return pfn;
    -}
    -
    -static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
    -{
    - if (xen_feature(XENFEAT_auto_translated_physmap)) {
    - BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
    - return;
    - }
    - phys_to_machine_mapping[pfn] = mfn;
    -}
    -
    -/* VIRT <-> MACHINE conversion */
    -#define virt_to_machine(v) (phys_to_machine(XPADDR(__pa(v))))
    -#define virt_to_mfn(v) (pfn_to_mfn(PFN_DOWN(__pa(v))))
    -#define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT))
    -
    -static inline unsigned long pte_mfn(pte_t pte)
    -{
    - return (pte.pte & ~_PAGE_NX) >> PAGE_SHIFT;
    -}
    -
    -static inline pte_t mfn_pte(unsigned long page_nr, pgprot_t pgprot)
    -{
    - pte_t pte;
    -
    - pte.pte = ((phys_addr_t)page_nr << PAGE_SHIFT) |
    - (pgprot_val(pgprot) & __supported_pte_mask);
    -
    - return pte;
    -}
    -
    -static inline pteval_t pte_val_ma(pte_t pte)
    -{
    - return pte.pte;
    -}
    -
    -static inline pte_t __pte_ma(pteval_t x)
    -{
    - return (pte_t) { .pte = x };
    -}
    -
    -#ifdef CONFIG_X86_PAE
    -#define pmd_val_ma(v) ((v).pmd)
    -#define pud_val_ma(v) ((v).pgd.pgd)
    -#define __pmd_ma(x) ((pmd_t) { (x) } )
    -#else /* !X86_PAE */
    -#define pmd_val_ma(v) ((v).pud.pgd.pgd)
    -#endif /* CONFIG_X86_PAE */
    -
    -#define pgd_val_ma(x) ((x).pgd)
    -
    -
    -xmaddr_t arbitrary_virt_to_machine(unsigned long address);
    -void make_lowmem_page_readonly(void *vaddr);
    -void make_lowmem_page_readwrite(void *vaddr);
    -
    -#endif /* __XEN_PAGE_H */
    +#include


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  10. [PATCH 08 of 24] Re: [PATCH 08/12] xen: add resend_irq_on_evtchn() definition into events.c

    From: Isaku Yamahata

    Define resend_irq_on_evtchn() which ia64/xen uses.
    Although it isn't used by current x86/xen code, it's arch generic
    so that put it into common code.

    Signed-off-by: Isaku Yamahata
    Signed-off-by: Jeremy Fitzhardinge
    ---
    drivers/xen/events.c | 16 ++++++++++++++++
    include/xen/events.h | 3 +--
    2 files changed, 17 insertions(+), 2 deletions(-)

    diff --git a/drivers/xen/events.c b/drivers/xen/events.c
    --- a/drivers/xen/events.c
    +++ b/drivers/xen/events.c
    @@ -586,6 +586,22 @@
    rebind_irq_to_cpu(irq, tcpu);
    }

    +int resend_irq_on_evtchn(unsigned int irq)
    +{
    + int masked, evtchn = evtchn_from_irq(irq);
    + struct shared_info *s = HYPERVISOR_shared_info;
    +
    + if (!VALID_EVTCHN(evtchn))
    + return 1;
    +
    + masked = sync_test_and_set_bit(evtchn, s->evtchn_mask);
    + sync_set_bit(evtchn, s->evtchn_pending);
    + if (!masked)
    + unmask_evtchn(evtchn);
    +
    + return 1;
    +}
    +
    static void enable_dynirq(unsigned int irq)
    {
    int evtchn = evtchn_from_irq(irq);
    diff --git a/include/xen/events.h b/include/xen/events.h
    --- a/include/xen/events.h
    +++ b/include/xen/events.h
    @@ -31,6 +31,7 @@
    void unbind_from_irqhandler(unsigned int irq, void *dev_id);

    void xen_send_IPI_one(unsigned int cpu, enum ipi_vector vector);
    +int resend_irq_on_evtchn(unsigned int irq);

    static inline void notify_remote_via_evtchn(int port)
    {


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  11. [PATCH 13 of 24] [PATCH] xen: Make xen-blkfront write its protocol ABI to xenstore

    From: Markus Armbruster

    Frontends are expected to write their protocol ABI to xenstore. Since
    the protocol ABI defaults to the backend's native ABI, things work
    fine without that as long as the frontend's native ABI is identical to
    the backend's native ABI. This is not the case for xen-blkfront
    running 32-on-64, because its ABI differs between 32 and 64 bit, and
    thus needs this fix.

    Based on http://xenbits.xensource.com/xen-uns...v/c545932a18f3
    and http://xenbits.xensource.com/xen-uns...v/ffe52263b430 by
    Gerd Hoffmann

    Signed-off-by: Markus Armbruster
    Signed-off-by: Jeremy Fitzhardinge
    ---
    drivers/block/xen-blkfront.c | 7 +++++++
    include/xen/interface/io/protocols.h | 22 +++++++++++++++++++++-
    2 files changed, 28 insertions(+), 1 deletion(-)

    diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
    --- a/drivers/block/xen-blkfront.c
    +++ b/drivers/block/xen-blkfront.c
    @@ -47,6 +47,7 @@

    #include
    #include
    +#include

    #include

    @@ -614,6 +615,12 @@
    message = "writing event-channel";
    goto abort_transaction;
    }
    + err = xenbus_printf(xbt, dev->nodename, "protocol", "%s",
    + XEN_IO_PROTO_ABI_NATIVE);
    + if (err) {
    + message = "writing protocol";
    + goto abort_transaction;
    + }

    err = xenbus_transaction_end(xbt, 0);
    if (err) {
    diff --git a/include/xen/interface/io/protocols.h b/include/xen/interface/io/protocols.h
    new file mode 100644
    --- /dev/null
    +++ b/include/xen/interface/io/protocols.h
    @@ -0,0 +1,21 @@
    +#ifndef __XEN_PROTOCOLS_H__
    +#define __XEN_PROTOCOLS_H__
    +
    +#define XEN_IO_PROTO_ABI_X86_32 "x86_32-abi"
    +#define XEN_IO_PROTO_ABI_X86_64 "x86_64-abi"
    +#define XEN_IO_PROTO_ABI_IA64 "ia64-abi"
    +#define XEN_IO_PROTO_ABI_POWERPC64 "powerpc64-abi"
    +
    +#if defined(__i386__)
    +# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32
    +#elif defined(__x86_64__)
    +# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_64
    +#elif defined(__ia64__)
    +# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_IA64
    +#elif defined(__powerpc64__)
    +# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_POWERPC64
    +#else
    +# error arch fixup needed here
    +#endif
    +
    +#endif


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  12. [PATCH 07 of 24] Xen: Make events.c portable for ia64/xen support

    From: Isaku Yamahata

    Remove x86 dependency in drivers/xen/events.c for ia64/xen support
    introducing include/asm/xen/events.h.
    Introduce xen_irqs_disabled() to hide regs->flags
    Introduce xen_do_IRQ() to hide regs->orig_ax.
    make enum ipi_vector definition arch specific. ia64/xen needs four vectors.
    Add one rmb() because on ia64 xchg() isn't barrier.

    Signed-off-by: Isaku Yamahata
    Signed-off-by: Jeremy Fitzhardinge
    ---
    drivers/xen/events.c | 13 +++++++------
    include/asm-x86/xen/events.h | 22 ++++++++++++++++++++++
    include/xen/events.h | 10 +---------
    3 files changed, 30 insertions(+), 15 deletions(-)

    diff --git a/drivers/xen/events.c b/drivers/xen/events.c
    --- a/drivers/xen/events.c
    +++ b/drivers/xen/events.c
    @@ -469,7 +469,7 @@
    for_each_online_cpu(i) {
    struct vcpu_info *v = per_cpu(xen_vcpu, i);
    printk("%d: masked=%d pending=%d event_sel %08lx\n ", i,
    - (get_irq_regs() && i == cpu) ? !(get_irq_regs()->flags & X86_EFLAGS_IF) : v->evtchn_upcall_mask,
    + (get_irq_regs() && i == cpu) ? xen_irqs_disabled(get_irq_regs()) : v->evtchn_upcall_mask,
    v->evtchn_upcall_pending,
    v->evtchn_pending_sel);
    }
    @@ -527,7 +527,10 @@
    if (__get_cpu_var(nesting_count)++)
    goto out;

    - /* NB. No need for a barrier here -- XCHG is a barrier on x86. */
    +#ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
    + /* Clear master flag /before/ clearing selector flag. */
    + rmb();
    +#endif
    pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0);
    while (pending_words != 0) {
    unsigned long pending_bits;
    @@ -539,10 +542,8 @@
    int port = (word_idx * BITS_PER_LONG) + bit_idx;
    int irq = evtchn_to_irq[port];

    - if (irq != -1) {
    - regs->orig_ax = ~irq;
    - do_IRQ(regs);
    - }
    + if (irq != -1)
    + xen_do_IRQ(irq, regs);
    }
    }

    diff --git a/include/asm-x86/xen/events.h b/include/asm-x86/xen/events.h
    new file mode 100644
    --- /dev/null
    +++ b/include/asm-x86/xen/events.h
    @@ -0,0 +1,22 @@
    +#ifndef __XEN_EVENTS_H
    +#define __XEN_EVENTS_H
    +
    +enum ipi_vector {
    + XEN_RESCHEDULE_VECTOR,
    + XEN_CALL_FUNCTION_VECTOR,
    +
    + XEN_NR_IPIS,
    +};
    +
    +static inline int xen_irqs_disabled(struct pt_regs *regs)
    +{
    + return raw_irqs_disabled_flags(regs->flags);
    +}
    +
    +static inline void xen_do_IRQ(int irq, struct pt_regs *regs)
    +{
    + regs->orig_ax = ~irq;
    + do_IRQ(regs);
    +}
    +
    +#endif /* __XEN_EVENTS_H */
    diff --git a/include/xen/events.h b/include/xen/events.h
    --- a/include/xen/events.h
    +++ b/include/xen/events.h
    @@ -5,13 +5,7 @@

    #include
    #include
    -
    -enum ipi_vector {
    - XEN_RESCHEDULE_VECTOR,
    - XEN_CALL_FUNCTION_VECTOR,
    -
    - XEN_NR_IPIS,
    -};
    +#include

    int bind_evtchn_to_irq(unsigned int evtchn);
    int bind_evtchn_to_irqhandler(unsigned int evtchn,


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  13. [PATCH 05 of 24] xen: move features.c from arch/x86/xen/features.c to drivers/xen

    From: Isaku Yamahata

    ia64/xen also uses it too. Move it into common place so that
    ia64/xen can share the code.

    Signed-off-by: Isaku Yamahata
    Signed-off-by: Jeremy Fitzhardinge
    ---
    arch/x86/xen/Makefile | 2 +-
    drivers/xen/Makefile | 2 +-
    drivers/xen/features.c | 1 -
    3 files changed, 2 insertions(+), 3 deletions(-)

    diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
    --- a/arch/x86/xen/Makefile
    +++ b/arch/x86/xen/Makefile
    @@ -1,4 +1,4 @@
    -obj-y := enlighten.o setup.o features.o multicalls.o mmu.o \
    +obj-y := enlighten.o setup.o multicalls.o mmu.o \
    events.o time.o manage.o xen-asm.o

    obj-$(CONFIG_SMP) += smp.o
    diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
    --- a/drivers/xen/Makefile
    +++ b/drivers/xen/Makefile
    @@ -1,2 +1,2 @@
    -obj-y += grant-table.o
    +obj-y += grant-table.o features.o
    obj-y += xenbus/
    diff --git a/arch/x86/xen/features.c b/drivers/xen/features.c
    rename from arch/x86/xen/features.c
    rename to drivers/xen/features.c


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  14. [PATCH 21 of 24] xen: allow set_pte_at on init_mm to be lockless

    The usual pagetable locking protocol doesn't seem to apply to updates
    to init_mm, so don't rely on preemption being disabled in xen_set_pte_at
    on init_mm.

    Signed-off-by: Jeremy Fitzhardinge
    ---
    arch/x86/xen/mmu.c | 12 ++++++++++--
    1 file changed, 10 insertions(+), 2 deletions(-)

    diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
    --- a/arch/x86/xen/mmu.c
    +++ b/arch/x86/xen/mmu.c
    @@ -156,6 +156,10 @@
    void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
    pte_t *ptep, pte_t pteval)
    {
    + /* updates to init_mm may be done without lock */
    + if (mm == &init_mm)
    + preempt_disable();
    +
    if (mm == current->mm || mm == &init_mm) {
    if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
    struct multicall_space mcs;
    @@ -163,12 +167,16 @@

    MULTI_update_va_mapping(mcs.mc, addr, pteval, 0);
    xen_mc_issue(PARAVIRT_LAZY_MMU);
    - return;
    + goto out;
    } else
    if (HYPERVISOR_update_va_mapping(addr, pteval, 0) == 0)
    - return;
    + goto out;
    }
    xen_set_pte(ptep, pteval);
    +
    +out:
    + if (mm == &init_mm)
    + preempt_enable();
    }

    pteval_t xen_pte_val(pte_t pte)


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  15. [PATCH 12 of 24] xen: import arch generic part of xencomm

    From: Isaku Yamahata

    On xen/ia64 and xen/powerpc hypercall arguments are passed by pseudo
    physical address (guest physical address) so that it's necessary to
    convert from virtual address into pseudo physical address. The frame
    work is called xencomm.
    Import arch generic part of xencomm.

    Signed-off-by: Isaku Yamahata
    Signed-off-by: Jeremy Fitzhardinge
    ---
    drivers/xen/Makefile | 1
    drivers/xen/xencomm.c | 232 +++++++++++++++++++++++++++++++++++++++
    include/xen/interface/xencomm.h | 41 ++++++
    include/xen/xencomm.h | 78 ++++++++++++-
    4 files changed, 351 insertions(+), 1 deletion(-)

    diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
    --- a/drivers/xen/Makefile
    +++ b/drivers/xen/Makefile
    @@ -1,2 +1,3 @@
    obj-y += grant-table.o features.o events.o
    obj-y += xenbus/
    +obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
    diff --git a/drivers/xen/xencomm.c b/drivers/xen/xencomm.c
    new file mode 100644
    --- /dev/null
    +++ b/drivers/xen/xencomm.c
    @@ -0,0 +1,232 @@
    +/*
    + * 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
    + *
    + * Copyright (C) IBM Corp. 2006
    + *
    + * Authors: Hollis Blanchard
    + */
    +
    +#include
    +#include
    +#include
    +#include
    +#include
    +#ifdef __ia64__
    +#include /* for is_kern_addr() */
    +#endif
    +
    +#ifdef HAVE_XEN_PLATFORM_COMPAT_H
    +#include
    +#endif
    +
    +static int xencomm_init(struct xencomm_desc *desc,
    + void *buffer, unsigned long bytes)
    +{
    + unsigned long recorded = 0;
    + int i = 0;
    +
    + while ((recorded < bytes) && (i < desc->nr_addrs)) {
    + unsigned long vaddr = (unsigned long)buffer + recorded;
    + unsigned long paddr;
    + int offset;
    + int chunksz;
    +
    + offset = vaddr % PAGE_SIZE; /* handle partial pages */
    + chunksz = min(PAGE_SIZE - offset, bytes - recorded);
    +
    + paddr = xencomm_vtop(vaddr);
    + if (paddr == ~0UL) {
    + printk(KERN_DEBUG "%s: couldn't translate vaddr %lx\n",
    + __func__, vaddr);
    + return -EINVAL;
    + }
    +
    + desc->address[i++] = paddr;
    + recorded += chunksz;
    + }
    +
    + if (recorded < bytes) {
    + printk(KERN_DEBUG
    + "%s: could only translate %ld of %ld bytes\n",
    + __func__, recorded, bytes);
    + return -ENOSPC;
    + }
    +
    + /* mark remaining addresses invalid (just for safety) */
    + while (i < desc->nr_addrs)
    + desc->address[i++] = XENCOMM_INVALID;
    +
    + desc->magic = XENCOMM_MAGIC;
    +
    + return 0;
    +}
    +
    +static struct xencomm_desc *xencomm_alloc(gfp_t gfp_mask,
    + void *buffer, unsigned long bytes)
    +{
    + struct xencomm_desc *desc;
    + unsigned long buffer_ulong = (unsigned long)buffer;
    + unsigned long start = buffer_ulong & PAGE_MASK;
    + unsigned long end = (buffer_ulong + bytes) | ~PAGE_MASK;
    + unsigned long nr_addrs = (end - start + 1) >> PAGE_SHIFT;
    + unsigned long size = sizeof(*desc) +
    + sizeof(desc->address[0]) * nr_addrs;
    +
    + /*
    + * slab allocator returns at least sizeof(void*) aligned pointer.
    + * When sizeof(*desc) > sizeof(void*), struct xencomm_desc might
    + * cross page boundary.
    + */
    + if (sizeof(*desc) > sizeof(void *)) {
    + unsigned long order = get_order(size);
    + desc = (struct xencomm_desc *)__get_free_pages(gfp_mask,
    + order);
    + if (desc == NULL)
    + return NULL;
    +
    + desc->nr_addrs =
    + ((PAGE_SIZE << order) - sizeof(struct xencomm_desc)) /
    + sizeof(*desc->address);
    + } else {
    + desc = kmalloc(size, gfp_mask);
    + if (desc == NULL)
    + return NULL;
    +
    + desc->nr_addrs = nr_addrs;
    + }
    + return desc;
    +}
    +
    +void xencomm_free(struct xencomm_handle *desc)
    +{
    + if (desc && !((ulong)desc & XENCOMM_INLINE_FLAG)) {
    + struct xencomm_desc *desc__ = (struct xencomm_desc *)desc;
    + if (sizeof(*desc__) > sizeof(void *)) {
    + unsigned long size = sizeof(*desc__) +
    + sizeof(desc__->address[0]) * desc__->nr_addrs;
    + unsigned long order = get_order(size);
    + free_pages((unsigned long)__va(desc), order);
    + } else
    + kfree(__va(desc));
    + }
    +}
    +
    +static int xencomm_create(void *buffer, unsigned long bytes,
    + struct xencomm_desc **ret, gfp_t gfp_mask)
    +{
    + struct xencomm_desc *desc;
    + int rc;
    +
    + pr_debug("%s: %p[%ld]\n", __func__, buffer, bytes);
    +
    + if (bytes == 0) {
    + /* don't create a descriptor; Xen recognizes NULL. */
    + BUG_ON(buffer != NULL);
    + *ret = NULL;
    + return 0;
    + }
    +
    + BUG_ON(buffer == NULL); /* 'bytes' is non-zero */
    +
    + desc = xencomm_alloc(gfp_mask, buffer, bytes);
    + if (!desc) {
    + printk(KERN_DEBUG "%s failure\n", "xencomm_alloc");
    + return -ENOMEM;
    + }
    +
    + rc = xencomm_init(desc, buffer, bytes);
    + if (rc) {
    + printk(KERN_DEBUG "%s failure: %d\n", "xencomm_init", rc);
    + xencomm_free((struct xencomm_handle *)__pa(desc));
    + return rc;
    + }
    +
    + *ret = desc;
    + return 0;
    +}
    +
    +/* check if memory address is within VMALLOC region */
    +static int is_phys_contiguous(unsigned long addr)
    +{
    + if (!is_kernel_addr(addr))
    + return 0;
    +
    + return (addr < VMALLOC_START) || (addr >= VMALLOC_END);
    +}
    +
    +static struct xencomm_handle *xencomm_create_inline(void *ptr)
    +{
    + unsigned long paddr;
    +
    + BUG_ON(!is_phys_contiguous((unsigned long)ptr));
    +
    + paddr = (unsigned long)xencomm_pa(ptr);
    + BUG_ON(paddr & XENCOMM_INLINE_FLAG);
    + return (struct xencomm_handle *)(paddr | XENCOMM_INLINE_FLAG);
    +}
    +
    +/* "mini" routine, for stack-based communications: */
    +static int xencomm_create_mini(void *buffer,
    + unsigned long bytes, struct xencomm_mini *xc_desc,
    + struct xencomm_desc **ret)
    +{
    + int rc = 0;
    + struct xencomm_desc *desc;
    + BUG_ON(((unsigned long)xc_desc) % sizeof(*xc_desc) != 0);
    +
    + desc = (void *)xc_desc;
    +
    + desc->nr_addrs = XENCOMM_MINI_ADDRS;
    +
    + rc = xencomm_init(desc, buffer, bytes);
    + if (!rc)
    + *ret = desc;
    +
    + return rc;
    +}
    +
    +struct xencomm_handle *xencomm_map(void *ptr, unsigned long bytes)
    +{
    + int rc;
    + struct xencomm_desc *desc;
    +
    + if (is_phys_contiguous((unsigned long)ptr))
    + return xencomm_create_inline(ptr);
    +
    + rc = xencomm_create(ptr, bytes, &desc, GFP_KERNEL);
    +
    + if (rc || desc == NULL)
    + return NULL;
    +
    + return xencomm_pa(desc);
    +}
    +
    +struct xencomm_handle *__xencomm_map_no_alloc(void *ptr, unsigned long bytes,
    + struct xencomm_mini *xc_desc)
    +{
    + int rc;
    + struct xencomm_desc *desc = NULL;
    +
    + if (is_phys_contiguous((unsigned long)ptr))
    + return xencomm_create_inline(ptr);
    +
    + rc = xencomm_create_mini(ptr, bytes, xc_desc,
    + &desc);
    +
    + if (rc)
    + return NULL;
    +
    + return xencomm_pa(desc);
    +}
    diff --git a/include/xen/interface/xencomm.h b/include/xen/interface/xencomm.h
    new file mode 100644
    --- /dev/null
    +++ b/include/xen/interface/xencomm.h
    @@ -0,0 +1,41 @@
    +/*
    + * Permission is hereby granted, free of charge, to any person obtaining a copy
    + * of this software and associated documentation files (the "Software"), to
    + * deal in the Software without restriction, including without limitation the
    + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    + * sell copies of the Software, and to permit persons to whom the Software is
    + * furnished to do so, subject to the following conditions:
    + *
    + * The above copyright notice and this permission notice shall be included in
    + * all copies or substantial portions of the Software.
    + *
    + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    + * DEALINGS IN THE SOFTWARE.
    + *
    + * Copyright (C) IBM Corp. 2006
    + */
    +
    +#ifndef _XEN_XENCOMM_H_
    +#define _XEN_XENCOMM_H_
    +
    +/* A xencomm descriptor is a scatter/gather list containing physical
    + * addresses corresponding to a virtually contiguous memory area. The
    + * hypervisor translates these physical addresses to machine addresses to copy
    + * to and from the virtually contiguous area.
    + */
    +
    +#define XENCOMM_MAGIC 0x58434F4D /* 'XCOM' */
    +#define XENCOMM_INVALID (~0UL)
    +
    +struct xencomm_desc {
    + uint32_t magic;
    + uint32_t nr_addrs; /* the number of entries in address[] */
    + uint64_t address[0];
    +};
    +
    +#endif /* _XEN_XENCOMM_H_ */
    diff --git a/include/xen/xencomm.h b/include/xen/xencomm.h
    new file mode 100644
    --- /dev/null
    +++ b/include/xen/xencomm.h
    @@ -0,0 +1,77 @@
    +/*
    + * 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
    + *
    + * Copyright (C) IBM Corp. 2006
    + *
    + * Authors: Hollis Blanchard
    + * Jerone Young
    + */
    +
    +#ifndef _LINUX_XENCOMM_H_
    +#define _LINUX_XENCOMM_H_
    +
    +#include
    +
    +#define XENCOMM_MINI_ADDRS 3
    +struct xencomm_mini {
    + struct xencomm_desc _desc;
    + uint64_t address[XENCOMM_MINI_ADDRS];
    +};
    +
    +/* To avoid additionnal virt to phys conversion, an opaque structure is
    + presented. */
    +struct xencomm_handle;
    +
    +extern void xencomm_free(struct xencomm_handle *desc);
    +extern struct xencomm_handle *xencomm_map(void *ptr, unsigned long bytes);
    +extern struct xencomm_handle *__xencomm_map_no_alloc(void *ptr,
    + unsigned long bytes, struct xencomm_mini *xc_area);
    +
    +#if 0
    +#define XENCOMM_MINI_ALIGNED(xc_desc, n) \
    + struct xencomm_mini xc_desc ## _base[(n)] \
    + __attribute__((__aligned__(sizeof(struct xencomm_mini)))); \
    + struct xencomm_mini *xc_desc = &xc_desc ## _base[0];
    +#else
    +/*
    + * gcc bug workaround:
    + * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16660
    + * gcc doesn't handle properly stack variable with
    + * __attribute__((__align__(sizeof(struct xencomm_mini))))
    + */
    +#define XENCOMM_MINI_ALIGNED(xc_desc, n) \
    + unsigned char xc_desc ## _base[((n) + 1 ) * \
    + sizeof(struct xencomm_mini)]; \
    + struct xencomm_mini *xc_desc = (struct xencomm_mini *) \
    + ((unsigned long)xc_desc ## _base + \
    + (sizeof(struct xencomm_mini) - \
    + ((unsigned long)xc_desc ## _base) % \
    + sizeof(struct xencomm_mini)));
    +#endif
    +#define xencomm_map_no_alloc(ptr, bytes) \
    + ({ XENCOMM_MINI_ALIGNED(xc_desc, 1); \
    + __xencomm_map_no_alloc(ptr, bytes, xc_desc); })
    +
    +/* provided by architecture code: */
    +extern unsigned long xencomm_vtop(unsigned long vaddr);
    +
    +static inline void *xencomm_pa(void *ptr)
    +{
    + return (void *)xencomm_vtop((unsigned long)ptr);
    +}
    +
    +#define xen_guest_handle(hnd) ((hnd).p)
    +
    +#endif /* _LINUX_XENCOMM_H_ */


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  16. [PATCH 18 of 24] xen pvfb: Para-virtual framebuffer, keyboard and pointer driver

    From: Markus Armbruster

    This is a pair of Xen para-virtual frontend device drivers:
    drivers/video/xen-fbfront.c provides a framebuffer, and
    drivers/input/xen-kbdfront provides keyboard and mouse.

    The backends run in dom0 user space.

    The two drivers are not in two separate patches, because the
    intermediate step (one driver, not the other) is somewhat problematic:
    the backend in dom0 needs both drivers, and will refuse to complete
    device initialization unless they're both present.

    Signed-off-by: Markus Armbruster

    ---
    drivers/input/Kconfig | 9
    drivers/input/Makefile | 2
    drivers/input/xen-kbdfront.c | 340 +++++++++++++++++++++++
    drivers/video/Kconfig | 14
    drivers/video/Makefile | 1
    drivers/video/xen-fbfront.c | 550 ++++++++++++++++++++++++++++++++++++++
    include/xen/interface/io/fbif.h | 124 ++++++++
    include/xen/interface/io/kbdif.h | 114 +++++++
    8 files changed, 1154 insertions(+)

    diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
    --- a/drivers/input/Kconfig
    +++ b/drivers/input/Kconfig
    @@ -149,6 +149,15 @@
    To compile this driver as a module, choose M here: the
    module will be called apm-power.

    +config XEN_KBDDEV_FRONTEND
    + tristate "Xen virtual keyboard and mouse support"
    + depends on XEN_FBDEV_FRONTEND
    + default y
    + help
    + This driver implements the front-end of the Xen virtual
    + keyboard and mouse device driver. It communicates with a back-end
    + in another domain.
    +
    comment "Input Device Drivers"

    source "drivers/input/keyboard/Kconfig"
    diff --git a/drivers/input/Makefile b/drivers/input/Makefile
    --- a/drivers/input/Makefile
    +++ b/drivers/input/Makefile
    @@ -23,3 +23,5 @@
    obj-$(CONFIG_INPUT_MISC) += misc/

    obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o
    +
    +obj-$(CONFIG_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o
    diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c
    new file mode 100644
    --- /dev/null
    +++ b/drivers/input/xen-kbdfront.c
    @@ -0,0 +1,340 @@
    +/*
    + * Xen para-virtual input device
    + *
    + * Copyright (C) 2005 Anthony Liguori
    + * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster
    + *
    + * Based on linux/drivers/input/mouse/sermouse.c
    + *
    + * This file is subject to the terms and conditions of the GNU General Public
    + * License. See the file COPYING in the main directory of this archive for
    + * more details.
    + */
    +
    +/*
    + * TODO:
    + *
    + * Switch to grant tables together with xen-fbfront.c.
    + */
    +
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +
    +struct xenkbd_info {
    + struct input_dev *kbd;
    + struct input_dev *ptr;
    + struct xenkbd_page *page;
    + int irq;
    + struct xenbus_device *xbdev;
    + char phys[32];
    +};
    +
    +static int xenkbd_remove(struct xenbus_device *);
    +static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
    +static void xenkbd_disconnect_backend(struct xenkbd_info *);
    +
    +/*
    + * Note: if you need to send out events, see xenfb_do_update() for how
    + * to do that.
    + */
    +
    +static irqreturn_t input_handler(int rq, void *dev_id)
    +{
    + struct xenkbd_info *info = dev_id;
    + struct xenkbd_page *page = info->page;
    + __u32 cons, prod;
    +
    + prod = page->in_prod;
    + if (prod == page->in_cons)
    + return IRQ_HANDLED;
    + rmb(); /* ensure we see ring contents up to prod */
    + for (cons = page->in_cons; cons != prod; cons++) {
    + union xenkbd_in_event *event;
    + struct input_dev *dev;
    + event = &XENKBD_IN_RING_REF(page, cons);
    +
    + dev = info->ptr;
    + switch (event->type) {
    + case XENKBD_TYPE_MOTION:
    + input_report_rel(dev, REL_X, event->motion.rel_x);
    + input_report_rel(dev, REL_Y, event->motion.rel_y);
    + break;
    + case XENKBD_TYPE_KEY:
    + dev = NULL;
    + if (test_bit(event->key.keycode, info->kbd->keybit))
    + dev = info->kbd;
    + if (test_bit(event->key.keycode, info->ptr->keybit))
    + dev = info->ptr;
    + if (dev)
    + input_report_key(dev, event->key.keycode,
    + event->key.pressed);
    + else
    + printk(KERN_WARNING
    + "xenkbd: unhandled keycode 0x%x\n",
    + event->key.keycode);
    + break;
    + case XENKBD_TYPE_POS:
    + input_report_abs(dev, ABS_X, event->pos.abs_x);
    + input_report_abs(dev, ABS_Y, event->pos.abs_y);
    + break;
    + }
    + if (dev)
    + input_sync(dev);
    + }
    + mb(); /* ensure we got ring contents */
    + page->in_cons = cons;
    + notify_remote_via_irq(info->irq);
    +
    + return IRQ_HANDLED;
    +}
    +
    +static int __devinit xenkbd_probe(struct xenbus_device *dev,
    + const struct xenbus_device_id *id)
    +{
    + int ret, i;
    + struct xenkbd_info *info;
    + struct input_dev *kbd, *ptr;
    +
    + info = kzalloc(sizeof(*info), GFP_KERNEL);
    + if (!info) {
    + xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
    + return -ENOMEM;
    + }
    + dev->dev.driver_data = info;
    + info->xbdev = dev;
    + info->irq = -1;
    + snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
    +
    + info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
    + if (!info->page)
    + goto error_nomem;
    +
    + /* keyboard */
    + kbd = input_allocate_device();
    + if (!kbd)
    + goto error_nomem;
    + kbd->name = "Xen Virtual Keyboard";
    + kbd->phys = info->phys;
    + kbd->id.bustype = BUS_PCI;
    + kbd->id.vendor = 0x5853;
    + kbd->id.product = 0xffff;
    + kbd->evbit[0] = BIT(EV_KEY);
    + for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
    + set_bit(i, kbd->keybit);
    + for (i = KEY_OK; i < KEY_MAX; i++)
    + set_bit(i, kbd->keybit);
    +
    + ret = input_register_device(kbd);
    + if (ret) {
    + input_free_device(kbd);
    + xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
    + goto error;
    + }
    + info->kbd = kbd;
    +
    + /* pointing device */
    + ptr = input_allocate_device();
    + if (!ptr)
    + goto error_nomem;
    + ptr->name = "Xen Virtual Pointer";
    + ptr->phys = info->phys;
    + ptr->id.bustype = BUS_PCI;
    + ptr->id.vendor = 0x5853;
    + ptr->id.product = 0xfffe;
    + ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
    + for (i = BTN_LEFT; i <= BTN_TASK; i++)
    + set_bit(i, ptr->keybit);
    + ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y);
    + input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
    + input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
    +
    + ret = input_register_device(ptr);
    + if (ret) {
    + input_free_device(ptr);
    + xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
    + goto error;
    + }
    + info->ptr = ptr;
    +
    + ret = xenkbd_connect_backend(dev, info);
    + if (ret < 0)
    + goto error;
    +
    + return 0;
    +
    + error_nomem:
    + ret = -ENOMEM;
    + xenbus_dev_fatal(dev, ret, "allocating device memory");
    + error:
    + xenkbd_remove(dev);
    + return ret;
    +}
    +
    +static int xenkbd_resume(struct xenbus_device *dev)
    +{
    + struct xenkbd_info *info = dev->dev.driver_data;
    +
    + xenkbd_disconnect_backend(info);
    + memset(info->page, 0, PAGE_SIZE);
    + return xenkbd_connect_backend(dev, info);
    +}
    +
    +static int xenkbd_remove(struct xenbus_device *dev)
    +{
    + struct xenkbd_info *info = dev->dev.driver_data;
    +
    + xenkbd_disconnect_backend(info);
    + if (info->kbd)
    + input_unregister_device(info->kbd);
    + if (info->ptr)
    + input_unregister_device(info->ptr);
    + free_page((unsigned long)info->page);
    + kfree(info);
    + return 0;
    +}
    +
    +static int xenkbd_connect_backend(struct xenbus_device *dev,
    + struct xenkbd_info *info)
    +{
    + int ret, evtchn;
    + struct xenbus_transaction xbt;
    +
    + ret = xenbus_alloc_evtchn(dev, &evtchn);
    + if (ret)
    + return ret;
    + ret = bind_evtchn_to_irqhandler(evtchn, input_handler,
    + 0, dev->devicetype, info);
    + if (ret < 0) {
    + xenbus_free_evtchn(dev, evtchn);
    + xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
    + return ret;
    + }
    + info->irq = ret;
    +
    + again:
    + ret = xenbus_transaction_start(&xbt);
    + if (ret) {
    + xenbus_dev_fatal(dev, ret, "starting transaction");
    + return ret;
    + }
    + ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
    + virt_to_mfn(info->page));
    + if (ret)
    + goto error_xenbus;
    + ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
    + evtchn);
    + if (ret)
    + goto error_xenbus;
    + ret = xenbus_transaction_end(xbt, 0);
    + if (ret) {
    + if (ret == -EAGAIN)
    + goto again;
    + xenbus_dev_fatal(dev, ret, "completing transaction");
    + return ret;
    + }
    +
    + xenbus_switch_state(dev, XenbusStateInitialised);
    + return 0;
    +
    + error_xenbus:
    + xenbus_transaction_end(xbt, 1);
    + xenbus_dev_fatal(dev, ret, "writing xenstore");
    + return ret;
    +}
    +
    +static void xenkbd_disconnect_backend(struct xenkbd_info *info)
    +{
    + if (info->irq >= 0)
    + unbind_from_irqhandler(info->irq, info);
    + info->irq = -1;
    +}
    +
    +static void xenkbd_backend_changed(struct xenbus_device *dev,
    + enum xenbus_state backend_state)
    +{
    + struct xenkbd_info *info = dev->dev.driver_data;
    + int ret, val;
    +
    + switch (backend_state) {
    + case XenbusStateInitialising:
    + case XenbusStateInitialised:
    + case XenbusStateUnknown:
    + case XenbusStateClosed:
    + break;
    +
    + case XenbusStateInitWait:
    +InitWait:
    + ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
    + "feature-abs-pointer", "%d", &val);
    + if (ret < 0)
    + val = 0;
    + if (val) {
    + ret = xenbus_printf(XBT_NIL, info->xbdev->nodename,
    + "request-abs-pointer", "1");
    + if (ret)
    + printk(KERN_WARNING
    + "xenkbd: can't request abs-pointer");
    + }
    + xenbus_switch_state(dev, XenbusStateConnected);
    + break;
    +
    + case XenbusStateConnected:
    + /*
    + * Work around xenbus race condition: If backend goes
    + * through InitWait to Connected fast enough, we can
    + * get Connected twice here.
    + */
    + if (dev->state != XenbusStateConnected)
    + goto InitWait; /* no InitWait seen yet, fudge it */
    + break;
    +
    + case XenbusStateClosing:
    + xenbus_frontend_closed(dev);
    + break;
    + }
    +}
    +
    +static struct xenbus_device_id xenkbd_ids[] = {
    + { "vkbd" },
    + { "" }
    +};
    +
    +static struct xenbus_driver xenkbd = {
    + .name = "vkbd",
    + .owner = THIS_MODULE,
    + .ids = xenkbd_ids,
    + .probe = xenkbd_probe,
    + .remove = xenkbd_remove,
    + .resume = xenkbd_resume,
    + .otherend_changed = xenkbd_backend_changed,
    +};
    +
    +static int __init xenkbd_init(void)
    +{
    + if (!is_running_on_xen())
    + return -ENODEV;
    +
    + /* Nothing to do if running in dom0. */
    + if (is_initial_xendomain())
    + return -ENODEV;
    +
    + return xenbus_register_frontend(&xenkbd);
    +}
    +
    +static void __exit xenkbd_cleanup(void)
    +{
    + xenbus_unregister_driver(&xenkbd);
    +}
    +
    +module_init(xenkbd_init);
    +module_exit(xenkbd_cleanup);
    +
    +MODULE_LICENSE("GPL");
    diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
    --- a/drivers/video/Kconfig
    +++ b/drivers/video/Kconfig
    @@ -1930,6 +1930,20 @@

    If unsure, say N.

    +config XEN_FBDEV_FRONTEND
    + tristate "Xen virtual frame buffer support"
    + depends on FB && XEN
    + select FB_SYS_FILLRECT
    + select FB_SYS_COPYAREA
    + select FB_SYS_IMAGEBLIT
    + select FB_SYS_FOPS
    + select FB_DEFERRED_IO
    + default y
    + help
    + This driver implements the front-end of the Xen virtual
    + frame buffer driver. It communicates with a back-end
    + in another domain.
    +
    source "drivers/video/omap/Kconfig"

    source "drivers/video/backlight/Kconfig"
    diff --git a/drivers/video/Makefile b/drivers/video/Makefile
    --- a/drivers/video/Makefile
    +++ b/drivers/video/Makefile
    @@ -114,6 +114,7 @@
    obj-$(CONFIG_FB_SM501) += sm501fb.o
    obj-$(CONFIG_FB_XILINX) += xilinxfb.o
    obj-$(CONFIG_FB_OMAP) += omap/
    +obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o

    # Platform or fallback drivers go here
    obj-$(CONFIG_FB_UVESA) += uvesafb.o
    diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
    new file mode 100644
    --- /dev/null
    +++ b/drivers/video/xen-fbfront.c
    @@ -0,0 +1,550 @@
    +/*
    + * Xen para-virtual frame buffer device
    + *
    + * Copyright (C) 2005-2006 Anthony Liguori
    + * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster
    + *
    + * Based on linux/drivers/video/q40fb.c
    + *
    + * This file is subject to the terms and conditions of the GNU General Public
    + * License. See the file COPYING in the main directory of this archive for
    + * more details.
    + */
    +
    +/*
    + * TODO:
    + *
    + * Switch to grant tables when they become capable of dealing with the
    + * frame buffer.
    + */
    +
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +
    +struct xenfb_info {
    + unsigned char *fb;
    + struct fb_info *fb_info;
    + int x1, y1, x2, y2; /* dirty rectangle,
    + protected by dirty_lock */
    + spinlock_t dirty_lock;
    + int nr_pages;
    + int irq;
    + struct xenfb_page *page;
    + unsigned long *mfns;
    + int update_wanted; /* XENFB_TYPE_UPDATE wanted */
    +
    + struct xenbus_device *xbdev;
    +};
    +
    +static u32 xenfb_mem_len = XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8;
    +
    +static int xenfb_remove(struct xenbus_device *);
    +static void xenfb_init_shared_page(struct xenfb_info *);
    +static int xenfb_connect_backend(struct xenbus_device *, struct xenfb_info *);
    +static void xenfb_disconnect_backend(struct xenfb_info *);
    +
    +static void xenfb_do_update(struct xenfb_info *info,
    + int x, int y, int w, int h)
    +{
    + union xenfb_out_event event;
    + u32 prod;
    +
    + event.type = XENFB_TYPE_UPDATE;
    + event.update.x = x;
    + event.update.y = y;
    + event.update.width = w;
    + event.update.height = h;
    +
    + prod = info->page->out_prod;
    + /* caller ensures !xenfb_queue_full() */
    + mb(); /* ensure ring space available */
    + XENFB_OUT_RING_REF(info->page, prod) = event;
    + wmb(); /* ensure ring contents visible */
    + info->page->out_prod = prod + 1;
    +
    + notify_remote_via_irq(info->irq);
    +}
    +
    +static int xenfb_queue_full(struct xenfb_info *info)
    +{
    + u32 cons, prod;
    +
    + prod = info->page->out_prod;
    + cons = info->page->out_cons;
    + return prod - cons == XENFB_OUT_RING_LEN;
    +}
    +
    +static void xenfb_refresh(struct xenfb_info *info,
    + int x1, int y1, int w, int h)
    +{
    + unsigned long flags;
    + int y2 = y1 + h - 1;
    + int x2 = x1 + w - 1;
    +
    + if (!info->update_wanted)
    + return;
    +
    + spin_lock_irqsave(&info->dirty_lock, flags);
    +
    + /* Combine with dirty rectangle: */
    + if (info->y1 < y1)
    + y1 = info->y1;
    + if (info->y2 > y2)
    + y2 = info->y2;
    + if (info->x1 < x1)
    + x1 = info->x1;
    + if (info->x2 > x2)
    + x2 = info->x2;
    +
    + if (xenfb_queue_full(info)) {
    + /* Can't send right now, stash it in the dirty rectangle */
    + info->x1 = x1;
    + info->x2 = x2;
    + info->y1 = y1;
    + info->y2 = y2;
    + spin_unlock_irqrestore(&info->dirty_lock, flags);
    + return;
    + }
    +
    + /* Clear dirty rectangle: */
    + info->x1 = info->y1 = INT_MAX;
    + info->x2 = info->y2 = 0;
    +
    + spin_unlock_irqrestore(&info->dirty_lock, flags);
    +
    + if (x1 <= x2 && y1 <= y2)
    + xenfb_do_update(info, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
    +}
    +
    +static void xenfb_deferred_io(struct fb_info *fb_info,
    + struct list_head *pagelist)
    +{
    + struct xenfb_info *info = fb_info->par;
    + struct page *page;
    + unsigned long beg, end;
    + int y1, y2, miny, maxy;
    +
    + miny = INT_MAX;
    + maxy = 0;
    + list_for_each_entry(page, pagelist, lru) {
    + beg = page->index << PAGE_SHIFT;
    + end = beg + PAGE_SIZE - 1;
    + y1 = beg / fb_info->fix.line_length;
    + y2 = end / fb_info->fix.line_length;
    + if (y2 >= fb_info->var.yres)
    + y2 = fb_info->var.yres - 1;
    + if (miny > y1)
    + miny = y1;
    + if (maxy < y2)
    + maxy = y2;
    + }
    + xenfb_refresh(info, 0, miny, fb_info->var.xres, maxy - miny + 1);
    +}
    +
    +static struct fb_deferred_io xenfb_defio = {
    + .delay = HZ / 20,
    + .deferred_io = xenfb_deferred_io,
    +};
    +
    +static int xenfb_setcolreg(unsigned regno, unsigned red, unsigned green,
    + unsigned blue, unsigned transp,
    + struct fb_info *info)
    +{
    + u32 v;
    +
    + if (regno > info->cmap.len)
    + return 1;
    +
    +#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
    + red = CNVT_TOHW(red, info->var.red.length);
    + green = CNVT_TOHW(green, info->var.green.length);
    + blue = CNVT_TOHW(blue, info->var.blue.length);
    + transp = CNVT_TOHW(transp, info->var.transp.length);
    +#undef CNVT_TOHW
    +
    + v = (red << info->var.red.offset) |
    + (green << info->var.green.offset) |
    + (blue << info->var.blue.offset);
    +
    + switch (info->var.bits_per_pixel) {
    + case 16:
    + case 24:
    + case 32:
    + ((u32 *)info->pseudo_palette)[regno] = v;
    + break;
    + }
    +
    + return 0;
    +}
    +
    +static void xenfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
    +{
    + struct xenfb_info *info = p->par;
    +
    + sys_fillrect(p, rect);
    + xenfb_refresh(info, rect->dx, rect->dy, rect->width, rect->height);
    +}
    +
    +static void xenfb_imageblit(struct fb_info *p, const struct fb_image *image)
    +{
    + struct xenfb_info *info = p->par;
    +
    + sys_imageblit(p, image);
    + xenfb_refresh(info, image->dx, image->dy, image->width, image->height);
    +}
    +
    +static void xenfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
    +{
    + struct xenfb_info *info = p->par;
    +
    + sys_copyarea(p, area);
    + xenfb_refresh(info, area->dx, area->dy, area->width, area->height);
    +}
    +
    +static ssize_t xenfb_write(struct fb_info *p, const char __user *buf,
    + size_t count, loff_t *ppos)
    +{
    + struct xenfb_info *info = p->par;
    + ssize_t res;
    +
    + res = fb_sys_write(p, buf, count, ppos);
    + xenfb_refresh(info, 0, 0, info->page->width, info->page->height);
    + return res;
    +}
    +
    +static struct fb_ops xenfb_fb_ops = {
    + .owner = THIS_MODULE,
    + .fb_read = fb_sys_read,
    + .fb_write = xenfb_write,
    + .fb_setcolreg = xenfb_setcolreg,
    + .fb_fillrect = xenfb_fillrect,
    + .fb_copyarea = xenfb_copyarea,
    + .fb_imageblit = xenfb_imageblit,
    +};
    +
    +static irqreturn_t xenfb_event_handler(int rq, void *dev_id)
    +{
    + /*
    + * No in events recognized, simply ignore them all.
    + * If you need to recognize some, see xen-kbdfront's
    + * input_handler() for how to do that.
    + */
    + struct xenfb_info *info = dev_id;
    + struct xenfb_page *page = info->page;
    +
    + if (page->in_cons != page->in_prod) {
    + info->page->in_cons = info->page->in_prod;
    + notify_remote_via_irq(info->irq);
    + }
    +
    + /* Flush dirty rectangle: */
    + xenfb_refresh(info, INT_MAX, INT_MAX, -INT_MAX, -INT_MAX);
    +
    + return IRQ_HANDLED;
    +}
    +
    +static int __devinit xenfb_probe(struct xenbus_device *dev,
    + const struct xenbus_device_id *id)
    +{
    + struct xenfb_info *info;
    + struct fb_info *fb_info;
    + int ret;
    +
    + info = kzalloc(sizeof(*info), GFP_KERNEL);
    + if (info == NULL) {
    + xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
    + return -ENOMEM;
    + }
    + dev->dev.driver_data = info;
    + info->xbdev = dev;
    + info->irq = -1;
    + info->x1 = info->y1 = INT_MAX;
    + spin_lock_init(&info->dirty_lock);
    +
    + info->fb = vmalloc(xenfb_mem_len);
    + if (info->fb == NULL)
    + goto error_nomem;
    + memset(info->fb, 0, xenfb_mem_len);
    +
    + info->nr_pages = (xenfb_mem_len + PAGE_SIZE - 1) >> PAGE_SHIFT;
    +
    + info->mfns = vmalloc(sizeof(unsigned long) * info->nr_pages);
    + if (!info->mfns)
    + goto error_nomem;
    +
    + /* set up shared page */
    + info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
    + if (!info->page)
    + goto error_nomem;
    +
    + xenfb_init_shared_page(info);
    +
    + /* abusing framebuffer_alloc() to allocate pseudo_palette */
    + fb_info = framebuffer_alloc(sizeof(u32) * 256, NULL);
    + if (fb_info == NULL)
    + goto error_nomem;
    +
    + /* complete the abuse: */
    + fb_info->pseudo_palette = fb_info->par;
    + fb_info->par = info;
    +
    + fb_info->screen_base = info->fb;
    +
    + fb_info->fbops = &xenfb_fb_ops;
    + fb_info->var.xres_virtual = fb_info->var.xres = info->page->width;
    + fb_info->var.yres_virtual = fb_info->var.yres = info->page->height;
    + fb_info->var.bits_per_pixel = info->page->depth;
    +
    + fb_info->var.red = (struct fb_bitfield){16, 8, 0};
    + fb_info->var.green = (struct fb_bitfield){8, 8, 0};
    + fb_info->var.blue = (struct fb_bitfield){0, 8, 0};
    +
    + fb_info->var.activate = FB_ACTIVATE_NOW;
    + fb_info->var.height = -1;
    + fb_info->var.width = -1;
    + fb_info->var.vmode = FB_VMODE_NONINTERLACED;
    +
    + fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
    + fb_info->fix.line_length = info->page->line_length;
    + fb_info->fix.smem_start = 0;
    + fb_info->fix.smem_len = xenfb_mem_len;
    + strcpy(fb_info->fix.id, "xen");
    + fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
    + fb_info->fix.accel = FB_ACCEL_NONE;
    +
    + fb_info->flags = FBINFO_FLAG_DEFAULT;
    +
    + ret = fb_alloc_cmap(&fb_info->cmap, 256, 0);
    + if (ret < 0) {
    + framebuffer_release(fb_info);
    + xenbus_dev_fatal(dev, ret, "fb_alloc_cmap");
    + goto error;
    + }
    +
    + fb_info->fbdefio = &xenfb_defio;
    + fb_deferred_io_init(fb_info);
    +
    + ret = register_framebuffer(fb_info);
    + if (ret) {
    + fb_deferred_io_cleanup(fb_info);
    + fb_dealloc_cmap(&fb_info->cmap);
    + framebuffer_release(fb_info);
    + xenbus_dev_fatal(dev, ret, "register_framebuffer");
    + goto error;
    + }
    + info->fb_info = fb_info;
    +
    + ret = xenfb_connect_backend(dev, info);
    + if (ret < 0)
    + goto error;
    +
    + return 0;
    +
    + error_nomem:
    + ret = -ENOMEM;
    + xenbus_dev_fatal(dev, ret, "allocating device memory");
    + error:
    + xenfb_remove(dev);
    + return ret;
    +}
    +
    +static int xenfb_resume(struct xenbus_device *dev)
    +{
    + struct xenfb_info *info = dev->dev.driver_data;
    +
    + xenfb_disconnect_backend(info);
    + xenfb_init_shared_page(info);
    + return xenfb_connect_backend(dev, info);
    +}
    +
    +static int xenfb_remove(struct xenbus_device *dev)
    +{
    + struct xenfb_info *info = dev->dev.driver_data;
    +
    + xenfb_disconnect_backend(info);
    + if (info->fb_info) {
    + fb_deferred_io_cleanup(info->fb_info);
    + unregister_framebuffer(info->fb_info);
    + fb_dealloc_cmap(&info->fb_info->cmap);
    + framebuffer_release(info->fb_info);
    + }
    + free_page((unsigned long)info->page);
    + vfree(info->mfns);
    + vfree(info->fb);
    + kfree(info);
    +
    + return 0;
    +}
    +
    +static unsigned long vmalloc_to_mfn(void *address)
    +{
    + return pfn_to_mfn(vmalloc_to_pfn(address));
    +}
    +
    +static void xenfb_init_shared_page(struct xenfb_info *info)
    +{
    + int i;
    +
    + for (i = 0; i < info->nr_pages; i++)
    + info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE);
    +
    + info->page->pd[0] = vmalloc_to_mfn(info->mfns);
    + info->page->pd[1] = 0;
    + info->page->width = XENFB_WIDTH;
    + info->page->height = XENFB_HEIGHT;
    + info->page->depth = XENFB_DEPTH;
    + info->page->line_length = (info->page->depth / 8) * info->page->width;
    + info->page->mem_length = xenfb_mem_len;
    + info->page->in_cons = info->page->in_prod = 0;
    + info->page->out_cons = info->page->out_prod = 0;
    +}
    +
    +static int xenfb_connect_backend(struct xenbus_device *dev,
    + struct xenfb_info *info)
    +{
    + int ret, evtchn;
    + struct xenbus_transaction xbt;
    +
    + ret = xenbus_alloc_evtchn(dev, &evtchn);
    + if (ret)
    + return ret;
    + ret = bind_evtchn_to_irqhandler(evtchn, xenfb_event_handler,
    + 0, dev->devicetype, info);
    + if (ret < 0) {
    + xenbus_free_evtchn(dev, evtchn);
    + xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
    + return ret;
    + }
    + info->irq = ret;
    +
    + again:
    + ret = xenbus_transaction_start(&xbt);
    + if (ret) {
    + xenbus_dev_fatal(dev, ret, "starting transaction");
    + return ret;
    + }
    + ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
    + virt_to_mfn(info->page));
    + if (ret)
    + goto error_xenbus;
    + ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
    + evtchn);
    + if (ret)
    + goto error_xenbus;
    + ret = xenbus_printf(xbt, dev->nodename, "protocol", "%s",
    + XEN_IO_PROTO_ABI_NATIVE);
    + if (ret)
    + goto error_xenbus;
    + ret = xenbus_printf(xbt, dev->nodename, "feature-update", "1");
    + if (ret)
    + goto error_xenbus;
    + ret = xenbus_transaction_end(xbt, 0);
    + if (ret) {
    + if (ret == -EAGAIN)
    + goto again;
    + xenbus_dev_fatal(dev, ret, "completing transaction");
    + return ret;
    + }
    +
    + xenbus_switch_state(dev, XenbusStateInitialised);
    + return 0;
    +
    + error_xenbus:
    + xenbus_transaction_end(xbt, 1);
    + xenbus_dev_fatal(dev, ret, "writing xenstore");
    + return ret;
    +}
    +
    +static void xenfb_disconnect_backend(struct xenfb_info *info)
    +{
    + if (info->irq >= 0)
    + unbind_from_irqhandler(info->irq, info);
    + info->irq = -1;
    +}
    +
    +static void xenfb_backend_changed(struct xenbus_device *dev,
    + enum xenbus_state backend_state)
    +{
    + struct xenfb_info *info = dev->dev.driver_data;
    + int val;
    +
    + switch (backend_state) {
    + case XenbusStateInitialising:
    + case XenbusStateInitialised:
    + case XenbusStateUnknown:
    + case XenbusStateClosed:
    + break;
    +
    + case XenbusStateInitWait:
    +InitWait:
    + xenbus_switch_state(dev, XenbusStateConnected);
    + break;
    +
    + case XenbusStateConnected:
    + /*
    + * Work around xenbus race condition: If backend goes
    + * through InitWait to Connected fast enough, we can
    + * get Connected twice here.
    + */
    + if (dev->state != XenbusStateConnected)
    + goto InitWait; /* no InitWait seen yet, fudge it */
    +
    + if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
    + "request-update", "%d", &val) < 0)
    + val = 0;
    + if (val)
    + info->update_wanted = 1;
    + break;
    +
    + case XenbusStateClosing:
    + xenbus_frontend_closed(dev);
    + break;
    + }
    +}
    +
    +static struct xenbus_device_id xenfb_ids[] = {
    + { "vfb" },
    + { "" }
    +};
    +
    +static struct xenbus_driver xenfb = {
    + .name = "vfb",
    + .owner = THIS_MODULE,
    + .ids = xenfb_ids,
    + .probe = xenfb_probe,
    + .remove = xenfb_remove,
    + .resume = xenfb_resume,
    + .otherend_changed = xenfb_backend_changed,
    +};
    +
    +static int __init xenfb_init(void)
    +{
    + if (!is_running_on_xen())
    + return -ENODEV;
    +
    + /* Nothing to do if running in dom0. */
    + if (is_initial_xendomain())
    + return -ENODEV;
    +
    + return xenbus_register_frontend(&xenfb);
    +}
    +
    +static void __exit xenfb_cleanup(void)
    +{
    + xenbus_unregister_driver(&xenfb);
    +}
    +
    +module_init(xenfb_init);
    +module_exit(xenfb_cleanup);
    +
    +MODULE_LICENSE("GPL");
    diff --git a/include/xen/interface/io/fbif.h b/include/xen/interface/io/fbif.h
    new file mode 100644
    --- /dev/null
    +++ b/include/xen/interface/io/fbif.h
    @@ -0,0 +1,124 @@
    +/*
    + * fbif.h -- Xen virtual frame buffer device
    + *
    + * Permission is hereby granted, free of charge, to any person obtaining a copy
    + * of this software and associated documentation files (the "Software"), to
    + * deal in the Software without restriction, including without limitation the
    + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    + * sell copies of the Software, and to permit persons to whom the Software is
    + * furnished to do so, subject to the following conditions:
    + *
    + * The above copyright notice and this permission notice shall be included in
    + * all copies or substantial portions of the Software.
    + *
    + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    + * DEALINGS IN THE SOFTWARE.
    + *
    + * Copyright (C) 2005 Anthony Liguori
    + * Copyright (C) 2006 Red Hat, Inc., Markus Armbruster
    + */
    +
    +#ifndef __XEN_PUBLIC_IO_FBIF_H__
    +#define __XEN_PUBLIC_IO_FBIF_H__
    +
    +/* Out events (frontend -> backend) */
    +
    +/*
    + * Out events may be sent only when requested by backend, and receipt
    + * of an unknown out event is an error.
    + */
    +
    +/* Event type 1 currently not used */
    +/*
    + * Framebuffer update notification event
    + * Capable frontend sets feature-update in xenstore.
    + * Backend requests it by setting request-update in xenstore.
    + */
    +#define XENFB_TYPE_UPDATE 2
    +
    +struct xenfb_update {
    + uint8_t type; /* XENFB_TYPE_UPDATE */
    + int32_t x; /* source x */
    + int32_t y; /* source y */
    + int32_t width; /* rect width */
    + int32_t height; /* rect height */
    +};
    +
    +#define XENFB_OUT_EVENT_SIZE 40
    +
    +union xenfb_out_event {
    + uint8_t type;
    + struct xenfb_update update;
    + char pad[XENFB_OUT_EVENT_SIZE];
    +};
    +
    +/* In events (backend -> frontend) */
    +
    +/*
    + * Frontends should ignore unknown in events.
    + * No in events currently defined.
    + */
    +
    +#define XENFB_IN_EVENT_SIZE 40
    +
    +union xenfb_in_event {
    + uint8_t type;
    + char pad[XENFB_IN_EVENT_SIZE];
    +};
    +
    +/* shared page */
    +
    +#define XENFB_IN_RING_SIZE 1024
    +#define XENFB_IN_RING_LEN (XENFB_IN_RING_SIZE / XENFB_IN_EVENT_SIZE)
    +#define XENFB_IN_RING_OFFS 1024
    +#define XENFB_IN_RING(page) \
    + ((union xenfb_in_event *)((char *)(page) + XENFB_IN_RING_OFFS))
    +#define XENFB_IN_RING_REF(page, idx) \
    + (XENFB_IN_RING((page))[(idx) % XENFB_IN_RING_LEN])
    +
    +#define XENFB_OUT_RING_SIZE 2048
    +#define XENFB_OUT_RING_LEN (XENFB_OUT_RING_SIZE / XENFB_OUT_EVENT_SIZE)
    +#define XENFB_OUT_RING_OFFS (XENFB_IN_RING_OFFS + XENFB_IN_RING_SIZE)
    +#define XENFB_OUT_RING(page) \
    + ((union xenfb_out_event *)((char *)(page) + XENFB_OUT_RING_OFFS))
    +#define XENFB_OUT_RING_REF(page, idx) \
    + (XENFB_OUT_RING((page))[(idx) % XENFB_OUT_RING_LEN])
    +
    +struct xenfb_page {
    + uint32_t in_cons, in_prod;
    + uint32_t out_cons, out_prod;
    +
    + int32_t width; /* width of the framebuffer (in pixels) */
    + int32_t height; /* height of the framebuffer (in pixels) */
    + uint32_t line_length; /* length of a row of pixels (in bytes) */
    + uint32_t mem_length; /* length of the framebuffer (in bytes) */
    + uint8_t depth; /* depth of a pixel (in bits) */
    +
    + /*
    + * Framebuffer page directory
    + *
    + * Each directory page holds PAGE_SIZE / sizeof(*pd)
    + * framebuffer pages, and can thus map up to PAGE_SIZE *
    + * PAGE_SIZE / sizeof(*pd) bytes. With PAGE_SIZE == 4096 and
    + * sizeof(unsigned long) == 4, that's 4 Megs. Two directory
    + * pages should be enough for a while.
    + */
    + unsigned long pd[2];
    +};
    +
    +/*
    + * Wart: xenkbd needs to know resolution. Put it here until a better
    + * solution is found, but don't leak it to the backend.
    + */
    +#ifdef __KERNEL__
    +#define XENFB_WIDTH 800
    +#define XENFB_HEIGHT 600
    +#define XENFB_DEPTH 32
    +#endif
    +
    +#endif
    diff --git a/include/xen/interface/io/kbdif.h b/include/xen/interface/io/kbdif.h
    new file mode 100644
    --- /dev/null
    +++ b/include/xen/interface/io/kbdif.h
    @@ -0,0 +1,114 @@
    +/*
    + * kbdif.h -- Xen virtual keyboard/mouse
    + *
    + * Permission is hereby granted, free of charge, to any person obtaining a copy
    + * of this software and associated documentation files (the "Software"), to
    + * deal in the Software without restriction, including without limitation the
    + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    + * sell copies of the Software, and to permit persons to whom the Software is
    + * furnished to do so, subject to the following conditions:
    + *
    + * The above copyright notice and this permission notice shall be included in
    + * all copies or substantial portions of the Software.
    + *
    + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    + * DEALINGS IN THE SOFTWARE.
    + *
    + * Copyright (C) 2005 Anthony Liguori
    + * Copyright (C) 2006 Red Hat, Inc., Markus Armbruster
    + */
    +
    +#ifndef __XEN_PUBLIC_IO_KBDIF_H__
    +#define __XEN_PUBLIC_IO_KBDIF_H__
    +
    +/* In events (backend -> frontend) */
    +
    +/*
    + * Frontends should ignore unknown in events.
    + */
    +
    +/* Pointer movement event */
    +#define XENKBD_TYPE_MOTION 1
    +/* Event type 2 currently not used */
    +/* Key event (includes pointer buttons) */
    +#define XENKBD_TYPE_KEY 3
    +/*
    + * Pointer position event
    + * Capable backend sets feature-abs-pointer in xenstore.
    + * Frontend requests ot instead of XENKBD_TYPE_MOTION by setting
    + * request-abs-update in xenstore.
    + */
    +#define XENKBD_TYPE_POS 4
    +
    +struct xenkbd_motion {
    + uint8_t type; /* XENKBD_TYPE_MOTION */
    + int32_t rel_x; /* relative X motion */
    + int32_t rel_y; /* relative Y motion */
    +};
    +
    +struct xenkbd_key {
    + uint8_t type; /* XENKBD_TYPE_KEY */
    + uint8_t pressed; /* 1 if pressed; 0 otherwise */
    + uint32_t keycode; /* KEY_* from linux/input.h */
    +};
    +
    +struct xenkbd_position {
    + uint8_t type; /* XENKBD_TYPE_POS */
    + int32_t abs_x; /* absolute X position (in FB pixels) */
    + int32_t abs_y; /* absolute Y position (in FB pixels) */
    +};
    +
    +#define XENKBD_IN_EVENT_SIZE 40
    +
    +union xenkbd_in_event {
    + uint8_t type;
    + struct xenkbd_motion motion;
    + struct xenkbd_key key;
    + struct xenkbd_position pos;
    + char pad[XENKBD_IN_EVENT_SIZE];
    +};
    +
    +/* Out events (frontend -> backend) */
    +
    +/*
    + * Out events may be sent only when requested by backend, and receipt
    + * of an unknown out event is an error.
    + * No out events currently defined.
    + */
    +
    +#define XENKBD_OUT_EVENT_SIZE 40
    +
    +union xenkbd_out_event {
    + uint8_t type;
    + char pad[XENKBD_OUT_EVENT_SIZE];
    +};
    +
    +/* shared page */
    +
    +#define XENKBD_IN_RING_SIZE 2048
    +#define XENKBD_IN_RING_LEN (XENKBD_IN_RING_SIZE / XENKBD_IN_EVENT_SIZE)
    +#define XENKBD_IN_RING_OFFS 1024
    +#define XENKBD_IN_RING(page) \
    + ((union xenkbd_in_event *)((char *)(page) + XENKBD_IN_RING_OFFS))
    +#define XENKBD_IN_RING_REF(page, idx) \
    + (XENKBD_IN_RING((page))[(idx) % XENKBD_IN_RING_LEN])
    +
    +#define XENKBD_OUT_RING_SIZE 1024
    +#define XENKBD_OUT_RING_LEN (XENKBD_OUT_RING_SIZE / XENKBD_OUT_EVENT_SIZE)
    +#define XENKBD_OUT_RING_OFFS (XENKBD_IN_RING_OFFS + XENKBD_IN_RING_SIZE)
    +#define XENKBD_OUT_RING(page) \
    + ((union xenkbd_out_event *)((char *)(page) + XENKBD_OUT_RING_OFFS))
    +#define XENKBD_OUT_RING_REF(page, idx) \
    + (XENKBD_OUT_RING((page))[(idx) % XENKBD_OUT_RING_LEN])
    +
    +struct xenkbd_page {
    + uint32_t in_cons, in_prod;
    + uint32_t out_cons, out_prod;
    +};
    +
    +#endif


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  17. [PATCH 20 of 24] xen: disable preemption during tlb flush

    Various places in the kernel flush the tlb even though preemption doens't
    guarantee the tlb flush is happening on any particular CPU. In many cases
    this doesn't seem to matter, so don't make a fuss about it.

    Signed-off-by: Jeremy Fitzhardinge
    ---
    arch/x86/xen/enlighten.c | 15 +++++++++++++--
    1 file changed, 13 insertions(+), 2 deletions(-)

    diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
    --- a/arch/x86/xen/enlighten.c
    +++ b/arch/x86/xen/enlighten.c
    @@ -532,26 +532,37 @@
    static void xen_flush_tlb(void)
    {
    struct mmuext_op *op;
    - struct multicall_space mcs = xen_mc_entry(sizeof(*op));
    + struct multicall_space mcs;
    +
    + preempt_disable();
    +
    + mcs = xen_mc_entry(sizeof(*op));

    op = mcs.args;
    op->cmd = MMUEXT_TLB_FLUSH_LOCAL;
    MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);

    xen_mc_issue(PARAVIRT_LAZY_MMU);
    +
    + preempt_enable();
    }

    static void xen_flush_tlb_single(unsigned long addr)
    {
    struct mmuext_op *op;
    - struct multicall_space mcs = xen_mc_entry(sizeof(*op));
    + struct multicall_space mcs;

    + preempt_disable();
    +
    + mcs = xen_mc_entry(sizeof(*op));
    op = mcs.args;
    op->cmd = MMUEXT_INVLPG_LOCAL;
    op->arg1.linear_addr = addr & PAGE_MASK;
    MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);

    xen_mc_issue(PARAVIRT_LAZY_MMU);
    +
    + preempt_enable();
    }

    static void xen_flush_tlb_others(const cpumask_t *cpus, struct mm_struct *mm,


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  18. [PATCH 10 of 24] xen: replace callers of alloc_vm_area()/free_vm_area() with xen_ prefixed one

    From: Isaku Yamahata

    Don't use alloc_vm_area()/free_vm_area() directly, instead define
    xen_alloc_vm_area()/xen_free_vm_area() and use them.

    alloc_vm_area()/free_vm_area() are used to allocate/free area which
    are for grant table mapping. Xen/x86 grant table is based on virtual
    address so that alloc_vm_area()/free_vm_area() are suitable.
    On the other hand Xen/ia64 (and Xen/powerpc) grant table is based on
    pseudo physical address (guest physical address) so that allocation
    should be done differently.
    The original version of xenified Linux/IA64 have its own
    allocate_vm_area()/free_vm_area() definitions which don't allocate vm area
    contradictory to those names.
    Now vanilla Linux already has its definitions so that it's impossible
    to have IA64 definitions of allocate_vm_area()/free_vm_area().
    Instead introduce xen_allocate_vm_area()/xen_free_vm_area() and use them.

    Signed-off-by: Isaku Yamahata
    Signed-off-by: Jeremy Fitzhardinge
    ---
    drivers/xen/grant-table.c | 2 +-
    drivers/xen/xenbus/xenbus_client.c | 6 +++---
    include/asm-x86/xen/grant_table.h | 7 +++++++
    include/xen/grant_table.h | 3 +--
    4 files changed, 12 insertions(+), 6 deletions(-)

    diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
    --- a/drivers/xen/grant-table.c
    +++ b/drivers/xen/grant-table.c
    @@ -478,7 +478,7 @@

    if (shared == NULL) {
    struct vm_struct *area;
    - area = alloc_vm_area(PAGE_SIZE * max_nr_grant_frames());
    + area = xen_alloc_vm_area(PAGE_SIZE * max_nr_grant_frames());
    BUG_ON(area == NULL);
    shared = area->addr;
    }
    diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
    --- a/drivers/xen/xenbus/xenbus_client.c
    +++ b/drivers/xen/xenbus/xenbus_client.c
    @@ -399,7 +399,7 @@

    *vaddr = NULL;

    - area = alloc_vm_area(PAGE_SIZE);
    + area = xen_alloc_vm_area(PAGE_SIZE);
    if (!area)
    return -ENOMEM;

    @@ -409,7 +409,7 @@
    BUG();

    if (op.status != GNTST_okay) {
    - free_vm_area(area);
    + xen_free_vm_area(area);
    xenbus_dev_fatal(dev, op.status,
    "mapping in shared page %d from domain %d",
    gnt_ref, dev->otherend_id);
    @@ -508,7 +508,7 @@
    BUG();

    if (op.status == GNTST_okay)
    - free_vm_area(area);
    + xen_free_vm_area(area);
    else
    xenbus_dev_error(dev, op.status,
    "unmapping page at handle %d error %d",
    diff --git a/include/asm-x86/xen/grant_table.h b/include/asm-x86/xen/grant_table.h
    new file mode 100644
    --- /dev/null
    +++ b/include/asm-x86/xen/grant_table.h
    @@ -0,0 +1,7 @@
    +#ifndef __XEN_GRANT_TABLE_H
    +#define __XEN_GRANT_TABLE_H
    +
    +#define xen_alloc_vm_area(size) alloc_vm_area(size)
    +#define xen_free_vm_area(area) free_vm_area(area)
    +
    +#endif /* __XEN_GRANT_TABLE_H */
    diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
    --- a/include/xen/grant_table.h
    +++ b/include/xen/grant_table.h
    @@ -39,6 +39,7 @@

    #include
    #include
    +#include

    /* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
    #define NR_GRANT_FRAMES 4


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  19. [PATCH 17 of 24] xen: Add compatibility aliases for frontend drivers

    From: Mark McLoughlin

    Before getting merged, xen-blkfront was xenblk and
    xen-netfront was xennet.

    Temporarily adding compatibility module aliases
    eases upgrades from older versions by e.g. allowing
    mkinitrd to find the new version of the module.

    Signed-off-by: Mark McLoughlin
    ---
    drivers/block/xen-blkfront.c | 1 +
    drivers/net/xen-netfront.c | 2 +-
    2 files changed, 2 insertions(+), 1 deletion(-)

    diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
    --- a/drivers/block/xen-blkfront.c
    +++ b/drivers/block/xen-blkfront.c
    @@ -1016,3 +1016,4 @@
    MODULE_LICENSE("GPL");
    MODULE_ALIAS_BLOCKDEV_MAJOR(XENVBD_MAJOR);
    MODULE_ALIAS("xen:vbd");
    +MODULE_ALIAS("xenblk");
    diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
    --- a/drivers/net/xen-netfront.c
    +++ b/drivers/net/xen-netfront.c
    @@ -1810,3 +1810,4 @@
    MODULE_DESCRIPTION("Xen virtual network device frontend");
    MODULE_LICENSE("GPL");
    MODULE_ALIAS("xen:vif");
    +MODULE_ALIAS("xennet");


    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  20. Re: [PATCH 00 of 24] More Xen updates


    * Jeremy Fitzhardinge wrote:

    > Hi Ingo,
    >
    > More patches. There are three groups:
    >
    > - some code movements to make common code available to other
    > architectures (namely, ia64)
    > - Xen device driver updates, including a new xen paravirt framebuffer driver,
    > - The Xen balloon driver (shrink only, so no dependency on memory hotplug yet)
    > - some "using smp_processor_id while preemptable" warning fixes,
    > mostly as a result of the core kernel's tendency to do tlb flushes
    > and update init_mm while preemptable,
    > - other little Xen cleanups


    thanks, applied for testing. The .25 Xen items we've got queued up are:

    Subject: xen: refactor xen_{alloc,release}_{pte,pmd}()
    Subject: xen: do not pin/unpin PMD pages
    Subject: xen: clear PG_pinned in release_{pte,pmd}()

    anything missing?

    Ingo
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

+ Reply to Thread
Page 1 of 2 1 2 LastLast