libpayload: Add x86_64 (64-bit) support
This patch introduces x86_64 (64-bit) support to the payload, building upon the existing x86 (32-bit) architecture. Files necessary for 64-bit compilation are now guarded by the `CONFIG_LP_ARCH_X86_64` Kconfig option. BUG=b:242829490 TEST=Able to verify all valid combinations between coreboot and payload with this patch. Payload Entry Point Behavior with below code. +----------------+--------------------+----------------------------+ | LP_ARCH_X86_64 | Payload Entry Mode | Description | +----------------+--------------------+----------------------------+ | No | 32-bit | Direct protected mode init | +----------------+--------------------+----------------------------+ | Yes | 32-bit | Protected to long mode | +----------------+--------------------+----------------------------+ | Yes | 64-bit | Long mode initialization | +----------------+--------------------+----------------------------+ Change-Id: I69fda47bedf1a14807b1515c4aed6e3a1d5b8585 Signed-off-by: Subrata Banik <subratabanik@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/81968 Reviewed-by: Julius Werner <jwerner@chromium.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
		| @@ -106,17 +106,22 @@ menu "Architecture Options" | |||||||
|  |  | ||||||
| choice | choice | ||||||
|         prompt "Target Architecture" |         prompt "Target Architecture" | ||||||
|         default ARCH_X86 |         default ARCH_X86_32 | ||||||
|  |  | ||||||
| config ARCH_ARM | config ARCH_ARM | ||||||
|         bool "ARM" |         bool "ARM" | ||||||
|         help |         help | ||||||
|           Support the ARM architecture |           Support the ARM architecture | ||||||
|  |  | ||||||
| config ARCH_X86 | config ARCH_X86_32 | ||||||
|         bool "x86" |         bool "x86_32" | ||||||
|         help |         help | ||||||
|           Support the x86 architecture |           Support the x86_32 architecture | ||||||
|  |  | ||||||
|  | config ARCH_X86_64 | ||||||
|  |         bool "x86_64" | ||||||
|  |         help | ||||||
|  |           Support the x86_64 architecture | ||||||
|  |  | ||||||
| config ARCH_ARM64 | config ARCH_ARM64 | ||||||
|         bool "ARM64" |         bool "ARM64" | ||||||
| @@ -133,6 +138,12 @@ config ARCH_MOCK | |||||||
|  |  | ||||||
| endchoice | endchoice | ||||||
|  |  | ||||||
|  | config ARCH_X86 | ||||||
|  | 	bool | ||||||
|  | 	default y if ARCH_X86_32 || ARCH_X86_64 | ||||||
|  | 	help | ||||||
|  | 	  Support the x86 architecture | ||||||
|  |  | ||||||
| config MULTIBOOT | config MULTIBOOT | ||||||
| 	bool "Multiboot header support" | 	bool "Multiboot header support" | ||||||
| 	depends on ARCH_X86 | 	depends on ARCH_X86 | ||||||
|   | |||||||
| @@ -118,7 +118,8 @@ ARCH-y := $(ARCHDIR-y) | |||||||
| # override here. | # override here. | ||||||
| ARCH-$(CONFIG_LP_ARCH_ARM)     := arm | ARCH-$(CONFIG_LP_ARCH_ARM)     := arm | ||||||
| ARCH-$(CONFIG_LP_ARCH_ARM64)   := arm64 | ARCH-$(CONFIG_LP_ARCH_ARM64)   := arm64 | ||||||
| ARCH-$(CONFIG_LP_ARCH_X86)     := x86_32 | ARCH-$(CONFIG_LP_ARCH_X86_32)  := x86_32 | ||||||
|  | ARCH-$(CONFIG_LP_ARCH_X86_64)  := x86_64 | ||||||
| ARCH-$(CONFIG_LP_ARCH_MOCK)    := mock | ARCH-$(CONFIG_LP_ARCH_MOCK)    := mock | ||||||
|  |  | ||||||
| # Five cases where we don't need fully populated $(obj) lists: | # Five cases where we don't need fully populated $(obj) lists: | ||||||
|   | |||||||
| @@ -96,7 +96,7 @@ $(obj)/libpayload-config.h: $(KCONFIG_AUTOHEADER) $(obj)/libpayload.config | |||||||
| 	cmp $@ $< 2>/dev/null || cp $< $@ | 	cmp $@ $< 2>/dev/null || cp $< $@ | ||||||
|  |  | ||||||
| library-targets = $(addsuffix .a,$(addprefix $(obj)/,$(libraries))) $(obj)/libpayload.a | library-targets = $(addsuffix .a,$(addprefix $(obj)/,$(libraries))) $(obj)/libpayload.a | ||||||
| lib: $$(library-targets) | lib: $$(library-targets) $(obj)/libpayload.ldscript | ||||||
|  |  | ||||||
| extract_nth=$(word $(1), $(subst |, ,$(2))) | extract_nth=$(word $(1), $(subst |, ,$(2))) | ||||||
|  |  | ||||||
| @@ -115,11 +115,15 @@ $(obj)/%.a: $$(%-objs) | |||||||
| 	printf "    AR         $(subst $(CURDIR)/,,$(@))\n" | 	printf "    AR         $(subst $(CURDIR)/,,$(@))\n" | ||||||
| 	printf "create $@\n$(foreach objc,$(filter-out %.a,$^),addmod $(objc)\n)$(foreach lib,$(filter %.a,$^),addlib $(lib)\n)save\nend\n" | $(AR) -M | 	printf "create $@\n$(foreach objc,$(filter-out %.a,$^),addmod $(objc)\n)$(foreach lib,$(filter %.a,$^),addlib $(lib)\n)save\nend\n" | $(AR) -M | ||||||
|  |  | ||||||
|  | $(obj)/libpayload.ldscript: arch/$(ARCHDIR-y)/libpayload.ldscript | ||||||
|  | 	@printf "  LDSCRIPT  $@\n" | ||||||
|  | 	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -E -P -x assembler-with-cpp -undef -o $@ $< | ||||||
|  |  | ||||||
| install: real-target | install: real-target | ||||||
| 	printf "    INSTALL    $(DESTDIR)/libpayload/lib\n" | 	printf "    INSTALL    $(DESTDIR)/libpayload/lib\n" | ||||||
| 	install -m 755 -d $(DESTDIR)/libpayload/lib | 	install -m 755 -d $(DESTDIR)/libpayload/lib | ||||||
| 	install -m 644 $(library-targets) $(DESTDIR)/libpayload/lib/ | 	install -m 644 $(library-targets) $(DESTDIR)/libpayload/lib/ | ||||||
| 	install -m 644 arch/$(ARCHDIR-y)/libpayload.ldscript $(DESTDIR)/libpayload/lib/ | 	install -m 644 $(obj)/libpayload.ldscript $(DESTDIR)/libpayload/lib/ | ||||||
| 	install -m 755 -d $(DESTDIR)/libpayload/lib/$(ARCHDIR-y) | 	install -m 755 -d $(DESTDIR)/libpayload/lib/$(ARCHDIR-y) | ||||||
| 	printf "    INSTALL    $(DESTDIR)/libpayload/include\n" | 	printf "    INSTALL    $(DESTDIR)/libpayload/include\n" | ||||||
| 	install -m 755 -d $(DESTDIR)/libpayload/include | 	install -m 755 -d $(DESTDIR)/libpayload/include | ||||||
|   | |||||||
| @@ -27,16 +27,26 @@ | |||||||
| ## | ## | ||||||
|  |  | ||||||
| ifneq ($(CONFIG_LP_COMPILER_LLVM_CLANG),y) | ifneq ($(CONFIG_LP_COMPILER_LLVM_CLANG),y) | ||||||
|  | ifeq ($(CONFIG_LP_ARCH_X86_64),y) | ||||||
|  | CFLAGS += -mpreferred-stack-boundary=4 | ||||||
|  | else | ||||||
| CFLAGS += -mpreferred-stack-boundary=2 | CFLAGS += -mpreferred-stack-boundary=2 | ||||||
| endif | endif | ||||||
|  | endif | ||||||
|  |  | ||||||
| libc-y += head.S | libc-$(CONFIG_LP_ARCH_X86_32)  += head.S | ||||||
|  | libc-$(CONFIG_LP_ARCH_X86_64)  += head_64.S | ||||||
|  | libc-$(CONFIG_LP_ARCH_X86_64) += pt.S | ||||||
| libc-y += main.c sysinfo.c | libc-y += main.c sysinfo.c | ||||||
| libc-y += timer.c coreboot.c util.S | libc-y += timer.c coreboot.c util.S | ||||||
| libc-y += exec.S virtual.c | libc-y += virtual.c | ||||||
| libc-y += selfboot.c cache.c | libc-y += selfboot.c cache.c | ||||||
| libc-y += exception_asm.S exception.c | libc-y += exception.c | ||||||
| libc-y += delay.c | libc-y += delay.c | ||||||
|  | libc-$(CONFIG_LP_ARCH_X86_32) += exec.c | ||||||
|  | libc-$(CONFIG_LP_ARCH_X86_32) += exec.S | ||||||
|  | libc-$(CONFIG_LP_ARCH_X86_32) += exception_asm.S | ||||||
|  | libc-$(CONFIG_LP_ARCH_X86_64) += exception_asm_64.S | ||||||
|  |  | ||||||
| # Will fall back to default_memXXX() in libc/memory.c if GPL not allowed. | # Will fall back to default_memXXX() in libc/memory.c if GPL not allowed. | ||||||
| libc-$(CONFIG_LP_GPL) += string.c | libc-$(CONFIG_LP_GPL) += string.c | ||||||
|   | |||||||
| @@ -34,7 +34,13 @@ | |||||||
|  |  | ||||||
| #define IF_FLAG				(1 << 9) | #define IF_FLAG				(1 << 9) | ||||||
|  |  | ||||||
| u32 exception_stack[0x400] __attribute__((aligned(8))); | #if CONFIG(LP_ARCH_X86_64) | ||||||
|  | #define REGISTER_FMT "0x%016zx" | ||||||
|  | #else | ||||||
|  | #define REGISTER_FMT "0x%08zx" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | u8 exception_stack[0x400] __aligned(16); | ||||||
|  |  | ||||||
| static interrupt_handler handlers[256]; | static interrupt_handler handlers[256]; | ||||||
|  |  | ||||||
| @@ -143,17 +149,27 @@ static void dump_exception_state(void) | |||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 	printf("\n"); | 	printf("\n"); | ||||||
| 	printf("EIP:    0x%08x\n", exception_state->regs.eip); | 	printf("REG_IP:    " REGISTER_FMT "\n", exception_state->regs.reg_ip); | ||||||
|  | 	printf("REG_FLAGS: " REGISTER_FMT "\n", exception_state->regs.reg_flags); | ||||||
|  | 	printf("REG_AX:    " REGISTER_FMT "\n", exception_state->regs.reg_ax); | ||||||
|  | 	printf("REG_BX:    " REGISTER_FMT "\n", exception_state->regs.reg_bx); | ||||||
|  | 	printf("REG_CX:    " REGISTER_FMT "\n", exception_state->regs.reg_cx); | ||||||
|  | 	printf("REG_DX:    " REGISTER_FMT "\n", exception_state->regs.reg_dx); | ||||||
|  | 	printf("REG_SP:    " REGISTER_FMT "\n", exception_state->regs.reg_sp); | ||||||
|  | 	printf("REG_BP:    " REGISTER_FMT "\n", exception_state->regs.reg_bp); | ||||||
|  | 	printf("REG_SI:    " REGISTER_FMT "\n", exception_state->regs.reg_si); | ||||||
|  | 	printf("REG_DI:    " REGISTER_FMT "\n", exception_state->regs.reg_di); | ||||||
|  | #if CONFIG(LP_ARCH_X86_64) | ||||||
|  | 	printf("REG_R8:    0x%016zx\n", exception_state->regs.reg_r8); | ||||||
|  | 	printf("REG_R9:    0x%016zx\n", exception_state->regs.reg_r9); | ||||||
|  | 	printf("REG_R10:    0x%016zx\n", exception_state->regs.reg_r10); | ||||||
|  | 	printf("REG_R11:    0x%016zx\n", exception_state->regs.reg_r11); | ||||||
|  | 	printf("REG_R12:    0x%016zx\n", exception_state->regs.reg_r12); | ||||||
|  | 	printf("REG_R13:    0x%016zx\n", exception_state->regs.reg_r13); | ||||||
|  | 	printf("REG_R14:    0x%016zx\n", exception_state->regs.reg_r14); | ||||||
|  | 	printf("REG_R15:    0x%016zx\n", exception_state->regs.reg_r15); | ||||||
|  | #endif | ||||||
| 	printf("CS:     0x%04x\n", exception_state->regs.cs); | 	printf("CS:     0x%04x\n", exception_state->regs.cs); | ||||||
| 	printf("EFLAGS: 0x%08x\n", exception_state->regs.eflags); |  | ||||||
| 	printf("EAX:    0x%08x\n", exception_state->regs.eax); |  | ||||||
| 	printf("ECX:    0x%08x\n", exception_state->regs.ecx); |  | ||||||
| 	printf("EDX:    0x%08x\n", exception_state->regs.edx); |  | ||||||
| 	printf("EBX:    0x%08x\n", exception_state->regs.ebx); |  | ||||||
| 	printf("ESP:    0x%08x\n", exception_state->regs.esp); |  | ||||||
| 	printf("EBP:    0x%08x\n", exception_state->regs.ebp); |  | ||||||
| 	printf("ESI:    0x%08x\n", exception_state->regs.esi); |  | ||||||
| 	printf("EDI:    0x%08x\n", exception_state->regs.edi); |  | ||||||
| 	printf("DS:     0x%04x\n", exception_state->regs.ds); | 	printf("DS:     0x%04x\n", exception_state->regs.ds); | ||||||
| 	printf("ES:     0x%04x\n", exception_state->regs.es); | 	printf("ES:     0x%04x\n", exception_state->regs.es); | ||||||
| 	printf("SS:     0x%04x\n", exception_state->regs.ss); | 	printf("SS:     0x%04x\n", exception_state->regs.ss); | ||||||
| @@ -164,7 +180,7 @@ static void dump_exception_state(void) | |||||||
| void exception_dispatch(void) | void exception_dispatch(void) | ||||||
| { | { | ||||||
| 	die_if(exception_state->vector >= ARRAY_SIZE(handlers), | 	die_if(exception_state->vector >= ARRAY_SIZE(handlers), | ||||||
| 	       "Invalid vector %u\n", exception_state->vector); | 	       "Invalid vector %zu\n", exception_state->vector); | ||||||
|  |  | ||||||
| 	u8 vec = exception_state->vector; | 	u8 vec = exception_state->vector; | ||||||
|  |  | ||||||
| @@ -184,7 +200,7 @@ void exception_dispatch(void) | |||||||
| 	       vec); | 	       vec); | ||||||
|  |  | ||||||
| 	dump_exception_state(); | 	dump_exception_state(); | ||||||
| 	dump_stack(exception_state->regs.esp, 512); | 	dump_stack(exception_state->regs.reg_sp, 512); | ||||||
| 	/* We don't call apic_eoi because we don't want to ack the interrupt and | 	/* We don't call apic_eoi because we don't want to ack the interrupt and | ||||||
| 	   allow another interrupt to wake the processor. */ | 	   allow another interrupt to wake the processor. */ | ||||||
| 	halt(); | 	halt(); | ||||||
| @@ -197,6 +213,10 @@ success: | |||||||
|  |  | ||||||
| void exception_init(void) | void exception_init(void) | ||||||
| { | { | ||||||
|  | 	/* TODO: Add exception init code for x64, currently only supporting 32-bit code */ | ||||||
|  | 	if (CONFIG(LP_ARCH_X86_64)) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
| 	exception_stack_end = exception_stack + ARRAY_SIZE(exception_stack); | 	exception_stack_end = exception_stack + ARRAY_SIZE(exception_stack); | ||||||
| 	exception_init_asm(); | 	exception_init_asm(); | ||||||
| } | } | ||||||
| @@ -206,6 +226,17 @@ void set_interrupt_handler(u8 vector, interrupt_handler handler) | |||||||
| 	handlers[vector] = handler; | 	handlers[vector] = handler; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #if CONFIG(LP_ARCH_X86_64) | ||||||
|  | static uint64_t eflags(void) | ||||||
|  | { | ||||||
|  | 	uint64_t eflags; | ||||||
|  | 	asm volatile( | ||||||
|  | 		"pushfq\n\t" | ||||||
|  | 		"popq %0\n\t" | ||||||
|  | 	: "=rm" (eflags)); | ||||||
|  | 	return eflags; | ||||||
|  | } | ||||||
|  | #else | ||||||
| static uint32_t eflags(void) | static uint32_t eflags(void) | ||||||
| { | { | ||||||
| 	uint32_t eflags; | 	uint32_t eflags; | ||||||
| @@ -215,6 +246,7 @@ static uint32_t eflags(void) | |||||||
| 	: "=rm" (eflags)); | 	: "=rm" (eflags)); | ||||||
| 	return eflags; | 	return eflags; | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
| void enable_interrupts(void) | void enable_interrupts(void) | ||||||
| { | { | ||||||
|   | |||||||
							
								
								
									
										221
									
								
								payloads/libpayload/arch/x86/exception_asm_64.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										221
									
								
								payloads/libpayload/arch/x86/exception_asm_64.S
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,221 @@ | |||||||
|  | /* | ||||||
|  |  * | ||||||
|  |  * Copyright 2024 Google Inc. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. The name of the author may not be used to endorse or promote products | ||||||
|  |  *    derived from this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||||||
|  |  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | ||||||
|  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||||
|  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||||||
|  |  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||||
|  |  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||||||
|  |  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||||
|  |  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||||
|  |  * SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | 	.align 16 | ||||||
|  | 	.global exception_stack_end | ||||||
|  | exception_stack_end: | ||||||
|  | 	.quad 0 | ||||||
|  | 	.global exception_state | ||||||
|  | exception_state: | ||||||
|  | 	.quad 0 | ||||||
|  |  | ||||||
|  | /* Some temporary variables which are used while saving exception state. */ | ||||||
|  | vector: | ||||||
|  | 	.quad 0 | ||||||
|  | error_code: | ||||||
|  | 	.quad 0 | ||||||
|  | old_rsp: | ||||||
|  | 	.quad 0 | ||||||
|  | old_rax: | ||||||
|  | 	.quad 0 | ||||||
|  |  | ||||||
|  | 	.align 16 | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Each exception vector has a small stub associated with it which sets aside | ||||||
|  |  * the error code, if any, records which vector we entered from, and calls | ||||||
|  |  * the common exception entry point. Some exceptions have error codes and some | ||||||
|  |  * don't, so we have a macro for each type. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | 	.macro stub num | ||||||
|  | exception_stub_\num: | ||||||
|  | 	movq	$0, error_code | ||||||
|  | 	movq	$\num, vector | ||||||
|  | 	jmp	exception_common | ||||||
|  | 	.endm | ||||||
|  |  | ||||||
|  | 	.macro stub_err num | ||||||
|  | exception_stub_\num: | ||||||
|  | 	pop	error_code | ||||||
|  | 	movq	$\num, vector | ||||||
|  | 	jmp	exception_common | ||||||
|  | 	.endm | ||||||
|  |  | ||||||
|  | 	.altmacro | ||||||
|  | 	.macro	user_defined_stubs from, to | ||||||
|  | 	stub	\from | ||||||
|  | 	.if	\to-\from | ||||||
|  | 	user_defined_stubs	%(from+1),\to | ||||||
|  | 	.endif | ||||||
|  | 	.endm | ||||||
|  |  | ||||||
|  | 	stub 0 | ||||||
|  | 	stub 1 | ||||||
|  | 	stub 2 | ||||||
|  | 	stub 3 | ||||||
|  | 	stub 4 | ||||||
|  | 	stub 5 | ||||||
|  | 	stub 6 | ||||||
|  | 	stub 7 | ||||||
|  | 	stub_err 8 | ||||||
|  | 	stub 9 | ||||||
|  | 	stub_err 10 | ||||||
|  | 	stub_err 11 | ||||||
|  | 	stub_err 12 | ||||||
|  | 	stub_err 13 | ||||||
|  | 	stub_err 14 | ||||||
|  | 	stub 15 | ||||||
|  | 	stub 16 | ||||||
|  | 	stub_err 17 | ||||||
|  | 	stub 18 | ||||||
|  | 	stub 19 | ||||||
|  | 	stub 20 | ||||||
|  | 	stub 21 | ||||||
|  | 	stub 22 | ||||||
|  | 	stub 23 | ||||||
|  | 	stub 24 | ||||||
|  | 	stub 25 | ||||||
|  | 	stub 26 | ||||||
|  | 	stub 27 | ||||||
|  | 	stub 28 | ||||||
|  | 	stub 29 | ||||||
|  | 	stub_err 30 | ||||||
|  | 	stub 31 | ||||||
|  | 	/* Split the macro so we avoid a stack overflow. */ | ||||||
|  | 	user_defined_stubs 32, 63 | ||||||
|  | 	user_defined_stubs 64, 127 | ||||||
|  | 	user_defined_stubs 128, 191 | ||||||
|  | 	user_defined_stubs 192, 255 | ||||||
|  |  | ||||||
|  | exception_common: | ||||||
|  |  | ||||||
|  | 	/* Return from the exception. */ | ||||||
|  | 	iretl | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * We need segment selectors for the IDT, so we need to know where things are | ||||||
|  |  * in the GDT. We set one up here which is pretty standard and largely copied | ||||||
|  |  * from coreboot. | ||||||
|  |  */ | ||||||
|  | 	.align 16 | ||||||
|  | gdt: | ||||||
|  | 	/* selgdt 0, unused */ | ||||||
|  | 	.word 0x0000, 0x0000 | ||||||
|  | 	.byte 0x00, 0x00, 0x00, 0x00 | ||||||
|  |  | ||||||
|  | 	/* selgdt 8, unused */ | ||||||
|  | 	.word 0x0000, 0x0000 | ||||||
|  | 	.byte 0x00, 0x00, 0x00, 0x00 | ||||||
|  |  | ||||||
|  | 	/* selgdt 0x10, flat 4GB code segment */ | ||||||
|  | 	.word 0xffff, 0x0000 | ||||||
|  | 	.byte 0x00, 0x9b, 0xcf, 0x00 | ||||||
|  |  | ||||||
|  | 	/* selgdt 0x18, flat 4GB data segment */ | ||||||
|  | 	.word 0xffff, 0x0000 | ||||||
|  | 	.byte	0x00, 0x92, 0xcf, 0x00 | ||||||
|  |  | ||||||
|  | 	/* selgdt 0x20, flat x64 code segment */ | ||||||
|  | 	.word	0xffff, 0x0000 | ||||||
|  | 	.byte	0x00, 0x9b, 0xaf, 0x00 | ||||||
|  | gdt_end: | ||||||
|  |  | ||||||
|  | /* GDT pointer for use with lgdt */ | ||||||
|  | .global gdt_ptr | ||||||
|  | gdt_ptr: | ||||||
|  | 	.word	gdt_end - gdt - 1 | ||||||
|  | 	.quad	gdt | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * Record the target and construct the actual entry at init time. This | ||||||
|  | 	 * is necessary because the linker doesn't want to construct the entry | ||||||
|  | 	 * for us. | ||||||
|  | 	 */ | ||||||
|  | 	.macro interrupt_gate target | ||||||
|  | 	.quad \target | ||||||
|  | 	.quad \target | ||||||
|  | 	.endm | ||||||
|  |  | ||||||
|  | 	.altmacro | ||||||
|  | 	.macro	user_defined_gates from, to | ||||||
|  | 	interrupt_gate	exception_stub_\from | ||||||
|  | 	.if	\to-\from | ||||||
|  | 	user_defined_gates	%(from+1),\to | ||||||
|  | 	.endif | ||||||
|  | 	.endm | ||||||
|  |  | ||||||
|  | 	.align 16 | ||||||
|  | 	.global	idt | ||||||
|  | idt: | ||||||
|  | 	interrupt_gate exception_stub_0 | ||||||
|  | 	interrupt_gate exception_stub_1 | ||||||
|  | 	interrupt_gate exception_stub_2 | ||||||
|  | 	interrupt_gate exception_stub_3 | ||||||
|  | 	interrupt_gate exception_stub_4 | ||||||
|  | 	interrupt_gate exception_stub_5 | ||||||
|  | 	interrupt_gate exception_stub_6 | ||||||
|  | 	interrupt_gate exception_stub_7 | ||||||
|  | 	interrupt_gate exception_stub_8 | ||||||
|  | 	interrupt_gate exception_stub_9 | ||||||
|  | 	interrupt_gate exception_stub_10 | ||||||
|  | 	interrupt_gate exception_stub_11 | ||||||
|  | 	interrupt_gate exception_stub_12 | ||||||
|  | 	interrupt_gate exception_stub_13 | ||||||
|  | 	interrupt_gate exception_stub_14 | ||||||
|  | 	interrupt_gate exception_stub_15 | ||||||
|  | 	interrupt_gate exception_stub_16 | ||||||
|  | 	interrupt_gate exception_stub_17 | ||||||
|  | 	interrupt_gate exception_stub_18 | ||||||
|  | 	interrupt_gate exception_stub_19 | ||||||
|  | 	interrupt_gate exception_stub_20 | ||||||
|  | 	interrupt_gate exception_stub_21 | ||||||
|  | 	interrupt_gate exception_stub_22 | ||||||
|  | 	interrupt_gate exception_stub_23 | ||||||
|  | 	interrupt_gate exception_stub_24 | ||||||
|  | 	interrupt_gate exception_stub_25 | ||||||
|  | 	interrupt_gate exception_stub_26 | ||||||
|  | 	interrupt_gate exception_stub_27 | ||||||
|  | 	interrupt_gate exception_stub_28 | ||||||
|  | 	interrupt_gate exception_stub_29 | ||||||
|  | 	interrupt_gate exception_stub_30 | ||||||
|  | 	interrupt_gate exception_stub_31 | ||||||
|  | 	user_defined_gates 32, 63 | ||||||
|  | 	user_defined_gates 64, 127 | ||||||
|  | 	user_defined_gates 128, 191 | ||||||
|  | 	user_defined_gates 192, 255 | ||||||
|  | idt_end: | ||||||
|  |  | ||||||
|  | /* IDT pointer for use with lidt */ | ||||||
|  | idt_ptr: | ||||||
|  | 	.word idt_end - idt - 1 | ||||||
|  | 	.quad idt | ||||||
|  |  | ||||||
|  | 	.global exception_init_asm | ||||||
|  | exception_init_asm: | ||||||
|  | 	ret | ||||||
| @@ -29,8 +29,10 @@ | |||||||
| #include <libpayload-config.h> | #include <libpayload-config.h> | ||||||
| #include <libpayload.h> | #include <libpayload.h> | ||||||
| 
 | 
 | ||||||
| #if CONFIG(LP_ARCH_X86) | #if CONFIG(LP_ARCH_X86_32) | ||||||
| extern void i386_do_exec(long addr, int argc, char **argv, int *ret); | extern void i386_do_exec(long addr, int argc, char **argv, int *ret); | ||||||
|  | #else | ||||||
|  | #error "exec does not currently support x86_64." | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
| @@ -45,7 +47,7 @@ int exec(long addr, int argc, char **argv) | |||||||
| { | { | ||||||
| 	int val = -1; | 	int val = -1; | ||||||
| 
 | 
 | ||||||
| #if CONFIG(LP_ARCH_X86) | #if CONFIG(LP_ARCH_X86_32) | ||||||
| 	i386_do_exec(addr, argc, argv, &val); | 	i386_do_exec(addr, argc, argv, &val); | ||||||
| #endif | #endif | ||||||
| 	return val; | 	return val; | ||||||
| @@ -15,6 +15,7 @@ | |||||||
| #include <exception.h> | #include <exception.h> | ||||||
| #include <gdb.h> | #include <gdb.h> | ||||||
| #include <libpayload.h> | #include <libpayload.h> | ||||||
|  | #include <stddef.h> | ||||||
|  |  | ||||||
| static const u8 type_to_signal[] = { | static const u8 type_to_signal[] = { | ||||||
| 	[EXC_DE]  = GDB_SIGFPE, | 	[EXC_DE]  = GDB_SIGFPE, | ||||||
| @@ -53,12 +54,15 @@ void gdb_arch_init(void) | |||||||
|  |  | ||||||
| void gdb_arch_enter(void) | void gdb_arch_enter(void) | ||||||
| { | { | ||||||
| 	u32 *esp; | 	u8 *stack_pointer; | ||||||
|  | #if CONFIG(LP_ARCH_X86_64) | ||||||
| 	asm volatile ("mov %%esp, %0" : "=r"(esp) ); | 	asm volatile ("movq %%rsp, %0" : "=r"(stack_pointer)); | ||||||
|  | #else | ||||||
|  | 	asm volatile ("mov %%esp, %0" : "=r"(stack_pointer)); | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	/* Avoid reentrant exceptions, just call the hook if in one already. */ | 	/* Avoid reentrant exceptions, just call the hook if in one already. */ | ||||||
| 	if (esp >= exception_stack && esp <= exception_stack_end) | 	if (stack_pointer >= exception_stack && stack_pointer <= exception_stack_end) | ||||||
| 		gdb_exception_hook(EXC_BP); | 		gdb_exception_hook(EXC_BP); | ||||||
| 	else | 	else | ||||||
| 		asm volatile ("int3"); | 		asm volatile ("int3"); | ||||||
| @@ -66,12 +70,12 @@ void gdb_arch_enter(void) | |||||||
|  |  | ||||||
| int gdb_arch_set_single_step(int on) | int gdb_arch_set_single_step(int on) | ||||||
| { | { | ||||||
| 	const u32 tf_bit = 1 << 8; | 	const size_t tf_bit = 1 << 8; | ||||||
|  |  | ||||||
| 	if (on) | 	if (on) | ||||||
| 		exception_state->regs.eflags |= tf_bit; | 		exception_state->regs.reg_flags |= tf_bit; | ||||||
| 	else | 	else | ||||||
| 		exception_state->regs.eflags &= ~tf_bit; | 		exception_state->regs.reg_flags &= ~tf_bit; | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										141
									
								
								payloads/libpayload/arch/x86/head_64.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								payloads/libpayload/arch/x86/head_64.S
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,141 @@ | |||||||
|  | /* | ||||||
|  |  * | ||||||
|  |  * Copyright (C) 2024 Google Inc. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. The name of the author may not be used to endorse or promote products | ||||||
|  |  *    derived from this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||||||
|  |  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | ||||||
|  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||||
|  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||||||
|  |  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||||
|  |  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||||||
|  |  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||||
|  |  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||||
|  |  * SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #define IA32_EFER	0xC0000080 | ||||||
|  | #define  EFER_LME	(1 << 8) | ||||||
|  |  | ||||||
|  | 	.code32 | ||||||
|  | 	.global _entry | ||||||
|  | 	.section .text._entry | ||||||
|  | 	.align 4 | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * WARNING: Critical Code Section - 32/64-bit Compatibility | ||||||
|  |  * This code between `_entry` and `jnz _init64` is executed during system initialization. | ||||||
|  |  * It MUST function correctly regardless of whether the system is booting in: | ||||||
|  |  *   - 32-bit protected mode | ||||||
|  |  *   - 64-bit long mode | ||||||
|  |  * To achieve this, ONLY use instructions that produce identical binary output in both modes. | ||||||
|  |  * Thoroughly test ALL modifications to this section in BOTH 32-bit and 64-bit boot | ||||||
|  |  * environments. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | _entry: | ||||||
|  |  | ||||||
|  | 	/* Add multiboot header and jump around it when building with multiboot support. */ | ||||||
|  | #if CONFIG(LP_MULTIBOOT) | ||||||
|  | 	#include "multiboot_header.inc" | ||||||
|  | #endif | ||||||
|  | 	/* No interrupts, please. */ | ||||||
|  | 	cli | ||||||
|  |  | ||||||
|  | 	movl $IA32_EFER, %ecx | ||||||
|  | 	rdmsr | ||||||
|  | 	testl $EFER_LME, %eax | ||||||
|  | 	jnz _init64 | ||||||
|  |  | ||||||
|  | 	lgdt %cs:gdt_ptr | ||||||
|  |  | ||||||
|  | 	/* save pointer to coreboot tables */ | ||||||
|  | 	movl 4(%esp), %eax | ||||||
|  | 	/* | ||||||
|  | 	 * NOTE: coreboot tables has passed over the top of the stack | ||||||
|  | 	 * while calling in protected mode. | ||||||
|  | 	 */ | ||||||
|  | 	movl %eax, cb_header_ptr | ||||||
|  |  | ||||||
|  | 	call init_page_table | ||||||
|  | 	movl $pm4le, %eax | ||||||
|  |  | ||||||
|  | 	/* load identity mapped page tables */ | ||||||
|  | 	movl %eax, %cr3 | ||||||
|  |  | ||||||
|  | 	/* enable PAE */ | ||||||
|  | 	movl %cr4, %eax | ||||||
|  | 	btsl $5, %eax | ||||||
|  | 	movl %eax, %cr4 | ||||||
|  |  | ||||||
|  | 	/* enable long mode */ | ||||||
|  | 	movl $(IA32_EFER), %ecx | ||||||
|  | 	rdmsr | ||||||
|  | 	btsl $8, %eax | ||||||
|  | 	wrmsr | ||||||
|  |  | ||||||
|  | 	/* enable paging */ | ||||||
|  | 	movl %cr0, %eax | ||||||
|  | 	btsl $31, %eax | ||||||
|  | 	movl %eax, %cr0 | ||||||
|  |  | ||||||
|  | 	/* Jump to selgdt 0x20, flat x64 code segment */ | ||||||
|  | 	ljmp $0x20, $_entry64 | ||||||
|  |  | ||||||
|  | .code64 | ||||||
|  | .align 16 | ||||||
|  | _init64: | ||||||
|  | 	movabs	$gdt_ptr, %rax | ||||||
|  | 	lgdt	(%rax) | ||||||
|  |  | ||||||
|  | 	/* | ||||||
|  | 	 * Note: The `cb_header_ptr` has passed as the first argument | ||||||
|  | 	 * to the x86-64 calling convention. | ||||||
|  | 	 */ | ||||||
|  | 	movq %rdi, cb_header_ptr | ||||||
|  |  | ||||||
|  | 	call init_page_table | ||||||
|  | 	movq $pm4le, %rax | ||||||
|  |  | ||||||
|  | 	/* load identity mapped page tables */ | ||||||
|  | 	movq %rax, %cr3 | ||||||
|  |  | ||||||
|  | _entry64: | ||||||
|  | 	/* Store current stack pointer and set up new stack. */ | ||||||
|  | 	movq %rsp, %rax | ||||||
|  | 	movabs	$_estack, %rsp | ||||||
|  |  | ||||||
|  | 	push %rax | ||||||
|  |  | ||||||
|  | 	fninit | ||||||
|  | 	movq %cr0, %rax | ||||||
|  | 	andq $0xFFFFFFFFFFFFFFFB, %rax	/* clear EM */ | ||||||
|  | 	orq $0x00000022, %rax	/* set MP, NE */ | ||||||
|  | 	movq %rax, %cr0 | ||||||
|  |  | ||||||
|  | 	movq %cr4, %rax | ||||||
|  | 	orq $0x00000600, %rax	/* set OSFXSR, OSXMMEXCPT */ | ||||||
|  | 	movq %rax, %cr4 | ||||||
|  |  | ||||||
|  | 	/* Let's rock. */ | ||||||
|  | 	call start_main | ||||||
|  |  | ||||||
|  | 	/* %rax has the return value - pass it on unmolested */ | ||||||
|  | _leave: | ||||||
|  | 	/* Restore old stack. */ | ||||||
|  | 	pop %rsp | ||||||
|  |  | ||||||
|  | 	/* Return to the original context. */ | ||||||
|  | 	ret | ||||||
| @@ -26,8 +26,13 @@ | |||||||
|  * SUCH DAMAGE. |  * SUCH DAMAGE. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | #if CONFIG(LP_ARCH_X86_64) | ||||||
|  | OUTPUT_FORMAT(elf64-x86-64) | ||||||
|  | OUTPUT_ARCH(x86_64) | ||||||
|  | #else | ||||||
| OUTPUT_FORMAT(elf32-i386) | OUTPUT_FORMAT(elf32-i386) | ||||||
| OUTPUT_ARCH(i386) | OUTPUT_ARCH(i386) | ||||||
|  | #endif | ||||||
|  |  | ||||||
| ENTRY(_entry) | ENTRY(_entry) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										149
									
								
								payloads/libpayload/arch/x86/pt.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								payloads/libpayload/arch/x86/pt.S
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,149 @@ | |||||||
|  | /* | ||||||
|  |  * | ||||||
|  |  * Copyright 2024 Google Inc. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions | ||||||
|  |  * are met: | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer. | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright | ||||||
|  |  *    notice, this list of conditions and the following disclaimer in the | ||||||
|  |  *    documentation and/or other materials provided with the distribution. | ||||||
|  |  * 3. The name of the author may not be used to endorse or promote products | ||||||
|  |  *    derived from this software without specific prior written permission. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | ||||||
|  |  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||||
|  |  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | ||||||
|  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||||
|  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||||||
|  |  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||||
|  |  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||||||
|  |  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||||
|  |  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||||
|  |  * SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * For reference see "AMD64 Architecture Programmer's Manual Volume 2", | ||||||
|  |  * Document 24593-Rev. 3.31-July 2019 Chapter 5.3.4 | ||||||
|  |  * | ||||||
|  |  * Page table attributes: WB, User+Supervisor, Present, Writeable, Accessed, Dirty | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | .section .bss | ||||||
|  | #define _PRES (1ULL << 0) | ||||||
|  | #define _RW   (1ULL << 1) | ||||||
|  | #define _US   (1ULL << 2) | ||||||
|  | #define _A    (1ULL << 5) | ||||||
|  | #define _D    (1ULL << 6) | ||||||
|  | #define _PS   (1ULL << 7) | ||||||
|  |  | ||||||
|  | .section .bss.pm4le | ||||||
|  | .global pm4le | ||||||
|  | .align 4096 | ||||||
|  | pm4le: | ||||||
|  | .skip 8 | ||||||
|  |  | ||||||
|  | .section .bss.main_page_table | ||||||
|  | .global main_page_table | ||||||
|  | .align 4096 | ||||||
|  | main_page_table: | ||||||
|  | .skip 8192 | ||||||
|  |  | ||||||
|  | .section .bss.extra_page_table | ||||||
|  | .global extra_page_table | ||||||
|  | .align 4096 | ||||||
|  | extra_page_table: | ||||||
|  | .skip 32 | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * WARNING: 32-bit/64-bit Mode Compatibility for Page Table Initialization | ||||||
|  |  * This `init_page_table` function is designed to work in both 32-bit protected | ||||||
|  |  * mode AND 64-bit long mode. | ||||||
|  |  * | ||||||
|  |  * Key Considerations: | ||||||
|  |  * - Assembly Instructions:  Use ONLY instructions that have the SAME binary representation | ||||||
|  |  *                           in both 32-bit and 64-bit modes. | ||||||
|  |  * - `.code64` Directive:  We're compiling with `.code64` to ensure the assembler uses | ||||||
|  |  *                         the correct 64-bit version of instructions (e.g., `inc`). | ||||||
|  |  * - Register Notation: | ||||||
|  |  *     - Use 64-bit register names (like `%rsi`) for register-indirect addressing to avoid | ||||||
|  |  *       incorrect address size prefixes. | ||||||
|  |  *     - It's safe to use `%esi` with `mov` instructions, as the high 32 bits are zeroed | ||||||
|  |  *       in 64-bit mode. | ||||||
|  |  * | ||||||
|  |  * IMPORTANT: | ||||||
|  |  * Thoroughly test ANY changes to this function in BOTH 32-bit and 64-bit boot environments. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | .code64 | ||||||
|  | .section .text.init_page_table | ||||||
|  | .globl init_page_table | ||||||
|  | .type init_page_table, @function | ||||||
|  |  | ||||||
|  | init_page_table: | ||||||
|  | 	mov $0x80000001, %eax | ||||||
|  | 	cpuid | ||||||
|  | 	test $(1 << 26), %edx | ||||||
|  | 	jnz setup_1gb | ||||||
|  |  | ||||||
|  | setup_2mb: | ||||||
|  | 	mov $2048, %edi | ||||||
|  | 	mov $(_PRES + _RW + _US + _PS + _A + _D), %eax | ||||||
|  | 	mov $0, %ecx | ||||||
|  | 	mov $main_page_table, %esi | ||||||
|  |  | ||||||
|  | loop_2mb: | ||||||
|  | 	mov %eax, (%rsi, %rcx, 8) | ||||||
|  | 	mov $0, 4(%rsi, %rcx, 8) | ||||||
|  | 	add $0x200000, %eax | ||||||
|  | 	inc %ecx | ||||||
|  | 	cmp %edi, %ecx | ||||||
|  | 	jb loop_2mb | ||||||
|  |  | ||||||
|  | 	mov $4, %edi | ||||||
|  | 	mov $main_page_table, %eax | ||||||
|  | 	add $(_PRES + _RW + _US + _A), %eax | ||||||
|  | 	mov $0, %ecx | ||||||
|  | 	mov $extra_page_table, %esi | ||||||
|  |  | ||||||
|  | fill_extra_page_table: | ||||||
|  | 	mov %eax, (%rsi, %rcx, 8) | ||||||
|  | 	mov $0, 4(%rsi, %rcx, 8) | ||||||
|  | 	add $4096, %eax | ||||||
|  | 	inc %ecx | ||||||
|  | 	cmp %edi, %ecx | ||||||
|  | 	jb fill_extra_page_table | ||||||
|  |  | ||||||
|  | 	mov $extra_page_table, %eax | ||||||
|  | 	jmp leave | ||||||
|  |  | ||||||
|  | setup_1gb: | ||||||
|  | 	mov $512, %edi | ||||||
|  | 	mov $(_PRES + _RW + _US + _PS + _A + _D), %eax | ||||||
|  | 	mov $0, %ebx | ||||||
|  | 	mov $0, %ecx | ||||||
|  | 	mov $main_page_table, %esi | ||||||
|  |  | ||||||
|  | loop_1gb: | ||||||
|  | 	mov %eax, (%rsi, %rcx, 8) | ||||||
|  | 	mov %ebx, 4(%rsi, %rcx, 8) | ||||||
|  | 	add $0x40000000, %eax | ||||||
|  | 	cmp $0x40000000, %eax | ||||||
|  | 	ja no_overflow_1gb | ||||||
|  | 	inc %ebx | ||||||
|  | no_overflow_1gb: | ||||||
|  | 	inc %ecx | ||||||
|  | 	cmp %edi, %ecx | ||||||
|  | 	jb loop_1gb | ||||||
|  |  | ||||||
|  | 	mov $main_page_table, %eax | ||||||
|  |  | ||||||
|  | leave: | ||||||
|  | 	or $(_PRES + _RW + _US + _A), %eax | ||||||
|  | 	mov %eax, pm4le | ||||||
|  |  | ||||||
|  | 	ret | ||||||
| @@ -81,6 +81,16 @@ void *memcpy(void *dest, const void *src, size_t n) | |||||||
| { | { | ||||||
| 	unsigned long d0, d1, d2; | 	unsigned long d0, d1, d2; | ||||||
|  |  | ||||||
|  | #if CONFIG(LP_ARCH_X86_64) | ||||||
|  | 	asm volatile( | ||||||
|  | 		"rep ; movsq\n\t" | ||||||
|  | 		"mov %4,%%rcx\n\t" | ||||||
|  | 		"rep ; movsb\n\t" | ||||||
|  | 		: "=&c" (d0), "=&D" (d1), "=&S" (d2) | ||||||
|  | 		: "0" (n >> 3), "g" (n & 7), "1" (dest), "2" (src) | ||||||
|  | 		: "memory" | ||||||
|  | 	); | ||||||
|  | #else | ||||||
| 	asm volatile( | 	asm volatile( | ||||||
| 		"rep ; movsl\n\t" | 		"rep ; movsl\n\t" | ||||||
| 		"movl %4,%%ecx\n\t" | 		"movl %4,%%ecx\n\t" | ||||||
| @@ -89,6 +99,7 @@ void *memcpy(void *dest, const void *src, size_t n) | |||||||
| 		: "0" (n >> 2), "g" (n & 3), "1" (dest), "2" (src) | 		: "0" (n >> 2), "g" (n & 3), "1" (dest), "2" (src) | ||||||
| 		: "memory" | 		: "memory" | ||||||
| 	); | 	); | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	return dest; | 	return dest; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -84,7 +84,11 @@ if [ "$CONFIG_LP_ARCH_ARM64" = "y" ]; then | |||||||
| fi | fi | ||||||
| if [ "$CONFIG_LP_ARCH_X86" = "y" ]; then | if [ "$CONFIG_LP_ARCH_X86" = "y" ]; then | ||||||
|   _ARCHDIR=x86 |   _ARCHDIR=x86 | ||||||
|   _ARCHEXTRA="-m32 " |   if [ "$CONFIG_LP_ARCH_X86_32" = "y" ]; then | ||||||
|  |     _ARCHEXTRA="-m32 " | ||||||
|  |   else | ||||||
|  |     _ARCHEXTRA="-m64 " | ||||||
|  |   fi | ||||||
| fi | fi | ||||||
| if [ "$CONFIG_LP_ARCH_MOCK" = "y" ]; then | if [ "$CONFIG_LP_ARCH_MOCK" = "y" ]; then | ||||||
|   _ARCHDIR=mock |   _ARCHDIR=mock | ||||||
| @@ -122,13 +126,10 @@ CMDLINE= | |||||||
|  |  | ||||||
| while [ $# -gt 0 ]; do | while [ $# -gt 0 ]; do | ||||||
| 	case $1 in | 	case $1 in | ||||||
| 	    -m32|-fno-stack-protector) | 	    -m32|-fno-stack-protector|-m64) | ||||||
| 		shift | 		shift | ||||||
| 		continue | 		continue | ||||||
| 		;; | 		;; | ||||||
| 	    -m64) |  | ||||||
| 		error "Invalid option --64 - only 32 bit architectures are supported" |  | ||||||
| 		;; |  | ||||||
| 	    -c) | 	    -c) | ||||||
| 		DOLINK=0 | 		DOLINK=0 | ||||||
| 		;; | 		;; | ||||||
|   | |||||||
| @@ -66,7 +66,7 @@ static u8 *ahci_prdbuf_init(ahci_dev_t *const dev, | |||||||
| 			    u8 *const user_buf, const size_t len, | 			    u8 *const user_buf, const size_t len, | ||||||
| 			    const int out) | 			    const int out) | ||||||
| { | { | ||||||
| 	if ((u32)user_buf & 1) { | 	if ((uintptr_t)user_buf & 1) { | ||||||
| 		printf("ahci: Odd buffer pointer (%p).\n", user_buf); | 		printf("ahci: Odd buffer pointer (%p).\n", user_buf); | ||||||
| 		if (dev->buf) /* orphaned buffer */ | 		if (dev->buf) /* orphaned buffer */ | ||||||
| 			free(dev->buf - *(dev->buf - 1)); | 			free(dev->buf - *(dev->buf - 1)); | ||||||
| @@ -76,7 +76,7 @@ static u8 *ahci_prdbuf_init(ahci_dev_t *const dev, | |||||||
| 		dev->user_buf = user_buf; | 		dev->user_buf = user_buf; | ||||||
| 		dev->write_back = !out; | 		dev->write_back = !out; | ||||||
| 		dev->buflen = len; | 		dev->buflen = len; | ||||||
| 		if ((u32)dev->buf & 1) { | 		if ((uintptr_t)dev->buf & 1) { | ||||||
| 			dev->buf[0] = 1; | 			dev->buf[0] = 1; | ||||||
| 			dev->buf += 1; | 			dev->buf += 1; | ||||||
| 		} else { | 		} else { | ||||||
|   | |||||||
| @@ -274,7 +274,7 @@ uhci_stop(hci_t *controller) | |||||||
|  |  | ||||||
| #define UHCI_SLEEP_TIME_US 30 | #define UHCI_SLEEP_TIME_US 30 | ||||||
| #define UHCI_TIMEOUT (USB_MAX_PROCESSING_TIME_US / UHCI_SLEEP_TIME_US) | #define UHCI_TIMEOUT (USB_MAX_PROCESSING_TIME_US / UHCI_SLEEP_TIME_US) | ||||||
| #define GET_TD(x) ((void*)(((unsigned int)(x))&~0xf)) | #define GET_TD(x) ((void *)(((unsigned long)(x))&~0xf)) | ||||||
|  |  | ||||||
| static td_t * | static td_t * | ||||||
| wait_for_completed_qh(hci_t *controller, qh_t *qh) | wait_for_completed_qh(hci_t *controller, qh_t *qh) | ||||||
|   | |||||||
| @@ -29,6 +29,7 @@ | |||||||
| #ifndef _ARCH_EXCEPTION_H | #ifndef _ARCH_EXCEPTION_H | ||||||
| #define _ARCH_EXCEPTION_H | #define _ARCH_EXCEPTION_H | ||||||
|  |  | ||||||
|  | #include <stddef.h> | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
|  |  | ||||||
| void exception_init_asm(void); | void exception_init_asm(void); | ||||||
| @@ -38,20 +39,28 @@ void disable_interrupts(void); | |||||||
| /** Returns 1 if interrupts are enabled. */ | /** Returns 1 if interrupts are enabled. */ | ||||||
| int interrupts_enabled(void); | int interrupts_enabled(void); | ||||||
|  |  | ||||||
| struct exception_state | #if CONFIG(LP_ARCH_X86_64) | ||||||
| { | struct exception_state { | ||||||
| 	/* Careful: x86/gdb.c currently relies on the size and order of regs. */ | 	/* Careful: x86/gdb.c currently relies on the size and order of regs. */ | ||||||
| 	struct { | 	struct { | ||||||
| 		u32 eax; | 		size_t reg_ax; | ||||||
| 		u32 ecx; | 		size_t reg_bx; | ||||||
| 		u32 edx; | 		size_t reg_cx; | ||||||
| 		u32 ebx; | 		size_t reg_dx; | ||||||
| 		u32 esp; | 		size_t reg_si; | ||||||
| 		u32 ebp; | 		size_t reg_di; | ||||||
| 		u32 esi; | 		size_t reg_bp; | ||||||
| 		u32 edi; | 		size_t reg_sp; | ||||||
| 		u32 eip; | 		size_t reg_r8; | ||||||
| 		u32 eflags; | 		size_t reg_r9; | ||||||
|  | 		size_t reg_r10; | ||||||
|  | 		size_t reg_r11; | ||||||
|  | 		size_t reg_r12; | ||||||
|  | 		size_t reg_r13; | ||||||
|  | 		size_t reg_r14; | ||||||
|  | 		size_t reg_r15; | ||||||
|  | 		size_t reg_ip; | ||||||
|  | 		size_t reg_flags; | ||||||
| 		u32 cs; | 		u32 cs; | ||||||
| 		u32 ss; | 		u32 ss; | ||||||
| 		u32 ds; | 		u32 ds; | ||||||
| @@ -59,13 +68,39 @@ struct exception_state | |||||||
| 		u32 fs; | 		u32 fs; | ||||||
| 		u32 gs; | 		u32 gs; | ||||||
| 	} regs; | 	} regs; | ||||||
| 	u32 error_code; | 	size_t error_code; | ||||||
| 	u32 vector; | 	size_t vector; | ||||||
| } __packed; | } __packed; | ||||||
|  | #else | ||||||
|  | struct exception_state { | ||||||
|  | 	/* Careful: x86/gdb.c currently relies on the size and order of regs. */ | ||||||
|  | 	struct { | ||||||
|  | 		size_t reg_ax; | ||||||
|  | 		size_t reg_cx; | ||||||
|  | 		size_t reg_dx; | ||||||
|  | 		size_t reg_bx; | ||||||
|  | 		size_t reg_sp; | ||||||
|  | 		size_t reg_bp; | ||||||
|  | 		size_t reg_si; | ||||||
|  | 		size_t reg_di; | ||||||
|  | 		size_t reg_ip; | ||||||
|  | 		size_t reg_flags; | ||||||
|  | 		u32 cs; | ||||||
|  | 		u32 ss; | ||||||
|  | 		u32 ds; | ||||||
|  | 		u32 es; | ||||||
|  | 		u32 fs; | ||||||
|  | 		u32 gs; | ||||||
|  | 	} regs; | ||||||
|  | 	size_t error_code; | ||||||
|  | 	size_t vector; | ||||||
|  | } __packed; | ||||||
|  | #endif | ||||||
|  |  | ||||||
| extern struct exception_state *exception_state; | extern struct exception_state *exception_state; | ||||||
|  |  | ||||||
| extern u32 exception_stack[]; | extern u8 exception_stack[]; | ||||||
| extern u32 *exception_stack_end; | extern u8 *exception_stack_end; | ||||||
|  |  | ||||||
| enum { | enum { | ||||||
| 	EXC_DE = 0, /* Divide by zero */ | 	EXC_DE = 0, /* Divide by zero */ | ||||||
|   | |||||||
| @@ -29,7 +29,7 @@ | |||||||
|  |  | ||||||
| libc-$(CONFIG_LP_LIBC) += malloc.c printf.c console.c string.c | libc-$(CONFIG_LP_LIBC) += malloc.c printf.c console.c string.c | ||||||
| libc-$(CONFIG_LP_LIBC) += memory.c ctype.c lib.c libgcc.c | libc-$(CONFIG_LP_LIBC) += memory.c ctype.c lib.c libgcc.c | ||||||
| libc-$(CONFIG_LP_LIBC) += rand.c time.c exec.c | libc-$(CONFIG_LP_LIBC) += rand.c time.c | ||||||
| libc-$(CONFIG_LP_LIBC) += readline.c getopt_long.c sysinfo.c | libc-$(CONFIG_LP_LIBC) += readline.c getopt_long.c sysinfo.c | ||||||
| libc-$(CONFIG_LP_LIBC) += args.c | libc-$(CONFIG_LP_LIBC) += args.c | ||||||
| libc-$(CONFIG_LP_LIBC) += strlcpy.c | libc-$(CONFIG_LP_LIBC) += strlcpy.c | ||||||
|   | |||||||
| @@ -15,7 +15,8 @@ vboot-fixup-includes = $(filter -I$(coreboottop)/%, $(1)) \ | |||||||
| 		       $(filter-out -I$(coreboottop)/%,$(1))))) | 		       $(filter-out -I$(coreboottop)/%,$(1))))) | ||||||
|  |  | ||||||
| VBOOT_FIRMWARE_ARCH-$(CONFIG_LP_ARCH_ARM) := arm | VBOOT_FIRMWARE_ARCH-$(CONFIG_LP_ARCH_ARM) := arm | ||||||
| VBOOT_FIRMWARE_ARCH-$(CONFIG_LP_ARCH_X86) := x86 | VBOOT_FIRMWARE_ARCH-$(CONFIG_LP_ARCH_X86_32) := x86 | ||||||
|  | VBOOT_FIRMWARE_ARCH-$(CONFIG_LP_ARCH_X86_64) := x86_64 | ||||||
| VBOOT_FIRMWARE_ARCH-$(CONFIG_LP_ARCH_ARM64) := arm64 | VBOOT_FIRMWARE_ARCH-$(CONFIG_LP_ARCH_ARM64) := arm64 | ||||||
|  |  | ||||||
| ifneq ($(CONFIG_LP_ARCH_MOCK),) | ifneq ($(CONFIG_LP_ARCH_MOCK),) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user