[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v4 10/11] xen: modify page table construction
From: |
Daniel Kiper |
Subject: |
Re: [PATCH v4 10/11] xen: modify page table construction |
Date: |
Mon, 22 Feb 2016 10:17:48 +0100 |
User-agent: |
Mutt/1.5.21 (2010-09-15) |
On Mon, Feb 22, 2016 at 07:03:18AM +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 <address@hidden>
> ---
> V4: align variables in assembly sources
> use separate structure define as requested by Daniel Kiper
>
> 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 | 88 ++++++----
> grub-core/lib/x86_64/xen/relocator.S | 135 ++++++---------
> grub-core/lib/xen/relocator.c | 28 ++-
> grub-core/loader/i386/xen.c | 325
> ++++++++++++++++++++++++-----------
> include/grub/i386/memory.h | 7 +
> include/grub/xen/relocator.h | 6 +-
> 6 files changed, 359 insertions(+), 230 deletions(-)
>
> diff --git a/grub-core/lib/i386/xen/relocator.S
> b/grub-core/lib/i386/xen/relocator.S
> index 694a54c..f8d135a 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,10 @@ VARIABLE(grub_relocator_xen_remap_continue)
>
> jmp *%eax
>
> + .p2align 2
I do not think this is needed but...
> +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 +123,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 +131,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 +160,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..38ae157 100644
> --- a/grub-core/lib/x86_64/xen/relocator.S
> +++ b/grub-core/lib/x86_64/xen/relocator.S
> @@ -16,95 +16,86 @@
> * 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 */
> + 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 */
> movq $__HYPERVISOR_update_va_mapping, %rax
> syscall
>
> movq %r9, %rcx
> - 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):
> + .p2align 3
Ditto...
> +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 +103,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..a05b253 100644
> --- a/grub-core/lib/xen/relocator.c
> +++ b/grub-core/lib/xen/relocator.c
> @@ -29,6 +29,11 @@
>
> typedef grub_addr_t grub_xen_reg_t;
>
> +struct grub_relocator_xen_paging_area {
> + grub_xen_reg_t start;
> + grub_xen_reg_t size;
> +};
> +
... this should have GRUB_PACKED because compiler may
add padding to align size member.
Daniel
- Re: [PATCH v4 09/11] xen: add capability to load initrd outside of initial mapping, (continued)
[PATCH v4 01/11] xen: make xen loader callable multiple times, Juergen Gross, 2016/02/22
[PATCH v4 05/11] xen: synchronize xen header, Juergen Gross, 2016/02/22
[PATCH v4 11/11] xen: add capability to load p2m list outside of kernel mapping, Juergen Gross, 2016/02/22
[PATCH v4 06/11] xen: factor out p2m list allocation into separate function, Juergen Gross, 2016/02/22
[PATCH v4 04/11] xen: add elfnote.h to avoid using numbers instead of constants, Juergen Gross, 2016/02/22
[PATCH v4 03/11] xen: reduce number of global variables in xen loader, Juergen Gross, 2016/02/22
[PATCH v4 10/11] xen: modify page table construction, Juergen Gross, 2016/02/22
- Re: [PATCH v4 10/11] xen: modify page table construction,
Daniel Kiper <=
- Re: [PATCH v4 10/11] xen: modify page table construction, Juergen Gross, 2016/02/22
- Re: [PATCH v4 10/11] xen: modify page table construction, Daniel Kiper, 2016/02/22
- Re: [PATCH v4 10/11] xen: modify page table construction, Juergen Gross, 2016/02/22
- Re: [PATCH v4 10/11] xen: modify page table construction, Daniel Kiper, 2016/02/22
- Re: [PATCH v4 10/11] xen: modify page table construction, Juergen Gross, 2016/02/22
- Re: [PATCH v4 10/11] xen: modify page table construction, Andrei Borzenkov, 2016/02/25
- Re: [PATCH v4 10/11] xen: modify page table construction, Juergen Gross, 2016/02/29
- Re: [PATCH v4 10/11] xen: modify page table construction, Juergen Gross, 2016/02/29
- Re: [PATCH v4 10/11] xen: modify page table construction, Andrei Borzenkov, 2016/02/29