View | Details | Raw Unified | Return to bug 209821 | Differences between
and this patch

Collapse All | Expand All

(-)b/stand/efi/loader/arch/amd64/amd64_tramp.S (-19 / +40 lines)
Lines 1-9 Link Here
1
/*-
1
/*-
2
 * Copyright (c) 2013 The FreeBSD Foundation
2
 * Copyright (c) 2013 The FreeBSD Foundation
3
 * Copyright 2020 David Sebek <dasebek@gmail.com>
3
 * All rights reserved.
4
 * All rights reserved.
4
 *
5
 *
5
 * This software was developed by Benno Rice under sponsorship from
6
 * This software was developed by Benno Rice under sponsorship from
6
 * the FreeBSD Foundation.
7
 * the FreeBSD Foundation.
8
 *
7
 * Redistribution and use in source and binary forms, with or without
9
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
10
 * modification, are permitted provided that the following conditions
9
 * are met:
11
 * are met:
Lines 31-64 Link Here
31
#include <machine/asmacros.h>
33
#include <machine/asmacros.h>
32
34
33
	.text
35
	.text
34
	.globl	amd64_tramp
36
	.globl	amd64_tramp_inline
35
37
36
/*
38
/*
37
 * void amd64_tramp(uint64_t stack, void *copy_finish, uint64_t kernend,
39
 * void amd64_tramp_inline(uint64_t stack %rdi, uint64_t kernend %rsi,
38
 *		    uint64_t modulep, uint64_t pagetable, uint64_t entry)
40
 *    uint64_t modulep %rdx, uint64_t pagetable %rcx, uint64_t entry %r8,
41
 *    uint64_t copy_dst %r9, uint64_t copy_src 8(%rsp),
42
 *    uint64_t copy_src_end 16(%rsp))
39
 */
43
 */
40
amd64_tramp:
44
amd64_tramp_inline:
41
	cli			/* Make sure we don't get interrupted. */
45
	cli			/* Make sure we don't get interrupted. */
42
	movq	%rdi,%rsp	/* Switch to our temporary stack. */
43
46
44
	movq	%rdx,%r12	/* Stash the kernel values for later. */
47
	/*
45
	movq	%rcx,%r13
48
	 * Copy the kernel from the staging area to the expected location
46
	movq	%r8,%r14
49
	 * in memory. The following code is equivalent to the efi_copy_finish
47
	movq	%r9,%r15
50
	 * function that amd64_tramp used to call. Inlining this code avoids
51
	 * a scenario when the system froze because efi_copy_finish
52
	 * overwrote its own code that just happened to be located somewhere
53
	 * in the destination range.
54
	 *
55
	 * while (copy_src < copy_src_end) *copy_dst++ = *copy_src++;
56
	 */
57
	movq	8(%rsp), %rax	/* rax = copy_src */
58
	movq	16(%rsp), %r10	/* rcx = copy_src_end */
59
	cmpq	%r10, %rax
60
	jnb	copy_done
61
	subq	%rax, %r9		/* r9 = copy_dst - copy_src */
62
loop:
63
	movq	(%rax), %r11
64
	movq	%r11, (%rax,%r9)
65
	addq	$8, %rax
66
	cmpq	%rax, %r10
67
	ja	loop
68
copy_done:
48
69
49
	callq	*%rsi		/* Call copy_finish so we're all ready to go. */
70
	movq	%rdi,%rsp	/* Switch to our temporary stack. */
50
71
51
	pushq	%r12		/* Push kernend. */
72
	pushq	%rsi		/* Push kernend. */
52
	salq	$32,%r13	/* Shift modulep and push it. */
73
	salq	$32,%rdx	/* Shift modulep and push it. */
53
	pushq	%r13
74
	pushq	%rdx
54
	pushq	%r15		/* Push the entry address. */
75
	pushq	%r8		/* Push the entry address. */
55
	movq	%r14,%cr3	/* Switch page tables. */
76
	movq	%rcx,%cr3	/* Switch page tables. */
56
	ret			/* "Return" to kernel entry. */
77
	ret			/* "Return" to kernel entry. */
57
78
58
	ALIGN_TEXT
79
	ALIGN_TEXT
59
amd64_tramp_end:
80
amd64_tramp_inline_end:
60
81
61
	.data
82
	.data
62
	.globl	amd64_tramp_size
83
	.globl	amd64_tramp_inline_size
63
amd64_tramp_size:
84
amd64_tramp_inline_size:
64
	.long	amd64_tramp_end-amd64_tramp
85
	.long	amd64_tramp_inline_end-amd64_tramp_inline
