455 changes: 0 additions & 455 deletions payloads/libpayload/arch/arm64/lib/pstate.c

This file was deleted.

1,061 changes: 0 additions & 1,061 deletions payloads/libpayload/arch/arm64/lib/sysctrl.c

This file was deleted.

95 changes: 0 additions & 95 deletions payloads/libpayload/arch/arm64/lib/tlb.c

This file was deleted.

9 changes: 0 additions & 9 deletions payloads/libpayload/arch/arm64/libpayload.ldscript
Expand Up @@ -77,15 +77,6 @@ SECTIONS
. += CONFIG_LP_STACK_SIZE;
. = ALIGN(16);
_stack = .;

/* Exception stack. Having a separate exception stack
* allows us to have later stages running in non-EL3 levels.
*/

_exc_estack = .;
. += CONFIG_LP_STACK_SIZE;
. = ALIGN(16);
_exc_stack = .;
}

_end = .;
Expand Down
23 changes: 11 additions & 12 deletions payloads/libpayload/arch/arm64/mmu.c
Expand Up @@ -252,7 +252,7 @@ void mmu_config_range(void *start, size_t size, uint64_t tag)

/* ARMv8 MMUs snoop L1 data cache, no need to flush it. */
dsb();
tlbiall_current();
tlbiall_el2();
dsb();
isb();
}
Expand Down Expand Up @@ -298,7 +298,7 @@ static uint32_t is_mmu_enabled(void)
{
uint32_t sctlr;

sctlr = raw_read_sctlr_current();
sctlr = raw_read_sctlr_el2();

return (sctlr & SCTLR_M);
}
Expand All @@ -309,19 +309,18 @@ static uint32_t is_mmu_enabled(void)
*/
void mmu_disable(void)
{
uint32_t el = get_current_el();
uint32_t sctlr;

sctlr = raw_read_sctlr(el);
sctlr = raw_read_sctlr_el2();
sctlr &= ~(SCTLR_C | SCTLR_M | SCTLR_I);

tlbiall_current();
tlbiall_el2();
dcache_clean_invalidate_all();

dsb();
isb();

raw_write_sctlr(sctlr, el);
raw_write_sctlr_el2(sctlr);

dcache_clean_invalidate_all();
dsb();
Expand All @@ -338,26 +337,26 @@ void mmu_enable(void)
uint32_t sctlr;

/* Initialize MAIR indices */
raw_write_mair_current(MAIR_ATTRIBUTES);
raw_write_mair_el2(MAIR_ATTRIBUTES);

/* Invalidate TLBs */
tlbiall_current();
tlbiall_el2();

/* Initialize TCR flags */
raw_write_tcr_current(TCR_TOSZ | TCR_IRGN0_NM_WBWAC | TCR_ORGN0_NM_WBWAC |
raw_write_tcr_el2(TCR_TOSZ | TCR_IRGN0_NM_WBWAC | TCR_ORGN0_NM_WBWAC |
TCR_SH0_IS | TCR_TG0_4KB | TCR_PS_256TB |
TCR_TBI_USED);

/* Initialize TTBR */
raw_write_ttbr0_current((uintptr_t)xlat_addr);
raw_write_ttbr0_el2((uintptr_t)xlat_addr);

/* Ensure system register writes are committed before enabling MMU */
isb();

/* Enable MMU */
sctlr = raw_read_sctlr_current();
sctlr = raw_read_sctlr_el2();
sctlr |= SCTLR_C | SCTLR_M | SCTLR_I;
raw_write_sctlr_current(sctlr);
raw_write_sctlr_el2(sctlr);

isb();

Expand Down
17 changes: 17 additions & 0 deletions payloads/libpayload/arch/x86/Kconfig
Expand Up @@ -37,4 +37,21 @@ config ARCH_SPECIFIC_OPTIONS # dummy
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
48 changes: 43 additions & 5 deletions payloads/libpayload/arch/x86/apic.c
@@ -1,7 +1,7 @@
/*
* This file is part of the libpayload project.
*
* Copyright 2018 Google LLC.
* Copyright 2018 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
Expand Down Expand Up @@ -42,7 +42,6 @@
#define XAPIC_ENABLED_BIT (1 << 11)
#define X2APIC_ENABLED_BIT (1 << 10)
#define APIC_MASKED_BIT (1 << 16)
#define APIC_SW_ENABLED_BIT (1 << 8)

#define APIC_ID 0x020
#define APIC_ID_SHIFT 24
Expand All @@ -54,14 +53,20 @@
#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 0x20
#define APIC_TIMER_VECTOR 0x20UL
#define APIC_SPURIOUS_VECTOR 0xFFUL

static uint32_t apic_bar;
static int _apic_initialized;
Expand Down Expand Up @@ -141,11 +146,30 @@ static void timer_interrupt_handler(u8 vector)
timer_waiting = 0;
}

void apic_eoi(void)
static void suprious_interrupt_handler(u8 vector) {}

void apic_eoi(uint8_t vector)
{
die_if(!apic_bar, "APIC is not initialized");

apic_write32(APIC_EOI, 0);
/*
* 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)
Expand Down Expand Up @@ -236,6 +260,17 @@ static void apic_sw_enable(void)
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;
Expand All @@ -255,12 +290,15 @@ void apic_init(void)

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;

Expand Down
2 changes: 1 addition & 1 deletion payloads/libpayload/arch/x86/delay.c
@@ -1,7 +1,7 @@
/*
* This file is part of the libpayload project.
*
* Copyright (C) 2018 Google LLC.
* Copyright (C) 2018 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
Expand Down
42 changes: 18 additions & 24 deletions payloads/libpayload/arch/x86/exception.c
Expand Up @@ -34,18 +34,9 @@
#include <arch/apic.h>

#define IF_FLAG (1 << 9)
/*
* Local and I/O APICs support 240 vectors (in the range of 16 to 255) as valid
* interrupts. The Intel 64 and IA-32 architectures reserve vectors 16
* through 31 for predefined interrupts, exceptions, and Intel-reserved
* encodings.
*/
#define FIRST_USER_DEFINED_VECTOR 32

u32 exception_stack[0x400] __attribute__((aligned(8)));

static exception_hook hook;

static interrupt_handler handlers[256];

static const char *names[EXC_COUNT] = {
Expand Down Expand Up @@ -173,27 +164,36 @@ static void dump_exception_state(void)

void exception_dispatch(void)
{
u32 vec = exception_state->vector;
die_if(exception_state->vector >= ARRAY_SIZE(handlers),
"Invalid vector %u\n", exception_state->vector);

die_if(vec >= ARRAY_SIZE(handlers), "Invalid vector %u\n", vec);
u8 vec = exception_state->vector;

if (handlers[vec]) {
handlers[vec](vec);
if (IS_ENABLED(CONFIG_LP_ENABLE_APIC)
&& vec >= FIRST_USER_DEFINED_VECTOR)
apic_eoi();
return;
goto success;
} else if (vec >= EXC_COUNT
&& IS_ENABLED(CONFIG_LP_IGNORE_UNKNOWN_INTERRUPTS)) {
goto success;
} else if (vec >= EXC_COUNT
&& IS_ENABLED(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);

if (hook && hook(vec))
return;

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 (IS_ENABLED(CONFIG_LP_ENABLE_APIC))
apic_eoi(vec);
}

void exception_init(void)
Expand All @@ -202,12 +202,6 @@ void exception_init(void)
exception_init_asm();
}

void exception_install_hook(exception_hook h)
{
die_if(hook, "Implement support for a list of hooks if you need it.");
hook = h;
}

void set_interrupt_handler(u8 vector, interrupt_handler handler)
{
handlers[vector] = handler;
Expand Down
114 changes: 57 additions & 57 deletions payloads/libpayload/curses/PDCurses/doc/intro.txt
Expand Up @@ -129,7 +129,7 @@ For chtype:
A_INVIS invisible
A_ITALIC italic
A_LEFTLINE line along the left edge
A_PROTECT protected (?) -- PDCurses renders this as a
A_PROTECT protected (?) -- PDCurses renders this as a
combination of the *LINE attributes
A_REVERSE reverse video
A_RIGHTLINE line along the right edge
Expand Down Expand Up @@ -291,62 +291,62 @@ particular terminal:
KEY_C1 lower left of virtual keypad
KEY_C3 lower right of virtual keypad

KEY_BTAB Back tab key
KEY_BEG Beginning key
KEY_CANCEL Cancel key
KEY_CLOSE Close key
KEY_COMMAND Cmd (command) key
KEY_COPY Copy key
KEY_CREATE Create key
KEY_END End key
KEY_EXIT Exit key
KEY_FIND Find key
KEY_HELP Help key
KEY_MARK Mark key
KEY_MESSAGE Message key
KEY_MOVE Move key
KEY_NEXT Next object key
KEY_OPEN Open key
KEY_OPTIONS Options key
KEY_PREVIOUS Previous object key
KEY_REDO Redo key
KEY_REFERENCE Reference key
KEY_REFRESH Refresh key
KEY_REPLACE Replace key
KEY_RESTART Restart key
KEY_RESUME Resume key
KEY_SAVE Save key
KEY_SBEG Shifted beginning key
KEY_SCANCEL Shifted cancel key
KEY_SCOMMAND Shifted command key
KEY_SCOPY Shifted copy key
KEY_SCREATE Shifted create key
KEY_SDC Shifted delete char key
KEY_SDL Shifted delete line key
KEY_SELECT Select key
KEY_SEND Shifted end key
KEY_SEOL Shifted clear line key
KEY_SEXIT Shifted exit key
KEY_SFIND Shifted find key
KEY_SHELP Shifted help key
KEY_SHOME Shifted home key
KEY_SIC Shifted input key
KEY_SLEFT Shifted left arrow key
KEY_SMESSAGE Shifted message key
KEY_SMOVE Shifted move key
KEY_SNEXT Shifted next key
KEY_SOPTIONS Shifted options key
KEY_SPREVIOUS Shifted prev key
KEY_SPRINT Shifted print key
KEY_SREDO Shifted redo key
KEY_SREPLACE Shifted replace key
KEY_SRIGHT Shifted right arrow
KEY_SRSUME Shifted resume key
KEY_SSAVE Shifted save key
KEY_SSUSPEND Shifted suspend key
KEY_SUNDO Shifted undo key
KEY_SUSPEND Suspend key
KEY_UNDO Undo key
KEY_BTAB Back tab key
KEY_BEG Beginning key
KEY_CANCEL Cancel key
KEY_CLOSE Close key
KEY_COMMAND Cmd (command) key
KEY_COPY Copy key
KEY_CREATE Create key
KEY_END End key
KEY_EXIT Exit key
KEY_FIND Find key
KEY_HELP Help key
KEY_MARK Mark key
KEY_MESSAGE Message key
KEY_MOVE Move key
KEY_NEXT Next object key
KEY_OPEN Open key
KEY_OPTIONS Options key
KEY_PREVIOUS Previous object key
KEY_REDO Redo key
KEY_REFERENCE Reference key
KEY_REFRESH Refresh key
KEY_REPLACE Replace key
KEY_RESTART Restart key
KEY_RESUME Resume key
KEY_SAVE Save key
KEY_SBEG Shifted beginning key
KEY_SCANCEL Shifted cancel key
KEY_SCOMMAND Shifted command key
KEY_SCOPY Shifted copy key
KEY_SCREATE Shifted create key
KEY_SDC Shifted delete char key
KEY_SDL Shifted delete line key
KEY_SELECT Select key
KEY_SEND Shifted end key
KEY_SEOL Shifted clear line key
KEY_SEXIT Shifted exit key
KEY_SFIND Shifted find key
KEY_SHELP Shifted help key
KEY_SHOME Shifted home key
KEY_SIC Shifted input key
KEY_SLEFT Shifted left arrow key
KEY_SMESSAGE Shifted message key
KEY_SMOVE Shifted move key
KEY_SNEXT Shifted next key
KEY_SOPTIONS Shifted options key
KEY_SPREVIOUS Shifted prev key
KEY_SPRINT Shifted print key
KEY_SREDO Shifted redo key
KEY_SREPLACE Shifted replace key
KEY_SRIGHT Shifted right arrow
KEY_SRSUME Shifted resume key
KEY_SSAVE Shifted save key
KEY_SSUSPEND Shifted suspend key
KEY_SUNDO Shifted undo key
KEY_SUSPEND Suspend key
KEY_UNDO Undo key

The virtual keypad is arranged like this:

Expand Down
2 changes: 1 addition & 1 deletion payloads/libpayload/drivers/i8042/i8042.h
@@ -1,7 +1,7 @@
/*
* This file is part of the libpayload project.
*
* Copyright 2018 Google LLC.
* Copyright 2018 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
Expand Down
4 changes: 4 additions & 0 deletions payloads/libpayload/drivers/usb/ehci.c
Expand Up @@ -776,6 +776,7 @@ ehci_init (unsigned long physical_bar)
int i;
hci_t *controller = new_controller ();
controller->instance = xzalloc(sizeof (ehci_t));
controller->reg_base = (uintptr_t)physical_bar;
controller->type = EHCI;
controller->start = ehci_start;
controller->stop = ehci_stop;
Expand Down Expand Up @@ -867,6 +868,9 @@ ehci_pci_init (pcidev_t addr)

controller = ehci_init((unsigned long)reg_base);

if (controller)
controller->pcidev = addr;

return controller;
}
#endif
1 change: 1 addition & 0 deletions payloads/libpayload/drivers/usb/ohci.c
Expand Up @@ -173,6 +173,7 @@ ohci_init (unsigned long physical_bar)

hci_t *controller = new_controller ();
controller->instance = xzalloc(sizeof (ohci_t));
controller->reg_base = (uintptr_t)physical_bar;
controller->type = OHCI;
controller->start = ohci_start;
controller->stop = ohci_stop;
Expand Down
1 change: 1 addition & 0 deletions payloads/libpayload/drivers/usb/uhci.c
Expand Up @@ -153,6 +153,7 @@ uhci_pci_init (pcidev_t addr)
u16 reg16;

hci_t *controller = new_controller ();
controller->pcidev = addr;
controller->instance = xzalloc(sizeof (uhci_t));
controller->type = UHCI;
controller->start = uhci_start;
Expand Down
15 changes: 11 additions & 4 deletions payloads/libpayload/drivers/usb/usb.c
Expand Up @@ -173,10 +173,10 @@ get_descriptor(usbdev_t *dev, int rtype, int desc_type, int desc_idx,

ret = dev->controller->control(dev, IN,
sizeof(dr), &dr, len, data);
if (ret)
udelay(10);
else
return 0;

if (ret == len)
break;
udelay(10);
}
return ret;
}
Expand Down Expand Up @@ -638,8 +638,15 @@ usb_detach_device(hci_t *controller, int devno)
been called yet by the usb class driver */
if (controller->devices[devno]) {
controller->devices[devno]->destroy (controller->devices[devno]);

if (controller->destroy_device)
controller->destroy_device(controller, devno);

free(controller->devices[devno]->descriptor);
controller->devices[devno]->descriptor = NULL;
free(controller->devices[devno]->configuration);
controller->devices[devno]->configuration = NULL;

/* Tear down the device itself *after* destroy_device()
* has had a chance to interoogate it. */
free(controller->devices[devno]);
Expand Down
5 changes: 2 additions & 3 deletions payloads/libpayload/drivers/usb/usb_dev.c
Expand Up @@ -32,8 +32,6 @@
static void
usb_nop_destroy (usbdev_t *dev)
{
if (dev->descriptor != 0)
free (dev->descriptor);
usb_nop_init (dev);
dev->address = -1;
dev->hub = -1;
Expand All @@ -49,7 +47,8 @@ usb_nop_poll (usbdev_t *dev)
void
usb_nop_init (usbdev_t *dev)
{
dev->descriptor = 0;
dev->descriptor = NULL;
dev->configuration = NULL;
dev->destroy = usb_nop_destroy;
dev->poll = usb_nop_poll;
}
3 changes: 3 additions & 0 deletions payloads/libpayload/drivers/usb/usbhid.c
Expand Up @@ -80,6 +80,9 @@ usb_hid_destroy (usbdev_t *dev)
&dev->endpoints[i], HID_INST(dev)->queue);
HID_INST(dev)->queue = NULL;
}
free(HID_INST(dev)->descriptor);
HID_INST(dev)->descriptor = NULL;

free (dev->data);
}

Expand Down
30 changes: 30 additions & 0 deletions payloads/libpayload/gdb/stub.c
Expand Up @@ -118,3 +118,33 @@ void gdb_exit(s8 exit_status)
gdb_state.connected = 0;
printf("Detached from GDB connection.\n");
}

/*
* This is a check architecture backends can run before entering the GDB command
* loop during exception handling. If it returns true, GDB was already running
* and must have caused an exception itself, which may happen if the GDB server
* tells us to do something stupid (e.g. write to an unmapped address). In that
* case, all we can do is blindly send a generic error code (since we're not
* sure which command caused the exception) and continue serving commands. When
* GDB eventually tells us to resume, we'll return from this function to the
* architecture backend which will have to do a "super exception return" that
* returns right back from the original (outermost) exception, "jumping over"
* all the intermediate exception frames we may have accumulated since. (This is
* the best we can do because our architecture backends generally don't support
* "full", unlimited exception reentrancy.)
*/
int gdb_handle_reentrant_exception(void)
{
if (!gdb_state.connected || gdb_state.resumed)
return 0; /* This is not a reentrant exception. */

static const char error_code[] = "E22"; /* EINVAL? */
static const struct gdb_message tmp_reply = {
.buf = (u8 *)error_code,
.used = sizeof(error_code),
.size = sizeof(error_code),
};
gdb_send_reply(&tmp_reply);
gdb_command_loop(gdb_state.signal); /* preserve old signal */
return 1;
}
90 changes: 86 additions & 4 deletions payloads/libpayload/include/arm64/arch/exception.h
Expand Up @@ -30,18 +30,98 @@
#ifndef _ARCH_EXCEPTION_H
#define _ARCH_EXCEPTION_H

#include <stdint.h>
#define EXCEPTION_STATE_ELR 0x0
#define EXCEPTION_STATE_ESR 0x8
#define EXCEPTION_STATE_SPSR 0x10
#define EXCEPTION_STATE_SP 0x18
#define EXCEPTION_STATE_REG(r) (0x20 + r * 0x8)

#define ESR_EC_UNKNOWN 0b000000
#define ESR_EC_SVC_64 0b010101
#define ESR_EC_INSN_ABT_LOWER 0b100000
#define ESR_EC_INSN_ABT_SAME 0b100001
#define ESR_EC_DATA_ABT_LOWER 0b100100
#define ESR_EC_DATA_ABT_SAME 0b100101
#define ESR_EC_SERROR 0b101111
#define ESR_EC_SS_SAME 0b110011
#define ESR_EC_BKPT_64 0b111100

#define MDCR_TDE (1 << 8)

void set_vbar(void* vbar);
#define MDSCR_SS (1 << 0)
#define MDSCR_KDE (1 << 13)
#define MDSCR_MDE (1 << 15)

#ifndef __ASSEMBLER__

#include <stddef.h>
#include <stdint.h>

struct exception_state
{
uint64_t elr;
uint64_t esr;
union {
uint64_t esr;
union {
struct {
uint64_t iss : 25;
uint64_t il : 1;
uint64_t ec : 6;
uint64_t _res0 : 32;
};
struct {
uint64_t isfc : 6;
uint64_t _res0 : 1;
uint64_t s1ptw : 1;
uint64_t _res1 : 1;
uint64_t ea : 1;
uint64_t fnv : 1;
uint64_t _res2 : 53;
} insn_abt;
};
};
union {
uint32_t spsr;
struct {
uint32_t sp : 1; /* M[0] */
uint32_t _res0 : 1; /* M[1] */
uint32_t el : 2; /* M[3:2] */
uint32_t arch : 1; /* M[4] */
uint32_t _res1 : 1;
uint32_t f : 1;
uint32_t i : 1;
uint32_t a : 1;
uint32_t d : 1;
uint32_t _res2 : 10;
uint32_t il : 1;
uint32_t ss : 1;
uint32_t _res3 : 6;
uint32_t v : 1;
uint32_t c : 1;
uint32_t z : 1;
uint32_t n : 1;
} pstate;
};
uint32_t spsr_high_unused;
uint64_t sp;
uint64_t regs[31];
} __packed;

extern struct exception_state *exception_state;
#define CHECK_ES(field, constant) \
_Static_assert(offsetof(struct exception_state, field) == constant, \
"(struct exception_state)." #field " doesn't match constant " #constant)
CHECK_ES(elr, EXCEPTION_STATE_ELR);
CHECK_ES(esr, EXCEPTION_STATE_ESR);
CHECK_ES(spsr, EXCEPTION_STATE_SPSR);
CHECK_ES(sp, EXCEPTION_STATE_SP);
CHECK_ES(regs[0], EXCEPTION_STATE_REG(0));
CHECK_ES(regs[30], EXCEPTION_STATE_REG(30));

extern struct exception_state exception_state;
extern u64 exception_stack[];
extern u64 *exception_stack_end;

void exception_set_state_ptr(struct exception_state *exception_state_ptr);

enum {
EXC_SYNC_SP0 = 0,
Expand All @@ -63,4 +143,6 @@ enum {
EXC_COUNT
};

#endif /* !__ASSEMBLER__ */

#endif
581 changes: 224 additions & 357 deletions payloads/libpayload/include/arm64/arch/lib_helpers.h

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions payloads/libpayload/include/gdb.h
Expand Up @@ -77,6 +77,7 @@ void gdb_send_reply(const struct gdb_message *reply);
/* gdb/stub.c */

void gdb_command_loop(uint8_t signal);
int gdb_handle_reentrant_exception(void);

enum {
GDB_SIG0 = 0, /* Signal 0 */
Expand Down
4 changes: 2 additions & 2 deletions payloads/libpayload/include/x86/arch/apic.h
@@ -1,7 +1,7 @@
/*
* This file is part of the libpayload project.
*
* Copyright 2018 Google LLC.
* Copyright 2018 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
Expand Down Expand Up @@ -38,7 +38,7 @@ void apic_init(void);
uint8_t apic_id(void);

/** Signal the end of the interrupt handler. */
void apic_eoi(void);
void apic_eoi(uint8_t vector);

void apic_delay(unsigned int usec);

Expand Down
9 changes: 1 addition & 8 deletions src/Kconfig
Expand Up @@ -153,7 +153,7 @@ config COMPRESS_BOOTBLOCK
a small self-decompression stub to its front. This can drastically
reduce boot time on platforms where the bootblock is loaded over a
very slow connection and bootblock size trumps all other factors for
speed. Since this using this option usually requires changes to the
speed. Since using this option usually requires changes to the
SoC memlayout and possibly extra support code, it should not be
user-selectable. (There's no real point in offering this to the user
anyway... if it works and saves boot time, you would always want it.)
Expand Down Expand Up @@ -449,13 +449,6 @@ config RESUME_PATH_SAME_AS_BOOT
same path as a regular boot. e.g. an x86 system runs from the
reset vector at 0xfffffff0 on both resume and warm/cold boot.

config HAVE_HARD_RESET
bool
default n
help
This variable specifies whether a given board has a hard_reset
function, no matter if it's provided by board code or chipset code.

config HAVE_ROMSTAGE_CONSOLE_SPINLOCK
bool
depends on EARLY_CBMEM_INIT
Expand Down
5 changes: 0 additions & 5 deletions src/arch/arm/boot.c
Expand Up @@ -25,8 +25,3 @@ void arch_prog_run(struct prog *prog)
doit = prog_entry(prog);
doit(prog_entry_arg(prog));
}

int arch_supports_bounce_buffer(void)
{
return 0;
}
2 changes: 0 additions & 2 deletions src/arch/arm/include/arch/hlt.h
Expand Up @@ -14,8 +14,6 @@
#ifndef ARCH_HLT_H
#define ARCH_HLT_H

#include <compiler.h>

static __always_inline void hlt(void)
{
for (;;) ;
Expand Down
10 changes: 0 additions & 10 deletions src/arch/arm/include/armv7/arch/cpu.h
Expand Up @@ -28,16 +28,6 @@ struct cpu_driver {
const struct cpu_device_id *id_table;
};

struct thread;

struct cpu_info {
device_t cpu;
unsigned long index;
#if IS_ENABLED(CONFIG_COOP_MULTITASKING)
struct thread *thread;
#endif
};

struct cpuinfo_arm {
uint8_t arm; /* CPU family */
uint8_t arm_vendor; /* CPU vendor */
Expand Down
1 change: 0 additions & 1 deletion src/arch/arm/stages.c
Expand Up @@ -26,7 +26,6 @@

#include <arch/stages.h>
#include <arch/cache.h>
#include <compiler.h>

/**
* generic stage entry point. override this if board specific code is needed.
Expand Down
3 changes: 1 addition & 2 deletions src/arch/arm64/arm_tf.c
Expand Up @@ -21,7 +21,6 @@
#include <assert.h>
#include <cbfs.h>
#include <cbmem.h>
#include <compiler.h>
#include <program_loading.h>

/*
Expand Down Expand Up @@ -51,7 +50,7 @@ void arm_tf_run_bl31(u64 payload_entry, u64 payload_arg0, u64 payload_spsr)
if (prog_locate(&bl31))
die("BL31 not found");

if (!selfload(&bl31, false))
if (!selfload(&bl31))
die("BL31 load failed");
bl31_entry = prog_entry(&bl31);

Expand Down
6 changes: 0 additions & 6 deletions src/arch/arm64/boot.c
Expand Up @@ -19,7 +19,6 @@
#include <arch/transition.h>
#include <arm_tf.h>
#include <cbmem.h>
#include <compiler.h>
#include <console/console.h>
#include <program_loading.h>
#include <rules.h>
Expand Down Expand Up @@ -56,11 +55,6 @@ void arch_prog_run(struct prog *prog)
doit(prog_entry_arg(prog));
}

int arch_supports_bounce_buffer(void)
{
return 0;
}

/* Generic stage entry point. Can be overridden by board/SoC if needed. */
__weak void stage_entry(void)
{
Expand Down
2 changes: 0 additions & 2 deletions src/arch/arm64/include/arch/hlt.h
Expand Up @@ -14,8 +14,6 @@
#ifndef ARCH_HLT_H
#define ARCH_HLT_H

#include <compiler.h>

static __always_inline void hlt(void)
{
for (;;) ;
Expand Down
4 changes: 4 additions & 0 deletions src/arch/arm64/include/armv8/arch/lib_helpers.h
Expand Up @@ -210,9 +210,13 @@ MAKE_REGISTER_ACCESSORS(hpfar_el2)
MAKE_REGISTER_ACCESSORS(hstr_el2)
MAKE_REGISTER_ACCESSORS(isr_el1)
MAKE_REGISTER_ACCESSORS_EL123(mair)
MAKE_REGISTER_ACCESSORS_EL123(mdcr)
MAKE_REGISTER_ACCESSORS(mdscr)
MAKE_REGISTER_ACCESSORS(midr_el1)
MAKE_REGISTER_ACCESSORS(mpidr_el1)
MAKE_REGISTER_ACCESSORS(nzcv)
MAKE_REGISTER_ACCESSORS(oslar_el1)
MAKE_REGISTER_ACCESSORS(oslsr_el1)
MAKE_REGISTER_ACCESSORS(par_el1)
MAKE_REGISTER_ACCESSORS(revdir_el1)
MAKE_REGISTER_ACCESSORS_EL123(rmr)
Expand Down
1 change: 0 additions & 1 deletion src/arch/arm64/transition.c
Expand Up @@ -18,7 +18,6 @@
#include <arch/mmu.h>
#include <arch/transition.h>
#include <assert.h>
#include <compiler.h>
#include <console/console.h>

/* Litte-endian, No XN-forced, Instr cache disabled,
Expand Down
5 changes: 0 additions & 5 deletions src/arch/mips/boot.c
Expand Up @@ -23,8 +23,3 @@ void arch_prog_run(struct prog *prog)

doit(cb_tables);
}

int arch_supports_bounce_buffer(void)
{
return 0;
}
2 changes: 1 addition & 1 deletion src/arch/mips/include/arch/cpu.h
Expand Up @@ -30,7 +30,7 @@ struct cpu_driver {
struct thread;

struct cpu_info {
device_t cpu;
struct device *cpu;
unsigned long index;
};

Expand Down
2 changes: 0 additions & 2 deletions src/arch/mips/include/arch/hlt.h
Expand Up @@ -16,8 +16,6 @@
#ifndef __MIPS_ARCH_HLT_H
#define __MIPS_ARCH_HLT_H

#include <compiler.h>

static inline __always_inline void hlt(void)
{
for (;;)
Expand Down
5 changes: 0 additions & 5 deletions src/arch/power8/boot.c
Expand Up @@ -21,8 +21,3 @@ void arch_prog_run(struct prog *prog)

doit(prog_entry_arg(prog));
}

int arch_supports_bounce_buffer(void)
{
return 0;
}
2 changes: 1 addition & 1 deletion src/arch/power8/include/arch/cpu.h
Expand Up @@ -29,7 +29,7 @@ struct cpu_driver {
struct thread;

struct cpu_info {
device_t cpu;
struct device *cpu;
unsigned long index;
#if IS_ENABLED(CONFIG_COOP_MULTITASKING)
struct thread *thread;
Expand Down
2 changes: 0 additions & 2 deletions src/arch/power8/include/arch/hlt.h
Expand Up @@ -11,8 +11,6 @@
* GNU General Public License for more details.
*/

#include <compiler.h>

static __always_inline void hlt(void)
{
while (1)
Expand Down
6 changes: 6 additions & 0 deletions src/arch/riscv/Kconfig
Expand Up @@ -32,3 +32,9 @@ config ARCH_RAMSTAGE_RISCV
config RISCV_USE_ARCH_TIMER
bool
default n

config RISCV_HART_NUM
int

config RISCV_WORKING_HARTID
int
15 changes: 14 additions & 1 deletion src/arch/riscv/Makefile.inc
Expand Up @@ -25,7 +25,12 @@ ifeq ($(CONFIG_ARCH_RAMSTAGE_RISCV),y)
check-ramstage-overlap-regions += stack
endif

riscv_flags = -I$(src)/arch/riscv/ -mcmodel=$(CONFIG_RISCV_CODEMODEL) -march=$(CONFIG_RISCV_ARCH) -mabi=$(CONFIG_RISCV_ABI)
riscv_flags = -I$(src)/arch/riscv/
ifeq ($(CCC_ANALYZER_OUTPUT_FORMAT),)
riscv_flags += -march=$(CONFIG_RISCV_ARCH) -mabi=$(CONFIG_RISCV_ABI) -mcmodel=$(CONFIG_RISCV_CODEMODEL)
else
riscv_flags += -D__riscv -D__riscv_xlen=64 -D__riscv_flen=64
endif

riscv_asm_flags = -march=$(CONFIG_RISCV_ARCH) -mabi=$(CONFIG_RISCV_ABI)

Expand All @@ -45,10 +50,13 @@ bootblock-y += trap_util.S
bootblock-y += trap_handler.c
bootblock-y += fp_asm.S
bootblock-y += misaligned.c
bootblock-y += sbi.c
bootblock-y += mcall.c
bootblock-y += virtual_memory.c
bootblock-y += boot.c
bootblock-y += smp.c
bootblock-y += misc.c
bootblock-y += pmp.c
bootblock-y += \
$(top)/src/lib/memchr.c \
$(top)/src/lib/memcmp.c \
Expand Down Expand Up @@ -77,6 +85,8 @@ ifeq ($(CONFIG_ARCH_ROMSTAGE_RISCV),y)
romstage-y += boot.c
romstage-y += stages.c
romstage-y += misc.c
romstage-y += pmp.c
romstage-y += smp.c
romstage-y += \
$(top)/src/lib/memchr.c \
$(top)/src/lib/memcmp.c \
Expand Down Expand Up @@ -109,12 +119,15 @@ ramstage-y += trap_util.S
ramstage-y += trap_handler.c
ramstage-y += fp_asm.S
ramstage-y += misaligned.c
ramstage-y += sbi.c
ramstage-y += virtual_memory.c
ramstage-y += stages.c
ramstage-y += misc.c
ramstage-y += smp.c
ramstage-y += boot.c
ramstage-y += tables.c
ramstage-y += payload.S
ramstage-y += pmp.c
ramstage-y += \
$(top)/src/lib/memchr.c \
$(top)/src/lib/memcmp.c \
Expand Down
7 changes: 4 additions & 3 deletions src/arch/riscv/boot.c
Expand Up @@ -19,6 +19,7 @@
#include <arch/encoding.h>
#include <rules.h>
#include <console/console.h>
#include <arch/smp/smp.h>

/*
* A pointer to the Flattened Device Tree passed to coreboot by the boot ROM.
Expand All @@ -28,7 +29,7 @@
*/
const void *rom_fdt;

void arch_prog_run(struct prog *prog)
static void do_arch_prog_run(struct prog *prog)
{
void (*doit)(void *) = prog_entry(prog);
void riscvpayload(const void *fdt, void *payload);
Expand All @@ -49,7 +50,7 @@ void arch_prog_run(struct prog *prog)
doit(prog_entry_arg(prog));
}

int arch_supports_bounce_buffer(void)
void arch_prog_run(struct prog *prog)
{
return 0;
smp_resume((void (*)(void *))do_arch_prog_run, prog);
}
12 changes: 4 additions & 8 deletions src/arch/riscv/bootblock.S
Expand Up @@ -24,13 +24,6 @@
.global _estack
.globl _start
_start:
csrr a0, mhartid
li a3, 0
beq a0, a3, _hart_zero
_hart_loop:
j _hart_loop
_hart_zero:

# The boot ROM may pass the following arguments to coreboot:
# a0: the value of mhartid
# a1: a pointer to the flattened devicetree
Expand Down Expand Up @@ -59,14 +52,17 @@ _hart_zero:
csrr a0, mhartid
call hls_init

li a0, CONFIG_RISCV_WORKING_HARTID
call smp_pause

# initialize entry of interrupt/exception
la t0, trap_entry
csrw mtvec, t0

# clear any pending interrupts
csrwi mip, 0

# set up the mstatus register for VM
# set up the mstatus register
call mstatus_init
tail main

Expand Down
2 changes: 1 addition & 1 deletion src/arch/riscv/include/arch/cpu.h
Expand Up @@ -31,7 +31,7 @@ struct cpu_driver {
struct thread;

struct cpu_info {
device_t cpu;
struct device *cpu;
unsigned long index;
#if IS_ENABLED(CONFIG_COOP_MULTITASKING)
struct thread *thread;
Expand Down
2 changes: 0 additions & 2 deletions src/arch/riscv/include/arch/hlt.h
Expand Up @@ -11,8 +11,6 @@
* GNU General Public License for more details.
*/

#include <compiler.h>

static __always_inline void hlt(void)
{
while (1);
Expand Down
1 change: 0 additions & 1 deletion src/arch/riscv/include/arch/io.h
Expand Up @@ -16,7 +16,6 @@

#include <endian.h>
#include <stdint.h>
#include <compiler.h>

static __always_inline uint8_t read8(const volatile void *addr)
{
Expand Down
33 changes: 33 additions & 0 deletions src/arch/riscv/include/arch/pmp.h
@@ -0,0 +1,33 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2018 HardenedLinux
*
* 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; version 2 of the License.
*
* 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.
*/

#ifndef __RISCV_PMP_H__
#define __RISCV_PMP_H__

#include <stdint.h>

/*
* this function needs to be implemented by a specific SoC.
* return number of PMP entries for current hart
*/
extern int pmp_entries_num(void);

/* reset PMP setting */
void reset_pmp(void);

/* set up PMP record */
void setup_pmp(uintptr_t base, uintptr_t size, uintptr_t flags);

#endif /* __RISCV_PMP_H__ */
33 changes: 33 additions & 0 deletions src/arch/riscv/include/arch/smp/smp.h
@@ -0,0 +1,33 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2018 HardenedLinux.
*
* 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; version 2 of the License.
*
* 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.
*/

#ifndef _RISCV_SMP_H
#define _RISCV_SMP_H

/*
* This function is used to pause smp. Only the hart with hartid equal
* to working_hartid can be returned from smp_pause, other harts will
* enter halt and wait for wakeup
*/
void smp_pause(int working_hartid);

/*
* This function is used to wake up the harts that are halted by the
* smp_pause function. And this function will not return, all hart will
* jump to fn execution, and arg is the argument of the function fn.
*/
void smp_resume(void (*fn)(void *), void *arg);

#endif
18 changes: 17 additions & 1 deletion src/arch/riscv/include/mcall.h
Expand Up @@ -18,7 +18,7 @@

// NOTE: this is the size of hls_t below. A static_assert would be
// nice to have.
#define HLS_SIZE 64
#define HLS_SIZE 88

/* We save 37 registers, currently. */
#define MENTRY_FRAME_SIZE (HLS_SIZE + 37 * 8)
Expand All @@ -35,6 +35,12 @@ typedef struct {
unsigned long sbi_private_data;
} sbi_device_message;

struct blocker {
void *arg;
void (*fn)(void *arg);
uint32_t sync_a;
uint32_t sync_b;
};

typedef struct {
sbi_device_message *device_request_queue_head;
Expand All @@ -46,6 +52,7 @@ typedef struct {
int ipi_pending;
uint64_t *timecmp;
uint64_t *time;
struct blocker entry;
} hls_t;

#define MACHINE_STACK_TOP() ({ \
Expand All @@ -64,6 +71,15 @@ void hls_init(uint32_t hart_id); // need to call this before launching linux
/* This function is used to initialize HLS()->time/HLS()->timecmp */
void mtime_init(void);

/*
* This function needs be implement by SoC code.
* Although the privileged instruction set defines that MSIP will be
* memory-mapped, but does not define how to map. SoC can be implemented as
* a bit, a byte, a word, and so on.
* So we can't provide code that is related to implementation.
*/
void set_msip(int hartid, int val);

#endif // __ASSEMBLER__

#endif
37 changes: 37 additions & 0 deletions src/arch/riscv/include/sbi.h
@@ -0,0 +1,37 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2018 HardenedLinux
*
* 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; version 2 of the License.
*
* 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.
*/

#ifndef RISCV_SBI_H
#define RISCV_SBI_H

#define SBI_SET_TIMER 0
#define SBI_CONSOLE_PUTCHAR 1
#define SBI_CONSOLE_GETCHAR 2
#define SBI_CLEAR_IPI 3
#define SBI_SEND_IPI 4
#define SBI_REMOTE_FENCE_I 5
#define SBI_REMOTE_SFENCE_VMA 6
#define SBI_REMOTE_SFENCE_VMA_ASID 7
#define SBI_SHUTDOWN 8

#define IPI_SOFT 1
#define IPI_FENCE_I 2
#define IPI_SFENCE_VMA 4
#define IPI_SFENCE_VMA_ASID 8
#define IPI_SHUTDOWN 16

void handle_sbi(trapframe *tf);

#endif /* RISCV_SBI_H */
8 changes: 8 additions & 0 deletions src/arch/riscv/include/vm.h
Expand Up @@ -102,6 +102,14 @@ DEFINE_MPRV_WRITE(mprv_write_u64, uint64_t, sd)
DEFINE_MPRV_WRITE(mprv_write_long, long, sd)
DEFINE_MPRV_WRITE(mprv_write_ulong, unsigned long, sd)

#if __riscv_xlen == 32
DEFINE_MPRV_READ(mprv_read_uintptr_t, uintptr_t, lw)
DEFINE_MPRV_READ(mprv_write_uintptr_t, uintptr_t, sw)
#elif __riscv_xlen == 64
DEFINE_MPRV_READ(mprv_read_uintptr_t, uintptr_t, ld)
DEFINE_MPRV_READ(mprv_write_uintptr_t, uintptr_t, sd)
#endif

#undef DEFINE_MPRV_READ_FLAGS
#undef DEFINE_MPRV_READ
#undef DEFINE_MPRV_READ_MXR
Expand Down
19 changes: 14 additions & 5 deletions src/arch/riscv/misaligned.c
Expand Up @@ -146,24 +146,26 @@ static struct memory_instruction_info *match_instruction(uintptr_t insn)
}


static int fetch_16bit_instruction(uintptr_t vaddr, uintptr_t *insn)
static int fetch_16bit_instruction(uintptr_t vaddr, uintptr_t *insn, int *size)
{
uint16_t ins = mprv_read_mxr_u16((uint16_t *)vaddr);
if (EXTRACT_FIELD(ins, 0x3) != 3) {
*insn = ins;
*size = 2;
return 0;
}
return -1;
}

static int fetch_32bit_instruction(uintptr_t vaddr, uintptr_t *insn)
static int fetch_32bit_instruction(uintptr_t vaddr, uintptr_t *insn, int *size)
{
uint32_t l = (uint32_t)mprv_read_mxr_u16((uint16_t *)vaddr + 0);
uint32_t h = (uint32_t)mprv_read_mxr_u16((uint16_t *)vaddr + 2);
uint32_t h = (uint32_t)mprv_read_mxr_u16((uint16_t *)vaddr + 1);
uint32_t ins = (h << 16) | l;
if ((EXTRACT_FIELD(ins, 0x3) == 3) &&
(EXTRACT_FIELD(ins, 0x1c) != 0x7)) {
*insn = ins;
*size = 4;
return 0;
}
return -1;
Expand All @@ -174,11 +176,15 @@ void handle_misaligned(trapframe *tf)
{
uintptr_t insn = 0;
union endian_buf buff;
int insn_size = 0;

/* try to fetch 16/32 bits instruction */
if (fetch_16bit_instruction(tf->epc, &insn))
if (fetch_32bit_instruction(tf->epc, &insn))
if (fetch_16bit_instruction(tf->epc, &insn, &insn_size) < 0) {
if (fetch_32bit_instruction(tf->epc, &insn, &insn_size) < 0) {
redirect_trap();
return;
}
}

/* matching instruction */
struct memory_instruction_info *match = match_instruction(insn);
Expand Down Expand Up @@ -264,4 +270,7 @@ void handle_misaligned(trapframe *tf)
mprv_write_u8(addr, buff.b[i]);
}
}

/* return to where we came from */
write_csr(mepc, read_csr(mepc) + insn_size);
}
321 changes: 321 additions & 0 deletions src/arch/riscv/pmp.c
@@ -0,0 +1,321 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2018 HardenedLinux
*
* 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; version 2 of the License.
*
* 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 <arch/encoding.h>
#include <stdint.h>
#include <arch/pmp.h>
#include <console/console.h>
#include <commonlib/helpers.h>

#define GRANULE (1 << PMP_SHIFT)

/*
* This structure is used to temporarily record PMP
* configuration information.
*/
typedef struct {
/* used to record the value of pmpcfg[i] */
uintptr_t cfg;
/*
* When generating a TOR type configuration,
* the previous entry needs to record the starting address.
* used to record the value of pmpaddr[i - 1]
*/
uintptr_t previous_address;
/* used to record the value of pmpaddr[i] */
uintptr_t address;
} pmpcfg_t;

/* This variable is used to record which entries have been used. */
static uintptr_t pmp_entry_used_mask;

/* helper function used to read pmpcfg[idx] */
static uintptr_t read_pmpcfg(int idx)
{
#if __riscv_xlen == 32
int shift = 8 * (idx & 3);
switch (idx >> 2) {
case 0:
return (read_csr(pmpcfg0) >> shift) & 0xff;
case 1:
return (read_csr(pmpcfg1) >> shift) & 0xff;
case 2:
return (read_csr(pmpcfg2) >> shift) & 0xff;
case 3:
return (read_csr(pmpcfg3) >> shift) & 0xff;
}
#elif __riscv_xlen == 64
int shift = 8 * (idx & 7);
switch (idx >> 3) {
case 0:
return (read_csr(pmpcfg0) >> shift) & 0xff;
case 1:
return (read_csr(pmpcfg2) >> shift) & 0xff;
}
#endif
return -1;
}

/* helper function used to write pmpcfg[idx] */
static void write_pmpcfg(int idx, uintptr_t cfg)
{
uintptr_t old;
uintptr_t new;
#if __riscv_xlen == 32
int shift = 8 * (idx & 3);
switch (idx >> 2) {
case 0:
old = read_csr(pmpcfg0);
new = (old & ~((uintptr_t)0xff << shift))
| ((cfg & 0xff) << shift);
write_csr(pmpcfg0, new);
break;
case 1:
old = read_csr(pmpcfg1);
new = (old & ~((uintptr_t)0xff << shift))
| ((cfg & 0xff) << shift);
write_csr(pmpcfg1, new);
break;
case 2:
old = read_csr(pmpcfg2);
new = (old & ~((uintptr_t)0xff << shift))
| ((cfg & 0xff) << shift);
write_csr(pmpcfg2, new);
break;
case 3:
old = read_csr(pmpcfg3);
new = (old & ~((uintptr_t)0xff << shift))
| ((cfg & 0xff) << shift);
write_csr(pmpcfg3, new);
break;
}
#elif __riscv_xlen == 64
int shift = 8 * (idx & 7);
switch (idx >> 3) {
case 0:
old = read_csr(pmpcfg0);
new = (old & ~((uintptr_t)0xff << shift))
| ((cfg & 0xff) << shift);
write_csr(pmpcfg0, new);
break;
case 1:
old = read_csr(pmpcfg2);
new = (old & ~((uintptr_t)0xff << shift))
| ((cfg & 0xff) << shift);
write_csr(pmpcfg2, new);
break;
}
#endif
if (read_pmpcfg(idx) != cfg)
die("write pmpcfg failure!");
}

/* helper function used to read pmpaddr[idx] */
static uintptr_t read_pmpaddr(int idx)
{
switch (idx) {
case 0:
return read_csr(pmpaddr0);
case 1:
return read_csr(pmpaddr1);
case 2:
return read_csr(pmpaddr2);
case 3:
return read_csr(pmpaddr3);
case 4:
return read_csr(pmpaddr4);
case 5:
return read_csr(pmpaddr5);
case 6:
return read_csr(pmpaddr6);
case 7:
return read_csr(pmpaddr7);
case 8:
return read_csr(pmpaddr8);
case 9:
return read_csr(pmpaddr9);
case 10:
return read_csr(pmpaddr10);
case 11:
return read_csr(pmpaddr11);
case 12:
return read_csr(pmpaddr12);
case 13:
return read_csr(pmpaddr13);
case 14:
return read_csr(pmpaddr14);
case 15:
return read_csr(pmpaddr15);
}
return -1;
}

/* helper function used to write pmpaddr[idx] */
static void write_pmpaddr(int idx, uintptr_t val)
{
switch (idx) {
case 0:
write_csr(pmpaddr0, val);
break;
case 1:
write_csr(pmpaddr1, val);
break;
case 2:
write_csr(pmpaddr2, val);
break;
case 3:
write_csr(pmpaddr3, val);
break;
case 4:
write_csr(pmpaddr4, val);
break;
case 5:
write_csr(pmpaddr5, val);
break;
case 6:
write_csr(pmpaddr6, val);
break;
case 7:
write_csr(pmpaddr7, val);
break;
case 8:
write_csr(pmpaddr8, val);
break;
case 9:
write_csr(pmpaddr9, val);
break;
case 10:
write_csr(pmpaddr10, val);
break;
case 11:
write_csr(pmpaddr11, val);
break;
case 12:
write_csr(pmpaddr12, val);
break;
case 13:
write_csr(pmpaddr13, val);
break;
case 14:
write_csr(pmpaddr14, val);
break;
case 15:
write_csr(pmpaddr15, val);
break;
}
if (read_pmpaddr(idx) != val)
die("write pmpaddr failure");
}

/* Generate a PMP configuration of type NA4/NAPOT */
static pmpcfg_t generate_pmp_napot(
uintptr_t base, uintptr_t size, uintptr_t flags)
{
pmpcfg_t p;
flags = flags & (PMP_R | PMP_W | PMP_X | PMP_L);
p.cfg = flags | (size > GRANULE ? PMP_NAPOT : PMP_NA4);
p.previous_address = 0;
p.address = (base + (size / 2 - 1)) >> PMP_SHIFT;
return p;
}

/* Generate a PMP configuration of type TOR */
static pmpcfg_t generate_pmp_range(
uintptr_t base, uintptr_t size, uintptr_t flags)
{
pmpcfg_t p;
flags = flags & (PMP_R | PMP_W | PMP_X | PMP_L);
p.cfg = flags | PMP_TOR;
p.previous_address = base >> PMP_SHIFT;
p.address = (base + size) >> PMP_SHIFT;
return p;
}

/* Generate a PMP configuration */
static pmpcfg_t generate_pmp(uintptr_t base, uintptr_t size, uintptr_t flags)
{
if (IS_POWER_OF_2(size) && (size >= 4) && ((base & (size - 1)) == 0))
return generate_pmp_napot(base, size, flags);
else
return generate_pmp_range(base, size, flags);
}

/*
* find empty PMP entry by type
* TOR type configuration requires two consecutive PMP entries,
* others requires one.
*/
static int find_empty_pmp_entry(int is_range)
{
int free_entries = 0;
for (int i = 0; i < pmp_entries_num(); i++) {
if (pmp_entry_used_mask & (1 << i))
free_entries = 0;
else
free_entries++;
if (is_range && (free_entries == 2))
return i;
if (!is_range && (free_entries == 1))
return i;
}
die("Too many PMP configurations, no free entries can be used!");
return -1;
}

/*
* mark PMP entry has be used
* this function need be used with find_entry_pmp_entry
*
* n = find_empty_pmp_entry(is_range)
* ... // PMP set operate
* mask_pmp_entry_used(n);
*/
static void mask_pmp_entry_used(int idx)
{
pmp_entry_used_mask |= 1 << idx;
}

/* reset PMP setting */
void reset_pmp(void)
{
for (int i = 0; i < pmp_entries_num(); i++) {
if (read_pmpcfg(i) & PMP_L)
die("Some PMP configurations are locked "
"and cannot be reset!");
write_pmpcfg(i, 0);
write_pmpaddr(i, 0);
}
}

/* set up PMP record */
void setup_pmp(uintptr_t base, uintptr_t size, uintptr_t flags)
{
pmpcfg_t p;
int is_range, n;

p = generate_pmp(base, size, flags);
is_range = ((p.cfg & PMP_A) == PMP_TOR);

n = find_empty_pmp_entry(is_range);

write_pmpaddr(n, p.address);
if (is_range)
write_pmpaddr(n - 1, p.previous_address);
write_pmpcfg(n, p.cfg);

mask_pmp_entry_used(n);
if (is_range)
mask_pmp_entry_used(n - 1);
}
5 changes: 4 additions & 1 deletion src/arch/riscv/ramstage.S
Expand Up @@ -35,6 +35,9 @@ _start:
csrr a0, mhartid
call hls_init

li a0, CONFIG_RISCV_WORKING_HARTID
call smp_pause

# initialize entry of interrupt/exception
la t0, trap_entry
csrw mtvec, t0
Expand All @@ -43,7 +46,7 @@ _start:
csrwi mip, 0

call exit_car
# set up the mstatus register for VM
# set up the mstatus register
call mstatus_init
tail main

Expand Down
121 changes: 121 additions & 0 deletions src/arch/riscv/sbi.c
@@ -0,0 +1,121 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2018 HardenedLinux
*
* 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; version 2 of the License.
*
* 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 <mcall.h>
#include <stdint.h>
#include <commonlib/compiler.h>
#include <arch/exception.h>
#include <sbi.h>
#include <vm.h>
#include <console/uart.h>
#include <console/console.h>
#include <commonlib/helpers.h>

static uintptr_t send_ipi(uintptr_t *pmask, intptr_t type)
{
uintptr_t mask = mprv_read_uintptr_t(pmask);
for (int i = 0; mask; i++) {
if (mask & 1) {
OTHER_HLS(i)->ipi_pending |= type;
/* send soft interrupt to target hart */
set_msip(i, 1);
}
mask = mask >> 1;
}
return 0;
}

static uintptr_t sbi_set_timer(uint64_t when)
{
clear_csr(mip, MIP_STIP);
set_csr(mie, MIP_MTIP);
*(HLS()->timecmp) = when;
return 0;
}

#if IS_ENABLED(CONFIG_CONSOLE_SERIAL)
static uintptr_t sbi_console_putchar(uint8_t ch)
{
uart_tx_byte(CONFIG_UART_FOR_CONSOLE, ch);
return 0;
}

static uintptr_t sbi_console_getchar(void)
{
return uart_rx_byte(CONFIG_UART_FOR_CONSOLE);
}
#endif

static uintptr_t sbi_clear_ipi(void)
{
clear_csr(mip, MIP_SSIP);
return 0;
}


/*
* sbi is triggered by the s-mode ecall
* parameter : register a0 a1 a2
* function : register a7
* return : register a0
*/
void handle_sbi(trapframe *tf)
{
uintptr_t ret = 0;
uintptr_t arg0 = tf->gpr[10];
__unused uintptr_t arg1 = tf->gpr[11];
uintptr_t which = tf->gpr[17];

switch (which) {
case SBI_SET_TIMER:
#if __riscv_xlen == 32
ret = sbi_set_timer(arg0 + ((uint64_t)arg1 << 32));
#else
ret = sbi_set_timer(arg0);
#endif
break;
#if IS_ENABLED(CONFIG_CONSOLE_SERIAL)
case SBI_CONSOLE_PUTCHAR:
ret = sbi_console_putchar(arg0);
break;
case SBI_CONSOLE_GETCHAR:
ret = sbi_console_getchar();
break;
#endif
case SBI_CLEAR_IPI:
ret = sbi_clear_ipi();
break;
case SBI_SEND_IPI:
ret = send_ipi((uintptr_t *)arg0, IPI_SOFT);
break;
case SBI_REMOTE_FENCE_I:
ret = send_ipi((uintptr_t *)arg0, IPI_FENCE_I);
break;
case SBI_REMOTE_SFENCE_VMA:
ret = send_ipi((uintptr_t *)arg0, IPI_SFENCE_VMA);
break;
case SBI_REMOTE_SFENCE_VMA_ASID:
ret = send_ipi((uintptr_t *)arg0, IPI_SFENCE_VMA_ASID);
break;
case SBI_SHUTDOWN:
ret = send_ipi((uintptr_t *)arg0, IPI_SHUTDOWN);
break;
default:
ret = -38;
break;
}
tf->gpr[10] = ret;
write_csr(mepc, read_csr(mepc) + 4);
}
85 changes: 85 additions & 0 deletions src/arch/riscv/smp.c
@@ -0,0 +1,85 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2018 HardenedLinux.
*
* 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; version 2 of the License.
*
* 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 <stddef.h>
#include <arch/encoding.h>
#include <arch/smp/smp.h>
#include <arch/smp/spinlock.h>
#include <mcall.h>
#include <commonlib/compiler.h>
#include <console/console.h>

void smp_pause(int working_hartid)
{
#define SYNCA (OTHER_HLS(working_hartid)->entry.sync_a)
#define SYNCB (OTHER_HLS(working_hartid)->entry.sync_b)

int hartid = read_csr(mhartid);

if (hartid != working_hartid) {
/* waiting for work hart */
do {
barrier();
} while (SYNCA != 0x01234567);

clear_csr(mstatus, MSTATUS_MIE);
write_csr(mie, MIP_MSIP);

/* count how many cores enter the halt */
__sync_fetch_and_add(&SYNCB, 1);

do {
barrier();
__asm__ volatile ("wfi");
} while ((read_csr(mip) & MIP_MSIP) == 0);
set_msip(hartid, 0);
HLS()->entry.fn(HLS()->entry.arg);
} else {
/* Initialize the counter and
* mark the work hart into smp_pause */
SYNCB = 0;
SYNCA = 0x01234567;

/* waiting for other Hart to enter the halt */
do {
barrier();
} while (SYNCB + 1 < CONFIG_RISCV_HART_NUM);

/* initialize for the next call */
SYNCA = 0;
SYNCB = 0;
}
#undef SYNCA
#undef SYNCB
}

void smp_resume(void (*fn)(void *), void *arg)
{
int hartid = read_csr(mhartid);

if (fn == NULL)
die("must pass a non-null function pointer\n");

for (int i = 0; i < CONFIG_RISCV_HART_NUM; i++) {
OTHER_HLS(i)->entry.fn = fn;
OTHER_HLS(i)->entry.arg = arg;
}

for (int i = 0; i < CONFIG_RISCV_HART_NUM; i++)
if (i != hartid)
set_msip(i, 1);

HLS()->entry.fn(HLS()->entry.arg);
}
3 changes: 3 additions & 0 deletions src/arch/riscv/stages.c
Expand Up @@ -27,10 +27,13 @@
#include <arch/boot.h>
#include <arch/encoding.h>
#include <arch/stages.h>
#include <arch/smp/smp.h>
#include <rules.h>

void stage_entry(void)
{
smp_pause(CONFIG_RISCV_WORKING_HARTID);

/*
* Save the FDT pointer before entering ramstage, because mscratch
* might be overwritten in the trap handler, and there is code in
Expand Down
81 changes: 28 additions & 53 deletions src/arch/riscv/trap_handler.c
Expand Up @@ -19,9 +19,8 @@
#include <console/console.h>
#include <string.h>
#include <vm.h>

static uint64_t *time;
static uint64_t *timecmp;
#include <mcall.h>
#include <sbi.h>

static const char *const exception_names[] = {
"Instruction address misaligned",
Expand Down Expand Up @@ -78,62 +77,36 @@ static void print_trap_information(const trapframe *tf)
printk(BIOS_DEBUG, "Stored sp: %p\n", (void*) tf->gpr[2]);
}

static void gettimer(void)
{
/*
* FIXME: This hard-coded value (currently) works on spike, but we
* should really read it from the device tree.
*/
uintptr_t clint = 0x02000000;

time = (void *)(clint + 0xbff8);
timecmp = (void *)(clint + 0x4000);

if (!time)
die("Got timer interrupt but found no timer.");
if (!timecmp)
die("Got timer interrupt but found no timecmp.");
}

static void interrupt_handler(trapframe *tf)
{
uint64_t cause = tf->cause & ~0x8000000000000000ULL;
uint32_t msip, ssie;

switch (cause) {
case IRQ_M_TIMER:
// The only way to reset the timer interrupt is to
// write mtimecmp. But we also have to ensure the
// comparison fails, for a long time, to let
// supervisor interrupt handler compute a new value
// and set it. Finally, it fires if mtimecmp is <=
// mtime, not =, so setting mtimecmp to 0 won't work
// to clear the interrupt and disable a new one. We
// have to set the mtimecmp far into the future.
// Akward!
//
// Further, maybe the platform doesn't have the
// hardware or the payload never uses it. We hold off
// querying some things until we are sure we need
// them. What to do if we can not find them? There are
// no good options.

// This hart may have disabled timer interrupts. If
// so, just return. Kernels should only enable timer
// interrupts on one hart, and that should be hart 0
// at present, as we only search for
// "core{0{0{timecmp" above.
ssie = read_csr(sie);
if (!(ssie & SIP_STIP))
break;
/*
* Set interrupt pending for supervisor mode and disable timer
* interrupt in machine mode.
* To receive another timer interrupt just set timecmp and
* enable machine mode timer interrupt again.
*/

if (!timecmp)
gettimer();
//printk(BIOS_SPEW, "timer interrupt\n");
*timecmp = (uint64_t) -1;
msip = read_csr(mip);
msip |= SIP_STIP;
write_csr(mip, msip);
clear_csr(mie, MIP_MTIP);
set_csr(mip, MIP_STIP);

break;
case IRQ_M_SOFT:
if (HLS()->ipi_pending & IPI_SOFT) {
set_csr(mip, MIP_SSIP);
} else if (HLS()->ipi_pending & IPI_FENCE_I) {
asm volatile("fence.i");
} else if (HLS()->ipi_pending & IPI_SFENCE_VMA) {
asm volatile("sfence.vma");
} else if (HLS()->ipi_pending & IPI_SFENCE_VMA_ASID) {
asm volatile("sfence.vma");
} else if (HLS()->ipi_pending & IPI_SHUTDOWN) {
while (HLS()->ipi_pending & IPI_SHUTDOWN)
asm volatile("wfi");
}
break;
default:
printk(BIOS_EMERG, "======================================\n");
Expand All @@ -160,11 +133,13 @@ void trap_handler(trapframe *tf)
case CAUSE_LOAD_ACCESS:
case CAUSE_STORE_ACCESS:
case CAUSE_USER_ECALL:
case CAUSE_SUPERVISOR_ECALL:
case CAUSE_HYPERVISOR_ECALL:
case CAUSE_MACHINE_ECALL:
print_trap_information(tf);
break;
case CAUSE_SUPERVISOR_ECALL:
handle_sbi(tf);
return;
case CAUSE_MISALIGNED_LOAD:
case CAUSE_MISALIGNED_STORE:
print_trap_information(tf);
Expand Down
26 changes: 24 additions & 2 deletions src/arch/x86/Kconfig
Expand Up @@ -35,6 +35,10 @@ config ARCH_ROMSTAGE_X86_32
bool
default n

config ARCH_POSTCAR_X86_32
bool
default ARCH_ROMSTAGE_X86_32 && POSTCAR_STAGE

config ARCH_RAMSTAGE_X86_32
bool
default n
Expand All @@ -55,6 +59,10 @@ config ARCH_ROMSTAGE_X86_64
bool
default n

config ARCH_POSTCAR_X86_64
bool
default ARCH_ROMSTAGE_X86_64 && POSTCAR_STAGE

config ARCH_RAMSTAGE_X86_64
bool
default n
Expand All @@ -80,13 +88,20 @@ config SIPI_VECTOR_IN_ROM
default n
depends on ARCH_X86

# Set the rambase for systems that still need it, only 5 chipsets as of
# Sep 2018. This value was 0x100000, chosen to match the entry point
# of Linux 2.2 in 1999. The new value, 14 MiB, makes a lot more sense
# for as long as we need it; with luck, that won't be much longer.
# In the long term, both RAMBASE and RAMTOP should be removed.
# This value leaves more than 1 MiB which is required for fam10
# and broadwell_de.
config RAMBASE
hex
default 0x100000
default 0xe00000

config RAMTOP
hex
default 0x200000
default 0x1000000
depends on ARCH_X86

# Traditionally BIOS region on SPI flash boot media was memory mapped right below
Expand Down Expand Up @@ -308,3 +323,10 @@ config IDT_IN_EVERY_STAGE
bool
default n
depends on ARCH_X86

config HAVE_CF9_RESET
bool

config HAVE_CF9_RESET_PREPARE
bool
depends on HAVE_CF9_RESET
12 changes: 11 additions & 1 deletion src/arch/x86/Makefile.inc
Expand Up @@ -16,6 +16,10 @@
## GNU General Public License for more details.
##

ifeq ($(CONFIG_POSTCAR_STAGE),y)
$(eval $(call init_standard_toolchain,postcar))
endif

################################################################################
# i386 specific tools
NVRAMTOOL:=$(objutil)/nvramtool/nvramtool
Expand Down Expand Up @@ -43,6 +47,12 @@ cbfs-files-$(CONFIG_VGA_BIOS) += pci$(stripped_vgabios_id).rom
pci$(stripped_vgabios_id).rom-file := $(call strip_quotes,$(CONFIG_VGA_BIOS_FILE))
pci$(stripped_vgabios_id).rom-type := optionrom

verstage-$(CONFIG_HAVE_CF9_RESET) += cf9_reset.c
bootblock-$(CONFIG_HAVE_CF9_RESET) += cf9_reset.c
romstage-$(CONFIG_HAVE_CF9_RESET) += cf9_reset.c
ramstage-$(CONFIG_HAVE_CF9_RESET) += cf9_reset.c
postcar-$(CONFIG_HAVE_CF9_RESET) += cf9_reset.c

###############################################################################
# common support for early assembly includes
###############################################################################
Expand Down Expand Up @@ -224,7 +234,7 @@ romstage-$(CONFIG_X86_TOP4G_BOOTMEDIA_MAP) += mmap_boot.c
romstage-y += postcar_loader.c
romstage-$(CONFIG_COLLECT_TIMESTAMPS_TSC) += timestamp.c

romstage-srcs += $(src)/mainboard/$(MAINBOARDDIR)/romstage.c
romstage-srcs += $(wildcard $(src)/mainboard/$(MAINBOARDDIR)/romstage.c)
romstage-libs ?=

$(eval $(call early_x86_assembly_entry_rule,romstage))
Expand Down
72 changes: 60 additions & 12 deletions src/arch/x86/acpi.c
Expand Up @@ -44,7 +44,6 @@
#include <arch/acpigen.h>
#include <device/pci.h>
#include <cbmem.h>
#include <compiler.h>
#include <cpu/x86/lapic_def.h>
#include <cpu/cpu.h>
#include <cbfs.h>
Expand Down Expand Up @@ -309,6 +308,33 @@ static void acpi_create_tcpa(acpi_tcpa_t *tcpa)
header->checksum = acpi_checksum((void *)tcpa, header->length);
}

static void acpi_create_tpm2(acpi_tpm2_t *tpm2)
{
acpi_header_t *header = &(tpm2->header);

memset((void *)tpm2, 0, sizeof(acpi_tpm2_t));

/* Fill out header fields. */
memcpy(header->signature, "TPM2", 4);
memcpy(header->oem_id, OEM_ID, 6);
memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
memcpy(header->asl_compiler_id, ASLC, 4);

header->length = sizeof(acpi_tpm2_t);
header->revision = get_acpi_table_revision(TPM2);

/* Hard to detect for coreboot. Just set it to 0 */
tpm2->platform_class = 0;
/* Must be set to 0 for TIS interface support */
tpm2->control_area = 0;
/* coreboot only supports the TIS interface driver. */
tpm2->start_method = 6;
memset(tpm2->msp, 0, sizeof(tpm2->msp));

/* Calculate checksum. */
header->checksum = acpi_checksum((void *)tpm2, header->length);
}

static void acpi_ssdt_write_cbtable(void)
{
const struct cbmem_entry *cbtable;
Expand Down Expand Up @@ -1031,6 +1057,7 @@ unsigned long write_acpi_tables(unsigned long start)
acpi_header_t *dsdt_file, *dsdt;
acpi_mcfg_t *mcfg;
acpi_tcpa_t *tcpa;
acpi_tpm2_t *tpm2;
acpi_madt_t *madt;
struct device *dev;
unsigned long fw;
Expand Down Expand Up @@ -1164,13 +1191,26 @@ unsigned long write_acpi_tables(unsigned long start)
acpi_add_table(rsdp, mcfg);
}

printk(BIOS_DEBUG, "ACPI: * TCPA\n");
tcpa = (acpi_tcpa_t *) current;
acpi_create_tcpa(tcpa);
if (tcpa->header.length >= sizeof(acpi_tcpa_t)) {
current += tcpa->header.length;
current = acpi_align_current(current);
acpi_add_table(rsdp, tcpa);
if (IS_ENABLED(CONFIG_TPM1)) {
printk(BIOS_DEBUG, "ACPI: * TCPA\n");
tcpa = (acpi_tcpa_t *) current;
acpi_create_tcpa(tcpa);
if (tcpa->header.length >= sizeof(acpi_tcpa_t)) {
current += tcpa->header.length;
current = acpi_align_current(current);
acpi_add_table(rsdp, tcpa);
}
}

if (IS_ENABLED(CONFIG_TPM2)) {
printk(BIOS_DEBUG, "ACPI: * TPM2\n");
tpm2 = (acpi_tpm2_t *) current;
acpi_create_tpm2(tpm2);
if (tpm2->header.length >= sizeof(acpi_tpm2_t)) {
current += tpm2->header.length;
current = acpi_align_current(current);
acpi_add_table(rsdp, tpm2);
}
}

printk(BIOS_DEBUG, "ACPI: * MADT\n");
Expand Down Expand Up @@ -1238,8 +1278,11 @@ void *acpi_find_wakeup_vector(void)
break;
}

if (rsdp == NULL)
if (rsdp == NULL) {
printk(BIOS_ALERT,
"No RSDP found, wake up from S3 not possible.\n");
return NULL;
}

printk(BIOS_DEBUG, "RSDP found at %p\n", rsdp);
rsdt = (acpi_rsdt_t *)(uintptr_t)rsdp->rsdt_address;
Expand All @@ -1254,15 +1297,18 @@ void *acpi_find_wakeup_vector(void)
fadt = NULL;
}

if (fadt == NULL)
if (fadt == NULL) {
printk(BIOS_ALERT,
"No FADT found, wake up from S3 not possible.\n");
return NULL;
}

printk(BIOS_DEBUG, "FADT found at %p\n", fadt);
facs = (acpi_facs_t *)(uintptr_t)fadt->firmware_ctrl;

if (facs == NULL) {
printk(BIOS_DEBUG, "No FACS found, wake up from S3 not "
"possible.\n");
printk(BIOS_ALERT,
"No FACS found, wake up from S3 not possible.\n");
return NULL;
}

Expand All @@ -1289,6 +1335,8 @@ int get_acpi_table_revision(enum acpi_tables table)
return 1;
case TCPA:
return 2;
case TPM2:
return 4;
case SSDT: /* ACPI 1.0/2.0: ?, ACPI 3.0/4.0: 2 */
return 2;
case SRAT: /* ACPI 1.0: N/A, 2.0: 1, 3.0: 2, 4.0: 3 */
Expand Down
1 change: 0 additions & 1 deletion src/arch/x86/acpi_s3.c
Expand Up @@ -17,7 +17,6 @@
#include <string.h>
#include <arch/acpi.h>
#include <cbmem.h>
#include <compiler.h>
#include <cpu/cpu.h>
#include <fallback.h>
#include <timestamp.h>
Expand Down
3 changes: 1 addition & 2 deletions src/arch/x86/acpigen.c
Expand Up @@ -28,7 +28,6 @@
#include <lib.h>
#include <string.h>
#include <arch/acpigen.h>
#include <compiler.h>
#include <console/console.h>
#include <device/device.h>

Expand Down Expand Up @@ -454,7 +453,7 @@ static void acpigen_write_field_name(const char *name, uint32_t size)
* FIELDLIST_OFFSET(0x84),
* FIELDLIST_NAMESTR("PMCS", 2),
* };
* acpigen_write_field("UART", l ,ARRAY_SIZE(l), FIELD_ANYACC | FIELD_NOLOCK |
* acpigen_write_field("UART", l, ARRAY_SIZE(l), FIELD_ANYACC | FIELD_NOLOCK |
* FIELD_PRESERVE);
* Output:
* Field (UART, AnyAcc, NoLock, Preserve)
Expand Down
201 changes: 0 additions & 201 deletions src/arch/x86/boot.c
Expand Up @@ -19,193 +19,6 @@
#include <string.h>
#include <symbols.h>

/* When the ramstage is relocatable the elf loading ensures an elf image cannot
* be loaded over the ramstage code. */
static void jmp_payload_no_bounce_buffer(void *entry)
{
/* Jump to kernel */
__asm__ __volatile__(
" cld\n\t"
/* Now jump to the loaded image */
" call *%0\n\t"

/* The loaded image returned? */
" cli\n\t"
" cld\n\t"

::
"r" (entry)
);
}

static void jmp_payload(void *entry, unsigned long buffer, unsigned long size)
{
unsigned long lb_start, lb_size;

lb_start = (unsigned long)&_program;
lb_size = _program_size;

printk(BIOS_SPEW, "entry = 0x%08lx\n", (unsigned long)entry);
printk(BIOS_SPEW, "lb_start = 0x%08lx\n", lb_start);
printk(BIOS_SPEW, "lb_size = 0x%08lx\n", lb_size);
printk(BIOS_SPEW, "buffer = 0x%08lx\n", buffer);

/* Jump to kernel */
__asm__ __volatile__(
" cld\n\t"
#ifdef __x86_64__
/* switch back to 32-bit mode */
" push %4\n\t"
" push %3\n\t"
" push %2\n\t"
" push %1\n\t"
" push %0\n\t"

/* use iret to switch to 32-bit code segment */
" xor %%rax,%%rax\n\t"
" mov %%ss, %%ax\n\t"
" push %%rax\n\t"
" mov %%rsp, %%rax\n\t"
" add $8, %%rax\n\t"
" push %%rax\n\t"
" pushfq\n\t"
" push $0x10\n\t"
" lea 3(%%rip), %%rax\n\t"
" push %%rax\n\t"
" iretq\n\t"
".code32\n\t"
/* disable paging */
" mov %%cr0, %%eax\n\t"
" btc $31, %%eax\n\t"
" mov %%eax, %%cr0\n\t"
/* disable long mode */
" mov $0xC0000080, %%ecx\n\t"
" rdmsr\n\t"
" btc $8, %%eax\n\t"
" wrmsr\n\t"

" pop %%eax\n\t"
" add $4, %%esp\n\t"
" pop %%ebx\n\t"
" add $4, %%esp\n\t"
" pop %%ecx\n\t"

" add $4, %%esp\n\t"
" pop %%edx\n\t"
" add $4, %%esp\n\t"
" pop %%esi\n\t"
" add $4, %%esp\n\t"
#endif

/* Save the callee save registers... */
" pushl %%esi\n\t"
" pushl %%edi\n\t"
" pushl %%ebx\n\t"
/* Save the parameters I was passed */
#ifdef __x86_64__
" pushl $0\n\t" /* 20 adjust */
" pushl %%eax\n\t" /* 16 lb_start */
" pushl %%ebx\n\t" /* 12 buffer */
" pushl %%ecx\n\t" /* 8 lb_size */
" pushl %%edx\n\t" /* 4 entry */
" pushl %%esi\n\t" /* 0 elf_boot_notes */
#else
" pushl $0\n\t" /* 20 adjust */
" pushl %0\n\t" /* 16 lb_start */
" pushl %1\n\t" /* 12 buffer */
" pushl %2\n\t" /* 8 lb_size */
" pushl %3\n\t" /* 4 entry */
" pushl %4\n\t" /* 0 elf_boot_notes */

#endif
/* Compute the adjustment */
" xorl %%eax, %%eax\n\t"
" subl 16(%%esp), %%eax\n\t"
" addl 12(%%esp), %%eax\n\t"
" addl 8(%%esp), %%eax\n\t"
" movl %%eax, 20(%%esp)\n\t"
/* Place a copy of coreboot in its new location */
/* Move ``longs'' the coreboot size is 4 byte aligned */
" movl 12(%%esp), %%edi\n\t"
" addl 8(%%esp), %%edi\n\t"
" movl 16(%%esp), %%esi\n\t"
" movl 8(%%esp), %%ecx\n\n"
" shrl $2, %%ecx\n\t"
" rep movsl\n\t"

/* Adjust the stack pointer to point into the new coreboot
* image
*/
" addl 20(%%esp), %%esp\n\t"
/* Adjust the instruction pointer to point into the new coreboot
* image
*/
" movl $1f, %%eax\n\t"
" addl 20(%%esp), %%eax\n\t"
" jmp *%%eax\n\t"
"1:\n\t"

/* Copy the coreboot bounce buffer over coreboot */
/* Move ``longs'' the coreboot size is 4 byte aligned */
" movl 16(%%esp), %%edi\n\t"
" movl 12(%%esp), %%esi\n\t"
" movl 8(%%esp), %%ecx\n\t"
" shrl $2, %%ecx\n\t"
" rep movsl\n\t"

/* Now jump to the loaded image */
" movl %5, %%eax\n\t"
" movl 0(%%esp), %%ebx\n\t"
" call *4(%%esp)\n\t"

/* The loaded image returned? */
" cli\n\t"
" cld\n\t"

/* Copy the saved copy of coreboot where coreboot runs */
/* Move ``longs'' the coreboot size is 4 byte aligned */
" movl 16(%%esp), %%edi\n\t"
" movl 12(%%esp), %%esi\n\t"
" addl 8(%%esp), %%esi\n\t"
" movl 8(%%esp), %%ecx\n\t"
" shrl $2, %%ecx\n\t"
" rep movsl\n\t"

/* Adjust the stack pointer to point into the old coreboot
* image
*/
" subl 20(%%esp), %%esp\n\t"

/* Adjust the instruction pointer to point into the old coreboot
* image
*/
" movl $1f, %%eax\n\t"
" subl 20(%%esp), %%eax\n\t"
" jmp *%%eax\n\t"
"1:\n\t"

/* Drop the parameters I was passed */
" addl $24, %%esp\n\t"

/* Restore the callee save registers */
" popl %%ebx\n\t"
" popl %%edi\n\t"
" popl %%esi\n\t"
#ifdef __x86_64__
".code64\n\t"
#endif
::
"ri" (lb_start), "ri" (buffer), "ri" (lb_size),
"ri" (entry),
"ri"(0), "ri" (0)
);
}

int arch_supports_bounce_buffer(void)
{
return !IS_ENABLED(CONFIG_RELOCATABLE_RAMSTAGE);
}

int payload_arch_usable_ram_quirk(uint64_t start, uint64_t size)
{
if (start < 1 * MiB && (start + size) <= 1 * MiB) {
Expand All @@ -217,22 +30,8 @@ int payload_arch_usable_ram_quirk(uint64_t start, uint64_t size)
return 0;
}

static void try_payload(struct prog *prog)
{
if (prog_type(prog) == PROG_PAYLOAD) {
if (IS_ENABLED(CONFIG_RELOCATABLE_RAMSTAGE))
jmp_payload_no_bounce_buffer(prog_entry(prog));
else
jmp_payload(prog_entry(prog),
(uintptr_t)prog_start(prog),
prog_size(prog));
}
}

void arch_prog_run(struct prog *prog)
{
if (ENV_RAMSTAGE)
try_payload(prog);
__asm__ volatile (
#ifdef __x86_64__
"jmp *%%rdi\n"
Expand Down
15 changes: 15 additions & 0 deletions src/arch/x86/car.ld
Expand Up @@ -71,7 +71,17 @@
* cbmem console. This is useful for clearing this area on a per-stage
* basis when more than one stage uses cache-as-ram for CAR_GLOBALs. */
_car_global_start = .;
#if IS_ENABLED(CONFIG_NO_CAR_GLOBAL_MIGRATION)
/* Allow global unitialized variables when CAR_GLOBALs are not used. */
*(.bss)
*(.bss.*)
*(.sbss)
*(.sbss.*)
#else
/* .car.global_data objects only around when
* !CONFIG_NO_CAR_GLOBAL_MIGRATION is employed. */
*(.car.global_data);
#endif
. = ALIGN(ARCH_POINTER_ALIGN_SIZE);
_car_global_end = .;
_car_relocatable_data_end = .;
Expand All @@ -88,10 +98,15 @@
.illegal_globals . : {
*(EXCLUDE_FILE ("*/libagesa.*.a:" "*/romstage*/buildOpts.o" "*/romstage*/agesawrapper.o" "*/vendorcode/amd/agesa/*" "*/vendorcode/amd/cimx/*") .data)
*(EXCLUDE_FILE ("*/libagesa.*.a:" "*/romstage*/buildOpts.o" "*/romstage*/agesawrapper.o" "*/vendorcode/amd/agesa/*" "*/vendorcode/amd/cimx/*") .data.*)
#if !IS_ENABLED(CONFIG_NO_CAR_GLOBAL_MIGRATION)
*(.bss)
*(.bss.*)
*(.sbss)
*(.sbss.*)
#else
/* In case something sneaks through when it shouldn't. */
*(.car.global_data);
#endif
}

_bogus = ASSERT((CONFIG_DCACHE_RAM_SIZE == 0) || (SIZEOF(.car.data) <= CONFIG_DCACHE_RAM_SIZE), "Cache as RAM area is too full");
Expand Down
1 change: 0 additions & 1 deletion src/arch/x86/cbmem.c
Expand Up @@ -13,7 +13,6 @@

#include <stdlib.h>
#include <cbmem.h>
#include <compiler.h>
#include <arch/acpi.h>

#if IS_ENABLED(CONFIG_LATE_CBMEM_INIT)
Expand Down
65 changes: 65 additions & 0 deletions src/arch/x86/cf9_reset.c
@@ -0,0 +1,65 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2017 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; version 2 of the License.
*
* 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 <arch/io.h>
#include <arch/cache.h>
#include <cf9_reset.h>
#include <console/console.h>
#include <halt.h>
#include <reset.h>

/*
* A system reset in terms of the CF9 register asserts the INIT#
* signal to reset the CPU along the PLTRST# signal to reset other
* board components. It is usually the hardest reset type that
* does not power cycle the board. Thus, it could be called a
* "warm reset".
*/
void do_system_reset(void)
{
dcache_clean_all();
outb(SYS_RST, RST_CNT);
outb(RST_CPU | SYS_RST, RST_CNT);
}

/*
* A full reset in terms of the CF9 register triggers a power cycle
* (i.e. S0 -> S5 -> S0 transition). Thus, it could be called a
* "cold reset".
* Note: Not all x86 implementations comply with this defitinion,
* some may require additional configuration to power cycle.
*/
void do_full_reset(void)
{
dcache_clean_all();
outb(FULL_RST | SYS_RST, RST_CNT);
outb(FULL_RST | RST_CPU | SYS_RST, RST_CNT);
}

void system_reset(void)
{
printk(BIOS_INFO, "%s() called!\n", __func__);
cf9_reset_prepare();
do_system_reset();
halt();
}

void full_reset(void)
{
printk(BIOS_INFO, "%s() called!\n", __func__);
cf9_reset_prepare();
do_full_reset();
halt();
}
5 changes: 2 additions & 3 deletions src/arch/x86/exception.c
Expand Up @@ -15,7 +15,6 @@
#include <arch/early_variables.h>
#include <arch/exception.h>
#include <commonlib/helpers.h>
#include <compiler.h>
#include <console/console.h>
#include <console/streams.h>
#include <cpu/x86/cr.h>
Expand Down Expand Up @@ -555,8 +554,8 @@ struct intr_gate {

/* Even though the vecX symbols are interrupt entry points just treat them
like data to more easily get the pointer values in C. Because IDT entries
format splits the offset field up one can't use the linker to resolve
parts of a relecation on x86 ABI an array of pointers is used to gather
format splits the offset field up, one can't use the linker to resolve
parts of a relocation on x86 ABI. An array of pointers is used to gather
the symbols. The IDT is initialized at runtime when exception_init() is
called. */
extern u8 vec0[], vec1[], vec2[], vec3[], vec4[], vec5[], vec6[], vec7[];
Expand Down
1 change: 0 additions & 1 deletion src/arch/x86/gdt.c
Expand Up @@ -15,7 +15,6 @@

#include <types.h>
#include <string.h>
#include <compiler.h>
#include <cbmem.h>
#include <console/console.h>
#include <cpu/x86/gdt.h>
Expand Down
10 changes: 9 additions & 1 deletion src/arch/x86/include/arch/acpi.h
Expand Up @@ -54,7 +54,6 @@

#if !defined(__ASSEMBLER__) && !defined(__ACPI__) && !defined(__ROMCC__)
#include <stdint.h>
#include <compiler.h>
#include <rules.h>
#include <commonlib/helpers.h>
#include <device/device.h>
Expand Down Expand Up @@ -192,6 +191,15 @@ typedef struct acpi_tcpa {
u64 lasa;
} __packed acpi_tcpa_t;

typedef struct acpi_tpm2 {
struct acpi_table_header header;
u16 platform_class;
u8 reserved[2];
u64 control_area;
u32 start_method;
u8 msp[12];
} __packed acpi_tpm2_t;

typedef struct acpi_mcfg_mmconfig {
u32 base_address;
u32 base_reserved;
Expand Down
65 changes: 38 additions & 27 deletions src/arch/x86/include/arch/acpi_device.h
Expand Up @@ -101,33 +101,44 @@ struct acpi_irq {
enum acpi_irq_wake wake;
};

#define ACPI_IRQ_EDGE_LOW(x) { \
.pin = (x), \
.mode = ACPI_IRQ_EDGE_TRIGGERED, \
.polarity = ACPI_IRQ_ACTIVE_LOW, \
.shared = ACPI_IRQ_EXCLUSIVE, \
.wake = ACPI_IRQ_NO_WAKE }

#define ACPI_IRQ_EDGE_HIGH(x) { \
.pin = (x), \
.mode = ACPI_IRQ_EDGE_TRIGGERED, \
.polarity = ACPI_IRQ_ACTIVE_HIGH, \
.shared = ACPI_IRQ_EXCLUSIVE, \
.wake = ACPI_IRQ_NO_WAKE }

#define ACPI_IRQ_LEVEL_LOW(x) { \
.pin = (x), \
.mode = ACPI_IRQ_LEVEL_TRIGGERED, \
.polarity = ACPI_IRQ_ACTIVE_LOW, \
.shared = ACPI_IRQ_SHARED, \
.wake = ACPI_IRQ_NO_WAKE }

#define ACPI_IRQ_LEVEL_HIGH(x) { \
.pin = (x), \
.mode = ACPI_IRQ_LEVEL_TRIGGERED, \
.polarity = ACPI_IRQ_ACTIVE_HIGH, \
.shared = ACPI_IRQ_SHARED, \
.wake = ACPI_IRQ_NO_WAKE }
#define ACPI_IRQ_CFG(_pin, _mode, _pol, _shared, _wake) { \
.pin = (_pin), \
.mode = (_mode), \
.polarity = (_pol), \
.shared = (_shared), \
.wake = (_wake) }

#define ACPI_IRQ_EDGE_LOW(x) \
ACPI_IRQ_CFG((x), ACPI_IRQ_EDGE_TRIGGERED, ACPI_IRQ_ACTIVE_LOW, \
ACPI_IRQ_EXCLUSIVE, ACPI_IRQ_NO_WAKE)

#define ACPI_IRQ_EDGE_HIGH(x) \
ACPI_IRQ_CFG((x), ACPI_IRQ_EDGE_TRIGGERED, ACPI_IRQ_ACTIVE_HIGH, \
ACPI_IRQ_EXCLUSIVE, ACPI_IRQ_NO_WAKE)

#define ACPI_IRQ_LEVEL_LOW(x) \
ACPI_IRQ_CFG((x), ACPI_IRQ_LEVEL_TRIGGERED, ACPI_IRQ_ACTIVE_LOW, \
ACPI_IRQ_SHARED, ACPI_IRQ_NO_WAKE)

#define ACPI_IRQ_LEVEL_HIGH(x) \
ACPI_IRQ_CFG((x), ACPI_IRQ_LEVEL_TRIGGERED, ACPI_IRQ_ACTIVE_HIGH, \
ACPI_IRQ_SHARED, ACPI_IRQ_NO_WAKE)

#define ACPI_IRQ_WAKE_EDGE_LOW(x) \
ACPI_IRQ_CFG((x), ACPI_IRQ_EDGE_TRIGGERED, ACPI_IRQ_ACTIVE_LOW, \
ACPI_IRQ_EXCLUSIVE, ACPI_IRQ_WAKE)

#define ACPI_IRQ_WAKE_EDGE_HIGH(x) \
ACPI_IRQ_CFG((x), ACPI_IRQ_EDGE_TRIGGERED, ACPI_IRQ_ACTIVE_HIGH, \
ACPI_IRQ_EXCLUSIVE, ACPI_IRQ_WAKE)

#define ACPI_IRQ_WAKE_LEVEL_LOW(x) \
ACPI_IRQ_CFG((x), ACPI_IRQ_LEVEL_TRIGGERED, ACPI_IRQ_ACTIVE_LOW, \
ACPI_IRQ_SHARED, ACPI_IRQ_WAKE)

#define ACPI_IRQ_WAKE_LEVEL_HIGH(x) \
ACPI_IRQ_CFG((x), ACPI_IRQ_LEVEL_TRIGGERED, ACPI_IRQ_ACTIVE_HIGH, \
ACPI_IRQ_SHARED, ACPI_IRQ_WAKE)

/* Write extended Interrupt() descriptor to SSDT AML output */
void acpi_device_write_interrupt(const struct acpi_irq *irq);
Expand Down
6 changes: 3 additions & 3 deletions src/arch/x86/include/arch/early_variables.h
Expand Up @@ -20,7 +20,7 @@
#include <stdlib.h>
#include <rules.h>

#if ENV_CACHE_AS_RAM
#if ENV_CACHE_AS_RAM && !IS_ENABLED(CONFIG_NO_CAR_GLOBAL_MIGRATION)
asm(".section .car.global_data,\"w\",@nobits");
asm(".previous");
#ifdef __clang__
Expand All @@ -34,7 +34,7 @@ asm(".previous");
* accessed unconditionally because cbmem is never initialized until romstage
* when dram comes up.
*/
#if ENV_VERSTAGE || ENV_BOOTBLOCK || IS_ENABLED(CONFIG_NO_CAR_GLOBAL_MIGRATION)
#if !ENV_ROMSTAGE
static inline void *car_get_var_ptr(void *var)
{
return var;
Expand All @@ -58,7 +58,7 @@ void *car_sync_var_ptr(void *var);

/* Return 1 when currently running with globals in Cache-as-RAM, 0 otherwise. */
int car_active(void);
#endif /* ENV_VERSTAGE */
#endif /* !ENV_ROMSTAGE */

/* Get and set a primitive type global variable. */
#define car_get_var(var) \
Expand Down
2 changes: 0 additions & 2 deletions src/arch/x86/include/arch/hlt.h
Expand Up @@ -20,8 +20,6 @@ static void hlt(void)
__builtin_hlt();
}
#else
#include <compiler.h>

static __always_inline void hlt(void)
{
asm("hlt");
Expand Down
1 change: 0 additions & 1 deletion src/arch/x86/include/arch/io.h
Expand Up @@ -14,7 +14,6 @@
#ifndef _ASM_IO_H
#define _ASM_IO_H

#include <compiler.h>
#include <endian.h>
#include <stdint.h>
#include <rules.h>
Expand Down
1 change: 0 additions & 1 deletion src/arch/x86/include/arch/pci_io_cfg.h
Expand Up @@ -14,7 +14,6 @@
#ifndef _PCI_IO_CFG_H
#define _PCI_IO_CFG_H

#include <compiler.h>
#include <arch/io.h>

static __always_inline
Expand Down
1 change: 0 additions & 1 deletion src/arch/x86/include/arch/pci_mmio_cfg.h
Expand Up @@ -17,7 +17,6 @@
#define _PCI_MMIO_CFG_H

#include <arch/io.h>
#include <compiler.h>

#define DEFAULT_PCIEXBAR CONFIG_MMCONF_BASE_ADDRESS

Expand Down
1 change: 0 additions & 1 deletion src/arch/x86/include/arch/pirq_routing.h
Expand Up @@ -28,7 +28,6 @@
#define MAX_INTX_ENTRIES 4

#include <stdint.h>
#include <compiler.h>

#define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24))
#define PIRQ_VERSION 0x0100
Expand Down
4 changes: 2 additions & 2 deletions src/arch/x86/include/arch/registers.h
Expand Up @@ -16,9 +16,9 @@
#ifndef __ARCH_REGISTERS_H
#define __ARCH_REGISTERS_H

#include <compiler.h>

#if !defined(__ASSEMBLER__)
#include <stdint.h>

#define DOWNTO8(A) \
union { \
struct { \
Expand Down
2 changes: 0 additions & 2 deletions src/arch/x86/include/arch/smp/atomic.h
Expand Up @@ -14,8 +14,6 @@
#ifndef ARCH_SMP_ATOMIC_H
#define ARCH_SMP_ATOMIC_H

#include <compiler.h>

/*
* Make sure gcc doesn't try to be clever and move things around
* on us. We need to use _exactly_ the address the user gave us,
Expand Down
1 change: 0 additions & 1 deletion src/arch/x86/include/arch/smp/mpspec.h
Expand Up @@ -16,7 +16,6 @@
#ifndef __ASM_MPSPEC_H
#define __ASM_MPSPEC_H

#include <compiler.h>
#include <device/device.h>
#include <cpu/x86/lapic_def.h>

Expand Down
2 changes: 0 additions & 2 deletions src/arch/x86/include/arch/smp/spinlock.h
Expand Up @@ -14,8 +14,6 @@
#ifndef ARCH_SMP_SPINLOCK_H
#define ARCH_SMP_SPINLOCK_H

#include <compiler.h>

#if !defined(__PRE_RAM__) \
|| IS_ENABLED(CONFIG_HAVE_ROMSTAGE_CONSOLE_SPINLOCK) \
|| IS_ENABLED(CONFIG_HAVE_ROMSTAGE_NVRAM_CBFS_SPINLOCK) \
Expand Down
40 changes: 40 additions & 0 deletions src/arch/x86/include/cf9_reset.h
@@ -0,0 +1,40 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2017 Intel Corp.
*
* 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; version 2 of the License.
*
* 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.
*/

#ifndef X86_CF9_RESET_H
#define X86_CF9_RESET_H

/* Reset control port */
#define RST_CNT 0xcf9
#define FULL_RST (1 << 3)
#define RST_CPU (1 << 2)
#define SYS_RST (1 << 1)

/* Implement the bare reset, i.e. write to cf9. */
void do_system_reset(void);
void do_full_reset(void);

/* Called by functions below before reset. */
#if IS_ENABLED(CONFIG_HAVE_CF9_RESET_PREPARE)
void cf9_reset_prepare(void);
#else
static inline void cf9_reset_prepare(void) {}
#endif

/* Prepare for reset, run do_*_reset(), halt. */
__noreturn void system_reset(void);
__noreturn void full_reset(void);

#endif /* X86_CF9_RESET_H */
1 change: 0 additions & 1 deletion src/arch/x86/mpspec.c
Expand Up @@ -17,7 +17,6 @@
#include <device/path.h>
#include <device/pci_ids.h>
#include <cpu/cpu.h>
#include <compiler.h>
#include <arch/smp/mpspec.h>
#include <string.h>
#include <arch/cpu.h>
Expand Down
1 change: 0 additions & 1 deletion src/arch/x86/pirq_routing.c
Expand Up @@ -15,7 +15,6 @@
* GNU General Public License for more details.
*/
#include <console/console.h>
#include <compiler.h>
#include <arch/pirq_routing.h>
#include <string.h>
#include <device/pci.h>
Expand Down
1 change: 0 additions & 1 deletion src/arch/x86/postcar.c
Expand Up @@ -15,7 +15,6 @@

#include <arch/cpu.h>
#include <cbmem.h>
#include <compiler.h>
#include <console/console.h>
#include <main_decl.h>
#include <program_loading.h>
Expand Down
1 change: 0 additions & 1 deletion src/arch/x86/smbios.c
Expand Up @@ -20,7 +20,6 @@
#include <stdlib.h>
#include <string.h>
#include <smbios.h>
#include <compiler.h>
#include <console/console.h>
#include <version.h>
#include <device/device.h>
Expand Down
1 change: 0 additions & 1 deletion src/arch/x86/timestamp.c
Expand Up @@ -13,7 +13,6 @@
* GNU General Public License for more details.
*/

#include <compiler.h>
#include <cpu/x86/tsc.h>
#include <timestamp.h>

Expand Down
1 change: 0 additions & 1 deletion src/commonlib/fsp_relocate.c
Expand Up @@ -13,7 +13,6 @@
* GNU General Public License for more details.
*/

#include <compiler.h>
#include <console/console.h>
#include <commonlib/endian.h>
#include <commonlib/fsp.h>
Expand Down
1 change: 0 additions & 1 deletion src/commonlib/include/commonlib/cbfs_serialized.h
Expand Up @@ -48,7 +48,6 @@
#define _CBFS_SERIALIZED_H_

#include <stdint.h>
#include <compiler.h>

/** These are standard values for the known compression
algorithms that coreboot knows about for stages and
Expand Down
Expand Up @@ -13,20 +13,39 @@
* GNU General Public License for more details.
*/

#ifndef __COMPILER_H__
#define __COMPILER_H__
#ifndef _COMMONLIB_COMPILER_H_
#define _COMMONLIB_COMPILER_H_

#ifndef __packed
#if defined(__WIN32) || defined(__WIN64)
#define __packed __attribute__((gcc_struct, packed))
#else
#define __packed __attribute__((packed))
#endif
#endif

#ifndef __aligned
#define __aligned(x) __attribute__((aligned(x)))
#endif

#ifndef __always_unused
#define __always_unused __attribute__((unused))
#endif

#ifndef __must_check
#define __must_check __attribute__((warn_unused_result))
#endif

#ifndef __weak
#define __weak __attribute__((weak))
#endif

#ifndef __noreturn
#define __noreturn __attribute__((noreturn))
#endif

#ifndef __always_inline
#define __always_inline inline __attribute__((always_inline))
#endif

#endif
1 change: 0 additions & 1 deletion src/commonlib/include/commonlib/fmap_serialized.h
Expand Up @@ -37,7 +37,6 @@
#define FLASHMAP_SERIALIZED_H__

#include <stdint.h>
#include <compiler.h>

#define FMAP_SIGNATURE "__FMAP__"
#define FMAP_VER_MAJOR 1 /* this header's FMAP minor version */
Expand Down
1 change: 0 additions & 1 deletion src/commonlib/include/commonlib/rmodule-defs.h
Expand Up @@ -17,7 +17,6 @@

#include <stdint.h>
#include <stddef.h>
#include <compiler.h>

#define RMODULE_MAGIC 0xf8fe
#define RMODULE_VERSION_1 1
Expand Down
1 change: 0 additions & 1 deletion src/commonlib/include/commonlib/tcpa_log_serialized.h
Expand Up @@ -16,7 +16,6 @@
#ifndef __TCPA_LOG_SERIALIZED_H__
#define __TCPA_LOG_SERIALIZED_H__

#include <compiler.h>
#include <stdint.h>

#define MAX_TCPA_LOG_ENTRIES 50
Expand Down