cpu/x86: Set thread local storage in C code

Doing this in C code is way easier to understand. Also the thread local
storage is now in .bss instead of the AP stack. This makes it more
robust against stack overflows, as APs stacks overflow in each other.

TESTED: work on qemu.

Change-Id: I19d3285daf97798a2d28408b5601ad991e29e718
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/69435
Reviewed-by: Raul Rangel <rrangel@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Arthur Heymans
2022-11-10 13:34:49 +01:00
parent 407e00dca0
commit d4dfc21f70
6 changed files with 55 additions and 110 deletions

View File

@ -6,6 +6,7 @@
#include <cpu/cpu.h>
#include <post.h>
#include <string.h>
#include <cpu/x86/gdt.h>
#include <cpu/x86/mp.h>
#include <cpu/x86/lapic.h>
#include <cpu/x86/tsc.h>
@ -340,3 +341,41 @@ int cpu_index(void)
}
return -1;
}
/* cpu_info() looks at address 0 at the base of %gs for a pointer to struct cpu_info */
static struct per_cpu_segment_data segment_data[CONFIG_MAX_CPUS];
static struct cpu_info cpu_infos[CONFIG_MAX_CPUS];
enum cb_err set_cpu_info(unsigned int index, struct device *cpu)
{
if (index >= ARRAY_SIZE(cpu_infos))
return CB_ERR;
if (!cpu)
return CB_ERR;
const struct cpu_info info = { .cpu = cpu, .index = index};
cpu_infos[index] = info;
segment_data[index].cpu_info = &cpu_infos[index];
struct segment_descriptor {
uint16_t segment_limit_0_15;
uint16_t base_address_0_15;
uint8_t base_address_16_23;
uint8_t attrs[2];
uint8_t base_address_24_31;
} *segment_descriptor = (void *)&per_cpu_segment_descriptors;
segment_descriptor[index].base_address_0_15 = (uintptr_t)&segment_data[index] & 0xffff;
segment_descriptor[index].base_address_16_23 = ((uintptr_t)&segment_data[index] >> 16) & 0xff;
segment_descriptor[index].base_address_24_31 = ((uintptr_t)&segment_data[index] >> 24) & 0xff;
const unsigned int cpu_segment = per_cpu_segment_selector + (index << 3);
__asm__ __volatile__ ("mov %0, %%gs\n"
:
: "r" (cpu_segment)
: );
return CB_SUCCESS;
}