diff --git a/arch/Kconfig b/arch/Kconfig index 83b7577ba3..7ed19ce05c 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -134,6 +134,7 @@ config ARCH_X86_64 select ARCH_HAVE_FPU select ARCH_HAVE_DPFPU select ARCH_HAVE_TESTSET + select ARCH_HAVE_INTERRUPTSTACK select ARCH_HAVE_CUSTOMOPT select LIBC_ARCH_ELF_64BIT if LIBC_ARCH_ELF ---help--- diff --git a/arch/x86_64/include/intel64/arch.h b/arch/x86_64/include/intel64/arch.h index fd85fcc437..5a770976ca 100644 --- a/arch/x86_64/include/intel64/arch.h +++ b/arch/x86_64/include/intel64/arch.h @@ -79,6 +79,8 @@ #define X86_GDT_DATA_SEL_NUM 2 # define X86_GDT_DATA_SEL (X86_GDT_DATA_SEL_NUM * X86_GDT_ENTRY_SIZE) +/* The first TSS entry */ + #define X86_GDT_ISTL_SEL_NUM 6 #define X86_GDT_ISTH_SEL_NUM (X86_GDT_ISTL_SEL_NUM + 1) @@ -263,7 +265,12 @@ #define X86_PIC_8086 1 #define X86_PIC_EOI 0x20 -#define BITS_PER_LONG 64 +#define BITS_PER_LONG 64 + +/* Interrupt Stack Table size */ + +#define X86_IST_SIZE 104 +#define X86_TSS_SIZE (104 + 8) /* Reset Control Register (RST_CNT) */ @@ -370,9 +377,13 @@ begin_packed_struct struct ist_s uint16_t IOPB_OFFSET; /* IOPB_offset */ } end_packed_struct; -/**************************************************************************** - * Public Types - ****************************************************************************/ +/* TSS */ + +begin_packed_struct struct tss_s +{ + struct ist_s ist; /* IST */ + void *cpu; /* CPU private data */ +} end_packed_struct; /**************************************************************************** * Public Data diff --git a/arch/x86_64/include/irq.h b/arch/x86_64/include/irq.h index 2e1e81fe5c..8cddf2a3e3 100644 --- a/arch/x86_64/include/irq.h +++ b/arch/x86_64/include/irq.h @@ -58,18 +58,27 @@ ****************************************************************************/ #ifndef __ASSEMBLY__ -/* This holds a references to the current interrupt level register storage - * structure. It is non-NULL only during interrupt processing. +/* CPU private data */ + +struct intel64_cpu_s +{ + int id; + uint8_t loapic_id; + bool ready; + +/* current_regs holds a references to the current interrupt level + * register storage structure. If is non-NULL only during interrupt + * processing. Access to current_regs must be through + * up_current_regs() and up_set_current_regs() functions */ -extern volatile uint64_t *g_current_regs; -#endif + uint64_t *current_regs; +}; /**************************************************************************** * Public Function Prototypes ****************************************************************************/ -#ifndef __ASSEMBLY__ #ifdef __cplusplus #define EXTERN extern "C" extern "C" @@ -100,6 +109,22 @@ extern "C" * Inline functions ****************************************************************************/ +static inline_function uint64_t *up_current_regs(void) +{ + uint64_t *regs; + asm volatile("movq %%gs:(%c1), %0" + : "=rm" (regs) + : "i" (offsetof(struct intel64_cpu_s, current_regs))); + return regs; +} + +static inline_function void up_set_current_regs(uint64_t *regs) +{ + asm volatile("movq %0, %%gs:(%c1)" + :: "r" (regs), "i" (offsetof(struct intel64_cpu_s, + current_regs))); +} + /**************************************************************************** * Name: up_interrupt_context * @@ -109,7 +134,11 @@ extern "C" * ****************************************************************************/ -#define up_interrupt_context() (g_current_regs != NULL) +noinstrument_function +static inline_function bool up_interrupt_context(void) +{ + return up_current_regs() != NULL; +} #undef EXTERN #ifdef __cplusplus diff --git a/arch/x86_64/src/common/x86_64_getintstack.c b/arch/x86_64/src/common/x86_64_getintstack.c index 12e646893e..71222c5eb1 100644 --- a/arch/x86_64/src/common/x86_64_getintstack.c +++ b/arch/x86_64/src/common/x86_64_getintstack.c @@ -39,6 +39,6 @@ #if CONFIG_ARCH_INTERRUPTSTACK > 3 uintptr_t up_get_intstackbase(int cpu) { - return (uintptr_t)g_intstackalloc; + return (uintptr_t)(g_intstackalloc + (cpu * IRQ_STACK_SIZE)); } #endif diff --git a/arch/x86_64/src/common/x86_64_internal.h b/arch/x86_64/src/common/x86_64_internal.h index 8ec08f845d..00278dfcf4 100644 --- a/arch/x86_64/src/common/x86_64_internal.h +++ b/arch/x86_64/src/common/x86_64_internal.h @@ -111,7 +111,15 @@ * referenced is passed to get the state from the TCB. */ -#define x86_64_restorestate(regs) (g_current_regs = regs) +#define x86_64_restorestate(regs) (up_set_current_regs(regs)) + +/* ISR/IRQ stack size */ + +#if CONFIG_ARCH_INTERRUPTSTACK == 0 +# define IRQ_STACK_SIZE 0x2000 +#else +# define IRQ_STACK_SIZE CONFIG_ARCH_INTERRUPTSTACK +#endif /**************************************************************************** * Public Types @@ -138,7 +146,7 @@ extern const uintptr_t g_idle_topstack; #if CONFIG_ARCH_INTERRUPTSTACK > 3 extern uint8_t g_intstackalloc[]; -extern uint8_t g_intstacktop[]; +extern uint8_t g_intstackalloc[]; #endif /* These symbols are setup by the linker script. */ diff --git a/arch/x86_64/src/common/x86_64_switchcontext.c b/arch/x86_64/src/common/x86_64_switchcontext.c index 15fec6159d..3397d2d493 100644 --- a/arch/x86_64/src/common/x86_64_switchcontext.c +++ b/arch/x86_64/src/common/x86_64_switchcontext.c @@ -63,7 +63,7 @@ void up_switch_context(struct tcb_s *tcb, struct tcb_s *rtcb) /* Are we in an interrupt handler? */ - if (g_current_regs) + if (up_current_regs()) { /* Yes, then we have to do things differently. * Just copy the g_current_regs into the OLD rtcb. diff --git a/arch/x86_64/src/intel64/CMakeLists.txt b/arch/x86_64/src/intel64/CMakeLists.txt index 4525a4d785..6ae067cc2f 100644 --- a/arch/x86_64/src/intel64/CMakeLists.txt +++ b/arch/x86_64/src/intel64/CMakeLists.txt @@ -45,7 +45,8 @@ set(SRCS intel64_lowsetup.c intel64_serial.c intel64_rng.c - intel64_check_capability.c) + intel64_check_capability.c + intel64_cpu.c) if(CONFIG_ARCH_HAVE_TESTSET) list(APPEND SRCS intel64_testset.S) diff --git a/arch/x86_64/src/intel64/Make.defs b/arch/x86_64/src/intel64/Make.defs index 082812f1f6..d9020c86c5 100644 --- a/arch/x86_64/src/intel64/Make.defs +++ b/arch/x86_64/src/intel64/Make.defs @@ -32,6 +32,7 @@ CMN_CSRCS += intel64_systemreset.c intel64_freq.c intel64_cache.c CHIP_ASRCS = intel64_saveusercontext.S intel64_fullcontextrestore.S intel64_vectors.S intel64_head.S CHIP_CSRCS = intel64_start.c intel64_handlers.c intel64_idle.c intel64_lowsetup.c CHIP_CSRCS += intel64_serial.c intel64_rng.c intel64_check_capability.c +CHIP_CSRCS += intel64_cpu.c ifeq ($(CONFIG_ARCH_HAVE_TESTSET), y) CHIP_ASRCS += intel64_testset.S diff --git a/arch/x86_64/src/intel64/intel64_cpu.c b/arch/x86_64/src/intel64/intel64_cpu.c new file mode 100644 index 0000000000..17f7497ae8 --- /dev/null +++ b/arch/x86_64/src/intel64/intel64_cpu.c @@ -0,0 +1,383 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/intel64_cpu.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include "x86_64_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Avoid undefined error when CONFIG_SPINLOCK=n */ + +#ifndef spin_lock +# define spin_lock(s) +#endif + +#define IRQ_STACK_ALLOC (IRQ_STACK_SIZE * CONFIG_SMP_NCPUS) + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern volatile uint32_t g_cpu_count; +volatile static spinlock_t g_ap_boot; + +/* CPU private data */ + +struct intel64_cpu_s g_cpu_priv[CONFIG_SMP_NCPUS]; + +/* Allocate stack for interrupts and isr */ + +uint8_t g_intstackalloc[IRQ_STACK_ALLOC] aligned_data(16); +uint8_t g_isrstackalloc[IRQ_STACK_ALLOC] aligned_data(16); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: x86_64_cpu_tss_get + * + * Description: + * Get TSS for a given CPU data. + * + ****************************************************************************/ + +static struct tss_s *x86_64_cpu_tss_get(uint8_t cpu) +{ + return (struct tss_s *)((uintptr_t)&g_ist64_low + X86_64_LOAD_OFFSET + + (X86_TSS_SIZE * cpu)); +} + +/**************************************************************************** + * Name: x86_64_cpu_tss_load + * + * Description: + * Load TSS for the current CPU + * + ****************************************************************************/ + +static void x86_64_cpu_tss_load(int cpu) +{ + uint16_t addr; + + /* Get offset for TSS */ + + addr = X86_GDT_ISTL_SEL_NUM * 8 + 16 * cpu; + + asm volatile ("mov %0, %%ax; ltr %%ax":: "m"(addr) : "memory", "rax"); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: x86_64_cpu_tss_init + * + * Description: + * Initialize the TSS + * + ****************************************************************************/ + +void x86_64_cpu_tss_init(int cpu) +{ + struct tss_s *tss = NULL; + struct ist_s *ist64 = NULL; + struct gdt_entry_s tss_l; + uint64_t tss_h; + + /* Get TSS - one per CPU */ + + tss = x86_64_cpu_tss_get(cpu); + + /* Setup IST pointer */ + + ist64 = &tss->ist; + + /* Reset local data */ + + memset(&tss_l, 0, sizeof(tss_l)); + memset(&tss_h, 0, sizeof(tss_h)); + + /* Segment limit = IST size - 1 */ + + tss_l.limit_low = ((X86_IST_SIZE - 1) & 0xffff); + + /* Low address 1 */ + + tss_l.base_low = ((uintptr_t)ist64 & 0x00ffffff); + + /* Low address 2 */ + + tss_l.base_high = (((uintptr_t)ist64 & 0xff000000) >> 24); + tss_l.P = 1; + + /* Set type as IST */ + + tss_l.AC = 1; + tss_l.EX = 1; + + /* High address */ + + tss_h = (((uintptr_t)ist64 >> 32) & 0xffffffff); + + g_gdt64[X86_GDT_ISTL_SEL_NUM + 2 * cpu] = tss_l; + + /* memcpy used to handle type punning compiler warning */ + + memcpy((void *)&g_gdt64[X86_GDT_ISTH_SEL_NUM + 2 * cpu], + &tss_h, sizeof(g_gdt64[0])); + + /* Stack for IRQ0-IRQ15 */ + + ist64->IST1 = (uintptr_t)(g_isrstackalloc + ((cpu + 1) * IRQ_STACK_SIZE)); + + /* Stack for the rest IRQ */ + + ist64->IST2 = (uintptr_t)(g_intstackalloc + ((cpu + 1) * IRQ_STACK_SIZE)); + + /* Now load TSS */ + + x86_64_cpu_tss_load(cpu); +} + +/**************************************************************************** + * Name: x86_64_cpu_tss_now_get + * + * Description: + * Get CPU TSS data associated with the current CPU + * + ****************************************************************************/ + +struct tss_s *x86_64_cpu_tss_now_get(void) +{ + uint64_t *ist = 0; + uint16_t seg = 0; + uint16_t ist_offset = 0; + uintptr_t tss_addr = 0; + + /* Get TSS associated with this CPU */ + + asm volatile ("str %%ax; mov %%ax, %0": "=rm"(seg) :: "memory", "rax"); + + /* This is BSP if TSS not configured yet */ + + if (seg == 0) + { + return NULL; + } + + /* Decode TSS */ + + ist_offset = ((seg - X86_GDT_ISTL_SEL_NUM * 8) / 8); + ist = (uint64_t *)((uintptr_t)&g_gdt64_ist_low + X86_64_LOAD_OFFSET); + + /* Low address */ + + tss_addr = (ist[ist_offset] >> 16) & 0x00ffffff; + tss_addr |= ((ist[ist_offset] >> 56) & 0xff) << 24; + + /* High address */ + + tss_addr |= ist[ist_offset + 1] << 32; + + return (struct tss_s *)tss_addr; +} + +/**************************************************************************** + * Name: x86_64_cpu_init + * + * Description: + * Initialize CPU data. + * + ****************************************************************************/ + +void x86_64_cpu_init(void) +{ + struct tss_s *tss = NULL; + struct acpi_lapic_s *lapic = NULL; + int i = 0; + int ret = OK; + + /* Map logical CPU to Local APIC IDs */ + + for (i = 0; i < CONFIG_SMP_NCPUS; i++) + { + ret = acpi_lapic_get(i, &lapic); + if (ret == OK) + { + g_cpu_priv[i].loapic_id = lapic->apic_id; + g_cpu_priv[i].id = i; + g_cpu_priv[i].ready = false; + + /* Store private CPU in TSS */ + + tss = x86_64_cpu_tss_get(i); + tss->cpu = &g_cpu_priv[i]; + } + else + { + /* We want to fail early when NCPUS doesn't match the number + * of availalbe CPUs + */ + + /* Panic if not found */ + + PANIC(); + } + } + + /* Set BSP ready flag */ + + g_cpu_priv[0].ready = true; +} + +/**************************************************************************** + * Name: x86_64_lopaic_to_cpu + * + * Description: + * Get CPU index for a given Local APIC ID + * + ****************************************************************************/ + +uint8_t x86_64_loapic_to_cpu(uint8_t loapic) +{ + int i; + + for (i = 0; i < CONFIG_SMP_NCPUS; i++) + { + if (g_cpu_priv[i].loapic_id == loapic) + { + return i; + } + } + + /* Panic if not found */ + + PANIC(); +} + +/**************************************************************************** + * Name: x86_64_cpu_to_loapic + * + * Description: + * Get Local APIC ID for a given CPU index + * + ****************************************************************************/ + +uint8_t x86_64_cpu_to_loapic(uint8_t cpu) +{ + return g_cpu_priv[cpu].loapic_id; +} + +/**************************************************************************** + * Name: x86_64_cpu_ready_set + * + * Description: + * Set CPU ready flag + * + ****************************************************************************/ + +void x86_64_cpu_ready_set(uint8_t cpu) +{ + spin_lock(&g_ap_boot); + + if (!g_cpu_priv[cpu].ready) + { + g_cpu_priv[cpu].ready = true; + g_cpu_count++; + } + + spin_unlock(&g_ap_boot); +} + +/**************************************************************************** + * Name: x86_64_cpu_ready_get + * + * Description: + * Get CPU ready flag + * + ****************************************************************************/ + +bool x86_64_cpu_ready_get(uint8_t cpu) +{ + struct intel64_cpu_s *priv = &g_cpu_priv[cpu]; + bool ready; + + spin_lock(&g_ap_boot); + ready = priv->ready; + spin_unlock(&g_ap_boot); + + return ready; +} + +/**************************************************************************** + * Name: x86_64_cpu_count_get + * + * Description: + * Get CPU counter + * + ****************************************************************************/ + +uint8_t x86_64_cpu_count_get(void) +{ + uint8_t count; + + spin_lock(&g_ap_boot); + count = g_cpu_count; + spin_unlock(&g_ap_boot); + + return count; +} + +/**************************************************************************** + * Name: x86_64_cpu_priv_set + * + * Description: + * Save CPU private data + * + ****************************************************************************/ + +void x86_64_cpu_priv_set(uint8_t cpu) +{ + /* Store private data pointer to GSBASE */ + + write_gsbase((uintptr_t)&g_cpu_priv[cpu]); +} diff --git a/arch/x86_64/src/intel64/intel64_cpu.h b/arch/x86_64/src/intel64/intel64_cpu.h new file mode 100644 index 0000000000..4b6b83fb53 --- /dev/null +++ b/arch/x86_64/src/intel64/intel64_cpu.h @@ -0,0 +1,154 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/intel64_cpu.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_X86_64_SRC_INTEL64_INTEL64_CPU_H +#define __ARCH_X86_64_SRC_INTEL64_INTEL64_CPU_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include + +#include + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: x86_64_cpu_tss_init + * + * Description: + * Initialize the TSS + * + ****************************************************************************/ + +void x86_64_cpu_tss_init(int cpu); + +/**************************************************************************** + * Name: x86_64_cpu_tss_now_get + * + * Description: + * Get CPU TSS data associated with the current CPU + * + ****************************************************************************/ + +struct tss_s *x86_64_cpu_tss_now_get(void); + +/**************************************************************************** + * Name: x86_64_cpu_init + * + * Description: + * Initialize CPU data. + * + ****************************************************************************/ + +void x86_64_cpu_init(void); + +/**************************************************************************** + * Name: x86_64_lopaic_to_cpu + * + * Description: + * Get CPU index for a given Local APIC ID + * + ****************************************************************************/ + +uint8_t x86_64_loapic_to_cpu(uint8_t loapic); + +/**************************************************************************** + * Name: x86_64_cpu_to_loapic + * + * Description: + * Get Local APIC ID for a given CPU index + * + ****************************************************************************/ + +uint8_t x86_64_cpu_to_loapic(uint8_t cpu); + +/**************************************************************************** + * Name: x86_64_cpu_ready_set + * + * Description: + * Set CPU ready flag + * + ****************************************************************************/ + +void x86_64_cpu_ready_set(uint8_t cpu); + +/**************************************************************************** + * Name: x86_64_cpu_ready_get + * + * Description: + * Get CPU ready flag + * + ****************************************************************************/ + +bool x86_64_cpu_ready_get(uint8_t cpu); + +/**************************************************************************** + * Name: x86_64_cpu_count_get + * + * Description: + * Get CPU counter + * + ****************************************************************************/ + +uint8_t x86_64_cpu_count_get(void); + +/**************************************************************************** + * Name: x86_64_cpu_priv_set + * + * Description: + * Save CPU private data + * + ****************************************************************************/ + +void x86_64_cpu_priv_set(uint8_t cpu); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_X86_64_SRC_INTEL64_INTEL64_CPU_H */ diff --git a/arch/x86_64/src/intel64/intel64_handlers.c b/arch/x86_64/src/intel64/intel64_handlers.c index 87d1e4c74d..8bf5843d6b 100644 --- a/arch/x86_64/src/intel64/intel64_handlers.c +++ b/arch/x86_64/src/intel64/intel64_handlers.c @@ -68,8 +68,8 @@ static uint64_t *common_handler(int irq, uint64_t *regs) * Nested interrupts are not supported. */ - DEBUGASSERT(g_current_regs == NULL); - g_current_regs = regs; + DEBUGASSERT(up_current_regs() == NULL); + up_set_current_regs(regs); /* Deliver the IRQ */ @@ -82,7 +82,7 @@ static uint64_t *common_handler(int irq, uint64_t *regs) * returning from the interrupt. */ - if (regs != g_current_regs) + if (regs != up_current_regs()) { #ifdef CONFIG_ARCH_ADDRENV /* Make sure that the address environment for the previously @@ -108,13 +108,13 @@ static uint64_t *common_handler(int irq, uint64_t *regs) * switch occurred during interrupt processing. */ - regs = (uint64_t *)g_current_regs; + regs = (uint64_t *)up_current_regs(); /* Set g_current_regs to NULL to indicate that we are no longer in an * interrupt handler. */ - g_current_regs = NULL; + up_set_current_regs(NULL); return regs; } #endif @@ -145,8 +145,8 @@ uint64_t *isr_handler(uint64_t *regs, uint64_t irq) return regs; #else - DEBUGASSERT(g_current_regs == NULL); - g_current_regs = regs; + DEBUGASSERT(up_current_regs() == NULL); + up_set_current_regs(regs); switch (irq) { @@ -174,13 +174,13 @@ uint64_t *isr_handler(uint64_t *regs, uint64_t irq) /* Maybe we need a context switch */ - regs = (uint64_t *)g_current_regs; + regs = (uint64_t *)up_current_regs(); /* Set g_current_regs to NULL to indicate that we are no longer in an * interrupt handler. */ - g_current_regs = NULL; + up_set_current_regs(NULL); return regs; #endif } diff --git a/arch/x86_64/src/intel64/intel64_head.S b/arch/x86_64/src/intel64/intel64_head.S index 47a5401880..72a3d1e5dd 100644 --- a/arch/x86_64/src/intel64/intel64_head.S +++ b/arch/x86_64/src/intel64/intel64_head.S @@ -53,6 +53,7 @@ .global g_idle_topstack /* The end of the idle stack, the start of the heap */ .global g_mb_info_struct .global g_mb_magic + .global g_cpu_count /* These are the page tables */ .global g_pdpt_low @@ -283,6 +284,9 @@ start64: jmp *%rbx .size __pmode_entry, . - __pmode_entry +g_cpu_count: + .long 1 + /**************************************************************************** * Name: __revoke_low_memory * diff --git a/arch/x86_64/src/intel64/intel64_irq.c b/arch/x86_64/src/intel64/intel64_irq.c index cc82c00deb..348e8ff7f9 100644 --- a/arch/x86_64/src/intel64/intel64_irq.c +++ b/arch/x86_64/src/intel64/intel64_irq.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -39,16 +40,13 @@ #include #include "x86_64_internal.h" +#include "intel64_cpu.h" #include "intel64.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -#define UART_BASE 0x3f8 - -#define IRQ_STACK_SIZE 0x2000 - /**************************************************************************** * Private Types ****************************************************************************/ @@ -71,14 +69,6 @@ static inline void up_idtinit(void); * Public Data ****************************************************************************/ -volatile uint64_t *g_current_regs; - -uint8_t g_interrupt_stack[IRQ_STACK_SIZE] aligned_data(16); -uint8_t *g_interrupt_stack_end = g_interrupt_stack + IRQ_STACK_SIZE - 16; - -uint8_t g_isr_stack[IRQ_STACK_SIZE] aligned_data(16); -uint8_t *g_isr_stack_end = g_isr_stack + IRQ_STACK_SIZE - 16; - /**************************************************************************** * Private Data ****************************************************************************/ @@ -171,49 +161,6 @@ void up_ioapic_unmask_pin(unsigned int pin) cur & ~(IOAPIC_PIN_DISABLE)); } -/**************************************************************************** - * Name: up_init_ist - * - * Description: - * Initialize the Interrupt Stack Table - * - ****************************************************************************/ - -static void up_ist_init(void) -{ - struct gdt_entry_s tss_l; - uint64_t tss_h; - - memset(&tss_l, 0, sizeof(tss_l)); - memset(&tss_h, 0, sizeof(tss_h)); - - tss_l.limit_low = (((104 - 1) & 0xffff)); /* Segment limit = TSS size - 1 */ - - tss_l.base_low = ((uintptr_t)g_ist64 & 0x00ffffff); /* Low address 1 */ - tss_l.base_high = (((uintptr_t)g_ist64 & 0xff000000) >> 24); /* Low address 2 */ - - tss_l.P = 1; - - /* Set type as IST */ - - tss_l.AC = 1; - tss_l.EX = 1; - - tss_h = (((uintptr_t)g_ist64 >> 32) & 0xffffffff); /* High address */ - - g_gdt64[X86_GDT_ISTL_SEL_NUM] = tss_l; - - /* memcpy used to handle type punning compiler warning */ - - memcpy((void *)&g_gdt64[X86_GDT_ISTH_SEL_NUM], - (void *)&tss_h, sizeof(g_gdt64[0])); - - g_ist64->IST1 = (uintptr_t)g_interrupt_stack_end; - g_ist64->IST2 = (uintptr_t)g_isr_stack_end; - - asm volatile ("mov $0x30, %%ax; ltr %%ax":::"memory", "rax"); -} - /**************************************************************************** * Name: up_deinit_8259 * @@ -486,21 +433,19 @@ static inline void up_idtinit(void) void up_irqinitialize(void) { - /* Initialize the IST */ + /* Initialize the TSS */ - up_ist_init(); - -#ifndef CONFIG_ARCH_INTEL64_DISABLE_INT_INIT - /* Disable 8259 PIC */ - - up_deinit_8259(); -#endif + x86_64_cpu_tss_init(0); /* Initialize the APIC */ up_apic_init(); #ifndef CONFIG_ARCH_INTEL64_DISABLE_INT_INIT + /* Disable 8259 PIC */ + + up_deinit_8259(); + /* Initialize the IOAPIC */ up_ioapic_init(); diff --git a/arch/x86_64/src/intel64/intel64_regdump.c b/arch/x86_64/src/intel64/intel64_regdump.c index d807ed0f13..e383acdd64 100644 --- a/arch/x86_64/src/intel64/intel64_regdump.c +++ b/arch/x86_64/src/intel64/intel64_regdump.c @@ -111,7 +111,7 @@ void backtrace(uint64_t rbp) void up_dump_register(void *dumpregs) { - volatile uint64_t *regs = dumpregs ? dumpregs : g_current_regs; + volatile uint64_t *regs = dumpregs ? dumpregs : up_current_regs(); uint64_t mxcsr; uint64_t cr2; diff --git a/arch/x86_64/src/intel64/intel64_savestate.c b/arch/x86_64/src/intel64/intel64_savestate.c index d7cd8332fa..c7fe726aa6 100644 --- a/arch/x86_64/src/intel64/intel64_savestate.c +++ b/arch/x86_64/src/intel64/intel64_savestate.c @@ -46,5 +46,5 @@ void x86_64_savestate(uint64_t *regs) { - x86_64_copystate(regs, (uint64_t *)g_current_regs); + x86_64_copystate(regs, (uint64_t *)up_current_regs()); } diff --git a/arch/x86_64/src/intel64/intel64_schedulesigaction.c b/arch/x86_64/src/intel64/intel64_schedulesigaction.c index 56f506d843..28f51334eb 100644 --- a/arch/x86_64/src/intel64/intel64_schedulesigaction.c +++ b/arch/x86_64/src/intel64/intel64_schedulesigaction.c @@ -73,7 +73,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) { sinfo("tcb=%p sigdeliver=%p\n", tcb, sigdeliver); - sinfo("rtcb=%p g_current_regs=%p\n", this_task(), g_current_regs); + sinfo("rtcb=%p g_current_regs=%p\n", this_task(), up_current_regs()); /* Refuse to handle nested signal actions */ @@ -91,7 +91,7 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * signalling itself for some reason. */ - if (!g_current_regs) + if (!up_current_regs()) { /* In this case just deliver the signal with a function call * now. @@ -120,16 +120,16 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) * have been delivered. */ - tcb->xcp.saved_rip = g_current_regs[REG_RIP]; + tcb->xcp.saved_rip = up_current_regs()[REG_RIP]; tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP]; - tcb->xcp.saved_rflags = g_current_regs[REG_RFLAGS]; + tcb->xcp.saved_rflags = up_current_regs()[REG_RFLAGS]; /* Then set up to vector to the trampoline with interrupts * disabled */ - g_current_regs[REG_RIP] = (uint64_t)x86_64_sigdeliver; - g_current_regs[REG_RFLAGS] = 0; + up_current_regs()[REG_RIP] = (uint64_t)x86_64_sigdeliver; + up_current_regs()[REG_RFLAGS] = 0; /* And make sure that the saved context in the TCB * is the same as the interrupt return context. diff --git a/arch/x86_64/src/intel64/intel64_start.c b/arch/x86_64/src/intel64/intel64_start.c index c1e02a6dda..79b1bb5f7e 100644 --- a/arch/x86_64/src/intel64/intel64_start.c +++ b/arch/x86_64/src/intel64/intel64_start.c @@ -33,6 +33,7 @@ #include "x86_64_internal.h" +#include "intel64_cpu.h" #include "intel64_lowsetup.h" /**************************************************************************** @@ -129,6 +130,8 @@ void __nxstart(void) { uint64_t *dest = NULL; + /* This is only for BSP core. */ + /* Do some checking on CPU compatibilities at the top of this function. * BSS cleanup can be optimized with vector instructions, so we need to * enable SSE at this point. @@ -161,6 +164,10 @@ void __nxstart(void) acpi_init(g_acpi_rsdp); #endif + /* Initialize CPU data (BSP and APs) */ + + x86_64_cpu_init(); + /* perform board-specific initializations */ x86_64_boardinitialize(); @@ -171,12 +178,18 @@ void __nxstart(void) x86_64_earlyserialinit(); #endif + /* Configure timer */ + x86_64_timer_calibrate_freq(); #ifdef CONFIG_LIB_SYSCALL enable_syscall(); #endif + /* Store CPU IDs */ + + x86_64_cpu_priv_set(0); + /* Start NuttX */ nx_start();