Subrata Banik has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/81968?usp=email )
Change subject: libpayload: Add initial patch or 64-bit compilation ......................................................................
libpayload: Add initial patch or 64-bit compilation
Change-Id: I69fda47bedf1a14807b1515c4aed6e3a1d5b8585 Signed-off-by: Subrata Banik subratabanik@google.com --- M payloads/libpayload/Kconfig M payloads/libpayload/Makefile M payloads/libpayload/Makefile.mk A payloads/libpayload/arch/x64/Kconfig A payloads/libpayload/arch/x64/Makefile.mk A payloads/libpayload/arch/x64/apic.c A payloads/libpayload/arch/x64/boot_media.c A payloads/libpayload/arch/x64/cache.c A payloads/libpayload/arch/x64/coreboot.c A payloads/libpayload/arch/x64/delay.c A payloads/libpayload/arch/x64/exception.c A payloads/libpayload/arch/x64/exception_asm.S A payloads/libpayload/arch/x64/exec.S A payloads/libpayload/arch/x64/gdb.c A payloads/libpayload/arch/x64/head.S A payloads/libpayload/arch/x64/libpayload.ldscript A payloads/libpayload/arch/x64/main.c A payloads/libpayload/arch/x64/multiboot.c A payloads/libpayload/arch/x64/selfboot.c A payloads/libpayload/arch/x64/string.c A payloads/libpayload/arch/x64/sysinfo.c A payloads/libpayload/arch/x64/timer.c A payloads/libpayload/arch/x64/util.S A payloads/libpayload/arch/x64/virtual.c M payloads/libpayload/arch/x86/Kconfig M payloads/libpayload/bin/lpgcc A payloads/libpayload/include/x64/arch/apic.h A payloads/libpayload/include/x64/arch/barrier.h A payloads/libpayload/include/x64/arch/cache.h A payloads/libpayload/include/x64/arch/cpuid.h A payloads/libpayload/include/x64/arch/exception.h A payloads/libpayload/include/x64/arch/io.h A payloads/libpayload/include/x64/arch/msr.h A payloads/libpayload/include/x64/arch/rdtsc.h A payloads/libpayload/include/x64/arch/types.h A payloads/libpayload/include/x64/arch/virtual.h M payloads/libpayload/vboot/Makefile.mk 37 files changed, 3,106 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/68/81968/1
diff --git a/payloads/libpayload/Kconfig b/payloads/libpayload/Kconfig index 39d316b..6caf9bc 100644 --- a/payloads/libpayload/Kconfig +++ b/payloads/libpayload/Kconfig @@ -160,6 +160,7 @@ default 0x04000000 if ARCH_ARM default 0x80100000 if ARCH_ARM64 default 0x00100000 if ARCH_X86 + default 0x80100000 if ARCH_X86_64 default 0x00000000 if ARCH_MOCK help This is the base address for the payload. diff --git a/payloads/libpayload/Makefile b/payloads/libpayload/Makefile index 71d60bc..2737216 100644 --- a/payloads/libpayload/Makefile +++ b/payloads/libpayload/Makefile @@ -110,6 +110,7 @@ ARCHDIR-$(CONFIG_LP_ARCH_ARM) := arm ARCHDIR-$(CONFIG_LP_ARCH_ARM64) := arm64 ARCHDIR-$(CONFIG_LP_ARCH_X86) := x86 +ARCHDIR-$(CONFIG_LP_ARCH_X86_64) := x64 ARCHDIR-$(CONFIG_LP_ARCH_MOCK) := mock
ARCH-y := $(ARCHDIR-y) @@ -119,6 +120,7 @@ ARCH-$(CONFIG_LP_ARCH_ARM) := arm ARCH-$(CONFIG_LP_ARCH_ARM64) := arm64 ARCH-$(CONFIG_LP_ARCH_X86) := x86_32 +ARCH-$(CONFIG_LP_ARCH_X86_64) := x86_64 ARCH-$(CONFIG_LP_ARCH_MOCK) := mock
# Five cases where we don't need fully populated $(obj) lists: diff --git a/payloads/libpayload/Makefile.mk b/payloads/libpayload/Makefile.mk index afaa06d..07abc7c 100644 --- a/payloads/libpayload/Makefile.mk +++ b/payloads/libpayload/Makefile.mk @@ -40,6 +40,7 @@ ARCHDIR-$(CONFIG_LP_ARCH_ARM) := arm ARCHDIR-$(CONFIG_LP_ARCH_ARM64) := arm64 ARCHDIR-$(CONFIG_LP_ARCH_X86) := x86 +ARCHDIR-$(CONFIG_LP_ARCH_X86_64) := x64 ARCHDIR-$(CONFIG_LP_ARCH_MOCK) := mock DESTDIR ?= install
diff --git a/payloads/libpayload/arch/x64/Kconfig b/payloads/libpayload/arch/x64/Kconfig new file mode 100644 index 0000000..e4b695b --- /dev/null +++ b/payloads/libpayload/arch/x64/Kconfig @@ -0,0 +1,61 @@ +## SPDX-License-Identifier: GPL-2.0-only + +## +## +## Copyright (c) 2012 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. +## + +config ARCH_X86 + select LITTLE_ENDIAN + select IO_ADDRESS_SPACE + +config ARCH_X86_64 + bool "x86_64" + help + Support the x86_64 architecture + +if ARCH_X86 + +config ENABLE_APIC + bool "Enables the Local APIC" + +choice + prompt "Interrupt Handling" + default LOG_UNKNOWN_INTERRUPTS if ENABLE_APIC + default DIE_ON_UNKNOWN_INTERRUPT + +config IGNORE_UNKNOWN_INTERRUPTS + bool "Ignore unknown user defined interrupts" + +config LOG_UNKNOWN_INTERRUPTS + bool "Logs unknown user defined interrupts to the console" + +config DIE_ON_UNKNOWN_INTERRUPT + bool "Die if an unknown user defined interrupt is encountered" + +endchoice + +endif diff --git a/payloads/libpayload/arch/x64/Makefile.mk b/payloads/libpayload/arch/x64/Makefile.mk new file mode 100644 index 0000000..604c001 --- /dev/null +++ b/payloads/libpayload/arch/x64/Makefile.mk @@ -0,0 +1,51 @@ +## +## +## Copyright (C) 2008 Advanced Micro Devices, 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. +## + +ifneq ($(CONFIG_LP_COMPILER_LLVM_CLANG),y) +CFLAGS += -mpreferred-stack-boundary=4 +endif + +head.o-y += head.S +libc-y += main.c sysinfo.c +libc-y += timer.c coreboot.c util.S +libc-y += exec.S virtual.c +libc-y += selfboot.c cache.c +libc-y += exception_asm.S exception.c +libc-y += delay.c + +# Will fall back to default_memXXX() in libc/memory.c if GPL not allowed. +libc-$(CONFIG_LP_GPL) += string.c + +libgdb-y += gdb.c + +libcbfs-$(CONFIG_LP_CBFS) += boot_media.c + +# Multiboot support is configurable +libc-$(CONFIG_LP_MULTIBOOT) += multiboot.c + +libc-$(CONFIG_LP_ENABLE_APIC) += apic.c diff --git a/payloads/libpayload/arch/x64/apic.c b/payloads/libpayload/arch/x64/apic.c new file mode 100644 index 0000000..e067106 --- /dev/null +++ b/payloads/libpayload/arch/x64/apic.c @@ -0,0 +1,332 @@ +/* + * + * Copyright 2018 Google LLC + * + * 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. + */ + +#include <libpayload.h> +#include <arch/apic.h> +#include <arch/cpuid.h> +#include <arch/msr.h> +#include <exception.h> + +#define APIC_BASE_MSR 0x0000001B +#define APIC_BASE_MASK (0xFFFFFFFULL << 12) + +#define CPUID_XAPIC_ENABLED_BIT (1 << 9) +#define CPUID_XAPIC2_ENABLED_BIT (1 << 21) + +#define XAPIC_ENABLED_BIT (1 << 11) +#define X2APIC_ENABLED_BIT (1 << 10) +#define APIC_MASKED_BIT (1 << 16) + +#define APIC_ID 0x020 +#define APIC_ID_SHIFT 24 +#define APIC_ID_MASK (0xFFUL << APIC_ID_SHIFT) +#define APIC_VERSION 0x030 +#define APIC_MAX_LVT_SHIFT 16 +#define APIC_MAX_LVT_MASK (0xFFUL << APIC_MAX_LVT_SHIFT) +#define APIC_TASK_PRIORITY 0x080 +#define APIC_TASK_PRIORITY_MASK 0xFFUL +#define APIC_EOI 0x0B0 +#define APIC_SPURIOUS 0x0F0 +#define APIC_SW_ENABLED_BIT (1 << 8) +#define APIC_SPURIOUS_VECTOR_MASK 0xFFUL +#define APIC_SPURIOUS 0x0F0 +#define APIC_LVT_TIMER 0x320 +#define APIC_TIMER_INIT_COUNT 0x380 +#define APIC_TIMER_CUR_COUNT 0x390 +#define APIC_TIMER_DIV_CFG 0x3E0 +#define APIC_ISR_0 0x100 +#define APIC_ISR_OFFSET 0x010 + +#define APIC_LVT_SIZE 0x010 + +#define APIC_TIMER_VECTOR 0x20UL +#define APIC_SPURIOUS_VECTOR 0xFFUL + +static uint32_t apic_bar; +static int _apic_initialized; +// TODO: Build a lookup table to avoid calculating it. +static uint32_t ticks_per_ms; +static volatile uint8_t timer_waiting; + +enum APIC_CAPABILITY { + DISABLED = 0, + XACPI = 1 << 0, + X2ACPI = 1 << 1 +}; + +int apic_initialized(void) +{ + return _apic_initialized; +} + +static inline uint32_t apic_read32(uint32_t offset) +{ + return read32((void *)(apic_bar + offset)); +} + +static inline void apic_write32(uint32_t offset, uint32_t value) +{ + write32((void *)(apic_bar + offset), value); +} + +uint8_t apic_id(void) +{ + die_if(!apic_bar, "APIC is not initialized"); + + uint8_t id = + (apic_read32(APIC_ID) & APIC_ID_MASK) >> APIC_ID_SHIFT; + + return id; +} + +void apic_start_delay(unsigned int usec) +{ + die_if(!ticks_per_ms, "apic_init_timer was not run."); + die_if(timer_waiting, "timer already started."); + die_if(!interrupts_enabled(), "Interrupts disabled."); + + /* The order is important so we don't underflow */ + uint64_t ticks = usec * ticks_per_ms / USECS_PER_MSEC; + + /* Not enough resolution */ + if (!ticks) + return; + + /* Disable interrupts so we don't get a race condition between + * starting the timer and the hlt instruction. */ + disable_interrupts(); + + timer_waiting = 1; + + apic_write32(APIC_TIMER_INIT_COUNT, ticks); + enable_interrupts(); +} + +void apic_wait_delay(void) +{ + /* Loop in case another interrupt has fired and resumed execution. */ + disable_interrupts(); + /* Note: when we test timer_waiting, interrupts are disabled by the line + * above and the cli below. */ + while (timer_waiting) { + asm volatile( + "sti\n\t" + "hlt\n\t" + /* Disable interrupts to prevent a race condition + * between checking timer_waiting and executing the hlt + * instruction again. */ + "cli\n\t"); + } + + /* Leave hardware interrupts enabled. */ + enable_interrupts(); +} + +void apic_delay(unsigned int usec) +{ + apic_start_delay(usec); + apic_wait_delay(); +} + +static void timer_interrupt_handler(u8 vector) +{ + timer_waiting = 0; + apic_eoi(APIC_TIMER_VECTOR); +} + +static void suprious_interrupt_handler(u8 vector) {} + +void apic_eoi(uint8_t vector) +{ + die_if(!apic_bar, "APIC is not initialized"); + + /* + * Local and I/O APICs support 240 vectors (in the range of 16 to 255) + * as valid interrupts. + */ + if (vector <= 15) + return; + + /* Each bank handles 32 vectors */ + uint8_t bank = vector / 32; + + uint32_t offset = APIC_ISR_0 + bank * APIC_ISR_OFFSET; + + uint32_t mask = apic_read32(offset); + + uint8_t shift = vector % 32; + + if (mask & (1 << shift)) + apic_write32(APIC_EOI, 0); +} + +static enum APIC_CAPABILITY apic_capabilities(void) +{ + uint32_t eax, ebx, ecx, edx; + + cpuid(1, eax, ebx, ecx, edx); + + enum APIC_CAPABILITY capabilities = DISABLED; + + if (edx & CPUID_XAPIC_ENABLED_BIT) + capabilities |= XACPI; + + if (ecx & CPUID_XAPIC2_ENABLED_BIT) + capabilities |= X2ACPI; + + return capabilities; +} + +static uint8_t apic_max_lvt_entries(void) +{ + die_if(!apic_bar, "APIC is not initialized"); + + uint32_t reg = apic_read32(APIC_VERSION); + reg &= APIC_MAX_LVT_MASK; + reg >>= APIC_MAX_LVT_SHIFT; + + return (uint8_t)reg; +} + +static void apic_reset_all_lvts(void) +{ + uint8_t max = apic_max_lvt_entries(); + for (int i = 0; i <= max; ++i) { + uint32_t offset = APIC_LVT_TIMER + APIC_LVT_SIZE * i; + apic_eoi(i); + apic_write32(offset, APIC_MASKED_BIT); + } +} + +static void apic_set_task_priority(uint8_t priority) +{ + die_if(!apic_bar, "APIC is not initialized"); + + uint32_t tpr = apic_read32(APIC_TASK_PRIORITY); + tpr &= ~APIC_TASK_PRIORITY_MASK; + tpr |= priority; + + apic_write32(APIC_TASK_PRIORITY, priority); +} + +static void apic_init_timer(void) +{ + die_if(!apic_bar, "APIC is not initialized"); + + apic_write32(APIC_LVT_TIMER, APIC_MASKED_BIT); + + /* Divide the clock by 1. */ + apic_write32(APIC_TIMER_DIV_CFG, 0xB); + + /* Calibrate the APIC timer */ + if (!ticks_per_ms) { + /* Set APIC init counter to MAX and count for 1 ms */ + apic_write32(APIC_TIMER_INIT_COUNT, UINT32_MAX); + + /* This is safe because apic_initialized() returns false so + * arch_ndelay() falls back to a busy loop. */ + mdelay(1); + + ticks_per_ms = + UINT32_MAX - apic_read32(APIC_TIMER_CUR_COUNT); + } + + /* Clear the count so we don't get any stale interrupts */ + apic_write32(APIC_TIMER_INIT_COUNT, 0); + + /* Unmask the timer and set the vector. */ + apic_write32(APIC_LVT_TIMER, APIC_TIMER_VECTOR); +} + +static void apic_sw_disable(void) +{ + uint32_t reg = apic_read32(APIC_SPURIOUS); + + reg &= ~APIC_SW_ENABLED_BIT; + printf("%s: writing %#x to %#x\n", __func__, reg, APIC_SPURIOUS); + + apic_write32(APIC_SPURIOUS, reg); +} + +static void apic_sw_enable(void) +{ + uint32_t reg = apic_read32(APIC_SPURIOUS); + if (reg & APIC_SW_ENABLED_BIT) + return; + + reg |= APIC_SW_ENABLED_BIT; + + apic_write32(APIC_SPURIOUS, reg); +} + +static void apic_setup_spurious(void) +{ + uint32_t reg = apic_read32(APIC_SPURIOUS); + + reg &= ~APIC_SPURIOUS_VECTOR_MASK; + + reg |= APIC_SPURIOUS_VECTOR; + + apic_write32(APIC_SPURIOUS, reg); +} + +void apic_init(void) +{ + uint64_t apic_bar_reg; + + printf("APIC Init Started\n"); + + die_if(apic_initialized(), "APIC already initialized"); + die_if(!(apic_capabilities() & XACPI), "APIC is not supported"); + + apic_bar_reg = _rdmsr(APIC_BASE_MSR); + printf("apic_bar_reg is 0x%llx\n", apic_bar_reg); + + die_if(!(apic_bar_reg & XAPIC_ENABLED_BIT), "APIC is not enabled"); + die_if(apic_bar_reg & X2APIC_ENABLED_BIT, + "APIC is configured in x2APIC mode which is not supported"); + + apic_bar = (uint32_t)(apic_bar_reg & APIC_BASE_MASK); + + apic_sw_disable(); + apic_reset_all_lvts(); + apic_set_task_priority(0); + apic_setup_spurious(); + + apic_sw_enable(); + + apic_init_timer(); + + set_interrupt_handler(APIC_TIMER_VECTOR, &timer_interrupt_handler); + set_interrupt_handler(APIC_SPURIOUS_VECTOR, + &suprious_interrupt_handler); + + _apic_initialized = 1; + + printf("APIC Configured\n"); +} diff --git a/payloads/libpayload/arch/x64/boot_media.c b/payloads/libpayload/arch/x64/boot_media.c new file mode 100644 index 0000000..07e08b6 --- /dev/null +++ b/payloads/libpayload/arch/x64/boot_media.c @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#include <libpayload.h> +#include <boot_device.h> + +__attribute__((weak)) ssize_t boot_device_read(void *buf, size_t offset, size_t size) +{ + /* Memory-mapping usually only works for the top 16MB. */ + if (!lib_sysinfo.boot_media_size || lib_sysinfo.boot_media_size - offset > 16 * MiB) + return CB_ERR_ARG; + const void *const ptr = phys_to_virt(0 - lib_sysinfo.boot_media_size + offset); + memcpy(buf, ptr, size); + return size; +} diff --git a/payloads/libpayload/arch/x64/cache.c b/payloads/libpayload/arch/x64/cache.c new file mode 100644 index 0000000..9fb33bc --- /dev/null +++ b/payloads/libpayload/arch/x64/cache.c @@ -0,0 +1,134 @@ +/* + * + * Copyright 2022 Google LLC + * + * 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. + */ + +#include <stdint.h> + +#include <arch/cache.h> +#include <arch/cpuid.h> + +unsigned int dcache_line_bytes(void) +{ + /* + * The value returned in EBX[15:8] is in 8-byte increments. + * Cache line size is EBX[15:8] * 8 + */ + return (cpuid_ebx(1) & 0xff00) >> 5; +} + +static inline int cpu_supports_wbnoinvd(void) +{ + return (cpuid_ebx(0x80000008) >> 9) & 1; +} + +static inline int cpu_supports_clwb(void) +{ + return (cpuid_ebx(7) >> 24) & 1; +} + +static inline int cpu_supports_clflushopt(void) +{ + return (cpuid_sub_leaf_ebx(7, 0) >> 23) & 1; +} + +static inline int cpu_supports_clflush(void) +{ + return (cpuid_ebx(1) >> 19) & 1; +} + +inline void dcache_invalidate_all(void) +{ + asm volatile("invd" ::: "memory"); +} + +inline void dcache_clean_invalidate_all(void) +{ + asm volatile("wbinvd" ::: "memory"); +} + +inline void dcache_clean_all(void) +{ + if (cpu_supports_wbnoinvd()) { + asm volatile( + "sfence\n\t" + "wbnoinvd\n\t" + ::: "memory"); + } else { + dcache_clean_invalidate_all(); + } +} + +void dcache_clean_by_mva(void const *addr, size_t len) +{ + unsigned long line, linesize; + + linesize = dcache_line_bytes(); + line = (uintptr_t)addr & ~(linesize - 1); + + if (cpu_supports_clwb()) { + asm volatile("sfence"); + while (line < (uintptr_t)addr + len) { + asm volatile("clwb (%0)" : : "r"(line) : "memory"); + line += linesize; + } + } else { + dcache_clean_invalidate_by_mva(addr, len); + } +} + +void dcache_invalidate_by_mva(void const *addr, size_t len) +{ + /* + * x86 doesn't have a "invalidate without clean" for a cache line, fall + * back to both. + */ + dcache_clean_invalidate_by_mva(addr, len); +} + +void dcache_clean_invalidate_by_mva(void const *addr, size_t len) +{ + unsigned long line, linesize; + + linesize = dcache_line_bytes(); + line = (uintptr_t)addr & ~(linesize - 1); + + if (cpu_supports_clflushopt()) { + asm volatile("sfence"); + while (line < (uintptr_t)addr + len) { + asm volatile("clflushopt (%0)" ::"r"(line) : "memory"); + line += linesize; + } + } else if (cpu_supports_clflush()) { + asm volatile("sfence"); + while (line < (uintptr_t)addr + len) { + asm volatile("clflush (%0)" : : "r"(line) : "memory"); + line += linesize; + } + } else { + dcache_clean_invalidate_all(); + } +} diff --git a/payloads/libpayload/arch/x64/coreboot.c b/payloads/libpayload/arch/x64/coreboot.c new file mode 100644 index 0000000..ea4b8e5 --- /dev/null +++ b/payloads/libpayload/arch/x64/coreboot.c @@ -0,0 +1,82 @@ +/* + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2009 coresystems GmbH + * + * 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. + */ + +#include <libpayload-config.h> +#include <libpayload.h> +#include <coreboot_tables.h> + +/* + * Some of this is x86 specific, and the rest of it is generic. Right now, + * since we only support x86, we'll avoid trying to make lots of infrastructure + * we don't need. If in the future, we want to use coreboot on some other + * architecture, then take out the generic parsing code and move it elsewhere. + */ + +/* === Parsing code === */ +/* This is the generic parsing code. */ + +static void cb_parse_x86_rom_var_mtrr(void *ptr, struct sysinfo_t *info) +{ + struct cb_x86_rom_mtrr *rom_mtrr = ptr; + info->x86_rom_var_mtrr_index = rom_mtrr->index; +} + +int cb_parse_arch_specific(struct cb_record *rec, struct sysinfo_t *info) +{ + switch(rec->tag) { + case CB_TAG_X86_ROM_MTRR: + cb_parse_x86_rom_var_mtrr(rec, info); + break; + default: + return 0; + } + return 1; +} + +/* This pointer gets set in head.S and is passed in from coreboot. */ +void *cb_header_ptr; + +int get_coreboot_info(struct sysinfo_t *info) +{ + int ret; + + /* Ensure the variable range MTRR index covering the ROM is set to + * an invalid value. */ + info->x86_rom_var_mtrr_index = -1; + + ret = cb_parse_header(cb_header_ptr, 1, info); + + if (ret) + ret = cb_parse_header(phys_to_virt(0x00000000), 0x1000, info); + + if (ret) + ret = cb_parse_header(phys_to_virt(0x000f0000), 0x1000, info); + + return ret; +} diff --git a/payloads/libpayload/arch/x64/delay.c b/payloads/libpayload/arch/x64/delay.c new file mode 100644 index 0000000..373c841 --- /dev/null +++ b/payloads/libpayload/arch/x64/delay.c @@ -0,0 +1,62 @@ +/* + * + * Copyright (C) 2018 Google LLC + * + * 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. + */ + +#include <libpayload.h> +#include <arch/apic.h> + +/* The pause instruction can delay 10-140 CPU cycles, so avoid calling it when + * getting close to finishing. Depending on the timer source, the timer can be + * running at CPU frequency, bus frequency, or some arbitrary value. We assume + * that the timer is running at the CPU frequency. */ +#define PAUSE_THRESHOLD_TICKS 150 + +/* Let's assume APIC interrupts take at least 100us */ +#define APIC_INTERRUPT_LATENCY_NS (100 * NSECS_PER_USEC) + +void arch_ndelay(uint64_t ns) +{ + uint64_t delta = ns * timer_hz() / NSECS_PER_SEC; + uint64_t pause_delta = 0; + uint64_t apic_us = 0; + uint64_t start = timer_raw_value(); + + if (ns > APIC_INTERRUPT_LATENCY_NS) + apic_us = (ns - APIC_INTERRUPT_LATENCY_NS) / NSECS_PER_USEC; + + if (CONFIG(LP_ENABLE_APIC) && apic_initialized() && apic_us) + apic_delay(apic_us); + + if (delta > PAUSE_THRESHOLD_TICKS) + pause_delta = delta - PAUSE_THRESHOLD_TICKS; + + while (timer_raw_value() - start < pause_delta) + asm volatile("pause\n\t"); + + while (timer_raw_value() - start < delta) + continue; +} diff --git a/payloads/libpayload/arch/x64/exception.c b/payloads/libpayload/arch/x64/exception.c new file mode 100644 index 0000000..18b7543 --- /dev/null +++ b/payloads/libpayload/arch/x64/exception.c @@ -0,0 +1,237 @@ +/* + * + * Copyright 2013 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. + */ + +#include <arch/exception.h> +#include <exception.h> +#include <libpayload.h> +#include <stdint.h> +#include <arch/apic.h> + +#define IF_FLAG (1 << 9) + +u32 exception_stack[2*KiB] __attribute__((aligned(16))); + +static interrupt_handler handlers[256]; + +static const char *names[EXC_COUNT] = { + [EXC_DE] = "Divide by Zero", + [EXC_DB] = "Debug", + [EXC_NMI] = "Non-Maskable-Interrupt", + [EXC_BP] = "Breakpoint", + [EXC_OF] = "Overflow", + [EXC_BR] = "Bound Range", + [EXC_UD] = "Invalid Opcode", + [EXC_NM] = "Device Not Available", + [EXC_DF] = "Double Fault", + [EXC_TS] = "Invalid TSS", + [EXC_NP] = "Segment Not Present", + [EXC_SS] = "Stack Fault", + [EXC_GP] = "General Protection Fault", + [EXC_PF] = "Page Fault", + [EXC_MF] = "x87 Floating Point", + [EXC_AC] = "Alignment Check", + [EXC_MC] = "Machine Check", + [EXC_XF] = "SIMD Floating Point", + [EXC_SX] = "Security", +}; + +static void print_segment_error_code(u32 code) +{ + printf("%#x - descriptor %#x in the ", code, (code >> 3) & 0x1FFF); + if (code & (0x1 << 1)) { + printf("IDT"); + } else { + if (code & 0x04) + printf("LDT"); + else + printf("GDT"); + } + if (code & (0x1 << 0)) + printf(", external to the CPU"); + else + printf(", internal to the CPU"); +} + +static void print_page_fault_error_code(u32 code) +{ + printf("%#x -", code); + if (code & (0x1 << 0)) + printf(" page protection"); + else + printf(" page not present"); + if (code & (0x1 << 1)) + printf(", write"); + else + printf(", read"); + if (code & (0x1 << 2)) + printf(", user"); + else + printf(", supervisor"); + if (code & (0x1 << 3)) + printf(", reserved bits set"); + if (code & (0x1 << 4)) + printf(", instruction fetch"); +} + +static void print_raw_error_code(u32 code) +{ + printf("%#x", code); +} + +static void dump_stack(uintptr_t addr, size_t bytes) +{ + int i, j; + const int line = 8; + uint32_t *ptr = (uint32_t *)(addr & ~(line * sizeof(*ptr) - 1)); + + printf("Dumping stack:\n"); + for (i = bytes / sizeof(*ptr); i >= 0; i -= line) { + printf("%p: ", ptr + i); + for (j = i; j < i + line; j++) + printf("%08x ", *(ptr + j)); + printf("\n"); + } +} + +static void dump_exception_state(void) +{ + printf("%s Exception\n", names[exception_state->vector]); + + printf("Error code: "); + switch (exception_state->vector) { + case EXC_PF: + print_page_fault_error_code(exception_state->error_code); + break; + case EXC_TS: + case EXC_NP: + case EXC_SS: + case EXC_GP: + print_segment_error_code(exception_state->error_code); + break; + case EXC_DF: + case EXC_AC: + case EXC_SX: + print_raw_error_code(exception_state->error_code); + break; + default: + printf("n/a"); + break; + } + printf("\n"); + printf("EIP: 0x%08x\n", exception_state->regs.eip); + 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("ES: 0x%04x\n", exception_state->regs.es); + printf("SS: 0x%04x\n", exception_state->regs.ss); + printf("FS: 0x%04x\n", exception_state->regs.fs); + printf("GS: 0x%04x\n", exception_state->regs.gs); +} + +void exception_dispatch(void) +{ + die_if(exception_state->vector >= ARRAY_SIZE(handlers), + "Invalid vector %u\n", exception_state->vector); + + u8 vec = exception_state->vector; + + if (handlers[vec]) { + handlers[vec](vec); + goto success; + } else if (vec >= EXC_COUNT + && CONFIG(LP_IGNORE_UNKNOWN_INTERRUPTS)) { + goto success; + } else if (vec >= EXC_COUNT + && CONFIG(LP_LOG_UNKNOWN_INTERRUPTS)) { + printf("Ignoring interrupt vector %u\n", vec); + goto success; + } + + die_if(vec >= EXC_COUNT || !names[vec], "Bad exception vector %u\n", + vec); + + dump_exception_state(); + dump_stack(exception_state->regs.esp, 512); + /* We don't call apic_eoi because we don't want to ack the interrupt and + allow another interrupt to wake the processor. */ + halt(); + return; + +success: + if (CONFIG(LP_ENABLE_APIC)) + apic_eoi(vec); +} + +void exception_init(void) +{ + exception_stack_end = exception_stack + ARRAY_SIZE(exception_stack); + exception_init_asm(); +} + +void set_interrupt_handler(u8 vector, interrupt_handler handler) +{ + handlers[vector] = handler; +} + +static uint64_t eflags(void) +{ + uint64_t eflags; + asm volatile( + "pushfq\n\t" + "popq %0\n\t" + : "=rm" (eflags)); + return eflags; +} + +void enable_interrupts(void) +{ + asm volatile ( + "sti\n" + : : : "cc" + ); +} +void disable_interrupts(void) +{ + asm volatile ( + "cli\n" + : : : "cc" + ); +} + +int interrupts_enabled(void) +{ + return !!(eflags() & IF_FLAG); +} diff --git a/payloads/libpayload/arch/x64/exception_asm.S b/payloads/libpayload/arch/x64/exception_asm.S new file mode 100644 index 0000000..d626dd3 --- /dev/null +++ b/payloads/libpayload/arch/x64/exception_asm.S @@ -0,0 +1,343 @@ +/* + * + * Copyright 2013 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: + /* + * Save off the stack pointer and old eax value and install the + * exception stack. eax points to the old stack which has the + * exception ip, cs, and flags. + */ + mov %rsp, old_rsp + addq $12, old_rsp + mov %rax, old_rax + mov %rsp, %rax + mov exception_stack_end, %rsp + + /* + * Push values onto the top of the exception stack to form an + * exception state structure. + */ + push vector + push error_code + push %gs + push %fs + push 4(%rax) + push 8(%rax) + push (%rax) + push %rdi + push %rsi + push %rbp + push old_rsp + push %rbx + push %rdx + push %rcx + push old_rax + + /* + * Call the C exception handler. It will find the exception state + * using the exception_state global pointer. Not + * passing parameters means we don't have to worry about what ABI + * is being used. + */ + mov %rsp, exception_state + call exception_dispatch + + /* + * Restore state from the exception state structure, including any + * changes that might have been made. + */ + pop old_rax + pop %rcx + pop %rdx + pop %rbx + pop old_rsp + + mov old_rsp, %rax + subq $12, %rax + + pop %rbp + pop %rsi + pop %rdi + pop (%rax) + pop 8(%rax) + pop 4(%rax) + pop %fs + pop %gs + + mov %rax, %rsp + mov old_rax, %rax + + /* 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, unused */ + .word 0x0000, 0x0000 /* dummy */ + .byte 0x00, 0x00, 0x00, 0x00 + + /* The next two entries are used for executing VGA option ROMs */ + + /* selgdt 0x28 16 bit 64k code at 0x00000000 */ + .word 0xffff, 0x0000 + .byte 0, 0x9a, 0, 0 + + /* selgdt 0x30 16 bit 64k data at 0x00000000 */ + .word 0xffff, 0x0000 + .byte 0, 0x92, 0, 0 + + /* The next two entries are used for ACPI S3 RESUME */ + + /* selgdt 0x38, flat data segment 16 bit */ + .word 0x0000, 0x0000 /* dummy */ + .byte 0x00, 0x93, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for + * limit + */ + + /* selgdt 0x40, flat code segment 16 bit */ + .word 0xffff, 0x0000 + .byte 0x00, 0x9b, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for + * limit + */ + + /* selgdt 0x48, flat x64 code segment */ + .word 0xffff, 0x0000 + .byte 0x00, 0x9b, 0xaf, 0x00 +gdt_end: + +/* GDT pointer for use with lgdt */ +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: + /* Save eax so we can use it as a temporary variable. */ + push %rax + + /* Install the GDT. */ + lgdt gdt_ptr + /* Load the segment registers from it. */ + jmp 1f +1: mov $0x18, %rax + mov %rax, %fs + mov %rax, %gs + + /* + * Loop over the entries which start out as two copies of the target + * address. We can turn them into real interrupt gates by selectively + * replacing certain bit fields. + */ + mov $idt, %rax +1: + and $0x00000000ffff, (%rax) + orq $0x000000100000, (%rax) + and $0xffffffffffff0000, 4(%rax) + orq $0x00000000ee00, 4(%rax) + add $8, %rax + cmp $idt_end, %rax + jne 1b + + /* Install the IDT. */ + lidt idt_ptr + + /* Restore rax and return to the caller. */ + pop %rax + ret diff --git a/payloads/libpayload/arch/x64/exec.S b/payloads/libpayload/arch/x64/exec.S new file mode 100644 index 0000000..ee5defb --- /dev/null +++ b/payloads/libpayload/arch/x64/exec.S @@ -0,0 +1,83 @@ +/* + * + * Copyright (C) 2008 Advanced Micro Devices, 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. + */ + +/* calling syntax: i386_do_exec(long addr, int argc, char **argv, int *ret) */ + +/* This implements the payload API detailed here: + * https://www.coreboot.org/Payload_API + */ + +.align 16 +.text + +.global i386_do_exec + .type i386_do_exec,@function + +i386_do_exec: + push %rbp + movq %rsp, %rbp + + /* Save the remaining callee preserved registers */ + push %rbx + push %rsi + push %rdi + + /* Push argc and argv on to the stack. + * + * We need to put a dummy value inbetween, as argc should be at offset + * 0x10, according to the payload API. + */ + push 12(%rbp) + push $0 + push 16(%rbp) + + /* Push a "magic" number on the stack - the other payload will use this + * as a clue that the argc and argv values on the stack are sane. + */ + push $0x12345678 + + /* Jump to the code */ + call *8(%rbp) + /* %eax has the return value */ + + /* Skip over the argc/argv stuff still on the stack. + * Don't assume %ebp is sane, here. Restore it from the stack. + */ + addq $0x10, %rsp + + /* Restore the saved registers */ + pop %rdi + pop %rsi + pop %rbx + pop %rbp + + /* Get pointer to return value and save the return value in it. */ + movq 16(%rsp), %rcx + movq %rax, (%rcx) + + ret diff --git a/payloads/libpayload/arch/x64/gdb.c b/payloads/libpayload/arch/x64/gdb.c new file mode 100644 index 0000000..7a0ac19 --- /dev/null +++ b/payloads/libpayload/arch/x64/gdb.c @@ -0,0 +1,89 @@ +/* + * Copyright 2014 Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but without any warranty; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <exception.h> +#include <gdb.h> +#include <libpayload.h> + +static const u8 type_to_signal[] = { + [EXC_DE] = GDB_SIGFPE, + [EXC_DB] = GDB_SIGTRAP, + [EXC_NMI] = GDB_SIGKILL, + [EXC_BP] = GDB_SIGTRAP, + [EXC_OF] = GDB_SIGFPE, + [EXC_BR] = GDB_SIGSEGV, + [EXC_UD] = GDB_SIGILL, + [EXC_NM] = GDB_SIGEMT, + [EXC_DF] = GDB_SIGKILL, + [EXC_TS] = GDB_SIGSEGV, + [EXC_NP] = GDB_SIGSEGV, + [EXC_SS] = GDB_SIGBUS, + [EXC_GP] = GDB_SIGSEGV, + [EXC_PF] = GDB_SIGSEGV, + [EXC_MF] = GDB_SIGEMT, + [EXC_AC] = GDB_SIGBUS, + [EXC_MC] = GDB_SIGKILL, + [EXC_XF] = GDB_SIGFPE, + [EXC_SX] = GDB_SIGFPE, +}; + +static void gdb_exception_hook(u8 vector) +{ + gdb_command_loop(type_to_signal[vector]); +} + +void gdb_arch_init(void) +{ + for (int vector = 0; vector < ARRAY_SIZE(type_to_signal); ++vector) { + if (type_to_signal[vector]) + set_interrupt_handler(vector, &gdb_exception_hook); + } +} + +void gdb_arch_enter(void) +{ + u32 *esp; + + asm volatile ("movq %%rsp, %0" : "=r"(esp) ); + + /* Avoid reentrant exceptions, just call the hook if in one already. */ + if (esp >= exception_stack && esp <= exception_stack_end) + gdb_exception_hook(EXC_BP); + else + asm volatile ("int3"); +} + +int gdb_arch_set_single_step(int on) +{ + const u32 tf_bit = 1 << 8; + + if (on) + exception_state->regs.eflags |= tf_bit; + else + exception_state->regs.eflags &= ~tf_bit; + + return 0; +} + +void gdb_arch_encode_regs(struct gdb_message *message) +{ + gdb_message_encode_bytes(message, &exception_state->regs, + sizeof(exception_state->regs)); +} + +void gdb_arch_decode_regs(int offset, struct gdb_message *message) +{ + gdb_message_decode_bytes(message, offset, &exception_state->regs, + sizeof(exception_state->regs)); +} diff --git a/payloads/libpayload/arch/x64/head.S b/payloads/libpayload/arch/x64/head.S new file mode 100644 index 0000000..0a44c94 --- /dev/null +++ b/payloads/libpayload/arch/x64/head.S @@ -0,0 +1,136 @@ +/* + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2017 Patrick Rudolph siro@das-labor.org + * + * 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. + */ + + .code64 + .global _entry + .text + .align 16 + +/* + * Our entry point - assume that the CPU is in 32 bit protected mode and + * all segments are in a flat model. That's our operating mode, so we won't + * change anything. + */ +_entry: + jmp _init + + .align 16 + +#define MB_MAGIC 0x1BADB002 +#define MB_FLAGS 0x00010003 + +mb_header: + .long MB_MAGIC + .long MB_FLAGS + .long -(MB_MAGIC + MB_FLAGS) + .long mb_header + .long _start + .long _edata + .long _end + .long _init + +/* + * This function saves off the previous stack and switches us to our + * own execution environment. + */ +_init: + /* No interrupts, please. */ + cli + + /* Store EAX and EBX */ + movl %eax, loader_eax + movl %ebx, loader_ebx + + /* save pointer to coreboot tables */ + movq %rdi, cb_header_ptr + + /* Store current stack pointer and set up new stack. */ + movq %rsp, %rax + movabs $_estack, %rsp + movq $(0xfffffffffffffff0), %rax + and %rax, %rsp + + push %rax + + /* Enable special x86 functions if present. */ + push %rdi + push %rsi + push %rdx + push %rcx + push %r8 + push %r9 + + movq $0, %rax + cpuid + /* Test if CPUID(eax=1) is available. */ + test %eax, %eax + je cpuid_done + + /* Get CPU features. */ + movq $1, %rax + cpuid + +cpuid_fpu: + /* Test if x87 FPU is present */ + test $1, %rdx + je cpuid_sse + + fninit + movq %cr0, %rax + andq $0xFFFFFFFFFFFFFFFB, %rax /* clear EM */ + orq $0x000000000022, %rax /* set MP, NE */ + movq %rax, %cr0 + +cpuid_sse: + /* Test if SSE is available */ + test $0x000002000000, %rdx + je cpuid_done + + movq %cr4, %rax + orq $0x000000000600, %rax /* set OSFXSR, OSXMMEXCPT */ + movq %rax, %cr4 + +cpuid_done: + pop %r9 + pop %r8 + pop %rcx + pop %rdx + pop %rsi + pop %rdi + + /* 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 diff --git a/payloads/libpayload/arch/x64/libpayload.ldscript b/payloads/libpayload/arch/x64/libpayload.ldscript new file mode 100644 index 0000000..2a661be --- /dev/null +++ b/payloads/libpayload/arch/x64/libpayload.ldscript @@ -0,0 +1,92 @@ +/* + * + * Copyright (C) 2008 Advanced Micro Devices, 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. + */ + +OUTPUT_FORMAT(elf64-x86-64) +OUTPUT_ARCH(x86_64) + +ENTRY(_entry) + +SECTIONS +{ + . = CONFIG_LP_BASE_ADDRESS; + + . = ALIGN(16); + _start = .; + + .text : { + _text = .; + *(.text._entry) + *(.text) + *(.text.*) + _etext = .; + } + + .rodata : { + _rodata = .; + *(.rodata) + *(.rodata.*) + _erodata = .; + } + + .data : { + _data = .; + *(.data) + *(.data.*) + _edata = .; + } + + .bss : { + _bss = .; + *(.sbss) + *(.sbss.*) + *(.bss) + *(.bss.*) + *(COMMON) + _ebss = .; + + /* Stack and heap */ + + . = ALIGN(16); + _heap = .; + . += CONFIG_LP_HEAP_SIZE; + . = ALIGN(16); + _eheap = .; + + _stack = .; + . += CONFIG_LP_STACK_SIZE; + . = ALIGN(16); + _estack = .; + } + + _end = .; + + /DISCARD/ : { + *(.comment) + *(.note*) + } +} diff --git a/payloads/libpayload/arch/x64/main.c b/payloads/libpayload/arch/x64/main.c new file mode 100644 index 0000000..288f474 --- /dev/null +++ b/payloads/libpayload/arch/x64/main.c @@ -0,0 +1,81 @@ +/* + * + * Copyright (C) 2008 Advanced Micro Devices, 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. + */ + +#include <exception.h> +#include <libpayload.h> +#include <arch/apic.h> + +unsigned long loader_eax; /**< The value of EAX passed from the loader */ +unsigned long loader_ebx; /**< The value of EBX passed from the loader */ + +int main_argc; /**< The argc value to pass to main() */ + +/** The argv value to pass to main() */ +char *main_argv[MAX_ARGC_COUNT]; + +/** + * This is our C entry function - set up the system + * and jump into the payload entry point. + */ +int start_main(void); +int start_main(void) +{ + extern int main(int argc, char **argv); + + /* Gather system information. */ + lib_get_sysinfo(); + + /* Optionally set up the consoles. */ +#if !CONFIG(LP_SKIP_CONSOLE_INIT) + console_init(); +#endif + + exception_init(); + + if (CONFIG(LP_ENABLE_APIC)) { + apic_init(); + + enable_interrupts(); + } + + /* + * Any other system init that has to happen before the + * user gets control goes here. + */ + + /* + * Go to the entry point. + * In the future we may care about the return value. + */ + + /* + * Returning from main() will go to the _leave function to return + * us to the original context. + */ + return main(main_argc, (main_argc != 0) ? main_argv : NULL); +} diff --git a/payloads/libpayload/arch/x64/multiboot.c b/payloads/libpayload/arch/x64/multiboot.c new file mode 100644 index 0000000..26dc4f8 --- /dev/null +++ b/payloads/libpayload/arch/x64/multiboot.c @@ -0,0 +1,127 @@ +/* + * + * Copyright (C) 2008 Advanced Micro Devices, 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. + */ + +#include <libpayload-config.h> +#include <libpayload.h> +#include <multiboot_tables.h> + +extern unsigned long loader_eax; +extern unsigned long loader_ebx; + +static int mb_add_memrange(struct sysinfo_t *info, unsigned long long base, + unsigned long long size, unsigned int type) +{ + if (info->n_memranges >= SYSINFO_MAX_MEM_RANGES) + return -1; + +#if CONFIG(LP_MEMMAP_RAM_ONLY) + /* 1 == normal RAM. Ignore everything else for now */ + if (type != 1) + return 0; +#endif + + info->memrange[info->n_memranges].base = base; + info->memrange[info->n_memranges].size = size; + info->memrange[info->n_memranges].type = type; + info->n_memranges++; + + return 0; +} + +static void mb_parse_mmap(struct multiboot_header *table, + struct sysinfo_t *info) +{ + u8 *start = (u8 *) phys_to_virt(table->mmap_addr); + u8 *ptr = start; + + info->n_memranges = 0; + + while(ptr < (start + table->mmap_length)) { + struct multiboot_mmap *mmap = (struct multiboot_mmap *) ptr; + + if (mb_add_memrange(info, mmap->addr, mmap->length, mmap->type)) + return; + + ptr += (mmap->size + sizeof(mmap->size)); + } +} + +static void mb_parse_meminfo(struct multiboot_header *table, + struct sysinfo_t *info) +{ + unsigned long long mem_low = table->mem_lower; + unsigned long long mem_high = table->mem_higher; + + info->n_memranges = 0; + + if (mem_low) + mb_add_memrange(info, 0 * MiB, mem_low * KiB, 1); + + if (mem_high) + mb_add_memrange(info, 1 * MiB, mem_high * KiB, 1); +} + +static void mb_parse_cmdline(struct multiboot_header *table) +{ + extern int main_argc; + extern char *main_argv[]; + char *c = phys_to_virt(table->cmdline); + + while(*c != '\0' && main_argc < MAX_ARGC_COUNT) { + main_argv[main_argc++] = c; + + for( ; *c != '\0' && !isspace(*c); c++); + + if (*c) { + *c = 0; + c++; + } + } +} + +int get_multiboot_info(struct sysinfo_t *info) +{ + struct multiboot_header *table; + + if (loader_eax != MULTIBOOT_MAGIC) + return -1; + + table = (struct multiboot_header *) phys_to_virt(loader_ebx); + + info->mbtable = phys_to_virt(loader_ebx); + + if (table->flags & MULTIBOOT_FLAGS_MMAP) + mb_parse_mmap(table, info); + else if (table->flags & MULTIBOOT_FLAGS_MEMINFO) + mb_parse_meminfo(table, info); + + if (table->flags & MULTIBOOT_FLAGS_CMDLINE) + mb_parse_cmdline(table); + + return 0; +} diff --git a/payloads/libpayload/arch/x64/selfboot.c b/payloads/libpayload/arch/x64/selfboot.c new file mode 100644 index 0000000..5c3e445 --- /dev/null +++ b/payloads/libpayload/arch/x64/selfboot.c @@ -0,0 +1,34 @@ +/* + * Copyright 2014 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. + */ + +#include <libpayload.h> + +void selfboot(void *entry) +{ + void (*entry_func)(void) = entry; + entry_func(); +} diff --git a/payloads/libpayload/arch/x64/string.c b/payloads/libpayload/arch/x64/string.c new file mode 100644 index 0000000..ae90a65 --- /dev/null +++ b/payloads/libpayload/arch/x64/string.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 1991,1992,1993,1997,1998,2003, 2005 Free Software Foundation, Inc. + * Copyright (c) 2011 The ChromiumOS Authors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* From glibc-2.14, sysdeps/i386/memset.c */ + +#include <stdint.h> + +#include "string.h" + +typedef uint32_t op_t; + +void *memset(void *dstpp, int c, size_t len) +{ + int d0; + unsigned long int dstp = (unsigned long int) dstpp; + + /* This explicit register allocation improves code very much indeed. */ + register op_t x asm("ax"); + + x = (unsigned char) c; + + /* Clear the direction flag, so filling will move forward. */ + asm volatile("cld"); + + /* This threshold value is optimal. */ + if (len >= 12) { + /* Fill X with four copies of the char we want to fill with. */ + x |= (x << 8); + x |= (x << 16); + + /* Adjust LEN for the bytes handled in the first loop. */ + len -= (-dstp) % sizeof(op_t); + + /* + * There are at least some bytes to set. No need to test for + * LEN == 0 in this alignment loop. + */ + + /* Fill bytes until DSTP is aligned on a longword boundary. */ + asm volatile( + "rep\n" + "stosb" /* %0, %2, %3 */ : + "=D" (dstp), "=c" (d0) : + "0" (dstp), "1" ((-dstp) % sizeof(op_t)), "a" (x) : + "memory"); + + /* Fill longwords. */ + asm volatile( + "rep\n" + "stosl" /* %0, %2, %3 */ : + "=D" (dstp), "=c" (d0) : + "0" (dstp), "1" (len / sizeof(op_t)), "a" (x) : + "memory"); + len %= sizeof(op_t); + } + + /* Write the last few bytes. */ + asm volatile( + "rep\n" + "stosb" /* %0, %2, %3 */ : + "=D" (dstp), "=c" (d0) : + "0" (dstp), "1" (len), "a" (x) : + "memory"); + + return dstpp; +} + +void *memcpy(void *dest, const void *src, size_t n) +{ + unsigned long d0, d1, d2; + + asm volatile( + "rep ; movsl\n\t" + "movq %4,%%rcx\n\t" + "rep ; movsb\n\t" + : "=&c" (d0), "=&D" (d1), "=&S" (d2) + : "0" (n >> 2), "g" (n & 3), "1" (dest), "2" (src) + : "memory" + ); + + return dest; +} diff --git a/payloads/libpayload/arch/x64/sysinfo.c b/payloads/libpayload/arch/x64/sysinfo.c new file mode 100644 index 0000000..5dd6067 --- /dev/null +++ b/payloads/libpayload/arch/x64/sysinfo.c @@ -0,0 +1,87 @@ +/* + * + * Copyright (C) 2008 Advanced Micro Devices, 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. + */ + +#include <libpayload-config.h> +#include <libpayload.h> +#include <coreboot_tables.h> +#include <multiboot_tables.h> + +#define CPU_KHZ_DEFAULT 200 + +/** + * This is a global structure that is used through the library - we set it + * up initially with some dummy values - hopefully they will be overridden. + */ +struct sysinfo_t lib_sysinfo = { + .cpu_khz = CPU_KHZ_DEFAULT, +#if CONFIG(LP_SERIAL_CONSOLE) + .ser_ioport = CONFIG_LP_SERIAL_IOBASE, +#else + .ser_ioport = 0x3f8, +#endif +}; + +int lib_get_sysinfo(void) +{ + int ret; + +#if CONFIG(LP_MULTIBOOT) + /* Get the information from the multiboot tables, + * if they exist */ + get_multiboot_info(&lib_sysinfo); +#endif + + /* Get information from the coreboot tables, + * if they exist */ + + ret = get_coreboot_info(&lib_sysinfo); + + /* Get the CPU speed (for delays) if not set from the default value. */ + if (lib_sysinfo.cpu_khz == CPU_KHZ_DEFAULT) + lib_sysinfo.cpu_khz = get_cpu_speed(); + + if (!lib_sysinfo.n_memranges) { + /* If we can't get a good memory range, use the default. */ + lib_sysinfo.n_memranges = 2; + + lib_sysinfo.memrange[0].base = 0; + lib_sysinfo.memrange[0].size = 640 * 1024; + lib_sysinfo.memrange[0].type = CB_MEM_RAM; + + lib_sysinfo.memrange[1].base = 1024 * 1024; + lib_sysinfo.memrange[1].size = 31 * 1024 * 1024; + lib_sysinfo.memrange[1].type = CB_MEM_RAM; + } + +#if CONFIG(LP_PCI) + pci_init(&lib_sysinfo.pacc); + pci_scan_bus(&lib_sysinfo.pacc); +#endif + + return ret; +} diff --git a/payloads/libpayload/arch/x64/timer.c b/payloads/libpayload/arch/x64/timer.c new file mode 100644 index 0000000..6dcfd5b --- /dev/null +++ b/payloads/libpayload/arch/x64/timer.c @@ -0,0 +1,190 @@ +/* + * + * Copyright (C) 2008 Advanced Micro Devices, 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. + */ + +/** + * @file x86/timer.c + * x86 specific timer routines + */ + +#include <libpayload.h> +#include <arch/rdtsc.h> +#include <arch/cpuid.h> +#include <arch/msr.h> + +#define MSR_PLATFORM_INFO 0xce + +/** + * @ingroup arch + * Global variable containing the speed of the processor in KHz. + */ +uint32_t cpu_khz; + +/** + * @brief Measure the speed of the processor for use in delays + * + * @return The CPU speed in kHz. + */ +static unsigned int calibrate_pit(void) +{ + unsigned long long start, end; + const uint32_t clock_rate = 1193182; // 1.193182 MHz + const uint16_t interval = (2 * clock_rate) / 1000; // 2 ms + + /* Set up the PPC port - disable the speaker, enable the T2 gate. */ + outb((inb(0x61) & ~0x02) | 0x01, 0x61); + + /* Set the PIT to Mode 0, counter 2, word access. */ + outb(0xB0, 0x43); + + /* Load the interval into the counter. */ + outb(interval & 0xff, 0x42); + outb((interval >> 8) & 0xff, 0x42); + + /* Read the number of ticks during the period. */ + start = rdtsc(); + while (!(inb(0x61) & 0x20)) ; + end = rdtsc(); + + /* + * The number of milliseconds for a period is + * clock_rate / (interval * 1000). Multiply that by the number of + * measured clocks to get the kHz value. + */ + return (end - start) * clock_rate / (1000 * interval); +} + +/** + * @brief Calculates the core clock frequency via CPUID 0x15 + * + * Newer Intel CPUs report their core clock in CPUID leaf 0x15. Early models + * supporting this leaf didn't provide the nominal crystal frequency in ecx, + * hence we use hard coded values for them. + */ +static int get_cpu_khz_xtal(void) +{ + uint32_t ecx, edx, num, denom; + uint64_t nominal; + + if (cpuid_max() < 0x15) + return -1; + cpuid(0x15, denom, num, ecx, edx); + + if (denom == 0 || num == 0) + return -1; + + if (ecx != 0) { + nominal = ecx; + } else { + if (cpuid_family() != 6) + return -1; + + switch (cpuid_model()) { + case SKYLAKE_U_Y: + case SKYLAKE_S_H: + case KABYLAKE_U_Y: + case KABYLAKE_S_H: + nominal = 24000000; + break; + case APOLLOLAKE: + nominal = 19200000; + break; + default: + return -1; + } + } + + return nominal * num / denom / 1000; +} + +/** + * @brief Returns three times the bus clock in kHz + * + * The result of calculations with the returned value shall be divided by 3. + * This helps to avoid rounding errors. + */ +static int get_bus_khz_x3(void) +{ + if (cpuid_family() != 6) + return -1; + + switch (cpuid_model()) { + case NEHALEM: + return 400 * 1000; /* 133 MHz */ + case SANDYBRIDGE: + case IVYBRIDGE: + case HASWELL: + case HASWELL_U: + case HASWELL_GT3E: + case BROADWELL: + case BROADWELL_U: + return 300 * 1000; /* 100 MHz */ + default: + return -1; + } +} + +/** + * @brief Returns the calculated CPU frequency + * + * Over the years, multiple ways to discover the CPU frequency have been + * exposed through CPUID and MSRs. Try the most recent and accurate first + * (crystal information in CPUID leaf 0x15) and then fall back to older + * methods. + * + * This should cover all Intel Core i processors at least. For older + * processors we fall back to the PIT calibration. + */ +static int get_cpu_khz_fast(void) +{ + /* Try core crystal clock frequency first (supposed to be more accurate). */ + const int cpu_khz_xtal = get_cpu_khz_xtal(); + if (cpu_khz_xtal > 0) + return cpu_khz_xtal; + + /* Try `bus clock * speedstep multiplier`. */ + const int bus_x3 = get_bus_khz_x3(); + if (bus_x3 <= 0) + return -1; + /* + * Systems with an invariant TSC report the multiplier (maximum + * non-turbo ratio) in MSR_PLATFORM_INFO[15:8]. + */ + const unsigned int mult = _rdmsr(MSR_PLATFORM_INFO) >> 8 & 0xff; + return bus_x3 * mult / 3; +} + +unsigned int get_cpu_speed(void) +{ + const int cpu_khz_fast = get_cpu_khz_fast(); + if (cpu_khz_fast > 0) + cpu_khz = (unsigned int)cpu_khz_fast; + else + cpu_khz = calibrate_pit(); + + return cpu_khz; +} diff --git a/payloads/libpayload/arch/x64/util.S b/payloads/libpayload/arch/x64/util.S new file mode 100644 index 0000000..9a8b20b --- /dev/null +++ b/payloads/libpayload/arch/x64/util.S @@ -0,0 +1,37 @@ +/* + * + * Copyright (C) 2008 Advanced Micro Devices, 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. + */ + + .global halt + .text + .align 4 + +/* This function puts the system into a halt. */ +halt: + cli + hlt + jmp halt diff --git a/payloads/libpayload/arch/x64/virtual.c b/payloads/libpayload/arch/x64/virtual.c new file mode 100644 index 0000000..9450ac0 --- /dev/null +++ b/payloads/libpayload/arch/x64/virtual.c @@ -0,0 +1,36 @@ +/* + * + * Copyright (C) 2008 coresystems GmbH + * + * 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. + */ + +#include <unistd.h> + +unsigned long virtual_offset = 0; + +int getpagesize(void) +{ + return 4096; +} diff --git a/payloads/libpayload/arch/x86/Kconfig b/payloads/libpayload/arch/x86/Kconfig index e59bd7e..e4b695b 100644 --- a/payloads/libpayload/arch/x86/Kconfig +++ b/payloads/libpayload/arch/x86/Kconfig @@ -32,6 +32,11 @@ select LITTLE_ENDIAN select IO_ADDRESS_SPACE
+config ARCH_X86_64 + bool "x86_64" + help + Support the x86_64 architecture + if ARCH_X86
config ENABLE_APIC diff --git a/payloads/libpayload/bin/lpgcc b/payloads/libpayload/bin/lpgcc index bdc1518..c759cbe 100755 --- a/payloads/libpayload/bin/lpgcc +++ b/payloads/libpayload/bin/lpgcc @@ -91,6 +91,12 @@ _ARCHEXTRA="-m32 " _ARCH=x86 fi +if [ "$CONFIG_LP_ARCH_X86_64" = "y" ]; then + _ARCHINCDIR=$_INCDIR/x64 + _ARCHLIBDIR=$_LIBDIR/x64 + _ARCHEXTRA="-m64 " + _ARCH=x64 +fi if [ "$CONFIG_LP_ARCH_MOCK" = "y" ]; then _ARCHINCDIR=$_INCDIR/mock _ARCHLIBDIR=$_LIBDIR/mock @@ -131,7 +137,8 @@ continue ;; -m64) - error "Invalid option --64 - only 32 bit architectures are supported" + shift + continue ;; -c) DOLINK=0 diff --git a/payloads/libpayload/include/x64/arch/apic.h b/payloads/libpayload/include/x64/arch/apic.h new file mode 100644 index 0000000..eedf1b4 --- /dev/null +++ b/payloads/libpayload/include/x64/arch/apic.h @@ -0,0 +1,46 @@ +/* + * + * Copyright 2018 Google LLC + * + * 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. + */ + +#ifndef __ARCH_X86_INCLUDES_ARCH_APIC_H__ +#define __ARCH_X86_INCLUDES_ARCH_APIC_H__ + +/** Returns 1 if apic_init has been called */ +int apic_initialized(void); + +void apic_init(void); + +uint8_t apic_id(void); + +/** Signal the end of the interrupt handler. */ +void apic_eoi(uint8_t vector); + +void apic_delay(unsigned int usec); +void apic_start_delay(unsigned int usec); +void apic_wait_delay(void); + +#endif /* __ARCH_X86_INCLUDES_ARCH_APIC_H__ */ diff --git a/payloads/libpayload/include/x64/arch/barrier.h b/payloads/libpayload/include/x64/arch/barrier.h new file mode 100644 index 0000000..dc75f1a --- /dev/null +++ b/payloads/libpayload/include/x64/arch/barrier.h @@ -0,0 +1,37 @@ +/* + * + * Copyright 2014 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. + * + */ + +#ifndef __ARCH_BARRIER_H__ +#define __ARCH_BARRIER_H__ + +#define mb() +#define rmb() +#define wmb() + +#endif /* __ARCH_BARRIER_H__ */ diff --git a/payloads/libpayload/include/x64/arch/cache.h b/payloads/libpayload/include/x64/arch/cache.h new file mode 100644 index 0000000..8c915c3 --- /dev/null +++ b/payloads/libpayload/include/x64/arch/cache.h @@ -0,0 +1,51 @@ +/* + * + * Copyright 2013 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. + * + * cache.h: Cache maintenance API for x86 + */ + +#ifndef __ARCH_CACHE_H__ +#define __ARCH_CACHE_H__ + +#include <stddef.h> +#include <stdint.h> + +/* returns number of bytes per cache line */ +unsigned int dcache_line_bytes(void); + +void dcache_invalidate_all(void); +void dcache_clean_invalidate_all(void); +void dcache_clean_all(void); +void dcache_clean_by_mva(void const *addr, size_t len); +void dcache_invalidate_by_mva(void const *addr, size_t len); +void dcache_clean_invalidate_by_mva(void const *addr, size_t len); +/* NOOPs mirroring ARM's cache API, since x86 devices usually cache snoop */ +#define dmb() +#define dsb() +#define cache_sync_instructions() + +#endif diff --git a/payloads/libpayload/include/x64/arch/cpuid.h b/payloads/libpayload/include/x64/arch/cpuid.h new file mode 100644 index 0000000..b01646d --- /dev/null +++ b/payloads/libpayload/include/x64/arch/cpuid.h @@ -0,0 +1,102 @@ +/* + * + * Copyright 2018 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. + */ + +#ifndef _ARCH_CPUID_H +#define _ARCH_CPUID_H + +#define cpuid(fn, eax, ebx, ecx, edx) \ + asm("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "0"(fn)) + +#define _declare_cpuid(reg) \ + static inline unsigned int cpuid_##reg(unsigned int fn) \ + { \ + unsigned int eax, ebx, ecx, edx; \ + cpuid(fn, eax, ebx, ecx, edx); \ + return reg; \ + } + +_declare_cpuid(eax) +_declare_cpuid(ebx) +_declare_cpuid(ecx) +_declare_cpuid(edx) + +#undef _declare_cpuid + +#define cpuid_sub_leaf(fn, sub_leaf, eax, ebx, ecx, edx) \ + asm("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "0"(fn), "1"(sub_leaf)) + +#define _declare_cpuid_sub_leaf(reg) \ + static inline unsigned int cpuid_sub_leaf_##reg( \ + unsigned int fn, unsigned int sub_leaf) \ + { \ + unsigned int eax, ebx, ecx, edx; \ + cpuid_sub_leaf(fn, sub_leaf, eax, ebx, ecx, edx); \ + return reg; \ + } + +_declare_cpuid_sub_leaf(eax) +_declare_cpuid_sub_leaf(ebx) +_declare_cpuid_sub_leaf(ecx) +_declare_cpuid_sub_leaf(edx) + +#undef _declare_cpuid_sub_leaf + +static inline unsigned int cpuid_max(void) +{ + return cpuid_eax(0); +} + +static inline unsigned int cpuid_family(void) +{ + const unsigned int eax = cpuid_eax(1); + return (eax & 0xff00000) >> (20 - 4) | (eax & 0xf00) >> 8; +} + +static inline unsigned int cpuid_model(void) +{ + const unsigned int eax = cpuid_eax(1); + return (eax & 0xf0000) >> (16 - 4) | (eax & 0xf0) >> 4; +} + +enum intel_fam6_model { + NEHALEM = 0x25, + SANDYBRIDGE = 0x2a, + IVYBRIDGE = 0x3a, + HASWELL = 0x3c, + BROADWELL_U = 0x3d, + HASWELL_U = 0x45, + HASWELL_GT3E = 0x46, + BROADWELL = 0x47, + SKYLAKE_U_Y = 0x4e, + APOLLOLAKE = 0x5c, + SKYLAKE_S_H = 0x5e, + KABYLAKE_U_Y = 0x8e, + KABYLAKE_S_H = 0x9e, +}; + +#endif diff --git a/payloads/libpayload/include/x64/arch/exception.h b/payloads/libpayload/include/x64/arch/exception.h new file mode 100644 index 0000000..d88029b --- /dev/null +++ b/payloads/libpayload/include/x64/arch/exception.h @@ -0,0 +1,93 @@ +/* + * + * Copyright 2013 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. + */ + +#ifndef _ARCH_EXCEPTION_H +#define _ARCH_EXCEPTION_H + +#include <stdint.h> + +void exception_init_asm(void); +void exception_dispatch(void); +void enable_interrupts(void); +void disable_interrupts(void); +/** Returns 1 if interrupts are enabled. */ +int interrupts_enabled(void); + +struct exception_state +{ + /* Careful: x86/gdb.c currently relies on the size and order of regs. */ + struct { + u32 eax; + u32 ecx; + u32 edx; + u32 ebx; + u32 esp; + u32 ebp; + u32 esi; + u32 edi; + u32 eip; + u32 eflags; + u32 cs; + u32 ss; + u32 ds; + u32 es; + u32 fs; + u32 gs; + } regs; + u32 error_code; + u32 vector; +} __packed; +extern struct exception_state *exception_state; + +extern u32 exception_stack[]; +extern u32 *exception_stack_end; + +enum { + EXC_DE = 0, /* Divide by zero */ + EXC_DB = 1, /* Debug */ + EXC_NMI = 2, /* Non maskable interrupt */ + EXC_BP = 3, /* Breakpoint */ + EXC_OF = 4, /* Overflow */ + EXC_BR = 5, /* Bound range */ + EXC_UD = 6, /* Invalid opcode */ + EXC_NM = 7, /* Device not available */ + EXC_DF = 8, /* Double fault */ + EXC_TS = 10, /* Invalid TSS */ + EXC_NP = 11, /* Segment not present */ + EXC_SS = 12, /* Stack */ + EXC_GP = 13, /* General protection */ + EXC_PF = 14, /* Page fault */ + EXC_MF = 16, /* x87 floating point */ + EXC_AC = 17, /* Alignment check */ + EXC_MC = 18, /* Machine check */ + EXC_XF = 19, /* SIMD floating point */ + EXC_SX = 30, /* Security */ + EXC_COUNT +}; + +#endif diff --git a/payloads/libpayload/include/x64/arch/io.h b/payloads/libpayload/include/x64/arch/io.h new file mode 100644 index 0000000..352affd --- /dev/null +++ b/payloads/libpayload/include/x64/arch/io.h @@ -0,0 +1,160 @@ +/* + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2008 coresystems GmbH + * + * 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. + */ + +#ifndef _ARCH_IO_H +#define _ARCH_IO_H + +#include <inttypes.h> + +/* + * readb/w/l writeb/w/l are deprecated. use read8/16/32 and write8/16/32 + * instead for future development. + * + * TODO: make the existing code use read8/16/32 and write8/16/32 then remove + * readb/w/l and writeb/w/l. + */ + +#define readb(_a) (*(volatile const unsigned char *) (_a)) +#define readw(_a) (*(volatile const unsigned short *) (_a)) +#define readl(_a) (*(volatile const unsigned int *) (_a)) + +#define writeb(_v, _a) (*(volatile unsigned char *) (_a) = (_v)) +#define writew(_v, _a) (*(volatile unsigned short *) (_a) = (_v)) +#define writel(_v, _a) (*(volatile unsigned int *) (_a) = (_v)) + +static inline __attribute__((always_inline)) uint8_t read8(const volatile void *addr) +{ + return *((volatile uint8_t *)(addr)); +} + +static inline __attribute__((always_inline)) uint16_t read16(const volatile void *addr) +{ + return *((volatile uint16_t *)(addr)); +} + +static inline __attribute__((always_inline)) uint32_t read32(const volatile void *addr) +{ + return *((volatile uint32_t *)(addr)); +} + +static inline __attribute__((always_inline)) uint64_t read64(const volatile void *addr) +{ + return *((volatile uint64_t *)(addr)); +} + +static inline __attribute__((always_inline)) void write8(volatile void *addr, uint8_t value) +{ + *((volatile uint8_t *)(addr)) = value; +} + +static inline __attribute__((always_inline)) void write16(volatile void *addr, uint16_t value) +{ + *((volatile uint16_t *)(addr)) = value; +} + +static inline __attribute__((always_inline)) void write32(volatile void *addr, uint32_t value) +{ + *((volatile uint32_t *)(addr)) = value; +} + +static inline __attribute__((always_inline)) void write64(volatile void *addr, uint64_t value) +{ + *((volatile uint64_t *)(addr)) = value; +} + +static inline unsigned int inl(int port) +{ + unsigned int val; + __asm__ __volatile__("inl %w1, %0" : "=a"(val) : "Nd"(port)); + return val; +} + +static inline unsigned short inw(int port) +{ + unsigned short val; + __asm__ __volatile__("inw %w1, %w0" : "=a"(val) : "Nd"(port)); + return val; +} + +static inline unsigned char inb(int port) +{ + unsigned char val; + __asm__ __volatile__("inb %w1, %b0" : "=a"(val) : "Nd"(port)); + return val; +} + +static inline void outl(unsigned int val, int port) +{ + __asm__ __volatile__("outl %0, %w1" : : "a"(val), "Nd"(port)); +} + +static inline void outw(unsigned short val, int port) +{ + __asm__ __volatile__("outw %w0, %w1" : : "a"(val), "Nd"(port)); +} + +static inline void outb(unsigned char val, int port) +{ + __asm__ __volatile__("outb %b0, %w1" : : "a"(val), "Nd"(port)); +} + +static inline void outsl(int port, const void *addr, unsigned long count) +{ + __asm__ __volatile__("rep; outsl" : "+S"(addr), "+c"(count) : "d"(port)); +} + +static inline void outsw(int port, const void *addr, unsigned long count) +{ + __asm__ __volatile__("rep; outsw" : "+S"(addr), "+c"(count) : "d"(port)); +} + +static inline void outsb(int port, const void *addr, unsigned long count) +{ + __asm__ __volatile__("rep; outsb" : "+S"(addr), "+c"(count) : "d"(port)); +} + +static inline void insl(int port, void *addr, unsigned long count) +{ + __asm__ __volatile__("rep; insl" : "+D"(addr), "+c"(count) : "d"(port) + : "memory"); +} + +static inline void insw(int port, void *addr, unsigned long count) +{ + __asm__ __volatile__("rep; insw" : "+D"(addr), "+c"(count) : "d"(port) + : "memory"); +} + +static inline void insb(int port, void *addr, unsigned long count) +{ + __asm__ __volatile__("rep; insb" : "+D"(addr), "+c"(count) : "d"(port) + : "memory"); +} + +#endif diff --git a/payloads/libpayload/include/x64/arch/msr.h b/payloads/libpayload/include/x64/arch/msr.h new file mode 100644 index 0000000..b20618d --- /dev/null +++ b/payloads/libpayload/include/x64/arch/msr.h @@ -0,0 +1,57 @@ +/* + * + * Copyright (C) 2008 Advanced Micro Devices, 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. + */ + +#ifndef _ARCH_MSR_H +#define _ARCH_MSR_H + +static inline unsigned long long _rdmsr(unsigned int msr) +{ + unsigned long long val; + asm volatile("rdmsr" : "=A" (val) : "c" (msr)); + return val; +} + +static inline void _wrmsr(unsigned int msr, unsigned long long val) +{ + asm volatile("wrmsr" : : "c" (msr), "A"(val)); +} + +#define rdmsr(_m, _l, _h) \ + do { \ + unsigned long long _v = _rdmsr((_m)); \ + (_l) = (unsigned int) _v; \ + (_h) = (unsigned int) ((_v >> 32) & 0xFFFFFFFF); \ + } while(0) + +static inline void wrmsr(unsigned int msr, unsigned int lo, unsigned int hi) +{ + unsigned long long val = (((unsigned long long) hi) << 32) | lo; + _wrmsr(msr, val); +} + +#endif diff --git a/payloads/libpayload/include/x64/arch/rdtsc.h b/payloads/libpayload/include/x64/arch/rdtsc.h new file mode 100644 index 0000000..41ab24a --- /dev/null +++ b/payloads/libpayload/include/x64/arch/rdtsc.h @@ -0,0 +1,41 @@ +/* + * + * Copyright (C) 2008 Advanced Micro Devices, 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. + */ + +#ifndef _ARCH_RDTSC_H +#define _ARCH_RDTSC_H + +#include <stdint.h> + +static u64 rdtsc(void) +{ + u64 val; + __asm__ __volatile__ ("rdtsc" : "=A" (val)); + return val; +} + +#endif diff --git a/payloads/libpayload/include/x64/arch/types.h b/payloads/libpayload/include/x64/arch/types.h new file mode 100644 index 0000000..3f2eeaa --- /dev/null +++ b/payloads/libpayload/include/x64/arch/types.h @@ -0,0 +1,59 @@ +/* + * + * Copyright (C) 2007 Uwe Hermann uwe@hermann-uwe.de + * + * 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. + */ + +#ifndef _ARCH_TYPES_H +#define _ARCH_TYPES_H + +typedef unsigned char uint8_t; +typedef unsigned char u8; +typedef signed char int8_t; +typedef signed char s8; + +typedef unsigned short uint16_t; +typedef unsigned short u16; +typedef signed short int16_t; +typedef signed short s16; + +typedef unsigned int uint32_t; +typedef unsigned int u32; +typedef signed int int32_t; +typedef signed int s32; + +typedef unsigned long long uint64_t; +typedef unsigned long long u64; +typedef signed long long int64_t; +typedef signed long long s64; + +typedef long time_t; +typedef long suseconds_t; + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#endif diff --git a/payloads/libpayload/include/x64/arch/virtual.h b/payloads/libpayload/include/x64/arch/virtual.h new file mode 100644 index 0000000..a88138d --- /dev/null +++ b/payloads/libpayload/include/x64/arch/virtual.h @@ -0,0 +1,40 @@ +/* + * + * Copyright (C) 2008 coresystems GmbH + * + * 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. + */ + +#ifndef _ARCH_VIRTUAL_H +#define _ARCH_VIRTUAL_H + +extern unsigned long virtual_offset; + +#define virt_to_phys(virt) ((unsigned long) (virt) + virtual_offset) +#define phys_to_virt(phys) ((void *) ((unsigned long) (phys) - virtual_offset)) + +#define virt_to_bus(addr) virt_to_phys(addr) +#define bus_to_virt(addr) phys_to_virt(addr) + +#endif diff --git a/payloads/libpayload/vboot/Makefile.mk b/payloads/libpayload/vboot/Makefile.mk index 554fec8..cadc968 100644 --- a/payloads/libpayload/vboot/Makefile.mk +++ b/payloads/libpayload/vboot/Makefile.mk @@ -16,6 +16,7 @@
VBOOT_FIRMWARE_ARCH-$(CONFIG_LP_ARCH_ARM) := arm VBOOT_FIRMWARE_ARCH-$(CONFIG_LP_ARCH_X86) := x86 +VBOOT_FIRMWARE_ARCH-$(CONFIG_LP_ARCH_X86_64) := x86_64 VBOOT_FIRMWARE_ARCH-$(CONFIG_LP_ARCH_ARM64) := arm64
ifneq ($(CONFIG_LP_ARCH_MOCK),)