[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v3 09/10] xen: modify page table construction



On Wed, Feb 17, 2016 at 06:19:36PM +0100, Juergen Gross wrote:
> Modify the page table construction to allow multiple virtual regions
> to be mapped. This is done as preparation for removing the p2m list
> from the initial kernel mapping in order to support huge pv domains.
>
> This allows a cleaner approach for mapping the relocator page by
> using this capability.
>
> The interface to the assembler level of the relocator has to be changed
> in order to be able to process multiple page table areas.
>
> Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
> ---
> V3: use constants instead of numbers as requested by Daniel Kiper
>     add lots of comments to assembly code as requested by Daniel Kiper
> ---
>  grub-core/lib/i386/xen/relocator.S   |  87 ++++++----
>  grub-core/lib/x86_64/xen/relocator.S | 134 ++++++---------
>  grub-core/lib/xen/relocator.c        |  25 ++-
>  grub-core/loader/i386/xen.c          | 325 
> ++++++++++++++++++++++++-----------
>  include/grub/i386/memory.h           |   7 +
>  include/grub/xen/relocator.h         |   6 +-
>  6 files changed, 354 insertions(+), 230 deletions(-)
>
> diff --git a/grub-core/lib/i386/xen/relocator.S 
> b/grub-core/lib/i386/xen/relocator.S
> index 694a54c..f1c729e 100644
> --- a/grub-core/lib/i386/xen/relocator.S
> +++ b/grub-core/lib/i386/xen/relocator.S
> @@ -16,6 +16,8 @@
>   *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
>   */
>
> +#include <grub/i386/memory.h>
> +#include <grub/i386/types.h>
>  #include <grub/symbol.h>
>  #include <grub/xen.h>
>
> @@ -23,78 +25,86 @@
>
>  VARIABLE(grub_relocator_xen_remap_start)
>  LOCAL(base):
> -     /* mov imm32, %ebx */
> +     /* Remap the remapper to it's new address. */
> +     /* mov imm32, %ebx - %ebx: new virtual address of remapper */
>       .byte   0xbb
>  VARIABLE(grub_relocator_xen_remapper_virt)
>       .long   0
>
> -     /* mov imm32, %ecx */
> +     /* mov imm32, %ecx - %ecx: low part of page table entry */
>       .byte   0xb9
>  VARIABLE(grub_relocator_xen_remapper_map)
>       .long   0
>
> -     /* mov imm32, %edx */
> +     /* mov imm32, %edx  - %edx: high part of page table entry */
>       .byte   0xba
>  VARIABLE(grub_relocator_xen_remapper_map_high)
>       .long   0
>
> -     movl    %ebx, %ebp
> +     movl    %ebx, %ebp      /* %ebx is clobbered by hypercall */
>
> -     movl    $2, %esi
> +     movl    $UVMF_INVLPG, %esi      /* esi: flags (inv. single entry) */
>       movl    $__HYPERVISOR_update_va_mapping, %eax
>       int     $0x82
>
>       movl    %ebp, %ebx
>       addl   $(LOCAL(cont) - LOCAL(base)), %ebx
>
> -     jmp *%ebx
> +     jmp *%ebx               /* Continue with new virtual address */
>
>  LOCAL(cont):
> -     xorl    %eax, %eax
> -     movl    %eax, %ebp
> +     /* Modify mappings of new page tables to be read-only. */
> +     /* mov imm32, %eax */
> +     .byte   0xb8
> +VARIABLE(grub_relocator_xen_paging_areas_addr)
> +     .long   0
> +     movl    %eax, %ebx
>  1:
> +     movl    0(%ebx), %ebp   /* Get start pfn of the current area */
> +     movl    GRUB_TARGET_SIZEOF_LONG(%ebx), %ecx     /* Get # of pg tables */
> +     testl   %ecx, %ecx      /* 0 -> last area reached */
> +     jz      3f
> +     addl    $(2 * GRUB_TARGET_SIZEOF_LONG), %ebx
> +     movl    %ebx, %esp      /* Save current area pointer */
>
> +2:
> +     movl    %ecx, %edi
>       /* mov imm32, %eax */
>       .byte   0xb8
>  VARIABLE(grub_relocator_xen_mfn_list)
>       .long   0
> -     movl    %eax, %edi
> -     movl    %ebp, %eax
> -     movl    0(%edi, %eax, 4), %ecx
> -
> -     /* mov imm32, %ebx */
> -     .byte   0xbb
> -VARIABLE(grub_relocator_xen_paging_start)
> -     .long   0
> -     shll    $12, %eax
> -     addl    %eax, %ebx
> +     movl    0(%eax, %ebp, 4), %ecx  /* mfn */
> +     movl    %ebp, %ebx
> +     shll    $PAGE_SHIFT, %ebx       /* virtual address (1:1 mapping) */
>       movl    %ecx, %edx
> -     shll    $12,  %ecx
> -     shrl    $20,  %edx
> -     orl     $5, %ecx
> -     movl    $2, %esi
> +     shll    $PAGE_SHIFT,  %ecx      /* prepare pte low part */
> +     shrl    $(32 - PAGE_SHIFT),  %edx       /* pte high part */
> +     orl     $(GRUB_PAGE_PRESENT | GRUB_PAGE_USER), %ecx     /* pte low */
> +     movl    $UVMF_INVLPG, %esi
>       movl    $__HYPERVISOR_update_va_mapping, %eax
> -     int     $0x82
> +     int     $0x82           /* parameters: eax, ebx, ecx, edx, esi */
>
> -     incl    %ebp
> -     /* mov imm32, %ecx */
> -     .byte   0xb9
> -VARIABLE(grub_relocator_xen_paging_size)
> -     .long   0
> -     cmpl    %ebp, %ecx
> +     incl    %ebp            /* next pfn */
> +     movl    %edi, %ecx
>
> -     ja      1b
> +     loop    2b
>
> +     mov     %esp, %ebx      /* restore area poniter */
> +     jmp     1b
> +
> +3:
> +     /* Switch page tables: pin new L3 pt, load cr3, unpin old L3. */
>       /* mov imm32, %ebx */
>       .byte   0xbb
>  VARIABLE(grub_relocator_xen_mmu_op_addr)
>       .long  0
> -     movl   $3, %ecx
> -     movl   $0, %edx
> -     movl   $0x7FF0, %esi
> +     movl   $3, %ecx         /* 3 mmu ops */
> +     movl   $0, %edx         /* pdone (not used) */
> +     movl   $DOMID_SELF, %esi
>       movl   $__HYPERVISOR_mmuext_op, %eax
>       int     $0x82
>
> +     /* Continue in virtual kernel mapping. */
>       /* mov imm32, %eax */
>       .byte   0xb8
>  VARIABLE(grub_relocator_xen_remap_continue)
> @@ -102,6 +112,9 @@ VARIABLE(grub_relocator_xen_remap_continue)
>
>       jmp *%eax
>
> +VARIABLE(grub_relocator_xen_paging_areas)
> +     .long   0, 0, 0, 0, 0, 0, 0, 0
> +
>  VARIABLE(grub_relocator_xen_mmu_op)
>       .space 256
>
> @@ -109,6 +122,7 @@ VARIABLE(grub_relocator_xen_remap_end)
>
>
>  VARIABLE(grub_relocator_xen_start)
> +     /* Unmap old remapper area. */
>       /* mov imm32, %eax */
>       .byte   0xb8
>  VARIABLE(grub_relocator_xen_remapper_virt2)
> @@ -116,14 +130,14 @@ VARIABLE(grub_relocator_xen_remapper_virt2)
>
>       movl    %eax, %edi
>
> -     xorl    %ecx, %ecx
> +     xorl    %ecx, %ecx      /* Invalid pte */
>       xorl    %edx, %edx
>
> -     movl    $2, %esi
> +     movl    $UVMF_INVLPG, %esi
>       movl    $__HYPERVISOR_update_va_mapping, %eax
>       int     $0x82
>
> -
> +     /* Prepare registers for starting kernel. */
>       /* mov imm32, %eax */
>       .byte   0xb8
>  VARIABLE(grub_relocator_xen_stack)
> @@ -145,6 +159,7 @@ VARIABLE(grub_relocator_xen_start_info)
>  VARIABLE(grub_relocator_xen_entry_point)
>       .long   0
>
> +     /* Now start the new kernel. */
>       jmp *%eax
>
>  VARIABLE(grub_relocator_xen_end)
> diff --git a/grub-core/lib/x86_64/xen/relocator.S 
> b/grub-core/lib/x86_64/xen/relocator.S
> index 92e9e72..f5364ed 100644
> --- a/grub-core/lib/x86_64/xen/relocator.S
> +++ b/grub-core/lib/x86_64/xen/relocator.S
> @@ -16,95 +16,85 @@
>   *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
>   */
>
> +#include <grub/x86_64/memory.h>
> +#include <grub/x86_64/types.h>
>  #include <grub/symbol.h>
>  #include <grub/xen.h>
>
> +/* Macro to load an imm64 value stored by the C-part into %rax: */
> +#define MOV_IMM64_RAX(var) .byte 0x48, 0xb8; VARIABLE(var); .quad 0
> +
>       .p2align        4       /* force 16-byte alignment */
>
>  VARIABLE(grub_relocator_xen_remap_start)
>  LOCAL(base):
> -     /* mov imm64, %rax */
> -     .byte   0x48
> -     .byte   0xb8
> -VARIABLE(grub_relocator_xen_remapper_virt)
> -     .quad   0
> +     /* Remap the remapper to it's new address. */
> +     MOV_IMM64_RAX(grub_relocator_xen_remapper_virt)
>
> -     movq    %rax, %rdi
> -     movq    %rax, %rbx
> +     movq    %rax, %rdi      /* %rdi: new virtual address of remapper */
> +     movq    %rax, %rbx      /* Remember new virtual address */
>
> -     /* mov imm64, %rax */
> -     .byte   0x48
> -     .byte   0xb8
> -VARIABLE(grub_relocator_xen_remapper_map)
> -     .quad   0
> +     MOV_IMM64_RAX(grub_relocator_xen_remapper_map)
>
> -     movq    %rax, %rsi
> +     movq    %rax, %rsi      /* %rsi: page table entry */
>
> -     movq    $2, %rdx
> +     movq    $UVMF_INVLPG, %rdx      /* %rdx: flags (inv. single entry) */
>       movq    $__HYPERVISOR_update_va_mapping, %rax
> -     syscall
> +     syscall                 /* Do the remap operation */
>
>       addq   $(LOCAL(cont) - LOCAL(base)), %rbx
>
> -     jmp *%rbx
> +     jmp *%rbx               /* Continue with new virtual address */
>
>  LOCAL(cont):
> -
> -     /* mov imm64, %rcx */
> -     .byte   0x48
> -     .byte   0xb9
> -VARIABLE(grub_relocator_xen_paging_size)
> -     .quad   0
> +     /* Modify mappings of new page tables to be read-only. */
> +     MOV_IMM64_RAX(grub_relocator_xen_mfn_list)
>
> -     /* mov imm64, %rax */
> -     .byte   0x48
> -     .byte   0xb8
> -VARIABLE(grub_relocator_xen_paging_start)
> -     .quad   0
> +     movq    %rax, %rbx      /* %rbx is the base of the p2m list */
> +     leaq    EXT_C(grub_relocator_xen_paging_areas) (%rip), %r8
>
> -     movq    %rax, %r12
> -
> -     /* mov imm64, %rax */
> -     .byte   0x48
> -     .byte   0xb8
> -VARIABLE(grub_relocator_xen_mfn_list)
> -     .quad   0
> -
> -     movq    %rax, %rsi
>  1:
> +     movq    0(%r8), %r12    /* Get start pfn of the current area */
> +     movq    GRUB_TARGET_SIZEOF_LONG(%r8), %rcx      /* Get # of pg tables */

