[PATCH] xen: fix allocation and use of large ldts - Kernel

This is a discussion on [PATCH] xen: fix allocation and use of large ldts - Kernel ; When the ldt gets to more than 1 page in size, the kernel uses vmalloc to allocate it. This means that: - when making the ldt RO, we must update the pages in both the vmalloc mapping and the linear ...

+ Reply to Thread
Results 1 to 4 of 4

Thread: [PATCH] xen: fix allocation and use of large ldts

  1. [PATCH] xen: fix allocation and use of large ldts

    When the ldt gets to more than 1 page in size, the kernel uses vmalloc
    to allocate it. This means that:
    - when making the ldt RO, we must update the pages in both the vmalloc
    mapping and the linear mapping to make sure there are no RW aliases.
    - we need to use arbitrary_virt_to_machine to compute the machine addr
    for each update

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

    ================================================== =================
    --- a/arch/x86/xen/enlighten.c
    +++ b/arch/x86/xen/enlighten.c
    @@ -305,24 +305,53 @@
    return 0;
    }

    +/* If 'v' is a vmalloc mapping, then find the linear mapping of the
    + page (if any) and also set its protections to match. */
    +static void set_aliased_prot(void *v, pgprot_t prot)
    +{
    + int level;
    + pte_t *ptep;
    + pte_t pte;
    + unsigned long pfn;
    + struct page *page;
    +
    + ptep = lookup_address((unsigned long)v, &level);
    + BUG_ON(ptep == NULL);
    +
    + pfn = pte_pfn(*ptep);
    + page = pfn_to_page(pfn);
    +
    + pte = pfn_pte(pfn, prot);
    +
    + if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0))
    + BUG();
    +
    + if (!PageHighMem(page)) {
    + void *av = __va(PFN_PHYS(pfn));
    +
    + if (av != v)
    + if (HYPERVISOR_update_va_mapping((unsigned long)av, pte, 0))
    + BUG();
    + } else
    + kmap_flush_unused();
    +}
    +
    static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries)
    {
    - unsigned pages = roundup(entries * LDT_ENTRY_SIZE, PAGE_SIZE);
    - void *v = ldt;
    + const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE;
    int i;

    - for(i = 0; i < pages; i += PAGE_SIZE)
    - make_lowmem_page_readonly(v + i);
    + for(i = 0; i < entries; i += entries_per_page)
    + set_aliased_prot(ldt + i, PAGE_KERNEL_RO);
    }

    static void xen_free_ldt(struct desc_struct *ldt, unsigned entries)
    {
    - unsigned pages = roundup(entries * LDT_ENTRY_SIZE, PAGE_SIZE);
    - void *v = ldt;
    + const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE;
    int i;

    - for(i = 0; i < pages; i += PAGE_SIZE)
    - make_lowmem_page_readwrite(v + i);
    + for(i = 0; i < entries; i += entries_per_page)
    + set_aliased_prot(ldt + i, PAGE_KERNEL);
    }

    static void xen_set_ldt(const void *addr, unsigned entries)
    @@ -426,7 +455,7 @@
    const void *ptr)
    {
    unsigned long lp = (unsigned long)&dt[entrynum];
    - xmaddr_t mach_lp = virt_to_machine(lp);
    + xmaddr_t mach_lp = arbitrary_virt_to_machine(lp);
    u64 entry = *(u64 *)ptr;

    preempt_disable();
    @@ -559,7 +588,7 @@
    }

    static void xen_load_sp0(struct tss_struct *tss,
    - struct thread_struct *thread)
    + struct thread_struct *thread)
    {
    struct multicall_space mcs = xen_mc_entry(0);
    MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->sp0);


    --
    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. Re: [PATCH] xen: fix allocation and use of large ldts


    * Jeremy Fitzhardinge wrote:

    > When the ldt gets to more than 1 page in size, the kernel uses vmalloc
    > to allocate it. This means that:
    > - when making the ldt RO, we must update the pages in both the vmalloc
    > mapping and the linear mapping to make sure there are no RW aliases.
    > - we need to use arbitrary_virt_to_machine to compute the machine addr
    > for each update


    applied to tip/x86/xen, thanks Jeremy.

    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/

  3. Re: [PATCH] xen: fix allocation and use of large ldts

    Ingo Molnar wrote:
    > * Jeremy Fitzhardinge wrote:
    >
    >
    >> When the ldt gets to more than 1 page in size, the kernel uses vmalloc
    >> to allocate it. This means that:
    >> - when making the ldt RO, we must update the pages in both the vmalloc
    >> mapping and the linear mapping to make sure there are no RW aliases.
    >> - we need to use arbitrary_virt_to_machine to compute the machine addr
    >> for each update
    >>

    >
    > applied to tip/x86/xen, thanks Jeremy.
    >


    Thanks. Here's a follow-up tidy patch.

    Subject: xen: tidy up ldt fixes

    Add a proper comment for set_aliased_prot() and fix an
    unsigned long/void * warning.

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

    ================================================== =================
    --- a/arch/x86/xen/enlighten.c
    +++ b/arch/x86/xen/enlighten.c
    @@ -395,8 +395,10 @@
    }

    /*
    - * If 'v' is a vmalloc mapping, then find the linear mapping of the
    - * page (if any) and also set its protections to match:
    + * Set the page permissions for a particular virtual address. If the
    + * address is a vmalloc mapping (or other non-linear mapping), then
    + * find the linear mapping of the page and also set its protections to
    + * match.
    */
    static void set_aliased_prot(void *v, pgprot_t prot)
    {
    @@ -545,8 +547,7 @@
    static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
    const void *ptr)
    {
    - unsigned long lp = (unsigned long)&dt[entrynum];
    - xmaddr_t mach_lp = arbitrary_virt_to_machine(lp);
    + xmaddr_t mach_lp = arbitrary_virt_to_machine(&dt[entrynum]);
    u64 entry = *(u64 *)ptr;

    preempt_disable();


    --
    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. Re: [PATCH] xen: fix allocation and use of large ldts


    * Jeremy Fitzhardinge wrote:

    > Thanks. Here's a follow-up tidy patch.
    >
    > Subject: xen: tidy up ldt fixes
    >
    > Add a proper comment for set_aliased_prot() and fix an unsigned
    > long/void * warning.


    applied to tip/x86/xen - thanks Jeremy.

    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