summaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/x86/c_start.S16
-rw-r--r--src/arch/x86/cpu.c39
-rw-r--r--src/arch/x86/include/arch/cpu.h4
3 files changed, 42 insertions, 17 deletions
diff --git a/src/arch/x86/c_start.S b/src/arch/x86/c_start.S
index 02a9b8933a..5b7052ef58 100644
--- a/src/arch/x86/c_start.S
+++ b/src/arch/x86/c_start.S
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
-#include <cpu/x86/cpu_info.S.inc>
#include <cpu/x86/post_code.h>
#include <arch/ram_segs.h>
@@ -78,21 +77,6 @@ _start:
movl $_estack, %esp
andl $(~(CONFIG_STACK_SIZE-1)), %esp
- push_cpu_info
-
- /* Allocate the per_cpu_segment_data on the stack */
- push_per_cpu_segment_data
-
- /*
- * Update the BSP's per_cpu_segment_descriptor to point to the
- * per_cpu_segment_data that was allocated on the stack.
- */
- set_segment_descriptor_base $per_cpu_segment_descriptors, %esp
-
- mov $per_cpu_segment_selector, %eax
- movl (%eax), %eax
- mov %eax, %gs
-
/*
* Now we are finished. Memory is up, data is copied and
* bss is cleared. Now we call the main routine and
diff --git a/src/arch/x86/cpu.c b/src/arch/x86/cpu.c
index f4cb83a4dd..6a8ddefa14 100644
--- a/src/arch/x86/cpu.c
+++ b/src/arch/x86/cpu.c
@@ -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;
+}
diff --git a/src/arch/x86/include/arch/cpu.h b/src/arch/x86/include/arch/cpu.h
index 0087a795ec..c7c6b4e074 100644
--- a/src/arch/x86/include/arch/cpu.h
+++ b/src/arch/x86/include/arch/cpu.h
@@ -147,11 +147,13 @@ struct per_cpu_segment_data {
struct cpu_info *cpu_info;
};
+enum cb_err set_cpu_info(unsigned int index, struct device *cpu);
+
static inline struct cpu_info *cpu_info(void)
{
struct cpu_info *ci = NULL;
- __asm__("mov %%gs:%c[offset], %[ci]"
+ __asm__ __volatile__("mov %%gs:%c[offset], %[ci]"
: [ci] "=r" (ci)
: [offset] "i" (offsetof(struct per_cpu_segment_data, cpu_info))
);