(-)b/stand/efi/loader/arch/amd64/elf64_freebsd.c (-7 / +11 lines)
Lines 78-88 static pml4_entry_t *PT4; Link Here
78
static pdp_entry_t *PT3;
78
static pdp_entry_t *PT3;
79
static pd_entry_t *PT2;
79
static pd_entry_t *PT2;
80
80
81
static void (*trampoline)(uint64_t stack, void *copy_finish, uint64_t kernend,
81
static void (*trampoline)(uint64_t stack, uint64_t kernend,
82
    uint64_t modulep, pml4_entry_t *pagetable, uint64_t entry);
82
    uint64_t modulep, pml4_entry_t *pagetable, uint64_t entry,
83
    uint64_t copy_dst, uint64_t copy_src, uint64_t copy_src_end);
83
84
84
extern uintptr_t amd64_tramp;
85
extern uintptr_t amd64_tramp_inline;
85
extern uint32_t amd64_tramp_size;
86
extern uint32_t amd64_tramp_inline_size;
86
87
87
/*
88
/*
88
 * There is an ELF kernel and one or more ELF modules loaded.
89
 * There is an ELF kernel and one or more ELF modules loaded.
Lines 95-100 elf64_exec(struct preloaded_file *fp) Link Here
95
	struct file_metadata	*md;
96
	struct file_metadata	*md;
96
	Elf_Ehdr 		*ehdr;
97
	Elf_Ehdr 		*ehdr;
97
	vm_offset_t		modulep, kernend, trampcode, trampstack;
98
	vm_offset_t		modulep, kernend, trampcode, trampstack;
99
	uint64_t		copy_dst, copy_src, copy_src_end;
98
	int			err, i;
100
	int			err, i;
99
	ACPI_TABLE_RSDP		*rsdp;
101
	ACPI_TABLE_RSDP		*rsdp;
100
	char			buf[24];
102
	char			buf[24];
Lines 153-159 elf64_exec(struct preloaded_file *fp) Link Here
153
	    (EFI_PHYSICAL_ADDRESS *)&trampcode);
155
	    (EFI_PHYSICAL_ADDRESS *)&trampcode);
154
	bzero((void *)trampcode, EFI_PAGE_SIZE);
156
	bzero((void *)trampcode, EFI_PAGE_SIZE);
155
	trampstack = trampcode + EFI_PAGE_SIZE - 8;
157
	trampstack = trampcode + EFI_PAGE_SIZE - 8;
156
	bcopy((void *)&amd64_tramp, (void *)trampcode, amd64_tramp_size);
158
	bcopy((void *)&amd64_tramp_inline, (void *)trampcode, amd64_tramp_inline_size);
157
	trampoline = (void *)trampcode;
159
	trampoline = (void *)trampcode;
158
160
159
	PT4 = (pml4_entry_t *)0x0000000040000000;
161
	PT4 = (pml4_entry_t *)0x0000000040000000;
Lines 194-201 elf64_exec(struct preloaded_file *fp) Link Here
194
196
195
	dev_cleanup();
197
	dev_cleanup();
196
198
197
	trampoline(trampstack, efi_copy_finish, kernend, modulep, PT4,
199
	efi_copy_get_locations(&copy_dst, &copy_src, &copy_src_end);
198
	    ehdr->e_entry);
200
201
	trampoline(trampstack, kernend, modulep, PT4,
202
	    ehdr->e_entry, copy_dst, copy_src, copy_src_end);
199
203
200
	panic("exec returned");
204
	panic("exec returned");
201
}
205
}
(-)b/stand/efi/loader/copy.c (+8 lines)
Lines 361-363 efi_copy_finish(void) Link Here
361
	while (src < last)
361
	while (src < last)
362
		*dst++ = *src++;
362
		*dst++ = *src++;
363
}
363
}
364
365
void
366
efi_copy_get_locations(uint64_t *dst, uint64_t *src, uint64_t *src_end)
367
{
368
	*src = (uint64_t)staging;
369
	*dst = (uint64_t)(staging - stage_offset);
370
	*src_end = (uint64_t)staging_end;
371
}
(-)b/stand/efi/loader/loader_efi.h (+1 lines)
Lines 44-48 ssize_t efi_readin(readin_handle_t fd, vm_offset_t dest, const size_t len); Link Here
44
void * efi_translate(vm_offset_t ptr);
44
void * efi_translate(vm_offset_t ptr);
45
45
46
void	efi_copy_finish(void);
46
void	efi_copy_finish(void);
47
void	efi_copy_get_locations(uint64_t *dst, uint64_t *src, uint64_t *src_end);
47
48
48
#endif	/* _LOADER_EFI_COPY_H_ */
49
#endif	/* _LOADER_EFI_COPY_H_ */

Return to bug 209821