direct-io.hg

changeset 13830:3ad4691d1d34

[XEN] kexec: add compatability shim for kexec in 32on64 mode.

Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
author Ian Campbell <ian.campbell@xensource.com>
date Thu Feb 08 11:03:32 2007 +0000 (2007-02-08)
parents b50350fb0fde
children 9d103e5fd471
files xen/arch/x86/machine_kexec.c xen/arch/x86/x86_64/Makefile xen/arch/x86/x86_64/compat_kexec.S
line diff
     1.1 --- a/xen/arch/x86/machine_kexec.c	Thu Feb 08 11:03:29 2007 +0000
     1.2 +++ b/xen/arch/x86/machine_kexec.c	Thu Feb 08 11:03:32 2007 +0000
     1.3 @@ -21,7 +21,7 @@
     1.4  
     1.5  typedef void (*relocate_new_kernel_t)(
     1.6                  unsigned long indirection_page,
     1.7 -                unsigned long page_list,
     1.8 +                unsigned long *page_list,
     1.9                  unsigned long start_address);
    1.10  
    1.11  int machine_kexec_load(int type, int slot, xen_kexec_image_t *image)
    1.12 @@ -44,8 +44,26 @@ int machine_kexec_load(int type, int slo
    1.13          else
    1.14          {
    1.15              /* Odd pages: va for previous ma. */
    1.16 -            set_fixmap(fix_base + (k >> 1), prev_ma);
    1.17 -            image->page_list[k] = fix_to_virt(fix_base + (k >> 1));
    1.18 +            if ( IS_COMPAT(dom0) )
    1.19 +            {
    1.20 +
    1.21 +                /*
    1.22 +                 * The compatability bounce code sets up a page table
    1.23 +                 * with a 1-1 mapping of the first 1G of memory so
    1.24 +                 * VA==PA here.
    1.25 +                 *
    1.26 +                 * This Linux purgatory code still sets up separate
    1.27 +                 * high and low mappings on the control page (entries
    1.28 +                 * 0 and 1) but it is harmless if they are equal since
    1.29 +                 * that PT is not live at the time.
    1.30 +                 */
    1.31 +                image->page_list[k] = prev_ma;
    1.32 +            }
    1.33 +            else
    1.34 +            {
    1.35 +                set_fixmap(fix_base + (k >> 1), prev_ma);
    1.36 +                image->page_list[k] = fix_to_virt(fix_base + (k >> 1));
    1.37 +            }
    1.38          }
    1.39      }
    1.40  
    1.41 @@ -100,11 +118,27 @@ void machine_reboot_kexec(xen_kexec_imag
    1.42  
    1.43  void machine_kexec(xen_kexec_image_t *image)
    1.44  {
    1.45 -    relocate_new_kernel_t rnk;
    1.46 +#ifdef CONFIG_COMPAT
    1.47 +    if ( IS_COMPAT(dom0) )
    1.48 +    {
    1.49 +        extern void compat_machine_kexec(unsigned long rnk,
    1.50 +                                         unsigned long indirection_page,
    1.51 +                                         unsigned long *page_list,
    1.52 +                                         unsigned long start_address);
    1.53 +        compat_machine_kexec(image->page_list[1],
    1.54 +                             image->indirection_page,
    1.55 +                             image->page_list,
    1.56 +                             image->start_address);
    1.57 +    }
    1.58 +    else
    1.59 +#endif
    1.60 +    {
    1.61 +        relocate_new_kernel_t rnk;
    1.62  
    1.63 -    rnk = (relocate_new_kernel_t) image->page_list[1];
    1.64 -    (*rnk)(image->indirection_page, (unsigned long)image->page_list, 
    1.65 -           image->start_address);
    1.66 +        rnk = (relocate_new_kernel_t) image->page_list[1];
    1.67 +        (*rnk)(image->indirection_page, image->page_list,
    1.68 +               image->start_address);
    1.69 +    }
    1.70  }
    1.71  
    1.72  /*
     2.1 --- a/xen/arch/x86/x86_64/Makefile	Thu Feb 08 11:03:29 2007 +0000
     2.2 +++ b/xen/arch/x86/x86_64/Makefile	Thu Feb 08 11:03:32 2007 +0000
     2.3 @@ -1,4 +1,5 @@
     2.4  obj-y += entry.o
     2.5 +obj-y += compat_kexec.o
     2.6  obj-y += gpr_switch.o
     2.7  obj-y += mm.o
     2.8  obj-y += traps.o
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/xen/arch/x86/x86_64/compat_kexec.S	Thu Feb 08 11:03:32 2007 +0000
     3.3 @@ -0,0 +1,126 @@
     3.4 +/*
     3.5 + * Compatibility kexec handler.
     3.6 + */
     3.7 +
     3.8 +#include <xen/config.h>
     3.9 +
    3.10 +#include <asm/asm_defns.h>
    3.11 +#include <asm/msr.h>
    3.12 +#include <asm/page.h>
    3.13 +
    3.14 +.text
    3.15 +
    3.16 +        .code64
    3.17 +
    3.18 +ENTRY(compat_machine_kexec)
    3.19 +        /* x86/64                        x86/32  */
    3.20 +        /* %rdi - relocate_new_kernel_t  CALL    */
    3.21 +        /* %rsi - indirection page       4(%esp) */
    3.22 +        /* %rdx - page_list              8(%esp) */
    3.23 +        /* %rcx - start address         12(%esp) */
    3.24 +        /*        cpu has pae           16(%esp) */
    3.25 +
    3.26 +        /* Shim the 64 bit page_list into a 32 bit page_list. */
    3.27 +        mov $12,%r9
    3.28 +        lea compat_page_list(%rip), %rbx
    3.29 +1:      dec %r9
    3.30 +        movl (%rdx,%r9,8),%eax
    3.31 +        movl %eax,(%rbx,%r9,4)
    3.32 +        test %r9,%r9
    3.33 +        jnz 1b
    3.34 +
    3.35 +        movq %rbx,%rdx
    3.36 +        mov $__PAGE_OFFSET,%rbx
    3.37 +        sub %rbx, %rdx
    3.38 +
    3.39 +        /*
    3.40 +         * Setup an identity mapped region in PML4[0] of idle page
    3.41 +         * table.
    3.42 +         */
    3.43 +        lea idle_pg_table_l3(%rip),%rax
    3.44 +        sub %rbx,%rax
    3.45 +        or  $0x63,%rax
    3.46 +        mov %rax, idle_pg_table(%rip)
    3.47 +
    3.48 +        /* Switch to idle page table. */
    3.49 +        movq $(idle_pg_table - __PAGE_OFFSET), %rax
    3.50 +        movq %rax, %cr3
    3.51 +
    3.52 +        /* Jump to low identity mapping in compatibility mode. */
    3.53 +        ljmp *compatibility_mode_far(%rip)
    3.54 +        ud2
    3.55 +
    3.56 +compatibility_mode_far:
    3.57 +        .long compatibility_mode - __PAGE_OFFSET
    3.58 +        .long __HYPERVISOR_CS32
    3.59 +
    3.60 +        .code32
    3.61 +
    3.62 +compatibility_mode:
    3.63 +        /* Setup some sane segments. */
    3.64 +        movl $__HYPERVISOR_DS32, %eax
    3.65 +        movl %eax, %ds
    3.66 +        movl %eax, %es
    3.67 +        movl %eax, %fs
    3.68 +        movl %eax, %gs
    3.69 +        movl %eax, %ss
    3.70 +
    3.71 +        /* Push arguments onto stack. */
    3.72 +        pushl $1   /* 16(%esp) - cpu has pae */
    3.73 +        pushl %ecx /* 12(%esp) - start address */
    3.74 +        pushl %edx /*  8(%esp) - page list */
    3.75 +        pushl %esi /*  4(%esp) - indirection page */
    3.76 +        pushl %edi /*  0(%esp) - CALL */
    3.77 +
    3.78 +        /* Disable paging and therefore leave 64 bit mode. */
    3.79 +        movl %cr0, %eax
    3.80 +        andl $~X86_CR0_PG, %eax
    3.81 +        movl %eax, %cr0
    3.82 +
    3.83 +        /* Switch to 32 bit page table. */
    3.84 +        movl  $compat_pg_table - __PAGE_OFFSET, %eax
    3.85 +        movl  %eax, %cr3
    3.86 +
    3.87 +        /* Clear MSR_EFER[LME], disabling long mode */
    3.88 +        movl    $MSR_EFER,%ecx
    3.89 +        rdmsr
    3.90 +        btcl    $_EFER_LME,%eax
    3.91 +        wrmsr
    3.92 +
    3.93 +        /* Re-enable paging, but only 32 bit mode now. */
    3.94 +        movl %cr0, %eax
    3.95 +        orl $X86_CR0_PG, %eax
    3.96 +        movl %eax, %cr0
    3.97 +
    3.98 +        popl %eax
    3.99 +        call *%eax
   3.100 +        ud2
   3.101 +
   3.102 +compat_page_list:
   3.103 +        .fill 12,4,0
   3.104 +
   3.105 +        .align 32,0
   3.106 +
   3.107 +        /*
   3.108 +         * These compat page tables contain an identity mapping of the
   3.109 +         * first 1G of the physical address space.
   3.110 +         */
   3.111 +compat_pg_table:
   3.112 +        .long compat_pg_table_l2 + 0*PAGE_SIZE + 0x01 - __PAGE_OFFSET, 0
   3.113 +        .long 0, 0
   3.114 +        .long 0, 0
   3.115 +        .long 0, 0
   3.116 +
   3.117 +        .align 4096,0
   3.118 +
   3.119 +compat_pg_table_l2:
   3.120 +        .macro identmap from=0, count=512
   3.121 +        .if \count-1
   3.122 +        identmap "(\from+0)","(\count/2)"
   3.123 +        identmap "(\from+(0x200000*(\count/2)))","(\count/2)"
   3.124 +        .else
   3.125 +        .quad 0x00000000000000e3 + \from
   3.126 +        .endif
   3.127 +        .endm
   3.128 +
   3.129 +        identmap