Use %r9 here and...

> +     testq   %rcx, %rcx      /* 0 -> last area reached */
> +     jz      3f
> +2:
>       movq    %r12, %rdi
> -     movq    %rsi, %rbx
> -     movq    0(%rsi), %rsi
> -     shlq    $12,  %rsi
> -     orq     $5, %rsi
> -     movq    $2, %rdx
> -     movq    %rcx, %r9
> +     shlq    $PAGE_SHIFT, %rdi       /* virtual address (1:1 mapping) */
> +     movq    (%rbx, %r12, 8), %rsi   /* mfn */
> +     shlq    $PAGE_SHIFT,  %rsi
> +     orq     $(GRUB_PAGE_PRESENT | GRUB_PAGE_USER), %rsi     /* Build pte */
> +     movq    $UVMF_INVLPG, %rdx
> +     movq    %rcx, %r9       /* %rcx clobbered by hypercall */

... you can avoid this...

>       movq    $__HYPERVISOR_update_va_mapping, %rax
>       syscall
>
>       movq    %r9, %rcx

and this...

> -     addq    $8, %rbx
> -     addq    $4096, %r12
> -     movq    %rbx, %rsi
> +     incq    %r12            /* next pfn */
>
> -     loop 1b
> +     loop 2b
>
> -     leaq   LOCAL(mmu_op) (%rip), %rdi
> -     movq   $3, %rsi
> -     movq   $0, %rdx
> -     movq   $0x7FF0, %r10
> +     addq    $(2 * GRUB_TARGET_SIZEOF_LONG), %r8     /* next pg table area */
> +     jmp     1b
> +
> +3:
> +     /* Switch page tables: pin new L4 pt, load cr3, unpin old L4. */
> +     leaq   EXT_C(grub_relocator_xen_mmu_op) (%rip), %rdi
> +     movq   $3, %rsi         /* 3 mmu ops */
> +     movq   $0, %rdx         /* pdone (not used) */
> +     movq   $DOMID_SELF, %r10
>       movq   $__HYPERVISOR_mmuext_op, %rax
>       syscall
>
> -     /* mov imm64, %rax */
> -     .byte   0x48
> -     .byte   0xb8
> -VARIABLE(grub_relocator_xen_remap_continue)
> -     .quad   0
> +     /* Continue in virtual kernel mapping. */
> +     MOV_IMM64_RAX(grub_relocator_xen_remap_continue)
>
>       jmp *%rax
>
> -LOCAL(mmu_op):
> +VARIABLE(grub_relocator_xen_paging_areas)
> +     /* array of start, size pairs, size 0 is end marker */
> +     .quad   0, 0, 0, 0, 0, 0, 0, 0
> +
>  VARIABLE(grub_relocator_xen_mmu_op)
>       .space 256
>
> @@ -112,46 +102,32 @@ VARIABLE(grub_relocator_xen_remap_end)
>
>
>  VARIABLE(grub_relocator_xen_start)
> -     /* mov imm64, %rax */
> -     .byte   0x48
> -     .byte   0xb8
> -VARIABLE(grub_relocator_xen_remapper_virt2)
> -     .quad   0
> +     /* Unmap old remapper area. */
> +     MOV_IMM64_RAX(grub_relocator_xen_remapper_virt2)
>
>       movq    %rax, %rdi
>
> -     xorq    %rax, %rax
> +     xorq    %rax, %rax      /* Invalid pte */
>       movq    %rax, %rsi
>
> -     movq    $2, %rdx
> +     movq    $UVMF_INVLPG, %rdx
>       movq    $__HYPERVISOR_update_va_mapping, %rax
>       syscall
>
> -
> -     /* mov imm64, %rax */
> -     .byte   0x48
> -     .byte   0xb8
> -VARIABLE(grub_relocator_xen_stack)
> -     .quad   0
> +     /* Prepare registers for starting kernel. */
> +     MOV_IMM64_RAX(grub_relocator_xen_stack)
>
>       movq    %rax, %rsp
>
> -     /* mov imm64, %rax */
> -     .byte   0x48
> -     .byte   0xb8
> -VARIABLE(grub_relocator_xen_start_info)
> -     .quad   0
> +     MOV_IMM64_RAX(grub_relocator_xen_start_info)
>
>       movq    %rax, %rsi
>
>       cld
>
> -     /* mov imm64, %rax */
> -     .byte   0x48
> -     .byte   0xb8
> -VARIABLE(grub_relocator_xen_entry_point)
> -     .quad   0
> +     MOV_IMM64_RAX(grub_relocator_xen_entry_point)
>
> +     /* Now start the new kernel. */
>       jmp *%rax
>
>  VARIABLE(grub_relocator_xen_end)
> diff --git a/grub-core/lib/xen/relocator.c b/grub-core/lib/xen/relocator.c
> index 8f427d3..250fbd4 100644
> --- a/grub-core/lib/xen/relocator.c
> +++ b/grub-core/lib/xen/relocator.c
> @@ -36,15 +36,18 @@ extern grub_uint8_t grub_relocator_xen_remap_end;
>  extern grub_xen_reg_t grub_relocator_xen_stack;
>  extern grub_xen_reg_t grub_relocator_xen_start_info;
>  extern grub_xen_reg_t grub_relocator_xen_entry_point;
> -extern grub_xen_reg_t grub_relocator_xen_paging_start;
> -extern grub_xen_reg_t grub_relocator_xen_paging_size;
>  extern grub_xen_reg_t grub_relocator_xen_remapper_virt;
>  extern grub_xen_reg_t grub_relocator_xen_remapper_virt2;
>  extern grub_xen_reg_t grub_relocator_xen_remapper_map;
>  extern grub_xen_reg_t grub_relocator_xen_mfn_list;
> +extern struct {
> +  grub_xen_reg_t start;
> +  grub_xen_reg_t size;
> +} grub_relocator_xen_paging_areas[XEN_MAX_MAPPINGS];

Should not you add GRUB_PACKED here? Could you define type
earlier and use it here?

Daniel

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.