diff --git a/arch/Kconfig b/arch/Kconfig index c88fd5a7966..84938706c0d 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -79,10 +79,15 @@ config ARCH_SIM ---help--- Linux/Cygwin user-mode simulation. -config ARCH_X86 +config arch_x86 bool "x86" ---help--- - Intel x86 architectures. + intel x86 architectures. + +config ARCH_X86_64 + bool "x86_64" + ---help--- + x86-64 architectures. config ARCH_XTENSA bool "Xtensa" @@ -136,6 +141,7 @@ source arch/renesas/Kconfig source arch/risc-v/Kconfig source arch/sim/Kconfig source arch/x86/Kconfig +source arch/x86_64/Kconfig source arch/xtensa/Kconfig source arch/z16/Kconfig source arch/z80/Kconfig diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig new file mode 100644 index 00000000000..7569e3294ff --- /dev/null +++ b/arch/x86_64/Kconfig @@ -0,0 +1,67 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_X86_64 +comment "x86_64 Configuration Options" + +config ARCH + string + default "x86_64" + +choice + prompt "x86_64 arch selection" + default ARCH_INTEL64 + +config ARCH_INTEL64 + bool "Intel x86_64" + select ARCH_HAVE_MPU + select ARCH_USE_MPU + select ARCH_HAVE_TICKLESS + select ARCH_HAVE_STACKCHECK + select ARCH_HAVE_RNG + ---help--- + Intel x86_64 architecture + +endchoice + +choice + prompt "x86_64 system selection" + default ARCH_BOARD_QEMU + +config ARCH_BOARD_QEMU + bool "Qemu envrionment" + ---help--- + Targeting virtualized qemu environment + +endchoice + +source arch/x86_64/src/common/Kconfig + +if ARCH_INTEL64 +source arch/x86_64/src/intel64/Kconfig + +config ARCH_CHIP + string + default "intel64" + +endif # ARCH_INTEL64 + +if ARCH_BOARD_QEMU +source arch/x86_64/src/qemu/Kconfig + +config ARCH_BOARD + string + default "qemu-intel64" + +endif # ARCH_CHIP_QEMU + +config ARCH_EXCLUDE_MULTIBOOT + bool "Don't append multiboot2 header" + default n + ---help--- + Some platforms, e.g. jailhouse, do not like to have a multiboot header + + +endif # ARCH_X86_64 diff --git a/arch/x86_64/include/.gitignore b/arch/x86_64/include/.gitignore new file mode 100644 index 00000000000..8b8a2b105ce --- /dev/null +++ b/arch/x86_64/include/.gitignore @@ -0,0 +1,3 @@ +/chip +/board + diff --git a/arch/x86_64/include/README.txt b/arch/x86_64/include/README.txt new file mode 100644 index 00000000000..65db0538451 --- /dev/null +++ b/arch/x86_64/include/README.txt @@ -0,0 +1,30 @@ +arch/x86_64/include/README.txt +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This directory holds x86_64-specific header files. The top-level header files in +arch/x86_64/include simply include corresponding header files from lower lower- +level chip-specific and architecture-specific directories. + +Architecture-Specific Directories +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Architecture-specific directories hold common header files for specific x86_64 +architectures. + +intel64 + This directory holds definitions appropriate for any instantiation of the + Intel architecture in 64bit long mode. + +Chip-Specific directories +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The same x86 architecture may be realized in different chip implementations. +For SoC chips, in particular, on-chip devices and differing interrupt +structures may require special, chip-specific definitions in these chip- +specific directories. + +broadwell + This is the implementation of NuttX on the Intel Broadwell processors. + + + diff --git a/arch/x86_64/include/arch.h b/arch/x86_64/include/arch.h new file mode 100644 index 00000000000..fc69aa5860a --- /dev/null +++ b/arch/x86_64/include/arch.h @@ -0,0 +1,77 @@ +/**************************************************************************** + * arch/x86_64/include/arch.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. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, only indirectly + * through arch/arch.h + */ + +#ifndef __ARCH_X86_64_INCLUDE_ARCH_H +#define __ARCH_X86_64_INCLUDE_ARCH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/* Include chip-specific definitions */ + +# include + +/* Include architecture-specific definitions */ + +#ifdef CONFIG_ARCH_INTEL64 +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ARCH_X86_64_INCLUDE_ARCH_H */ diff --git a/arch/x86_64/include/intel64/arch.h b/arch/x86_64/include/intel64/arch.h new file mode 100644 index 00000000000..f385ca8e361 --- /dev/null +++ b/arch/x86_64/include/intel64/arch.h @@ -0,0 +1,596 @@ +/**************************************************************************** + * arch/x86_64/include/intel64/arch.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. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, + * only indirectly through nuttx/arch.h + */ + +#ifndef __ARCH_X86_64_INCLUDE_INTEL64_ARCH_H +#define __ARCH_X86_64_INCLUDE_INTEL64_ARCH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define X86_64_LOAD_OFFSET 0x100000000 + +/* RFLAGS bits */ + +#define X86_64_RFLAGS_CF (1 << 0) /* Bit 0: Carry Flag */ + /* Bit 1: Reserved */ +#define X86_64_RFLAGS_PF (1 << 2) /* Bit 2: Parity Flag */ + /* Bit 3: Reserved */ +#define X86_64_RFLAGS_AF (1 << 4) /* Bit 4: Auxillary carry Flag */ + /* Bit 5: Reserved */ +#define X86_64_RFLAGS_ZF (1 << 6) /* Bit 6: Zero Flag */ +#define X86_64_RFLAGS_SF (1 << 7) /* Bit 7: Sign Flag */ +#define X86_64_RFLAGS_TF (1 << 8) /* Bit 8: Trap Flag */ +#define X86_64_RFLAGS_IF (1 << 9) /* Bit 9: Interrupt Flag */ +#define X86_64_RFLAGS_DF (1 << 10) /* Bit 10: Direction Flag */ +#define X86_64_RFLAGS_OF (1 << 11) /* Bit 11: Overflow Flag */ +#define X86_64_RFLAGS_IOPL_SHIFT (12) /* Bits 12-13: IOPL mask (286+ only)*/ +#define X86_64_RFLAGS_IOPL_MASK (3 << X86_64_RFLAGS_IOPL_SHIFT) +#define X86_64_RFLAGS_NT (1 << 14) /* Bit 14: Nested Task */ + /* Bit 15: Reserved */ +#define X86_64_RFLAGS_RF (1 << 16) /* Bit 16: Resume Flag (386+ only) */ +#define X86_64_RFLAGS_VM (1 << 17) /* Bit 17: Virtual Mode (386+ only) */ +#define X86_64_RFLAGS_AC (1 << 18) /* Bit 18: Alignment Check (486SX+ only) */ +#define X86_64_RFLAGS_VIF (1 << 19) /* Bit 19: Virtual Interrupt Flag (Pentium+) */ +#define X86_64_RFLAGS_VIP (1 << 20) /* Bit 20: Virtual Interrupt Pending (Pentium+) */ +#define X86_64_RFLAGS_ID (1 << 21) /* Bit 21: CPUID detection flag (Pentium+) */ + +/* GDT Definitions */ + +/* Starting from third selector to confirm the syscall interface */ + +#define X86_GDT_ENTRY_SIZE 0x8 + +#define X86_GDT_CODE_SEL_NUM 1 +# define X86_GDT_CODE_SEL (X86_GDT_CODE_SEL_NUM * X86_GDT_ENTRY_SIZE) + +#define X86_GDT_DATA_SEL_NUM 2 +# define X86_GDT_DATA_SEL (X86_GDT_DATA_SEL_NUM * X86_GDT_ENTRY_SIZE) + +#define X86_GDT_ISTL_SEL_NUM 6 +#define X86_GDT_ISTH_SEL_NUM (X86_GDT_ISTL_SEL_NUM + 1) + +#define X86_GDT_BASE 0x0000000000000000 +#define X86_GDT_LIMIT 0x000f00000000ffff + +#define X86_GDT_FLAG_LONG 0x0020000000000000 + +#define X86_GDT_ACC_PR 0x0000800000000000 +#define X86_GDT_ACC_SEG 0x0000100000000000 +#define X86_GDT_ACC_EX 0x0000080000000000 +#define X86_GDT_ACC_WR 0x0000020000000000 + +#define X86_GDT_CODE64_ENTRY (X86_GDT_BASE + X86_GDT_LIMIT + X86_GDT_FLAG_LONG + X86_GDT_ACC_PR + X86_GDT_ACC_SEG + X86_GDT_ACC_EX) +#define X86_GDT_CODE32_ENTRY (X86_GDT_BASE + X86_GDT_LIMIT + X86_GDT_ACC_PR + X86_GDT_ACC_SEG + X86_GDT_ACC_EX) +#define X86_GDT_DATA_ENTRY (X86_GDT_BASE + X86_GDT_LIMIT + X86_GDT_ACC_PR + X86_GDT_ACC_SEG + X86_GDT_ACC_WR) + +/* CR0 Definitions */ + +#define X86_CR0_PE 0x00000001 +#define X86_CR0_MP 0x00000002 +#define X86_CR0_EM 0x00000004 +#define X86_CR0_WP 0x00010000 +#define X86_CR0_PG 0x80000000 + +/* CR4 Definitions */ + +#define X86_CR4_PAE 0x00000020 +#define X86_CR4_PGE 0x00000080 +#define X86_CR4_OSXFSR 0x00000200 +#define X86_CR4_XMMEXCPT 0x00000400 +#define X86_CR4_FGSBASE 0x00010000 +#define X86_CR4_PCIDE 0x00020000 + +/* PAGE TABLE ENTRY Definitions */ + +#define X86_PAGE_PRESENT (1 << 0) +#define X86_PAGE_WR (1 << 1) +#define X86_PAGE_USER (1 << 2) +#define X86_PAGE_WRTHR (1 << 3) +#define X86_PAGE_NOCACHE (1 << 4) +#define X86_PAGE_HUGE (1 << 7) +#define X86_PAGE_GLOBAL (1 << 8) +#define X86_PAGE_NX (1 << 63) + +#define X86_PAGE_ENTRY_SIZE 8 +#define X86_NUM_PAGE_ENTRY (PAGE_SIZE / X86_PAGE_ENTRY_SIZE) + +#define PAGE_SIZE (0x1000) +# define PAGE_MASK (~(PAGE_SIZE - 1)) + +#define HUGE_PAGE_SIZE (0x200000) +# define HUGE_PAGE_MASK (~(HUGE_PAGE_SIZE - 1)) + +/* CPUID Leaf Definitions */ + +#define X86_64_CPUID_CAP 0x01 +# define X86_64_CPUID_01_SSE3 (1 << 0) +# define X86_64_CPUID_01_PCID (1 << 17) +# define X86_64_CPUID_01_X2APIC (1 << 21) +# define X86_64_CPUID_01_TSCDEA (1 << 24) +# define X86_64_CPUID_01_XSAVE (1 << 26) +# define X86_64_CPUID_01_RDRAND (1 << 30) +#define X86_64_CPUID_TSC 0x15 + +/* MSR Definitions */ + +#define MSR_FS_BASE 0xc0000100 /* 64bit FS base */ + +#define MSR_EFER 0xc0000080 +# define EFER_LME 0x00000100 + +#define MSR_MTRR_DEF_TYPE 0x000002ff +# define MTRR_ENABLE 0x00000800 + +#define MSR_IA32_TSC_DEADLINE 0x6e0 + +#define MSR_IA32_APIC_BASE 0x01b +# define MSR_IA32_APIC_EN 0x800 +# define MSR_IA32_APIC_X2APIC 0x400 +# define MSR_IA32_APIC_BSP 0x100 + +#define MSR_X2APIC_ID 0x802 +#define MSR_X2APIC_VER 0x803 +#define MSR_X2APIC_TPR 0x808 +#define MSR_X2APIC_PPR 0x80a +#define MSR_X2APIC_EOI 0x80b +#define MSR_X2APIC_LDR 0x80d + +#define MSR_X2APIC_SPIV 0x80f +# define MSR_X2APIC_SPIV_EN 0x100 + +#define MSR_X2APIC_ISR0 0x810 +#define MSR_X2APIC_ISR1 0x811 +#define MSR_X2APIC_ISR2 0x812 +#define MSR_X2APIC_ISR3 0x813 +#define MSR_X2APIC_ISR4 0x814 +#define MSR_X2APIC_ISR5 0x815 +#define MSR_X2APIC_ISR6 0x816 +#define MSR_X2APIC_ISR7 0x817 + +#define MSR_X2APIC_TMR0 0x818 +#define MSR_X2APIC_TMR1 0x819 +#define MSR_X2APIC_TMR2 0x81a +#define MSR_X2APIC_TMR3 0x81b +#define MSR_X2APIC_TMR4 0x81c +#define MSR_X2APIC_TMR5 0x81d +#define MSR_X2APIC_TMR6 0x81e +#define MSR_X2APIC_TMR7 0x81f + +#define MSR_X2APIC_IRR0 0x820 +#define MSR_X2APIC_IRR1 0x821 +#define MSR_X2APIC_IRR2 0x822 +#define MSR_X2APIC_IRR3 0x823 +#define MSR_X2APIC_IRR4 0x824 +#define MSR_X2APIC_IRR5 0x825 +#define MSR_X2APIC_IRR6 0x826 +#define MSR_X2APIC_IRR7 0x827 + +#define MSR_X2APIC_ESR 0x828 +#define MSR_X2APIC_ICR 0x830 +# define MSR_X2APIC_ICR_INIT 0x00000500 /* INIT/RESET */ +# define MSR_X2APIC_ICR_STARTUP 0x00000600 /* Startup IPI */ +# define MSR_X2APIC_ICR_DELIVS 0x00001000 /* Delivery status */ +# define MSR_X2APIC_ICR_ASSERT 0x00004000 /* Assert interrupt (vs deassert) */ +# define MSR_X2APIC_ICR_DEASSERT 0x00000000 +# define MSR_X2APIC_ICR_LEVEL 0x00008000 /* Level triggered */ +# define MSR_X2APIC_ICR_BCAST 0x00080000 /* Send to all APICs, including self. */ +# define MSR_X2APIC_ICR_BUSY 0x00001000 +# define MSR_X2APIC_ICR_FIXED 0x00000000 +#define MSR_X2APIC_LVTT 0x832 +# define MSR_X2APIC_LVTT_X1 0x0000000B /* divide counts by 1 */ +# define MSR_X2APIC_LVTT_PERIODIC 0x00020000 /* Periodic */ +# define MSR_X2APIC_LVTT_TSC_DEADLINE 0x00040000 /* Enable TSC DEADLINE One-shot timer */ +#define MSR_X2APIC_LVTTHER 0x833 +#define MSR_X2APIC_LVTPMR 0x834 +#define MSR_X2APIC_LINT0 0x835 +#define MSR_X2APIC_LINT1 0x836 +#define MSR_X2APIC_LERR 0x837 +# define MSR_X2APIC_MASKED 0x00010000 /* Interrupt masked */ +#define MSR_X2APIC_TMICT 0x838 +#define MSR_X2APIC_TMCCT 0x839 +#define MSR_X2APIC_TDCR 0x83e + +/* IOAPIC related Definitions */ + +#define IOAPIC_BASE 0xfec00000 +#define IOAPIC_REG_INDEX 0x00 +#define IOAPIC_REG_DATA 0x10 +# define IOAPIC_REG_ID 0x00 /* Register index: ID */ +# define IOAPIC_REG_VER 0x01 /* Register index: version */ +# define IOAPIC_REG_TABLE 0x10 /* Redirection table base */ +# define IOAPIC_PIN_DISABLE (1 << 16) /* Disable */ + +/* PIC related Definitions */ + +#define X86_IO_PORT_PIC1_CMD 0x20 +#define X86_IO_PORT_PIC1_DATA (X86_IO_PORT_PIC1_CMD + 1) +#define X86_IO_PORT_PIC2_CMD 0xA0 +#define X86_IO_PORT_PIC2_DATA (X86_IO_PORT_PIC2_CMD + 2) + +#define X86_PIC_INIT 0x11 +#define X86_PIC1_CASCADE 4 +#define X86_PIC2_CASCADE 2 +#define X86_PIC_8086 1 +#define X86_PIC_EOI 0x20 + +#define BITS_PER_LONG 64 + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* IDT data structures ****************************************************** + * + * The Interrupt Descriptor Table (IDT) is a data structure used by the x86 + * architecture to implement an interrupt vector table. The IDT is used by the + * processor to determine the correct response to interrupts and exceptions. + */ + +begin_packed_struct struct idt_entry_s +{ + uint16_t lobase; /* Lower 16-bits of vector address for interrupt */ + uint16_t sel; /* Kernel segment selector */ + uint8_t ist; /* 0..2 bits is Interrupt Stack Table offset, reset is zero */ + uint8_t flags; /* (See documentation) */ + uint16_t hibase; /* Upper 16-bits of vector address for interrupt */ + uint32_t xhibase; /* Top 32-bits of vector address for interrupt */ + uint32_t zero; /* reserved */ +} end_packed_struct; + +/* A struct describing a pointer to an array of interrupt handlers. This is + * in a format suitable for giving to 'lidt'. + */ + +begin_packed_struct struct idt_ptr_s +{ + uint16_t limit; + uint64_t base; /* The address of the first GDT entry */ +} end_packed_struct; + +/* GDT data structures ****************************************************** + * + * The Global Descriptor Table (GDT) is a data structure used by the x86 + * architecture to implement segments and privilege levels. The GDT is used + * by the processor to determine current privilege level and memory access right. + */ + +begin_packed_struct struct gdt_entry_s +{ + uint16_t limit_low; /* Lower 16-bits of segment limit */ + uint32_t base_low:24; /* Lower 24-bits of base address */ + uint8_t AC:1; /* 1: CPU accessed this segement */ + uint8_t RW:1; /* 1: Data Segement 0: Code Segement */ + uint8_t DC:1; /* Direction bit/Conforming bit. */ + uint8_t EX:1; /* 1: Segment can be executed */ + uint8_t S:1; /* S: 0:TSS 1:Code/Data Segement */ + uint8_t DPL:2; /* DPL */ + uint8_t P:1; /* Present? 1:Segment is preset */ + uint8_t limit_high:4; /* Upper 4-bits of segment limit */ + uint8_t RESV:1; /* Reserved */ + uint8_t L:1; /* 1: Long Mode 0: IA32e Mode */ + uint8_t SZ:1; /* 1: 32bit protected mode 0: 16bit protected mode */ + uint8_t GR:1; /* 0: Byte Granularity 1: 4KB Granularity */ + uint32_t base_high:8; /* Upper 8-bits of base address */ +} end_packed_struct; + +/* A struct describing a pointer to an array of global descriptors. This is + * in a format suitable for giving to 'lgdt'. + */ + +begin_packed_struct struct gdt_ptr_s +{ + uint16_t limit; + uint64_t base; /* The address of the first GDT entry */ +} end_packed_struct; + +/* IST data structures ****************************************************** + * + * The Interrupt Stack Table (GDT) is a data structure used by the x86-64 + * architecture to automatically switch stack on interrupt and privilege change. + * It allows setting up to 7 different stack for interrupts. + */ + +begin_packed_struct struct ist_s +{ + uint32_t reserved1; /* reserved */ + uint64_t RSP0; /* Stack for Ring 0 */ + uint64_t RSP1; /* Stack for Ring 1 */ + uint64_t RSP2; /* Stack for Ring 2 */ + uint64_t reserved2; /* reserved */ + uint64_t IST1; /* Interrupt Stack 1 */ + uint64_t IST2; /* Interrupt Stack 2 */ + uint64_t IST3; /* Interrupt Stack 3 */ + uint64_t IST4; /* Interrupt Stack 4 */ + uint64_t IST5; /* Interrupt Stack 5 */ + uint64_t IST6; /* Interrupt Stack 6 */ + uint64_t IST7; /* Interrupt Stack 7 */ + uint64_t reserved3; /* reserved */ + uint64_t reserved4; /* reserved */ + uint16_t reserved5; /* reserved */ + uint16_t IOPB_offset; /* IOPB_offset */ +} end_packed_struct; + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +static inline void setgdt(void *gdt, int size) +{ + struct gdt_ptr_s gdt_ptr; + gdt_ptr.limit = size; + gdt_ptr.base = (uintptr_t)gdt; + + asm volatile ("lgdt %0"::"m"(gdt_ptr):"memory"); +} + +static inline void setidt(void *idt, int size) +{ + struct idt_ptr_s idt_ptr; + idt_ptr.limit = size; + idt_ptr.base = (uintptr_t)idt; + + asm volatile ("lidt %0"::"m"(idt_ptr):"memory"); +} + +static inline uint64_t rdtsc(void) +{ + uint32_t lo; + uint32_t hi; + + asm volatile("rdtscp" : "=a" (lo), "=d" (hi)::"memory"); + return (uint64_t)lo | (((uint64_t)hi) << 32); +} + +static inline uint64_t _rdtsc(void) +{ + uint32_t lo; + uint32_t hi; + + asm volatile("rdtsc" : "=a" (lo), "=d" (hi)::"memory"); + return (uint64_t)lo | (((uint64_t)hi) << 32); +} + +static inline void set_pcid(uint64_t pcid) +{ + if (pcid < 4095) + { + asm volatile("mov %%cr3, %%rbx; andq $-4096, %%rbx; or %0, " + "%%rbx; mov %%rbx, %%cr3;" + ::"g"(pcid):"memory", "rbx", "rax"); + } + else + { + PANIC(); + } +} + +static inline unsigned long read_msr(unsigned int msr) +{ + uint32_t low; + uint32_t high; + + asm volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr)); + return low | ((unsigned long)high << 32); +} + +static inline void write_msr(unsigned int msr, unsigned long val) +{ + asm volatile("wrmsr" + : /* no output */ + : "c" (msr), "a" (val), "d" (val >> 32) + : "memory"); +} + +static inline uint64_t read_fsbase() +{ + uint64_t val; + asm volatile("rdfsbase %0" + : "=r" (val) + : /* no output */ + : "memory"); + + return val; +} + +static inline void write_fsbase(unsigned long val) +{ + asm volatile("wrfsbase %0" + : /* no output */ + : "r" (val) + : "memory"); +} + +static inline uint64_t read_gsbase() +{ + uint64_t val; + asm volatile("rdgsbase %0" + : "=r" (val) + : /* no output */ + : "memory"); + + return val; +} + +static inline void write_gsbase(unsigned long val) +{ + asm volatile("wrgsbase %0" + : /* no output */ + : "r" (val) + : "memory"); +} + +/* Return stack pointer */ + +static inline uint64_t up_getrsp() +{ + uint64_t regval; + + asm volatile( + "\tmovq %%rsp, %0\n" + : "=rm" (regval) + : + : "memory"); + return regval; +} + +/* Get segment registers */ + +static inline uint32_t up_getds() +{ + uint32_t regval; + + asm volatile( + "\tmov %%ds, %0\n" + : "=rm" (regval) + : + : "memory"); + return regval; +} + +static inline uint32_t up_getcs() +{ + uint32_t regval; + + asm volatile( + "\tmov %%cs, %0\n" + : "=rm" (regval) + : + : "memory"); + return regval; +} + +static inline uint32_t up_getss() +{ + uint32_t regval; + + asm volatile( + "\tmov %%ss, %0\n" + : "=rm" (regval) + : + : "memory"); + return regval; +} + +static inline uint32_t up_getes() +{ + uint32_t regval; + + asm volatile( + "\tmov %%es, %0\n" + : "=rm" (regval) + : + : "memory"); + return regval; +} + +static inline uint32_t up_getfs() +{ + uint32_t regval; + + asm volatile( + "\tmov %%fs, %0\n" + : "=rm" (regval) + : + : "memory"); + return regval; +} + +static inline uint32_t up_getgs() +{ + uint32_t regval; + + asm volatile( + "\tmov %%gs, %0\n" + : "=rm" (regval) + : + : "memory"); + return regval; +} +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* These are defined in intel64_head.S */ + +extern volatile uint8_t pdpt_low; +extern volatile uint8_t pd_low; +extern volatile uint8_t pt_low; + +extern volatile uint8_t ist64_low; +extern volatile uint8_t gdt64_low; +extern volatile uint8_t gdt64_ist_low; +extern volatile uint8_t gdt64_low_end; + +/* The actual address of the page table and gdt/ist after mapping the kernel in high address*/ + +volatile uint64_t *pdpt; +volatile uint64_t *pd; +volatile uint64_t *pt; + +volatile struct ist_s *ist64; +volatile struct gdt_entry_s *gdt64; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +int up_map_region(void *base, int size, int flags); +void x86_64_check_and_enable_capability(void); + +extern void __enable_sse3(void); +extern void __enable_pcid(void); + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_X86_64_INCLUDE_INTEL64_ARCH_H */ diff --git a/arch/x86_64/include/intel64/inttypes.h b/arch/x86_64/include/intel64/inttypes.h new file mode 100644 index 00000000000..6cee7919d78 --- /dev/null +++ b/arch/x86_64/include/intel64/inttypes.h @@ -0,0 +1,230 @@ +/**************************************************************************** + * arch/x86_64/include/intel64/inttypes.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_INCLUDE_INTEL64_INTTYPES_H +#define __ARCH_X86_64_INCLUDE_INTEL64_INTTYPES_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define PRId8 "d" +#define PRId16 "d" +#define PRId32 "d" +#define PRId64 "lld" + +#define PRIdLEAST8 "d" +#define PRIdLEAST16 "d" +#define PRIdLEAST32 "d" +#define PRIdLEAST64 "lld" + +#define PRIdFAST8 "d" +#define PRIdFAST16 "d" +#define PRIdFAST32 "d" +#define PRIdFAST64 "lld" + +#define PRIdMAX "lld" +#define PRIdPTR "lld" + +#define PRIi8 "i" +#define PRIi16 "i" +#define PRIi32 "i" +#define PRIi64 "lli" + +#define PRIiLEAST8 "i" +#define PRIiLEAST16 "i" +#define PRIiLEAST32 "i" +#define PRIiLEAST64 "lli" + +#define PRIiFAST8 "i" +#define PRIiFAST16 "i" +#define PRIiFAST32 "i" +#define PRIiFAST64 "lli" + +#define PRIiMAX "lli" +#define PRIiPTR "lli" + +#define PRIo8 "o" +#define PRIo16 "o" +#define PRIo32 "o" +#define PRIo64 "llo" + +#define PRIoLEAST8 "o" +#define PRIoLEAST16 "o" +#define PRIoLEAST32 "o" +#define PRIoLEAST64 "llo" + +#define PRIoFAST8 "o" +#define PRIoFAST16 "o" +#define PRIoFAST32 "o" +#define PRIoFAST64 "llo" + +#define PRIoMAX "llo" +#define PRIoPTR "llo" + +#define PRIu8 "u" +#define PRIu16 "u" +#define PRIu32 "u" +#define PRIu64 "llu" + +#define PRIuLEAST8 "u" +#define PRIuLEAST16 "u" +#define PRIuLEAST32 "u" +#define PRIuLEAST64 "llu" + +#define PRIuFAST8 "u" +#define PRIuFAST16 "u" +#define PRIuFAST32 "u" +#define PRIuFAST64 "llu" + +#define PRIuMAX "llu" +#define PRIuPTR "llu" + +#define PRIx8 "x" +#define PRIx16 "x" +#define PRIx32 "x" +#define PRIx64 "llx" + +#define PRIxLEAST8 "x" +#define PRIxLEAST16 "x" +#define PRIxLEAST32 "x" +#define PRIxLEAST64 "llx" + +#define PRIxFAST8 "x" +#define PRIxFAST16 "x" +#define PRIxFAST32 "x" +#define PRIxFAST64 "llx" + +#define PRIxMAX "llx" +#define PRIxPTR "llx" + +#define PRIX8 "X" +#define PRIX16 "X" +#define PRIX32 "X" +#define PRIX64 "llX" + +#define PRIXLEAST8 "X" +#define PRIXLEAST16 "X" +#define PRIXLEAST32 "X" +#define PRIXLEAST64 "llX" + +#define PRIXFAST8 "X" +#define PRIXFAST16 "X" +#define PRIXFAST32 "X" +#define PRIXFAST64 "llX" + +#define PRIXMAX "llX" +#define PRIXPTR "llX" + +#define SCNd8 "hhd" +#define SCNd16 "hd" +#define SCNd32 "d" +#define SCNd64 "lld" + +#define SCNdLEAST8 "hhd" +#define SCNdLEAST16 "hd" +#define SCNdLEAST32 "d" +#define SCNdLEAST64 "lld" + +#define SCNdFAST8 "hhd" +#define SCNdFAST16 "hd" +#define SCNdFAST32 "d" +#define SCNdFAST64 "lld" + +#define SCNdMAX "lld" +#define SCNdPTR "lld" + +#define SCNi8 "hhi" +#define SCNi16 "hi" +#define SCNi32 "i" +#define SCNi64 "lli" + +#define SCNiLEAST8 "hhi" +#define SCNiLEAST16 "hi" +#define SCNiLEAST32 "i" +#define SCNiLEAST64 "lli" + +#define SCNiFAST8 "hhi" +#define SCNiFAST16 "hi" +#define SCNiFAST32 "i" +#define SCNiFAST64 "lli" + +#define SCNiMAX "lli" +#define SCNiPTR "lli" + +#define SCNo8 "hho" +#define SCNo16 "ho" +#define SCNo32 "o" +#define SCNo64 "llo" + +#define SCNoLEAST8 "hho" +#define SCNoLEAST16 "ho" +#define SCNoLEAST32 "o" +#define SCNoLEAST64 "llo" + +#define SCNoFAST8 "hho" +#define SCNoFAST16 "ho" +#define SCNoFAST32 "o" +#define SCNoFAST64 "llo" + +#define SCNoMAX "llo" +#define SCNoPTR "llo" + +#define SCNu8 "hhu" +#define SCNu16 "hu" +#define SCNu32 "u" +#define SCNu64 "llu" + +#define SCNuLEAST8 "hhu" +#define SCNuLEAST16 "hu" +#define SCNuLEAST32 "u" +#define SCNuLEAST64 "llu" + +#define SCNuFAST8 "hhu" +#define SCNuFAST16 "hu" +#define SCNuFAST32 "u" +#define SCNuFAST64 "llu" + +#define SCNuMAX "llu" +#define SCNuPTR "u" + +#define SCNx8 "hhx" +#define SCNx16 "hx" +#define SCNx32 "x" +#define SCNx64 "llx" + +#define SCNxLEAST8 "hhx" +#define SCNxLEAST16 "hx" +#define SCNxLEAST32 "x" +#define SCNxLEAST64 "llx" + +#define SCNxFAST8 "hhx" +#define SCNxFAST16 "hx" +#define SCNxFAST32 "x" +#define SCNxFAST64 "llx" + +#define SCNxMAX "llx" +#define SCNxPTR "x" + +#endif /* __ARCH_X86_64_INCLUDE_INTEL64_INTTYPES_H */ diff --git a/arch/x86_64/include/intel64/io.h b/arch/x86_64/include/intel64/io.h new file mode 100644 index 00000000000..66b91fe7757 --- /dev/null +++ b/arch/x86_64/include/intel64/io.h @@ -0,0 +1,206 @@ +/**************************************************************************** + * arch/x86_64/include/intel64/io.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. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, only indirectly + * through arch/io.h + */ + +#ifndef __ARCH_X86_64_INCLUDE_INTEL64_IO_H +#define __ARCH_X86_64_INCLUDE_INTEL64_IO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +/* Standard x86 Port I/O */ + +static inline void outb(uint8_t regval, uint16_t port) +{ + asm volatile( + "\toutb %0,%1\n" + : + : "a" (regval), "dN" (port) + ); +} + +static inline uint8_t inb(uint16_t port) +{ + uint8_t regval; + asm volatile( + "\tinb %1,%0\n" + : "=a" (regval) + : "dN" (port) + ); + return regval; +} + +static inline void outw(uint16_t regval, uint16_t port) +{ + asm volatile( + "\toutw %0,%1\n" + : + : "a" (regval), "dN" (port) + ); +} + +static inline uint16_t inw(uint16_t port) +{ + uint16_t regval; + + asm volatile( + "\tinw %1,%0\n" + : "=a" (regval) + : "dN" (port) + ); + return regval; +} + +static inline void outl(uint32_t regval, uint16_t port) +{ + asm volatile( + "\toutl %0,%1\n" + : + : "a" (regval), "dN" (port) + ); +} + +static inline uint32_t inl(uint16_t port) +{ + uint32_t regval; + asm volatile( + "\tinl %1,%0\n" + : "=a" (regval) + : "dN" (port) + ); + return regval; +} + +/* MMIO */ + +static inline uint8_t mmio_read8(void *address) +{ + return *(volatile uint8_t *)address; +} + +static inline uint16_t mmio_read16(void *address) +{ + return *(volatile uint16_t *)address; +} + +static inline uint32_t mmio_read32(void *address) +{ + uint32_t value; + + /* Assembly-encoded to match the hypervisor MMIO parser support */ + + asm volatile("movl (%1),%0" : "=r" (value) : "r" (address)); + return value; +} + +static inline uint64_t mmio_read64(void *address) +{ + return *(volatile uint64_t *)address; +} + +static inline void mmio_write8(void *address, uint8_t value) +{ + *(volatile uint8_t *)address = value; +} + +static inline void mmio_write16(void *address, uint16_t value) +{ + *(volatile uint16_t *)address = value; +} + +static inline void mmio_write32(void *address, uint32_t value) +{ + /* Assembly-encoded to match the hypervisor MMIO parser support */ + + asm volatile("movl %0,(%1)" : : "r" (value), "r" (address)); +} + +static inline void mmio_write64(void *address, uint64_t value) +{ + *(volatile uint64_t *)address = value; +} + +static inline void up_trash_cpu(void) +{ + for (; ; ) + { + asm volatile ("cli;hlt;"); + } + + asm("ud2":::"memory"); +} + +static inline void up_invalid_TLB(uintptr_t start, uintptr_t end) +{ + uintptr_t i; + + start = start & PAGE_MASK; + end = (end + PAGE_SIZE - 1) & PAGE_MASK; + + for (i = start; i < end; i += PAGE_SIZE) + { + asm("invlpg %0;":: "m"(i):"memory"); + } +} + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_X86_64_INCLUDE_INTEL64_IO_H */ diff --git a/arch/x86_64/include/intel64/irq.h b/arch/x86_64/include/intel64/irq.h new file mode 100644 index 00000000000..c612716b30e --- /dev/null +++ b/arch/x86_64/include/intel64/irq.h @@ -0,0 +1,304 @@ +/**************************************************************************** + * arch/x86_64/include/intel64/irq.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. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, only indirectly + * through nuttx/irq.h + */ + +#ifndef __ARCH_X86_64_INCLUDE_INTEL64_IRQ_H +#define __ARCH_X86_64_INCLUDE_INTEL64_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +# include +# include +# include +# include +# include +# include +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* ISR and IRQ numbers */ + +#define ISR0 0 /* Division by zero exception */ +#define ISR1 1 /* Debug exception */ +#define ISR2 2 /* Non maskable interrupt */ +#define ISR3 3 /* Breakpoint exception */ +#define ISR4 4 /* 'Into detected overflow' */ +#define ISR5 5 /* Out of bounds exception */ +#define ISR6 6 /* Invalid opcode exception */ +#define ISR7 7 /* No coprocessor exception */ +#define ISR8 8 /* Double fault (pushes an error code) */ +#define ISR9 9 /* Coprocessor segment overrun */ +#define ISR10 10 /* Bad TSS (pushes an error code) */ +#define ISR11 11 /* Segment not present (pushes an error code) */ +#define ISR12 12 /* Stack fault (pushes an error code) */ +#define ISR13 13 /* General protection fault (pushes an error code) */ +#define ISR14 14 /* Page fault (pushes an error code) */ +#define ISR15 15 /* Unknown interrupt exception */ +#define ISR16 16 /* Coprocessor fault */ +#define ISR17 17 /* Alignment check exception */ +#define ISR18 18 /* Machine check exception */ +#define ISR19 19 /* SIMD Float-Point Exception*/ +#define ISR20 20 /* Virtualization Exception */ +#define ISR21 21 /* Reserved */ +#define ISR22 22 /* Reserved */ +#define ISR23 23 /* Reserved */ +#define ISR24 24 /* Reserved */ +#define ISR25 25 /* Reserved */ +#define ISR26 26 /* Reserved */ +#define ISR27 27 /* Reserved */ +#define ISR28 28 /* Reserved */ +#define ISR29 29 /* Reserved */ +#define ISR30 30 /* Security Exception */ +#define ISR31 31 /* Reserved */ + +#define IRQ0 32 /* System timer (cannot be changed) */ +#define IRQ1 33 /* Keyboard controller (cannot be changed) */ +#define IRQ2 34 /* Cascaded signals from IRQs 8~15 */ +#define IRQ3 35 /* Serial port controller for COM2/4 */ +#define IRQ4 36 /* serial port controller for COM1/3 */ +#define IRQ5 37 /* LPT port 2 or sound card */ +#define IRQ6 38 /* Floppy disk controller */ +#define IRQ7 39 /* LPT port 1 or sound card */ +#define IRQ8 40 /* Real time clock (RTC) */ +#define IRQ9 41 /* Open interrupt/available or SCSI host adapter */ +#define IRQ10 42 /* Open interrupt/available or SCSI or NIC */ +#define IRQ11 43 /* Open interrupt/available or SCSI or NIC */ +#define IRQ12 44 /* Mouse on PS/2 connector */ +#define IRQ13 45 /* Math coprocessor */ +#define IRQ14 46 /* Primary ATA channel */ +#define IRQ15 47 /* Secondary ATA channel */ + +#define IRQ_ERROR 51 /* APIC Error */ +#define IRQ_SPURIOUS 0xff /* Spurious Interrupts */ + +#define NR_IRQS 48 + +/* Common register save structure created by up_saveusercontext() and by + * ISR/IRQ interrupt processing. + */ + +#define XCPTCONTEXT_XMM_AREA_SIZE 512 +#define XMMAREA_OFFSET XCPTCONTEXT_XMM_AREA_SIZE / 8 + +/* Data segments */ + +#define REG_ALIGN (0 + XMMAREA_OFFSET) /* " " "" " " "" " " " " */ +#define REG_FS (1 + XMMAREA_OFFSET) /* " " "" " " "" " " " " */ +#define REG_GS (2 + XMMAREA_OFFSET) /* " " "" " " "" " " " " */ +#define REG_ES (3 + XMMAREA_OFFSET) /* " " "" " " "" " " " " */ +#define REG_DS (4 + XMMAREA_OFFSET) /* Data segment selector */ + +/* Remaining regs */ + +#define REG_RAX (5 + XMMAREA_OFFSET) /* " " "" " " */ +#define REG_RBX (6 + XMMAREA_OFFSET) /* " " "" " " */ +#define REG_RBP (7 + XMMAREA_OFFSET) /* " " "" " " */ +#define REG_R10 (8 + XMMAREA_OFFSET) /* " " "" " " */ +#define REG_R11 (9 + XMMAREA_OFFSET) /* " " "" " " */ +#define REG_R12 (10 + XMMAREA_OFFSET) /* " " "" " " */ +#define REG_R13 (11 + XMMAREA_OFFSET) /* " " "" " " */ +#define REG_R14 (12 + XMMAREA_OFFSET) /* " " "" " " */ +#define REG_R15 (13 + XMMAREA_OFFSET) /* " " "" " " */ + +/* ABI calling convention */ + +#define REG_R9 (14 + XMMAREA_OFFSET) /* " " "" " " */ +#define REG_R8 (15 + XMMAREA_OFFSET) /* " " "" " " */ +#define REG_RCX (16 + XMMAREA_OFFSET) /* " " "" " " */ +#define REG_RDX (17 + XMMAREA_OFFSET) /* " " "" " " */ +#define REG_RSI (18 + XMMAREA_OFFSET) /* " " "" " " */ +#define REG_RDI (19 + XMMAREA_OFFSET) /* " " "" " " */ + +/* IRQ saved */ + +#define REG_ERRCODE (20 + XMMAREA_OFFSET) /* Error code */ +#define REG_RIP (21 + XMMAREA_OFFSET) /* Pushed by process on interrupt processing */ +#define REG_CS (22 + XMMAREA_OFFSET) /* " " "" " " "" " " " " */ +#define REG_RFLAGS (23 + XMMAREA_OFFSET) /* " " "" " " "" " " " " */ +#define REG_RSP (24 + XMMAREA_OFFSET) /* " " "" " " "" " " " " */ +#define REG_SS (25 + XMMAREA_OFFSET) /* " " "" " " "" " " " " */ + +/* NOTE 2: This is not really state data. Rather, this is just a convenient + * way to pass parameters from the interrupt handler to C code. + */ + +#define XCPTCONTEXT_REGS (26 + XCPTCONTEXT_XMM_AREA_SIZE / 8) +#define XCPTCONTEXT_SIZE (8 * XCPTCONTEXT_REGS + XCPTCONTEXT_XMM_AREA_SIZE) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +enum ioapic_trigger_mode +{ + TRIGGER_RISING_EDGE = 0, + TRIGGER_FALLING_EDGE = (1 << 13), + TRIGGER_LEVEL_ACTIVE_HIGH = 1 << 15, + TRIGGER_LEVEL_ACTIVE_LOW = (1 << 15) | (1 << 13), +}; + +/* This struct defines the way the registers are stored */ + +struct xcptcontext +{ + /* The following function pointer is non-zero if there are pending signals + * to be processed. + */ + +#ifndef CONFIG_DISABLE_SIGNALS + void *sigdeliver; /* Actual type is sig_deliver_t */ + + /* These are saved copies of instruction pointer and EFLAGS used during + * signal processing. + */ + + uint64_t saved_rip; + uint64_t saved_rflags; + uint64_t saved_rsp; +#endif + + /* Register save area */ + + uint64_t regs[XCPTCONTEXT_REGS] __attribute__((aligned (16))); +}; +#endif + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* Name: up_irq_save, up_irq_restore, and friends. + * + * NOTE: This function should never be called from application code and, + * as a general rule unless you really know what you are doing, this + * function should not be called directly from operation system code either: + * Typically, the wrapper functions, enter_critical_section() and + * leave_critical section(), are probably what you really want. + */ + +/* Get the current FLAGS register contents */ + +static inline irqstate_t irqflags() +{ + irqstate_t flags; + + asm volatile( + "\tpushfq\n" + "\tpopq %0\n" + : "=rm" (flags) + : + : "memory"); + return flags; +} + +/* Get a sample of the FLAGS register, determine if interrupts are disabled. + * If the X86_FLAGS_IF is cleared by cli, then interrupts are disabled. If + * if the X86_FLAGS_IF is set by sti, then interrupts are enable. + */ + +static inline bool up_irq_disabled(irqstate_t flags) +{ + return ((flags & X86_64_RFLAGS_IF) == 0); +} + +static inline bool up_irq_enabled(irqstate_t flags) +{ + return ((flags & X86_64_RFLAGS_IF) != 0); +} + +/* Disable interrupts unconditionally */ + +static inline void up_irq_disable(void) +{ + asm volatile("cli": : :"memory"); +} + +/* Enable interrupts unconditionally */ + +static inline void up_irq_enable(void) +{ + asm volatile("sti": : :"memory"); +} + +/* Disable interrupts, but return previous interrupt state */ + +static inline irqstate_t up_irq_save(void) +{ + irqstate_t flags = irqflags(); + up_irq_disable(); + return flags; +} + +/* Conditionally disable interrupts */ + +static inline void up_irq_restore(irqstate_t flags) +{ + if (up_irq_enabled(flags)) + { + up_irq_enable(); + } +} + +static inline unsigned int up_apic_cpu_id(void) +{ + return read_msr(MSR_X2APIC_ID); +} + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void up_ioapic_pin_set_vector(unsigned int pin, + enum ioapic_trigger_mode trigger_mode, + unsigned int vector); + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_X86_INCLUDE_I486_IRQ_H */ + diff --git a/arch/x86_64/include/intel64/limits.h b/arch/x86_64/include/intel64/limits.h new file mode 100644 index 00000000000..ae7cdfc9dea --- /dev/null +++ b/arch/x86_64/include/intel64/limits.h @@ -0,0 +1,71 @@ +/**************************************************************************** + * arch/x86_64/include/intel64/limits.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_INCLUDE_INTEL64_LIMITS_H +#define __ARCH_X86_64_INCLUDE_INTEL64_LIMITS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define CHAR_BIT 8 +#define SCHAR_MIN (-SCHAR_MAX - 1) +#define SCHAR_MAX 127 +#define UCHAR_MAX 255 + +/* These could be different on machines where char is unsigned */ + +#ifdef __CHAR_UNSIGNED__ +#define CHAR_MIN 0 +#define CHAR_MAX UCHAR_MAX +#else +#define CHAR_MIN SCHAR_MIN +#define CHAR_MAX SCHAR_MAX +#endif + +#define SHRT_MIN (-SHRT_MAX - 1) +#define SHRT_MAX 32767 +#define USHRT_MAX 65535U + +#define INT_MIN (-INT_MAX - 1) +#define INT_MAX 2147483647 +#define UINT_MAX 4294967295U + +/* For 64-bit x86 with Linux ABI, long is identical to long long */ + +#define LONG_MIN LLONG_MIN +#define LONG_MAX LLONG_MAX +#define ULONG_MAX ULLONG_MAX + +#define LLONG_MIN (-LLONG_MAX - 1) +#define LLONG_MAX 9223372036854775807LL +#define ULLONG_MAX 18446744073709551615ULL + +/* A pointer is 8 bytes */ + +#define PTR_MIN (-PTR_MAX - 1) +#define PTR_MAX LLONG_MAX +#define UPTR_MAX ULLONG_MAX + +#endif /* __ARCH_X86_64_INCLUDE_INTEL64_LIMITS_H */ diff --git a/arch/x86_64/include/intel64/syscall.h b/arch/x86_64/include/intel64/syscall.h new file mode 100644 index 00000000000..f8acd90beae --- /dev/null +++ b/arch/x86_64/include/intel64/syscall.h @@ -0,0 +1,156 @@ +/**************************************************************************** + * arch/x86_64/include/intel64/syscall.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. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, only indirectly + * through include/syscall.h or include/sys/sycall.h + */ + +#ifndef __ARCH_X86_64_INCLUDE_INTEL64_SYSCALL_H +#define __ARCH_X86_64_INCLUDE_INTEL64_SYSCALL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +void enable_syscall(void); +void syscall_entry(void); +uint64_t syscall_handler(unsigned long nbr, uintptr_t parm1, uintptr_t parm2, + uintptr_t parm3, uintptr_t parm4, uintptr_t parm5, + uintptr_t parm6); +uint64_t linux_interface(unsigned long nbr, uintptr_t parm1, uintptr_t parm2, + uintptr_t parm3, uintptr_t parm4, uintptr_t parm5, + uintptr_t parm6); + +/* SWI with SYS_ call number and six parameters */ + +static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1, + uintptr_t parm2, uintptr_t parm3, + uintptr_t parm4, uintptr_t parm5, + uintptr_t parm6); + +/* SWI with SYS_ call number and no parameters */ + +static inline uintptr_t sys_call0(unsigned int nbr) +{ + return sys_call6(nbr, 0, 0, 0, 0, 0, 0); +} + +/* SWI with SYS_ call number and one parameter */ + +static inline uintptr_t sys_call1(unsigned int nbr, uintptr_t parm1) +{ + return sys_call6(nbr, parm1, 0, 0, 0, 0, 0); +} + +/* SWI with SYS_ call number and two parameters */ + +static inline uintptr_t sys_call2(unsigned int nbr, uintptr_t parm1, + uintptr_t parm2) +{ + return sys_call6(nbr, parm1, parm2, 0, 0, 0, 0); +} + +/* SWI with SYS_ call number and three parameters */ + +static inline uintptr_t sys_call3(unsigned int nbr, uintptr_t parm1, + uintptr_t parm2, uintptr_t parm3) +{ + return sys_call6(nbr, parm1, parm2, parm3, 0, 0, 0); +} + +/* SWI with SYS_ call number and four parameters */ + +static inline uintptr_t sys_call4(unsigned int nbr, uintptr_t parm1, + uintptr_t parm2, uintptr_t parm3, + uintptr_t parm4) +{ + return sys_call6(nbr, parm1, parm2, parm3, parm4, 0, 0); +} + +/* SWI with SYS_ call number and five parameters */ + +static inline uintptr_t sys_call5(unsigned int nbr, uintptr_t parm1, + uintptr_t parm2, uintptr_t parm3, + uintptr_t parm4, uintptr_t parm5) +{ + return sys_call6(nbr, parm1, parm2, parm3, parm4, parm5, 0); +} + +static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1, + uintptr_t parm2, uintptr_t parm3, + uintptr_t parm4, uintptr_t parm5, + uintptr_t parm6) +{ + register uint64_t reg0 __asm__("rax") = (uint64_t)(nbr); + register uint64_t reg1 __asm__("rdi") = (uint64_t)(parm1); + register uint64_t reg2 __asm__("rsi") = (uint64_t)(parm2); + register uint64_t reg3 __asm__("rdx") = (uint64_t)(parm3); + register uint64_t reg4 __asm__("r10") = (uint64_t)(parm4); + register uint64_t reg5 __asm__("r8") = (uint64_t)(parm5); + register uint64_t reg6 __asm__("r9") = (uint64_t)(parm6); + + __asm__ __volatile__ + ( + "syscall" + : "=r"(reg0) + : "r"(reg0), "r"(reg1), "r"(reg2), + "r"(reg3), "r"(reg4), "r"(reg5), "r"(reg6) + : "memory" + ); + + return reg0; +} + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_X86_64_INCLUDE_INTEL64_SYSCALL_H */ + diff --git a/arch/x86_64/include/intel64/types.h b/arch/x86_64/include/intel64/types.h new file mode 100644 index 00000000000..fd6a43d9f4b --- /dev/null +++ b/arch/x86_64/include/intel64/types.h @@ -0,0 +1,105 @@ +/**************************************************************************** + * arch/x86_64/include/intel64/types.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. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, only + * indirectly through arch/types.h (which is, in turn only accessed + * through sys/types.h or stdint.h). + */ + +#ifndef __ARCH_X86_64_INCLUDE_INTEL64_TYPES_H +#define __ARCH_X86_64_INCLUDE_INTEL64_TYPES_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Type Declarations + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/* These are the sizes of the standard integer types. NOTE that these type + * names have a leading underscore character. This file will be included + * (indirectly) by include/stdint.h and typedef'ed to the final name without + * the underscore character. This roundabout way of doings things allows + * the stdint.h to be removed from the include/ directory in the event that + * the user prefers to use the definitions provided by their toolchain header + * files + */ + +typedef signed char _int8_t; +typedef unsigned char _uint8_t; + +typedef signed short _int16_t; +typedef unsigned short _uint16_t; + +typedef signed int _int32_t; +typedef unsigned int _uint32_t; + +typedef signed long long _int64_t; +typedef unsigned long long _uint64_t; +#define __INT64_DEFINED + +/* A pointer is 8 bytes */ + +typedef signed long long _intptr_t; +typedef unsigned long long _uintptr_t; + +#if defined(__SIZE_TYPE__) +/* If __SIZE_TYPE__ is defined we define ssize_t based on size_t. + * We simply change "unsigned" to "signed" for this single definition + * to make sure ssize_t and size_t only differ by their signedness. + */ + +#define unsigned signed +typedef __SIZE_TYPE__ _ssize_t; +#undef unsigned +typedef __SIZE_TYPE__ _size_t; + +#elif defined(CONFIG_ARCH_SIZET_LONG) + +typedef signed long _ssize_t; +typedef unsigned long _size_t; + +#else + +typedef signed int _ssize_t; +typedef unsigned int _size_t; + +#endif + +/* This is the size of the interrupt state save returned by + * up_irq_save() + */ + +typedef unsigned long irqstate_t; + +#endif /* __ASSEMBLY__ */ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __ARCH_X86_64_INCLUDE_INTEL64_TYPES_H */ diff --git a/arch/x86_64/include/inttypes.h b/arch/x86_64/include/inttypes.h new file mode 100644 index 00000000000..f07e08ac91c --- /dev/null +++ b/arch/x86_64/include/inttypes.h @@ -0,0 +1,36 @@ +/**************************************************************************** + * arch/x86_64/include/inttypes.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_INCLUDE_INTTYPES_H +#define __ARCH_X86_64_INCLUDE_INTTYPES_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#ifdef CONFIG_ARCH_INTEL64 +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#endif /* __ARCH_X86_64_INCLUDE_INTTYPES_H */ diff --git a/arch/x86_64/include/io.h b/arch/x86_64/include/io.h new file mode 100644 index 00000000000..0e8f49bd95e --- /dev/null +++ b/arch/x86_64/include/io.h @@ -0,0 +1,72 @@ +/**************************************************************************** + * arch/x86_64/include/io.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_INCLUDE_IO_H +#define __ARCH_X86_64_INCLUDE_IO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Include architecture-specific IO definitions (These are probably common + * across all architectures, but this gives a little bit of flexibility). + */ + +#ifdef CONFIG_ARCH_INTEL64 +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_X86_64_INCLUDE_IO_H */ + diff --git a/arch/x86_64/include/irq.h b/arch/x86_64/include/irq.h new file mode 100644 index 00000000000..5a27f037f5f --- /dev/null +++ b/arch/x86_64/include/irq.h @@ -0,0 +1,84 @@ +/**************************************************************************** + * arch/x86_64/include/irq.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. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, only indirectly + * through nuttx/irq.h + */ + +#ifndef __ARCH_X86_64_INCLUDE_IRQ_H +#define __ARCH_X86_64_INCLUDE_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Include NuttX-specific IRQ definitions */ + +#include + +/* Include chip-specific IRQ definitions (including IRQ numbers) */ + +#include + +/* Include architecture-specific IRQ definitions (including register save + * structure and up_irq_save()/up_irq_restore() macros). + */ + +#ifdef CONFIG_ARCH_INTEL64 +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_X86_64_INCLUDE_IRQ_H */ + diff --git a/arch/x86_64/include/limits.h b/arch/x86_64/include/limits.h new file mode 100644 index 00000000000..57c858fab65 --- /dev/null +++ b/arch/x86_64/include/limits.h @@ -0,0 +1,38 @@ +/**************************************************************************** + * arch/x86_64/include/limits.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_INCLUDE_LIMITS_H +#define __ARCH_X86_64_INCLUDE_LIMITS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Include architecture-specific limits */ + +#ifdef CONFIG_ARCH_INTEL64 +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#endif /* __ARCH_X86_64_INCLUDE_LIMITS_H */ diff --git a/arch/x86_64/include/multiboot2.h b/arch/x86_64/include/multiboot2.h new file mode 100644 index 00000000000..ba117535a3b --- /dev/null +++ b/arch/x86_64/include/multiboot2.h @@ -0,0 +1,438 @@ +/**************************************************************************** + * multiboot2.h - Multiboot 2 header file. + * + * Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY + * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************/ + +#ifndef __ARCH_X86_64_INCLUDE_MULTIBOOT2_H +#define __ARCH_X86_64_INCLUDE_MULTIBOOT2_H 1 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* How many bytes from the start of the file we search for the header. */ + +#define MULTIBOOT_SEARCH 32768 +#define MULTIBOOT_HEADER_ALIGN 8 + +/* The magic field should contain this. */ + +#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6 + +/* This should be in %eax. */ + +#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289 + +/* Alignment of multiboot modules. */ + +#define MULTIBOOT_MOD_ALIGN 0x00001000 + +/* Alignment of the multiboot info structure. */ + +#define MULTIBOOT_INFO_ALIGN 0x00000008 + +/* Flags set in the ’flags’ member of the multiboot header. */ + +#define MULTIBOOT_TAG_ALIGN 8 +#define MULTIBOOT_TAG_TYPE_END 0 +#define MULTIBOOT_TAG_TYPE_CMDLINE 1 +#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2 +#define MULTIBOOT_TAG_TYPE_MODULE 3 +#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4 +#define MULTIBOOT_TAG_TYPE_BOOTDEV 5 +#define MULTIBOOT_TAG_TYPE_MMAP 6 +#define MULTIBOOT_TAG_TYPE_VBE 7 +#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8 +#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9 +#define MULTIBOOT_TAG_TYPE_APM 10 +#define MULTIBOOT_TAG_TYPE_EFI32 11 +#define MULTIBOOT_TAG_TYPE_EFI64 12 +#define MULTIBOOT_TAG_TYPE_SMBIOS 13 +#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14 +#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15 +#define MULTIBOOT_TAG_TYPE_NETWORK 16 +#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17 +#define MULTIBOOT_TAG_TYPE_EFI_BS 18 +#define MULTIBOOT_TAG_TYPE_EFI32_IH 19 +#define MULTIBOOT_TAG_TYPE_EFI64_IH 20 +#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21 + +#define MULTIBOOT_HEADER_TAG_END 0 +#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1 +#define MULTIBOOT_HEADER_TAG_ADDRESS 2 +#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3 +#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4 +#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5 +#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6 +#define MULTIBOOT_HEADER_TAG_EFI_BS 7 +#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8 +#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9 +#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10 + +#define MULTIBOOT_ARCHITECTURE_I386 0 +#define MULTIBOOT_ARCHITECTURE_MIPS32 4 +#define MULTIBOOT_HEADER_TAG_OPTIONAL 1 + +#define MULTIBOOT_LOAD_PREFERENCE_NONE 0 +#define MULTIBOOT_LOAD_PREFERENCE_LOW 1 +#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2 + +#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1 +#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2 + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +typedef unsigned char multiboot_uint8_t; +typedef unsigned short multiboot_uint16_t; +typedef unsigned int multiboot_uint32_t; +typedef unsigned long long multiboot_uint64_t; + +struct multiboot_header +{ + /* Must be MULTIBOOT_MAGIC - see above. */ + + multiboot_uint32_t magic; + + /* ISA */ + + multiboot_uint32_t architecture; + + /* Total header length. */ + + multiboot_uint32_t header_length; + + /* The above fields plus this one must equal 0 mod 2^32. */ + + multiboot_uint32_t checksum; +}; + +struct multiboot_header_tag +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; +}; + +struct multiboot_header_tag_information_request +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; + multiboot_uint32_t requests[0]; +}; + +struct multiboot_header_tag_address +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; + multiboot_uint32_t header_addr; + multiboot_uint32_t load_addr; + multiboot_uint32_t load_end_addr; + multiboot_uint32_t bss_end_addr; +}; + +struct multiboot_header_tag_entry_address +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; + multiboot_uint32_t entry_addr; +}; + +struct multiboot_header_tag_console_flags +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; + multiboot_uint32_t console_flags; +}; + +struct multiboot_header_tag_framebuffer +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; + multiboot_uint32_t width; + multiboot_uint32_t height; + multiboot_uint32_t depth; +}; + +struct multiboot_header_tag_module_align +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; +}; + +struct multiboot_header_tag_relocatable +{ + multiboot_uint16_t type; + multiboot_uint16_t flags; + multiboot_uint32_t size; + multiboot_uint32_t min_addr; + multiboot_uint32_t max_addr; + multiboot_uint32_t align; + multiboot_uint32_t preference; +}; + +struct multiboot_color +{ + multiboot_uint8_t red; + multiboot_uint8_t green; + multiboot_uint8_t blue; +}; + +struct multiboot_mmap_entry +{ + multiboot_uint64_t addr; + multiboot_uint64_t len; +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 +#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 +#define MULTIBOOT_MEMORY_NVS 4 +#define MULTIBOOT_MEMORY_BADRAM 5 + multiboot_uint32_t type; + multiboot_uint32_t zero; +}; + +typedef struct multiboot_mmap_entry multiboot_memory_map_t; + +struct multiboot_tag +{ + multiboot_uint32_t type; + multiboot_uint32_t size; +}; + +struct multiboot_tag_string +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + char string[0]; +}; + +struct multiboot_tag_module +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t mod_start; + multiboot_uint32_t mod_end; + char cmdline[0]; +}; + +struct multiboot_tag_basic_meminfo +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t mem_lower; + multiboot_uint32_t mem_upper; +}; + +struct multiboot_tag_bootdev +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t biosdev; + multiboot_uint32_t slice; + multiboot_uint32_t part; +}; + +struct multiboot_tag_mmap +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t entry_size; + multiboot_uint32_t entry_version; + struct multiboot_mmap_entry entries[0]; +}; + +struct multiboot_vbe_info_block +{ + multiboot_uint8_t external_specification[512]; +}; + +struct multiboot_vbe_mode_info_block +{ + multiboot_uint8_t external_specification[256]; +}; + +struct multiboot_tag_vbe +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + + multiboot_uint16_t vbe_mode; + multiboot_uint16_t vbe_interface_seg; + multiboot_uint16_t vbe_interface_off; + multiboot_uint16_t vbe_interface_len; + + struct multiboot_vbe_info_block vbe_control_info; + struct multiboot_vbe_mode_info_block vbe_mode_info; +}; + +struct multiboot_tag_framebuffer_common +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + + multiboot_uint64_t framebuffer_addr; + multiboot_uint32_t framebuffer_pitch; + multiboot_uint32_t framebuffer_width; + multiboot_uint32_t framebuffer_height; + multiboot_uint8_t framebuffer_bpp; +#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 +#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 +#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 + multiboot_uint8_t framebuffer_type; + multiboot_uint16_t reserved; +}; + +struct multiboot_tag_framebuffer +{ + struct multiboot_tag_framebuffer_common common; + + union + { + struct + { + multiboot_uint16_t framebuffer_palette_num_colors; + struct multiboot_color framebuffer_palette[0]; + }; + struct + { + multiboot_uint8_t framebuffer_red_field_position; + multiboot_uint8_t framebuffer_red_mask_size; + multiboot_uint8_t framebuffer_green_field_position; + multiboot_uint8_t framebuffer_green_mask_size; + multiboot_uint8_t framebuffer_blue_field_position; + multiboot_uint8_t framebuffer_blue_mask_size; + }; + }; +}; + +struct multiboot_tag_elf_sections +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t num; + multiboot_uint32_t entsize; + multiboot_uint32_t shndx; + char sections[0]; +}; + +struct multiboot_tag_apm +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint16_t version; + multiboot_uint16_t cseg; + multiboot_uint32_t offset; + multiboot_uint16_t cseg_16; + multiboot_uint16_t dseg; + multiboot_uint16_t flags; + multiboot_uint16_t cseg_len; + multiboot_uint16_t cseg_16_len; + multiboot_uint16_t dseg_len; +}; + +struct multiboot_tag_efi32 +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t pointer; +}; + +struct multiboot_tag_efi64 +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint64_t pointer; +}; + +struct multiboot_tag_smbios +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint8_t major; + multiboot_uint8_t minor; + multiboot_uint8_t reserved[6]; + multiboot_uint8_t tables[0]; +}; + +struct multiboot_tag_old_acpi +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint8_t rsdp[0]; +}; + +struct multiboot_tag_new_acpi +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint8_t rsdp[0]; +}; + +struct multiboot_tag_network +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint8_t dhcpack[0]; +}; + +struct multiboot_tag_efi_mmap +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t descr_size; + multiboot_uint32_t descr_vers; + multiboot_uint8_t efi_mmap[0]; +}; + +struct multiboot_tag_efi32_ih +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t pointer; +}; + +struct multiboot_tag_efi64_ih +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint64_t pointer; +}; + +struct multiboot_tag_load_base_addr +{ + multiboot_uint32_t type; + multiboot_uint32_t size; + multiboot_uint32_t load_base_addr; +}; + +#endif /* !ASM_FILE */ + +#endif /* !__ARCH_X86_64_INCLUDE_MULTIBOOT2_H */ diff --git a/arch/x86_64/include/syscall.h b/arch/x86_64/include/syscall.h new file mode 100644 index 00000000000..88cb2d164a6 --- /dev/null +++ b/arch/x86_64/include/syscall.h @@ -0,0 +1,73 @@ +/**************************************************************************** + * arch/x86_64/include/syscall.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. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, only indirectly + * through include/syscall.h or include/sys/sycall.h + */ + +#ifndef __ARCH_X86_64_INCLUDE_SYSCALL_H +#define __ARCH_X86_64_INCLUDE_SYSCALL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Include x86 architecture-specific syscall macros */ + +#ifdef CONFIG_ARCH_INTEL64 +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Inline functions + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_X86_64_INCLUDE_SYSCALL_H */ diff --git a/arch/x86_64/include/types.h b/arch/x86_64/include/types.h new file mode 100644 index 00000000000..1d2b1887c79 --- /dev/null +++ b/arch/x86_64/include/types.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * arch/x86_64/include/types.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. + * + ****************************************************************************/ + +/* This file should never be included directed but, rather, only indirectly + * through sys/types.h + */ + +#ifndef __ARCH_X86_64_INCLUDE_TYPES_H +#define __ARCH_X86_64_INCLUDE_TYPES_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/* Include architecture-specific limits */ + +#ifdef CONFIG_ARCH_INTEL64 +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Type Declarations + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __ARCH_X86_64_INCLUDE_TYPES_H */ diff --git a/arch/x86_64/src/.gitignore b/arch/x86_64/src/.gitignore new file mode 100644 index 00000000000..b47dbaebbb9 --- /dev/null +++ b/arch/x86_64/src/.gitignore @@ -0,0 +1,4 @@ +/chip +/board +/.depend +/Make.dep diff --git a/arch/x86_64/src/Makefile b/arch/x86_64/src/Makefile new file mode 100644 index 00000000000..33aba7ae7bd --- /dev/null +++ b/arch/x86_64/src/Makefile @@ -0,0 +1,184 @@ +############################################################################ +# arch/x86_64/src/Makefile +# +# 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. +# +############################################################################ + +-include $(TOPDIR)/Make.defs +-include chip/Make.defs + +ifeq ($(CONFIG_ARCH_INTEL64),y) +ARCH_SUBDIR = intel64 +endif + +CPPFLAGS += $(EXTRADEFINES) +CFLAGS += $(EXTRADEFINES) +CXXFLAGS += $(EXTRADEFINES) + +ifeq ($(CONFIG_WINDOWS_NATIVE),y) + ARCH_SRCDIR = $(TOPDIR)\arch\$(CONFIG_ARCH)\src + NUTTX = $(TOPDIR)\nuttx$(EXEEXT) + CFLAGS += -I$(ARCH_SRCDIR)\chip + CFLAGS += -I$(ARCH_SRCDIR)\common + CFLAGS += -I$(ARCH_SRCDIR)\$(ARCH_SUBDIR) + CFLAGS += -I$(TOPDIR)\sched +else + ARCH_SRCDIR = $(TOPDIR)/arch/$(CONFIG_ARCH)/src +ifeq ($(WINTOOL),y) + NUTTX = "${shell cygpath -w $(TOPDIR)/nuttx$(EXEEXT)}" + CFLAGS += -I "${shell cygpath -w $(ARCH_SRCDIR)/chip}" + CFLAGS += -I "${shell cygpath -w $(ARCH_SRCDIR)/common}" + CFLAGS += -I "${shell cygpath -w $(ARCH_SRCDIR)/$(ARCH_SUBDIR)}" + CFLAGS += -I "${shell cygpath -w $(TOPDIR)/sched}" +else + NUTTX = $(TOPDIR)/nuttx$(EXEEXT) + LOADER = $(TOPDIR)/loader$(EXEEXT) + CFLAGS += -I$(ARCH_SRCDIR)/chip + CFLAGS += -I$(ARCH_SRCDIR)/common + CFLAGS += -I$(ARCH_SRCDIR)/$(ARCH_SUBDIR) + CFLAGS += -I$(TOPDIR)/sched +endif +endif + +ASRCS = $(CHIP_ASRCS) $(CMN_ASRCS) +AOBJS = $(ASRCS:.S=$(OBJEXT)) + +CSRCS = $(CHIP_CSRCS) $(CMN_CSRCS) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +KBIN = libkarch$(LIBEXT) +UBIN = libuarch$(LIBEXT) +BIN = libarch$(LIBEXT) + +# Override in Make.defs if linker is not 'ld' + +LDSTARTGROUP ?= --start-group +LDENDGROUP ?= --end-group + +LDFLAGS += -z max-page-size=0x1000 $(ARCHSCRIPT) +LOADER_LDFLAGS += $(LOADER_ARCHSCRIPT) +EXTRA_LIBS ?= +LINKLIBS ?= + +OBJCOPYARGS = + +ifeq ($(CONFIG_WINDOWS_NATIVE),y) + BOARDMAKE = $(if $(wildcard .\board\Makefile),y,) + LIBPATHS += -L"$(TOPDIR)\staging" +ifeq ($(BOARDMAKE),y) + LIBPATHS += -L"$(TOPDIR)\arch\$(CONFIG_ARCH)\src\board" +endif + +else + BOARDMAKE = $(if $(wildcard ./board/Makefile),y,) + +ifeq ($(WINTOOL),y) + LIBPATHS += -L"${shell cygpath -w "$(TOPDIR)/staging"}" +ifeq ($(BOARDMAKE),y) + LIBPATHS += -L"${shell cygpath -w "$(TOPDIR)/arch/$(CONFIG_ARCH)/src/board"}" +endif + +else + LIBPATHS += -L"$(TOPDIR)/staging" +ifeq ($(BOARDMAKE),y) + LIBPATHS += -L"$(TOPDIR)/arch/$(CONFIG_ARCH)/src/board" +endif +endif +endif + +LDLIBS = $(patsubst %.a,%,$(patsubst lib%,-l%,$(LINKLIBS))) +ifeq ($(BOARDMAKE),y) + LDLIBS += -lboard +endif + +LIBGCC = "${shell "$(CC)" $(ARCHCPUFLAGS) -print-libgcc-file-name}" + +ifeq ($(HOSTOS),FreeBSD) + HOST_ARCH = ${shell uname -m 2>/dev/null || echo "Other"} +endif + +VPATH = chip:common:$(ARCH_SUBDIR) + +all: libarch$(LIBEXT) + +.PHONY: board/libboard$(LIBEXT) + +$(AOBJS): %$(OBJEXT): %.S + $(call ASSEMBLE, $<, $@) + +$(COBJS): %$(OBJEXT): %.c + $(call COMPILE, $<, $@) + +$(BIN) $(KBIN): $(OBJS) + $(call ARCHIVE, $@, $(OBJS)) + +$(UBIN): $(UOBJS) + $(call ARCHIVE, $@, $(UOBJS)) + +board/libboard$(LIBEXT): + $(Q) $(MAKE) -C board TOPDIR="$(TOPDIR)" libboard$(LIBEXT) EXTRADEFINES=$(EXTRADEFINES) + +nuttx$(EXEEXT): board/libboard$(LIBEXT) + @echo "LD: nuttx$(EXEEXT)" + $(Q) $(LD) $(LDFLAGS) $(LIBPATHS) -o $(NUTTX) $(EXTRA_OBJS) \ + $(LDSTARTGROUP) $(LIBGCC) --whole-archive $(LDLIBS) $(EXTRA_LIBS) $(LDENDGROUP) +ifneq ($(CONFIG_WINDOWS_NATIVE),y) + $(Q) $(NM) $(NUTTX) | \ + grep -v '\(compiled\)\|\(\$(OBJEXT)$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | \ + sort > $(TOPDIR)/System.map +endif + +# This is part of the top-level export target + +export_startup: board/libboard$(LIBEXT) $(STARTUP_OBJS) + $(Q) if [ -d "$(EXPORT_DIR)/startup" ]; then \ + cp -f $(STARTUP_OBJS) "$(EXPORT_DIR)/startup"; \ + else \ + echo "$(EXPORT_DIR)/startup does not exist"; \ + exit 1; \ + fi + +# Dependencies + +.depend: Makefile chip/Make.defs $(SRCS) +ifeq ($(BOARDMAKE),y) + $(Q) $(MAKE) -C board TOPDIR="$(TOPDIR)" depend +endif + $(Q) $(MKDEP) --dep-path chip --dep-path common --dep-path $(ARCH_SUBDIR) \ + "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep + $(Q) touch $@ + +depend: .depend + +clean: +ifeq ($(BOARDMAKE),y) + $(Q) $(MAKE) -C board TOPDIR="$(TOPDIR)" clean +endif + $(call DELFILE, libarch$(LIBEXT)) + $(call CLEAN) + +distclean: clean +ifeq ($(BOARDMAKE),y) + $(Q) $(MAKE) -C board TOPDIR="$(TOPDIR)" distclean +endif + $(call DELFILE, Make.dep) + $(call DELFILE, .depend) + +-include Make.dep diff --git a/arch/x86_64/src/README.txt b/arch/x86_64/src/README.txt new file mode 100644 index 00000000000..160f29fa884 --- /dev/null +++ b/arch/x86_64/src/README.txt @@ -0,0 +1,31 @@ +arch/x86/src/README.txt +^^^^^^^^^^^^^^^^^^^^^^^ + +This directory holds x86_64-specific source files. All x86 source reside in +lower-level common, chip-specific, and architecture-specific directories. + +common/ Directory +^^^^^^^^^^^^^^^^^ + +This directory holds source files common to all x86_64 architectures. + +Architecture-Specific Directories +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Architecture-specific directories hold common source files shared for by +implementations of specific x86_64 architectures. + +intel64 + This directory holds logic appropriate for any instantiation of the 64-bit + intel64 architecture. + +Chip-Specific directories +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The same x86 architecture may be realized in different chip implementations. +For SoC chips, in particular, on-chip devices and differing interrupt +structures may require special, chip-specific definitions in these chip- +specific directories. + +broadwell + This is the implementation of NuttX on the Intel Broadwell processors. diff --git a/arch/x86_64/src/common/Kconfig b/arch/x86_64/src/common/Kconfig new file mode 100644 index 00000000000..6dcd0d64f96 --- /dev/null +++ b/arch/x86_64/src/common/Kconfig @@ -0,0 +1,9 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_X86_64 +comment "Common Configuration Options" + +endif diff --git a/arch/x86_64/src/common/up_allocateheap.c b/arch/x86_64/src/common/up_allocateheap.c new file mode 100644 index 00000000000..e978858b376 --- /dev/null +++ b/arch/x86_64/src/common/up_allocateheap.c @@ -0,0 +1,78 @@ +/**************************************************************************** + * arch/x86_64/src/common/up_allocateheap.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 "up_arch.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_allocate_heap + * + * Description: + * This function will be called to dynamically set aside the heap region. + * + * For the kernel build (CONFIG_BUILD_KERNEL=y) with both kernel- and + * user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function provides the + * size of the unprotected, user-space heap. + * + * If a protected kernel-space heap is provided, the kernel heap must be + * allocated (and protected) by an analogous up_allocate_kheap(). + * + ****************************************************************************/ + +void up_allocate_heap(FAR void **heap_start, size_t *heap_size) +{ + board_autoled_on(LED_HEAPALLOCATE); + + // Calculate the end of .bss section + uintptr_t hstart = (((uintptr_t)&_ebss + PAGE_SIZE - 1) & PAGE_MASK); + *heap_start = (void*)hstart; + + // The size is the rest of the RAM + *heap_size = (size_t)(CONFIG_RAM_SIZE - (hstart - 0x100000000 - 1)); +} diff --git a/arch/x86_64/src/common/up_arch.h b/arch/x86_64/src/common/up_arch.h new file mode 100644 index 00000000000..85982cb496b --- /dev/null +++ b/arch/x86_64/src/common/up_arch.h @@ -0,0 +1,76 @@ +/**************************************************************************** + * arch/x86_64/src/common/up_arch.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_COMMON_UP_ARCH_H +#define ___ARCH_X86_64_SRC_COMMON_UP_ARCH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#ifndef __ASSEMBLY__ +# include +#endif +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +# define getreg8(p) inb(p) +# define putreg8(v,p) outb(v,p) +# define getreg16(p) inw(p) +# define putreg16(v,p) outw(v,p) +# define getreg32(p) inl(p) +# define putreg32(v,p) outl(v,p) + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/* Atomic modification of registers */ + +void modifyreg8(unsigned int addr, uint8_t clearbits, uint8_t setbits); +void modifyreg16(unsigned int addr, uint16_t clearbits, uint16_t setbits); +void modifyreg32(unsigned int addr, uint32_t clearbits, uint32_t setbits); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* ___ARCH_X86_64_SRC_COMMON_UP_ARCH_H */ diff --git a/arch/x86_64/src/common/up_assert.c b/arch/x86_64/src/common/up_assert.c new file mode 100644 index 00000000000..186f9670ef9 --- /dev/null +++ b/arch/x86_64/src/common/up_assert.c @@ -0,0 +1,267 @@ +/**************************************************************************** + * arch/x86_64/src/common/up_assert.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 + +#include + +#include "up_arch.h" +#include "sched/sched.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* USB trace dumping */ + +#ifndef CONFIG_USBDEV_TRACE +# undef CONFIG_ARCH_USBDUMP +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_stackdump + ****************************************************************************/ + +#ifdef CONFIG_ARCH_STACKDUMP +static void up_stackdump(uint64_t sp, uint64_t stack_base) +{ + uint64_t stack ; + + for (stack = sp & ~0x1f; stack < stack_base; stack += 32) + { + uint32_t *ptr = (uint32_t *)stack; + _alert("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n", + stack, ptr[0], ptr[1], ptr[2], ptr[3], + ptr[4], ptr[5], ptr[6], ptr[7]); + } +} +#else +# define up_stackdump() +#endif + +/**************************************************************************** + * Name: assert_tracecallback + ****************************************************************************/ + +#ifdef CONFIG_ARCH_USBDUMP +static int usbtrace_syslog(FAR const char *fmt, ...) +{ + va_list ap; + int ret; + + /* Let nx_vsyslog do the real work */ + + va_start(ap, fmt); + ret = nx_vsyslog(LOG_EMERG, fmt, &ap); + va_end(ap); + return ret; +} + +static int assert_tracecallback(FAR struct usbtrace_s *trace, FAR void *arg) +{ + usbtrace_trprintf(usbtrace_syslog, trace->event, trace->value); + return 0; +} +#endif + +/**************************************************************************** + * Name: up_dumpstate + ****************************************************************************/ + +#ifdef CONFIG_ARCH_STACKDUMP +static void up_dumpstate(void) +{ + struct tcb_s *rtcb = this_task(); + uint64_t sp = up_getrsp(); + uint64_t ustackbase; + uint64_t ustacksize; +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + uint64_t istackbase; + uint64_t istacksize; +#endif + + /* Get the limits on the user stack memory */ + + if (rtcb->pid == 0) + { + ustackbase = g_idle_topstack - 8; + ustacksize = CONFIG_IDLETHREAD_STACKSIZE; + } + else + { + ustackbase = (uint64_t)rtcb->adj_stack_ptr; + ustacksize = (uint64_t)rtcb->adj_stack_size; + } + + /* Get the limits on the interrupt stack memory */ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + istackbase = (uint64_t)&g_intstackbase; + istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3) - 8; + + /* Show interrupt stack info */ + + _alert("sp: %016x\n", sp); + _alert("IRQ stack:\n"); + _alert(" base: %016x\n", istackbase); + _alert(" size: %016x\n", istacksize); + + /* Does the current stack pointer lie within the interrupt + * stack? + */ + + if (sp <= istackbase && sp > istackbase - istacksize) + { + /* Yes.. dump the interrupt stack */ + + up_stackdump(sp, istackbase); + + /* Extract the user stack pointer which should lie + * at the base of the interrupt stack. + */ + + sp = g_intstackbase; + _alert("sp: %016x\n", sp); + } + + /* Show user stack info */ + + _alert("User stack:\n"); + _alert(" base: %016x\n", ustackbase); + _alert(" size: %016x\n", ustacksize); +#else + _alert("sp: %016x\n", sp); + _alert("stack base: %016x\n", ustackbase); + _alert("stack size: %016x\n", ustacksize); +#endif + + /* Dump the user stack if the stack pointer lies within the allocated user + * stack memory. + */ + + if (sp > ustackbase || sp <= ustackbase - ustacksize) + { +#if !defined(CONFIG_ARCH_INTERRUPTSTACK) || CONFIG_ARCH_INTERRUPTSTACK < 4 + _alert("ERROR: Stack pointer is not within allocated stack\n"); +#endif + } + else + { + up_stackdump(sp, ustackbase); + } + + /* Then dump the registers (if available) */ + + if (g_current_regs != NULL) + { + up_registerdump((uint64_t *)g_current_regs); + } + +#ifdef CONFIG_ARCH_USBDUMP + /* Dump USB trace data */ + + (void)usbtrace_enumerate(assert_tracecallback, NULL); +#endif +} +#else +# define up_dumpstate() +#endif + +/**************************************************************************** + * Name: _up_assert + ****************************************************************************/ + +static void _up_assert(int errorcode) noreturn_function; +static void _up_assert(int errorcode) +{ + /* Are we in an interrupt handler or the idle task? */ + + if (g_current_regs || (this_task())->pid == 0) + { + (void)up_irq_save(); + for (; ; ) + { +#ifdef CONFIG_ARCH_LEDS + board_autoled_on(LED_PANIC); + up_mdelay(250); + board_autoled_off(LED_PANIC); + up_mdelay(250); +#endif + } + } + else + { + exit(errorcode); + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_assert + ****************************************************************************/ + +void up_assert(const uint8_t *filename, int lineno) +{ +#if CONFIG_TASK_NAME_SIZE > 0 && defined(CONFIG_DEBUG_ALERT) + struct tcb_s *rtcb = this_task(); +#endif + + board_autoled_on(LED_ASSERTION); + +#if CONFIG_TASK_NAME_SIZE > 0 + _alert("Assertion failed at file:%s line: %d task: %s\n", + filename, lineno, rtcb->name); +#else + _alert("Assertion failed at file:%s line: %d\n", + filename, lineno); +#endif + + up_dumpstate(); + +#ifdef CONFIG_BOARD_CRASHDUMP + board_crashdump(up_getrsp(), this_task(), filename, lineno); +#endif + + _up_assert(EXIT_FAILURE); +} diff --git a/arch/x86_64/src/common/up_blocktask.c b/arch/x86_64/src/common/up_blocktask.c new file mode 100644 index 00000000000..708c6b21dda --- /dev/null +++ b/arch/x86_64/src/common/up_blocktask.c @@ -0,0 +1,161 @@ +/**************************************************************************** + * arch/x86_64/src/common/up_blocktask.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 "sched/sched.h" +#include "group/group.h" +#include "up_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_block_task + * + * Description: + * The currently executing task at the head of the ready to run list must + * be stopped. Save its context and move it to the inactive list specified + * by task_state. + * + * Input Parameters: + * tcb: Refers to a task in the ready-to-run list (normally the task at the + * head of the list). It most be stopped, its context saved and moved + * into one of the waiting task lists. It it was the task at the head + * of the ready-to-run list, then a context to the new ready to run task + * must be performed. + * task_state: Specifies which waiting task list should be + * hold the blocked task TCB. + * + ****************************************************************************/ + +void up_block_task(struct tcb_s *tcb, tstate_t task_state) +{ + struct tcb_s *rtcb = this_task(); + bool switch_needed; + + /* Verify that the context switch can be performed */ + + ASSERT((tcb->task_state >= FIRST_READY_TO_RUN_STATE) && + (tcb->task_state <= LAST_READY_TO_RUN_STATE)); + + /* Remove the tcb task from the ready-to-run list. If we + * are blocking the task at the head of the task list (the + * most likely case), then a context switch to the next + * ready-to-run task is needed. In this case, it should + * also be true that rtcb == tcb. + */ + + switch_needed = sched_removereadytorun(tcb); + + /* Add the task to the specified blocked task list */ + + sched_addblocked(tcb, (tstate_t)task_state); + + /* If there are any pending tasks, then add them to the ready-to-run + * task list now + */ + + if (g_pendingtasks.head) + { + switch_needed |= sched_mergepending(); + } + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + /* Update scheduler parameters */ + + sched_suspend_scheduler(rtcb); + + /* Are we in an interrupt handler? */ + + if (g_current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + up_restore_auxstate(rtcb); + + /* Reset scheduler parameters */ + + sched_resume_scheduler(rtcb); + + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ + + up_restorestate(rtcb->xcp.regs); + } + + /* Copy the user C context into the TCB at the (old) head of the + * ready-to-run Task list. if up_saveusercontext returns a non-zero + * value, then this is really the previously running task restarting! + */ + + else if (!up_saveusercontext(rtcb->xcp.regs)) + { + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + up_restore_auxstate(rtcb); + +#ifdef CONFIG_ARCH_ADDRENV + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ + + (void)group_addrenv(rtcb); +#endif + /* Reset scheduler parameters */ + + sched_resume_scheduler(rtcb); + + /* Then switch contexts */ + + up_fullcontextrestore(rtcb->xcp.regs); + } + } +} diff --git a/arch/x86_64/src/common/up_copystate.c b/arch/x86_64/src/common/up_copystate.c new file mode 100644 index 00000000000..dd4c8e3da3d --- /dev/null +++ b/arch/x86_64/src/common/up_copystate.c @@ -0,0 +1,63 @@ +/**************************************************************************** + * arch/x86_64/src/common/up_copystate.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 "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_undefinedinsn + ****************************************************************************/ + +/* A little faster than most memcpy's */ + +void up_copystate(uint64_t *dest, uint64_t *src) +{ + int i; + + for (i = 0; i < XCPTCONTEXT_REGS; i++) + { + *dest++ = *src++; + } +} + diff --git a/arch/x86_64/src/common/up_exit.c b/arch/x86_64/src/common/up_exit.c new file mode 100644 index 00000000000..50f3b5a735d --- /dev/null +++ b/arch/x86_64/src/common/up_exit.c @@ -0,0 +1,175 @@ +/**************************************************************************** + * common/up_exit.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 +#ifdef CONFIG_DUMP_ON_EXIT +# include +#endif + +#include "task/task.h" +#include "sched/sched.h" +#include "group/group.h" +#include "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_DEBUG_SCHED_INFO +# undef CONFIG_DUMP_ON_EXIT +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: _up_dumponexit + * + * Description: + * Dump the state of all tasks whenever on task exits. This is debug + * instrumentation that was added to check file-related reference counting + * but could be useful again sometime in the future. + * + ****************************************************************************/ + +#ifdef CONFIG_DUMP_ON_EXIT +static void _up_dumponexit(FAR struct tcb_s *tcb, FAR void *arg) +{ +#if CONFIG_NFILE_DESCRIPTORS > 0 + FAR struct filelist *filelist; +#if CONFIG_NFILE_STREAMS > 0 + FAR struct streamlist *streamlist; +#endif + int i; +#endif + + sinfo(" TCB=%p name=%s pid=%d\n", tcb, tcb->argv[0], tcb->pid); + sinfo(" priority=%d state=%d\n", tcb->sched_priority, tcb->task_state); + +#if CONFIG_NFILE_DESCRIPTORS > 0 + filelist = tcb->group->tg_filelist; + for (i = 0; i < CONFIG_NFILE_DESCRIPTORS; i++) + { + struct inode *inode = filelist->fl_files[i].f_inode; + if (inode) + { + sinfo(" fd=%d refcount=%d\n", + i, inode->i_crefs); + } + } +#endif + +#if CONFIG_NFILE_STREAMS > 0 + streamlist = tcb->group->tg_streamlist; + for (i = 0; i < CONFIG_NFILE_STREAMS; i++) + { + struct file_struct *filep = &streamlist->sl_streams[i]; + if (filep->fs_fd >= 0) + { +#ifndef CONFIG_STDIO_DISABLE_BUFFERING + if (filep->fs_bufstart != NULL) + { + sinfo(" fd=%d nbytes=%d\n", + filep->fs_fd, + filep->fs_bufpos - filep->fs_bufstart); + } + else +#endif + { + sinfo(" fd=%d\n", filep->fs_fd); + } + } + } +#endif +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: _exit + * + * Description: + * This function causes the currently executing task to cease to exist. + * This is a special case of task_delete() where the task to be deleted is + * the currently executing task. It is more complex because a context + * switch must be perform to the next ready to run task. + * + ****************************************************************************/ + +void _exit(int status) +{ + struct tcb_s *tcb; + + /* Make sure that we are in a critical section with local interrupts. + * The IRQ state will be restored when the next task is started. + */ + + (void)enter_critical_section(); + + sinfo("TCB=%p exiting\n", this_task()); + +#ifdef CONFIG_DUMP_ON_EXIT + sinfo("Other tasks:\n"); + sched_foreach(_up_dumponexit, NULL); +#endif + + /* Destroy the task at the head of the ready to run list. */ + + (void)nxtask_exit(); + + /* Now, perform the context switch to the new ready-to-run task at the + * head of the list. + */ + + tcb = this_task(); + + /* Context switch, rearrange MMU */ + + up_restore_auxstate(tcb); + +#ifdef CONFIG_ARCH_ADDRENV + /* Make sure that the address environment for the previously running + * task is closed down gracefully (data caches dump, MMU flushed) and + * set up the address environment for the new thread at the head of + * the ready-to-run list. + */ + + (void)group_addrenv(tcb); +#endif + + /* Then switch contexts */ + + up_fullcontextrestore(tcb->xcp.regs); +} + diff --git a/arch/x86_64/src/common/up_initialize.c b/arch/x86_64/src/common/up_initialize.c new file mode 100644 index 00000000000..61e2c3d6f92 --- /dev/null +++ b/arch/x86_64/src/common/up_initialize.c @@ -0,0 +1,223 @@ +/**************************************************************************** + * arch/x86_64/src/common/up_initialize.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 +#include +#include +#include +#include +#include + +#include + +#include "up_arch.h" +#include "up_internal.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_calibratedelay + * + * Description: + * Delay loops are provided for short timing loops. This function, if + * enabled, will just wait for 100 seconds. Using a stopwatch, you can + * can then determine if the timing loops are properly calibrated. + * + ****************************************************************************/ + +#if defined(CONFIG_ARCH_CALIBRATION) && defined(CONFIG_DEBUG_FEATURES) +static void up_calibratedelay(void) +{ + int i; + + _warn("Beginning 100s delay\n"); + for (i = 0; i < 100; i++) + { + up_mdelay(1000); + } + + _warn("End 100s delay\n"); +} +#else +# define up_calibratedelay() +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_initialize + * + * Description: + * up_initialize will be called once during OS initialization after the + * basic OS services have been initialized. The architecture specific + * details of initializing the OS will be handled here. Such things as + * setting up interrupt service routines, starting the clock, and + * registering device drivers are some of the things that are different + * for each processor and hardware platform. + * + * up_initialize is called after the OS initialized but before the user + * initialization logic has been started and before the libraries have + * been initialized. OS services and driver services are available. + * + ****************************************************************************/ + +void up_initialize(void) +{ + /* Initialize global variables */ + + g_current_regs = NULL; + + /* Add any extra memory fragments to the memory manager */ + + up_addregion(); + +#ifdef CONFIG_PM + /* Initialize the power management subsystem. This MCU-specific function + * must be called *very* early in the initialization sequence *before* any + * other device drivers are initialized (since they may attempt to register + * with the power management subsystem). + */ + + up_pminitialize(); +#endif + +#ifdef CONFIG_ARCH_DMA + /* Initialize the DMA subsystem if the weak function up_dma_initialize has been + * brought into the build + */ + +#ifdef CONFIG_HAVE_WEAKFUNCTIONS + if (up_dma_initialize) +#endif + { + up_dma_initialize(); + } +#endif + + /* Register devices */ + +#if defined(CONFIG_DEV_NULL) + devnull_register(); /* Standard /dev/null */ +#endif + +#if defined(CONFIG_DEV_RANDOM) + devrandom_register(); /* Standard /dev/random */ +#endif + +#if defined(CONFIG_DEV_URANDOM) + devurandom_register(); /* Standard /dev/urandom */ +#endif + +#if defined(CONFIG_DEV_ZERO) + devzero_register(); /* Standard /dev/zero */ +#endif + +#if defined(CONFIG_DEV_LOOP) + loop_register(); /* Standard /dev/loop */ +#endif + +#if defined(CONFIG_SCHED_INSTRUMENTATION_BUFFER) && \ + defined(CONFIG_DRIVER_NOTE) + note_register(); /* Non-standard /dev/note */ +#endif + + /* Initialize the serial device driver */ + +#ifdef USE_SERIALDRIVER + up_serialinit(); +#endif + +#ifdef CONFIG_RPMSG_UART + rpmsg_serialinit(); +#endif + + /* Initialize the console device driver (if it is other than the standard + * serial driver). + */ + +#if defined(CONFIG_CONSOLE_SYSLOG) + syslog_console_init(); +#endif + +#ifdef CONFIG_PSEUDOTERM_SUSV1 + /* Register the master pseudo-terminal multiplexor device */ + + ptmx_register(); +#endif + +#if defined(CONFIG_CRYPTO) + /* Initialize the HW crypto and /dev/crypto */ + + up_cryptoinitialize(); +#endif + +#ifdef CONFIG_CRYPTO_CRYPTODEV + devcrypto_register(); +#endif + +#ifndef CONFIG_NETDEV_LATEINIT + /* Initialize the network */ + + up_netinitialize(); +#endif + +#ifdef CONFIG_NET_LOOPBACK + /* Initialize the local loopback device */ + + localhost_initialize(); +#endif + +#ifdef CONFIG_NET_TUN + /* Initialize the TUN device */ + + tun_initialize(); +#endif + +#ifdef CONFIG_NETDEV_TELNET + /* Initialize the Telnet session factory */ + + telnet_initialize(); +#endif + + /* Initialize USB -- device and/or host */ + + up_usbinitialize(); + board_autoled_on(LED_IRQSENABLED); +} diff --git a/arch/x86_64/src/common/up_internal.h b/arch/x86_64/src/common/up_internal.h new file mode 100644 index 00000000000..7e0c5280feb --- /dev/null +++ b/arch/x86_64/src/common/up_internal.h @@ -0,0 +1,240 @@ +/**************************************************************************** + * arch/x86_64/src/common/up_internal.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_COMMON_UP_INTERNAL_H +#define __ARCH_X86_64_SRC_COMMON_UP_INTERNAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +# include +# include +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Bring-up debug configurations. These are here (vs defconfig) because + * these should only be controlled during low level board bring-up and not + * part of normal platform configuration. + */ + +#undef CONFIG_SUPPRESS_INTERRUPTS /* DEFINED: Do not enable interrupts */ +#undef CONFIG_SUPPRESS_TIMER_INTS /* DEFINED: No timer */ +#undef CONFIG_SUPPRESS_SERIAL_INTS /* DEFINED: Console will poll */ +#undef CONFIG_SUPPRESS_UART_CONFIG /* DEFINED: Do not reconfig UART */ +#undef CONFIG_DUMP_ON_EXIT /* DEFINED: Dump task state on exit */ + +#ifndef CONFIG_DEBUG_SCHED_INFO +# undef CONFIG_DUMP_ON_EXIT /* Needs CONFIG_DEBUG_SCHED_INFO */ +#endif + +/* Determine which (if any) console driver to use. If a console is enabled + * and no other console device is specified, then a serial console is + * assumed. + */ + +#if !defined(CONFIG_DEV_CONSOLE) || CONFIG_NFILE_DESCRIPTORS <= 0 +# undef USE_SERIALDRIVER +# undef USE_EARLYSERIALINIT +# undef CONFIG_DEV_LOWCONSOLE +# undef CONFIG_RAMLOG_CONSOLE +#else +# if defined(CONFIG_RAMLOG_CONSOLE) +# undef USE_SERIALDRIVER +# undef USE_EARLYSERIALINIT +# undef CONFIG_DEV_LOWCONSOLE +# else +# define USE_SERIALDRIVER 1 +# define USE_EARLYSERIALINIT 1 +# endif +#endif + +/* If some other device is used as the console, then the serial driver may + * still be needed. Let's assume that if the upper half serial driver is + * built, then the lower half will also be needed. There is no need for + * the early serial initialization in this case. + */ + +#if !defined(USE_SERIALDRIVER) && defined(CONFIG_STANDARD_SERIAL) +# define USE_SERIALDRIVER 1 +#endif + +/* Check if an interrupt stack size is configured */ + +#ifndef CONFIG_ARCH_INTERRUPTSTACK +# define CONFIG_ARCH_INTERRUPTSTACK 0 +#endif + +/* Macros to handle saving and restore interrupt state. In the current + * model, the state is copied from the stack to the TCB, but only a + * referenced is passed to get the state from the TCB. + */ + +#define up_restorestate(regs) (g_current_regs = regs) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +typedef void (*up_vector_t)(void); +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +/* This holds a references to the current interrupt level register storage + * structure. If is non-NULL only during interrupt processing. + */ + +extern volatile uint64_t *g_current_regs; + +/* This is the beginning of heap as provided from up_head.S. This is the first + * address in DRAM after the loaded program+bss+idle stack. The end of the + * heap is CONFIG_RAM_END + */ + +extern uint64_t g_idle_topstack; + +/* Address of the saved user stack pointer */ + +#if CONFIG_ARCH_INTERRUPTSTACK > 3 +extern uint64_t g_intstackbase; +#endif + +/* These 'addresses' of these values are setup by the linker script. They are + * not actual uint32_t storage locations! They are only used meaningfully in the + * following way: + * + * - The linker script defines, for example, the symbol_sdata. + * - The declareion extern uint32_t _sdata; makes C happy. C will believe + * that the value _sdata is the address of a uint32_t variable _data (it is + * not!). + * - We can recoved the linker value then by simply taking the address of + * of _data. like: uint32_t *pdata = &_sdata; + */ + +extern uint64_t _stext; /* Start of .text */ +extern uint64_t _etext; /* End_1 of .text + .rodata */ +extern const uint64_t _eronly; /* End+1 of read only section (.text + .rodata) */ +extern uint64_t _sdata; /* Start of .data */ +extern uint64_t _edata; /* End+1 of .data */ +extern uint64_t _sbss; /* Start of .bss */ +extern uint64_t _ebss; /* End+1 of .bss */ +#endif + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Name: x86_64_boardinitialize + * + * Description: + * This function must be provided by the board-specific logic in the + * directory configs//src/. + * + ****************************************************************************/ + +void x86_64_boardinitialize(void); + +/* Defined in files with the same name as the function */ + +void up_copystate(uint64_t *dest, uint64_t *src); +void up_savestate(uint64_t *regs); +void up_decodeirq(uint64_t *regs); +void up_irqinitialize(void); +#ifdef CONFIG_ARCH_DMA +void weak_function up_dmainitialize(void); +#endif +int up_saveusercontext(uint64_t *saveregs); +void up_fullcontextrestore(uint64_t *restoreregs) noreturn_function; +void up_switchcontext(uint64_t *saveregs, uint64_t *restoreregs); +void up_sigdeliver(void); +void up_lowputc(char ch); +void up_puts(const char *str); +void up_lowputs(const char *str); +void up_restore_auxstate(struct tcb_s *rtcb); +void up_checktasks(void); + +void up_syscall(uint64_t *regs); +void up_registerdump(uint64_t *regs); + +/* Defined in up_allocateheap.c */ + +#if CONFIG_MM_REGIONS > 1 +void up_addregion(void); +#else +# define up_addregion() +#endif + +/* Defined in xyz_serial.c */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 +void up_earlyserialinit(void); +void up_serialinit(void); +#else +# define up_earlyserialinit() +# define up_serialinit() +#endif + +/* Defined in xyz_watchdog.c */ + +void up_wdtinit(void); + +/* Defined in xyz_timerisr.c */ + +void x86_64_timer_calibrate_freq(void); +void x86_64_timer_initialize(void); + +/* Defined in board/up_network.c */ + +#ifdef CONFIG_NET +void up_netinitialize(void); +#else +# define up_netinitialize() +#endif + +#ifdef CONFIG_USBDEV +void up_usbinitialize(void); +void up_usbuninitialize(void); +#else +# define up_usbinitialize() +# define up_usbuninitialize() +#endif + +#endif /* __ASSEMBLY__ */ + +#endif /* __ARCH_X86_64_SRC_COMMON_UP_INTERNAL_H */ diff --git a/arch/x86_64/src/common/up_interruptcontext.c b/arch/x86_64/src/common/up_interruptcontext.c new file mode 100644 index 00000000000..d83fb74b659 --- /dev/null +++ b/arch/x86_64/src/common/up_interruptcontext.c @@ -0,0 +1,57 @@ +/**************************************************************************** + * arch/x86/src/common/up_interruptcontext.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 "up_internal.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_interrupt_context + * + * Description: + * Return true is we are currently executing in the interrupt handler + * context. + * + ****************************************************************************/ + +bool up_interrupt_context(void) +{ + return g_current_regs != NULL; +} diff --git a/arch/x86_64/src/common/up_lowputs.c b/arch/x86_64/src/common/up_lowputs.c new file mode 100644 index 00000000000..062b6e3c5d4 --- /dev/null +++ b/arch/x86_64/src/common/up_lowputs.c @@ -0,0 +1,59 @@ +/**************************************************************************** + * arch/x86_64/src/common/up_lowputs.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 "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_lowputs + * + * Description: + * This is a low-level helper function used to support debug. + * + ****************************************************************************/ + +void up_lowputs(const char *str) +{ + while (*str) + { + up_lowputc(*str++); + } +} diff --git a/arch/x86_64/src/common/up_mdelay.c b/arch/x86_64/src/common/up_mdelay.c new file mode 100644 index 00000000000..1d939304552 --- /dev/null +++ b/arch/x86_64/src/common/up_mdelay.c @@ -0,0 +1,75 @@ +/**************************************************************************** + * arch/x86/src/common/up_mdelay.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 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_mdelay + * + * Description: + * Delay inline for the requested number of milliseconds. + * *** NOT multi-tasking friendly *** + * + * ASSUMPTIONS: + * The setting CONFIG_BOARD_LOOPSPERMSEC has been calibrated + * + ****************************************************************************/ + +void up_mdelay(unsigned int milliseconds) +{ + volatile int i; + volatile int j; + + for (i = 0; i < milliseconds; i++) + { + for (j = 0; j < CONFIG_BOARD_LOOPSPERMSEC; j++) + { + } + } +} diff --git a/arch/x86_64/src/common/up_modifyreg16.c b/arch/x86_64/src/common/up_modifyreg16.c new file mode 100644 index 00000000000..dce9e4ca401 --- /dev/null +++ b/arch/x86_64/src/common/up_modifyreg16.c @@ -0,0 +1,70 @@ +/**************************************************************************** + * arch/x86/src/common/up_modifyreg16.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 "up_arch.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: modifyreg16 + * + * Description: + * Atomically modify the specified bits in a memory mapped register + * + ****************************************************************************/ + +void modifyreg16(unsigned int addr, uint16_t clearbits, uint16_t setbits) +{ + irqstate_t flags; + uint16_t regval; + + flags = enter_critical_section(); + regval = getreg16((uint16_t)addr); + regval &= ~clearbits; + regval |= setbits; + putreg16(regval, (uint16_t)addr); + leave_critical_section(flags); +} diff --git a/arch/x86_64/src/common/up_modifyreg32.c b/arch/x86_64/src/common/up_modifyreg32.c new file mode 100644 index 00000000000..993d4d0a0c2 --- /dev/null +++ b/arch/x86_64/src/common/up_modifyreg32.c @@ -0,0 +1,70 @@ +/**************************************************************************** + * arch/x86/src/common/up_modifyreg32.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 "up_arch.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: modifyreg32 + * + * Description: + * Atomically modify the specified bits in a memory mapped register + * + ****************************************************************************/ + +void modifyreg32(unsigned int addr, uint32_t clearbits, uint32_t setbits) +{ + irqstate_t flags; + uint32_t regval; + + flags = enter_critical_section(); + regval = getreg32((uint16_t)addr); + regval &= ~clearbits; + regval |= setbits; + putreg32(regval, (uint16_t)addr); + leave_critical_section(flags); +} diff --git a/arch/x86_64/src/common/up_modifyreg8.c b/arch/x86_64/src/common/up_modifyreg8.c new file mode 100644 index 00000000000..28bf894755e --- /dev/null +++ b/arch/x86_64/src/common/up_modifyreg8.c @@ -0,0 +1,70 @@ +/**************************************************************************** + * arch/x86/src/common/up_modifyreg8.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 "up_arch.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: modifyreg8 + * + * Description: + * Atomically modify the specified bits in a memory mapped register + * + ****************************************************************************/ + +void modifyreg8(unsigned int addr, uint8_t clearbits, uint8_t setbits) +{ + irqstate_t flags; + uint8_t regval; + + flags = enter_critical_section(); + regval = getreg8((uint16_t)addr); + regval &= ~clearbits; + regval |= setbits; + putreg8(regval, (uint16_t)addr); + leave_critical_section(flags); +} diff --git a/arch/x86_64/src/common/up_puts.c b/arch/x86_64/src/common/up_puts.c new file mode 100644 index 00000000000..cb21fed40a3 --- /dev/null +++ b/arch/x86_64/src/common/up_puts.c @@ -0,0 +1,60 @@ +/**************************************************************************** + * arch/x86/src/common/up_puts.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 "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_puts + * + * Description: + * This is a low-level helper function used to support debug. + * + ****************************************************************************/ + +void up_puts(const char *str) +{ + while (*str) + { + up_putc(*str++); + } +} diff --git a/arch/x86_64/src/common/up_releasepending.c b/arch/x86_64/src/common/up_releasepending.c new file mode 100644 index 00000000000..95440cb08f1 --- /dev/null +++ b/arch/x86_64/src/common/up_releasepending.c @@ -0,0 +1,130 @@ +/**************************************************************************** + * arch/x86_64/src/common/up_releasepending.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 "sched/sched.h" +#include "group/group.h" +#include "up_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_release_pending + * + * Description: + * Release and ready-to-run tasks that have + * collected in the pending task list. This can call a + * context switch if a new task is placed at the head of + * the ready to run list. + * + ****************************************************************************/ + +void up_release_pending(void) +{ + struct tcb_s *rtcb = this_task(); + + sinfo("From TCB=%p\n", rtcb); + + /* Merge the g_pendingtasks list into the ready-to-run task list */ + + if (sched_mergepending()) + { + /* The currently active task has changed! We will need to switch + * contexts. + * + * Update scheduler parameters. + */ + + sched_suspend_scheduler(rtcb); + + /* Are we operating in interrupt context? */ + + if (g_current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + up_restore_auxstate(rtcb); + + /* Update scheduler parameters */ + + sched_resume_scheduler(rtcb); + + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ + + up_restorestate(rtcb->xcp.regs); + } + + /* Copy the exception context into the TCB of the task that + * was currently active. if up_saveusercontext returns a non-zero + * value, then this is really the previously running task + * restarting! + */ + + else if (!up_saveusercontext(rtcb->xcp.regs)) + { + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + up_restore_auxstate(rtcb); + +#ifdef CONFIG_ARCH_ADDRENV + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ + + (void)group_addrenv(rtcb); +#endif + /* Update scheduler parameters */ + + sched_resume_scheduler(rtcb); + + /* Then switch contexts */ + + up_fullcontextrestore(rtcb->xcp.regs); + } + } +} diff --git a/arch/x86_64/src/common/up_reprioritizertr.c b/arch/x86_64/src/common/up_reprioritizertr.c new file mode 100644 index 00000000000..d1053a3ea96 --- /dev/null +++ b/arch/x86_64/src/common/up_reprioritizertr.c @@ -0,0 +1,185 @@ +/**************************************************************************** + * arch/x86_64/src/common/up_reprioritizertr.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 "sched/sched.h" +#include "group/group.h" +#include "up_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_reprioritize_rtr + * + * Description: + * Called when the priority of a running or + * ready-to-run task changes and the reprioritization will + * cause a context switch. Two cases: + * + * 1) The priority of the currently running task drops and the next + * task in the ready to run list has priority. + * 2) An idle, ready to run task's priority has been raised above the + * the priority of the current, running task and it now has the + * priority. + * + * Input Parameters: + * tcb: The TCB of the task that has been reprioritized + * priority: The new task priority + * + ****************************************************************************/ + +void up_reprioritize_rtr(struct tcb_s *tcb, uint8_t priority) +{ + /* Verify that the caller is sane */ + + if (tcb->task_state < FIRST_READY_TO_RUN_STATE || + tcb->task_state > LAST_READY_TO_RUN_STATE +#if SCHED_PRIORITY_MIN > 0 + || priority < SCHED_PRIORITY_MIN +#endif +#if SCHED_PRIORITY_MAX < UINT8_MAX + || priority > SCHED_PRIORITY_MAX +#endif + ) + { + PANIC(); + } + else + { + struct tcb_s *rtcb = this_task(); + bool switch_needed; + + sinfo("TCB=%p PRI=%d\n", tcb, priority); + + /* Remove the tcb task from the ready-to-run list. + * sched_removereadytorun will return true if we just + * remove the head of the ready to run list. + */ + + switch_needed = sched_removereadytorun(tcb); + + /* Setup up the new task priority */ + + tcb->sched_priority = (uint8_t)priority; + + /* Return the task to the specified blocked task list. + * sched_addreadytorun will return true if the task was + * added to the new list. We will need to perform a context + * switch only if the EXCLUSIVE or of the two calls is non-zero + * (i.e., one and only one the calls changes the head of the + * ready-to-run list). + */ + + switch_needed ^= sched_addreadytorun(tcb); + + /* Now, perform the context switch if one is needed */ + + if (switch_needed) + { + /* If we are going to do a context switch, then now is the right + * time to add any pending tasks back into the ready-to-run list. + * task list now + */ + + if (g_pendingtasks.head) + { + sched_mergepending(); + } + + /* Update scheduler parameters */ + + sched_suspend_scheduler(rtcb); + + /* Are we in an interrupt handler? */ + + if (g_current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + up_restore_auxstate(rtcb); + + /* Update scheduler parameters */ + + sched_resume_scheduler(rtcb); + + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ + + up_restorestate(rtcb->xcp.regs); + } + + /* Copy the exception context into the TCB at the (old) head of the + * ready-to-run Task list. if up_saveusercontext returns a non-zero + * value, then this is really the previously running task restarting! + */ + + else if (!up_saveusercontext(rtcb->xcp.regs)) + { + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + up_restore_auxstate(rtcb); + +#ifdef CONFIG_ARCH_ADDRENV + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ + + (void)group_addrenv(rtcb); +#endif + /* Update scheduler parameters */ + + sched_resume_scheduler(rtcb); + + /* Then switch contexts */ + + up_fullcontextrestore(rtcb->xcp.regs); + } + } + } +} diff --git a/arch/x86_64/src/common/up_udelay.c b/arch/x86_64/src/common/up_udelay.c new file mode 100644 index 00000000000..d25a0bd764b --- /dev/null +++ b/arch/x86_64/src/common/up_udelay.c @@ -0,0 +1,102 @@ +/**************************************************************************** + * arch/x86/src/common/up_udelay.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 + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define CONFIG_BOARD_LOOPSPER100USEC ((CONFIG_BOARD_LOOPSPERMSEC+5)/10) +#define CONFIG_BOARD_LOOPSPER10USEC ((CONFIG_BOARD_LOOPSPERMSEC+50)/100) +#define CONFIG_BOARD_LOOPSPERUSEC ((CONFIG_BOARD_LOOPSPERMSEC+500)/1000) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_udelay + * + * Description: + * Delay inline for the requested number of microseconds. NOTE: Because + * of all of the setup, several microseconds will be lost before the actual + * timing loop begins. Thus, the delay will always be a few microseconds + * longer than requested. + * + * *** NOT multi-tasking friendly *** + * + * ASSUMPTIONS: + * The setting CONFIG_BOARD_LOOPSPERMSEC has been calibrated + * + ****************************************************************************/ + +void up_udelay(useconds_t microseconds) +{ + volatile int i; + + /* We'll do this a little at a time because we expect that the + * CONFIG_BOARD_LOOPSPERUSEC is very inaccurate during to truncation in + * the divisions of its calculation. We'll use the largest values that + * we can in order to prevent significant error buildup in the loops. + */ + + while (microseconds > 1000) + { + for (i = 0; i < CONFIG_BOARD_LOOPSPERMSEC; i++) + { + } + + microseconds -= 1000; + } + + while (microseconds > 100) + { + for (i = 0; i < CONFIG_BOARD_LOOPSPER100USEC; i++) + { + } + + microseconds -= 100; + } + + while (microseconds > 10) + { + for (i = 0; i < CONFIG_BOARD_LOOPSPER10USEC; i++) + { + } + + microseconds -= 10; + } + + while (microseconds > 0) + { + for (i = 0; i < CONFIG_BOARD_LOOPSPERUSEC; i++) + { + } + + microseconds--; + } +} diff --git a/arch/x86_64/src/common/up_unblocktask.c b/arch/x86_64/src/common/up_unblocktask.c new file mode 100644 index 00000000000..585c46317d1 --- /dev/null +++ b/arch/x86_64/src/common/up_unblocktask.c @@ -0,0 +1,147 @@ +/**************************************************************************** + * arch/x86/src/common/up_unblocktask.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 "sched/sched.h" +#include "group/group.h" +#include "clock/clock.h" +#include "up_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_unblock_task + * + * Description: + * A task is currently in an inactive task list but has been prepped to + * execute. Move the TCB to the ready-to-run list, restore its context, + * and start execution. + * + * Input Parameters: + * tcb: Refers to the tcb to be unblocked. This tcb is in one of the + * waiting tasks lists. It must be moved to the ready-to-run list and, + * if it is the highest priority ready to run task, executed. + * + ****************************************************************************/ + +void up_unblock_task(struct tcb_s *tcb) +{ + struct tcb_s *rtcb = this_task(); + + /* Verify that the context switch can be performed */ + + ASSERT((tcb->task_state >= FIRST_BLOCKED_STATE) && + (tcb->task_state <= LAST_BLOCKED_STATE)); + + /* Remove the task from the blocked task list */ + + sched_removeblocked(tcb); + + /* Add the task in the correct location in the prioritized + * ready-to-run task list + */ + + if (sched_addreadytorun(tcb)) + { + /* The currently active task has changed! We need to do + * a context switch to the new task. + */ + + /* Update scheduler parameters */ + + sched_suspend_scheduler(rtcb); + + /* Are we in an interrupt handler? */ + + if (g_current_regs) + { + /* Yes, then we have to do things differently. + * Just copy the g_current_regs into the OLD rtcb. + */ + + up_savestate(rtcb->xcp.regs); + + /* Restore the exception context of the rtcb at the (new) head + * of the ready-to-run task list. + */ + + rtcb = this_task(); + up_restore_auxstate(rtcb); + + /* Update scheduler parameters */ + + sched_resume_scheduler(rtcb); + + /* Then switch contexts. Any necessary address environment + * changes will be made when the interrupt returns. + */ + + up_restorestate(rtcb->xcp.regs); + } + + /* We are not in an interrupt handler. Copy the user C context + * into the TCB of the task that was previously active. if + * up_saveusercontext returns a non-zero value, then this is really the + * previously running task restarting! + */ + + else if (!up_saveusercontext(rtcb->xcp.regs)) + { + /* Restore the exception context of the new task that is ready to + * run (probably tcb). This is the new rtcb at the head of the + * ready-to-run task list. + */ + + rtcb = this_task(); + up_restore_auxstate(rtcb); + +#ifdef CONFIG_ARCH_ADDRENV + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ + + (void)group_addrenv(rtcb); +#endif + /* Update scheduler parameters */ + + sched_resume_scheduler(rtcb); + + /* Then switch contexts */ + + up_fullcontextrestore(rtcb->xcp.regs); + } + } +} diff --git a/arch/x86_64/src/intel64/Kconfig b/arch/x86_64/src/intel64/Kconfig new file mode 100644 index 00000000000..6fc42c21671 --- /dev/null +++ b/arch/x86_64/src/intel64/Kconfig @@ -0,0 +1,55 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_INTEL64 +comment "intel64 Configuration Options" + +config ARCH_INTEL64_HAVE_TSC_DEADLINE + bool "TSC DEADLINE timer support" + default y + ---help--- + Select to enable the use of TSC DEADLINE timer of x86_64 + +if ARCH_INTEL64_HAVE_TSC_DEADLINE + +config ARCH_INTEL64_CORE_FREQ_KHZ + int "CPU Core frequency in kHz" + default 2000000 + ---help--- + The CPU Core frequency (without Turbo boost). This is used + to set the TSC deadline timer frequency. + +endif + +if !ARCH_INTEL64_HAVE_TSC_DEADLINE + +config ARCH_INTEL64_APIC_FREQ_KHZ + int "APIC timer frequency in kHz" + default 2000000 + ---help--- + The APIC timer frequency. This is used to set the APIC timer + frequency in case of no TSC DEADLINE timer is available. + +endif + +config ARCH_INTEL64_HAVE_SSE3 + bool "SSE3 support" + default y + ---help--- + Select to enable the use of SSE3 and FPU functions of x86_64 + +config ARCH_INTEL64_HAVE_PCID + bool "PCID support" + default y + ---help--- + Select to enable the use of PCID to reduce TLB flush + +config ARCH_INTEL64_HAVE_RDRAND + bool "RDRAND support" + default y + ---help--- + Select to enable the use of RDRAND for /dev/random + +endif diff --git a/arch/x86_64/src/intel64/Make.defs b/arch/x86_64/src/intel64/Make.defs new file mode 100644 index 00000000000..30bbcbe219c --- /dev/null +++ b/arch/x86_64/src/intel64/Make.defs @@ -0,0 +1,49 @@ +############################################################################ +# arch/x86_64/src/intel64/Make.defs +# +# 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. +# +############################################################################ + +# Common x86_64 and intel64 files + +CMN_CSRCS += up_allocateheap.c up_assert.c up_blocktask.c up_copystate.c up_restore_auxstate.c +CMN_CSRCS += up_createstack.c up_mdelay.c up_udelay.c up_exit.c +CMN_CSRCS += up_initialize.c up_initialstate.c up_interruptcontext.c +CMN_CSRCS += up_irq.c up_modifyreg8.c up_modifyreg16.c up_modifyreg32.c +CMN_CSRCS += up_regdump.c up_releasepending.c up_releasestack.c +CMN_CSRCS += up_reprioritizertr.c up_savestate.c up_sigdeliver.c +CMN_CSRCS += up_schedulesigaction.c up_stackframe.c up_unblocktask.c +CMN_CSRCS += up_usestack.c +CMN_CSRCS += up_rtc.c +CMN_CSRCS += up_map_region.c + +# Required Intel64 files + +CHIP_ASRCS = intel64_saveusercontext.S intel64_fullcontextrestore.S intel64_vectors.S intel64_head.S +CHIP_CSRCS = intel64_handlers.c intel64_idle.c intel64_lowsetup.c +CHIP_CSRCS += intel64_serial.c intel64_rng.c intel64_check_capability.c + +# Configuration-dependent intel64 files + +ifneq ($(CONFIG_SCHED_TICKLESS),y) +CHIP_CSRCS += intel64_timerisr.c +endif + +ifeq ($(CONFIG_SCHED_TICKLESS),y) +CHIP_CSRCS += intel64_tickless.c +endif + diff --git a/arch/x86_64/src/intel64/chip.h b/arch/x86_64/src/intel64/chip.h new file mode 100644 index 00000000000..3c0820cec1a --- /dev/null +++ b/arch/x86_64/src/intel64/chip.h @@ -0,0 +1,46 @@ +/************************************************************************************ + * arch/x86_64/src/broadwell/chip.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_BROADWELL_BROADWELL_CHIP_H +#define __ARCH_X86_64_SRC_BROADWELL_BROADWELL_CHIP_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +#endif /* __ARCH_X86_64_SRC_BROADWELL_BROADWELL_CHIP_H */ diff --git a/arch/x86_64/src/intel64/intel64.h b/arch/x86_64/src/intel64/intel64.h new file mode 100644 index 00000000000..753d12c3ba0 --- /dev/null +++ b/arch/x86_64/src/intel64/intel64.h @@ -0,0 +1,148 @@ +/************************************************************************************ + * arch/x86_64/src/intel64/intel64.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_H +#define __ARCH_X86_64_SRC_INTEL64_INTEL64_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include + +#include +#include +#include + +#include "up_internal.h" +#include "chip.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Configuration ********************************************************************/ + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +/************************************************************************************ + * Inline Functions + ************************************************************************************/ + +#ifndef __ASSEMBLY__ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/************************************************************************************ + * Public Function Prototypes + ************************************************************************************/ + +/************************************************************************************ + * Name: intel64_lowsetup + * + * Description: + * Called at the very beginning of _start. Performs low level initialization + * including setup of the console UART. This UART done early so that the serial + * console is available for debugging very early in the boot sequence. + * + ************************************************************************************/ + +void intel64_lowsetup(void); + +/************************************************************************************ + * Name: vector_* + * + * Description: + * These are the various ISR/IRQ vector address exported from + * intel64_vectors.S. These addresses need to have global scope so that they + * can be known to the interrupt initialization logic in intel64_irq.c. + * + ************************************************************************************/ + +void vector_isr0(void); +void vector_isr1(void); +void vector_isr2(void); +void vector_isr3(void); +void vector_isr4(void); +void vector_isr5(void); +void vector_isr6(void); +void vector_isr7(void); +void vector_isr8(void); +void vector_isr9(void); +void vector_isr10(void); +void vector_isr11(void); +void vector_isr12(void); +void vector_isr13(void); +void vector_isr14(void); +void vector_isr15(void); +void vector_isr16(void); +void vector_isr17(void); +void vector_isr18(void); +void vector_isr19(void); +void vector_isr20(void); +void vector_isr21(void); +void vector_isr22(void); +void vector_isr23(void); +void vector_isr24(void); +void vector_isr25(void); +void vector_isr26(void); +void vector_isr27(void); +void vector_isr28(void); +void vector_isr29(void); +void vector_isr30(void); +void vector_isr31(void); +void vector_irq0(void); +void vector_irq1(void); +void vector_irq2(void); +void vector_irq3(void); +void vector_irq4(void); +void vector_irq5(void); +void vector_irq6(void); +void vector_irq7(void); +void vector_irq8(void); +void vector_irq9(void); +void vector_irq10(void); +void vector_irq11(void); +void vector_irq12(void); +void vector_irq13(void); +void vector_irq14(void); +void vector_irq15(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_X86_64_SRC_INTEL64_INTEL64_H */ diff --git a/arch/x86_64/src/intel64/intel64_check_capability.c b/arch/x86_64/src/intel64/intel64_check_capability.c new file mode 100644 index 00000000000..958839e6429 --- /dev/null +++ b/arch/x86_64/src/intel64/intel64_check_capability.c @@ -0,0 +1,108 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/intel64_capability.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 "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: x86_64_check_capability + * + * Description: + * Called from up_lowsetup to check various CPU capabilities, matching the + * RTOS config + * + ****************************************************************************/ + +void x86_64_check_and_enable_capability(void) +{ + unsigned long ecx; + unsigned long require; + + require = X86_64_CPUID_01_X2APIC; + + /* Check timer availability */ + +#ifdef CONFIG_ARCH_INTEL64_HAVE_TSC_DEADLINE + require |= X86_64_CPUID_01_TSCDEA; +#endif + +#ifdef CONFIG_ARCH_INTEL64_HAVE_SSE3 + require |= X86_64_CPUID_01_SSE3; + require |= X86_64_CPUID_01_XSAVE; +#endif + +#ifdef CONFIG_ARCH_INTEL64_HAVE_RDRAND + require |= X86_64_CPUID_01_RDRAND; +#endif + +#ifdef CONFIG_ARCH_INTEL64_HAVE_PCID + require |= X86_64_CPUID_01_PCID; +#endif + + asm volatile("cpuid" : "=c" (ecx) : "a" (X86_64_CPUID_CAP) + : "rbx", "rdx", "memory"); + + /* Check x2APIC availability */ + + if ((ecx & require) != require) + { + goto err; + } + +#ifdef CONFIG_ARCH_INTEL64_HAVE_SSE3 + __enable_sse3(); +#endif + +#ifdef CONFIG_ARCH_INTEL64_HAVE_PCID + __enable_pcid(); +#endif + + return; + +err: + asm volatile ("cli"); + asm volatile ("hlt"); + goto err; +} + diff --git a/arch/x86_64/src/intel64/intel64_fullcontextrestore.S b/arch/x86_64/src/intel64/intel64_fullcontextrestore.S new file mode 100644 index 00000000000..2ec121c0706 --- /dev/null +++ b/arch/x86_64/src/intel64/intel64_fullcontextrestore.S @@ -0,0 +1,157 @@ +/************************************************************************** + * arch/x86_64/src/intel64/intel64_fullcontextrestore.S + * + * 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 "up_internal.h" + + .file "intel64_fullcontextrestore.S" + +/************************************************************************** + * Pre-processor Definitions + **************************************************************************/ + +/************************************************************************** + * Public Data + **************************************************************************/ + +/**************************************************************************** + * Macros + ****************************************************************************/ + +/* Trace macros, use like trace 'i' to print char to serial port. */ + + .macro chout, addr, ch +#ifdef CONFIG_DEBUG_FEATURES + mov $\addr, %dx + mov $\ch, %al + out %al, %dx +#endif + .endm + + .macro trace, ch +#ifdef CONFIG_DEBUG_FEATURES + push %eax + push %edx + chout 0x3f8, \ch + pop %edx + pop %eax +#endif + .endm + +/************************************************************************** + * Public Functions + **************************************************************************/ + + .text + +/************************************************************************** + * Name: up_fullcontextrestore + * + * Full C prototype: + * void up_fullcontextrestore(uint32_t *regs) noreturn_function; + * + **************************************************************************/ + + .globl up_fullcontextrestore + .type up_fullcontextrestore, @function +up_fullcontextrestore: + /* The pointer to the register save array in RDI. */ + + /* Disable interrupts now (the correct RFLAGS will be restored before we + * return + */ + + cli + + /* Create an interrupt stack frame for the final iret. + * + * + * IRET STACK + * --------------- + * RSP Before -> + * SS + * RSP + * RFLAGS + * CS + * RSP After -> RIP + * + */ + + movq (8*REG_SS)(%rdi), %rbx + push %rbx + movq (8*REG_RSP)(%rdi), %rbx + push %rbx + + movq (8*REG_RFLAGS)(%rdi), %rbx + push %rbx + movq (8*REG_CS)(%rdi), %rbx + push %rbx + movq (8*REG_RIP)(%rdi), %rbx + push %rbx + + /* Save the value of RDI on the stack too */ + + movq (8*REG_RDI)(%rdi), %rbx + push %rbx + + /* Now restore the remaining registers */ + movq (8*REG_RSI)(%rdi), %rsi + movq (8*REG_RDX)(%rdi), %rdx + movq (8*REG_RCX)(%rdi), %rcx + movq (8*REG_R8 )(%rdi), %r8 + movq (8*REG_R9 )(%rdi), %r9 + + movq (8*REG_R15)(%rdi), %r15 + movq (8*REG_R14)(%rdi), %r14 + movq (8*REG_R13)(%rdi), %r13 + movq (8*REG_R12)(%rdi), %r12 + movq (8*REG_R11)(%rdi), %r11 + movq (8*REG_R10)(%rdi), %r10 + movq (8*REG_RBP)(%rdi), %rbp + movq (8*REG_RBX)(%rdi), %rbx + movq (8*REG_RAX)(%rdi), %rax + + /* Restore the data segment register. I think there is an issue that will + * need to be address here at some time: If the register save area is in + * one data segment and the stack is in another, then the above would not + * work (and, conversely, if they are in the same data segment, the + * following is unnecessary and redundant). + */ + + mov (8*REG_DS)(%rdi), %ds + // mov (8*REG_ES)(%rdi), %es // Not used in 64 bit + // mov (8*REG_GS)(%rdi), %gs // Disabled, otherwise we will destroy MSR_GS_BASE + // mov (8*REG_FS)(%rdi), %fs // Disabled, otherwise we will destroy MSR_FS_BASE + // XXX: Should use wrgsbase and wrfsbase to restore the gs and fs register + + /* restore xmm registers */ + fxrstorq (%rdi) + + /* Restore the correct value of EAX and then return */ + + popq %rdi + iretq + .size up_fullcontextrestore, . - up_fullcontextrestore + .end diff --git a/arch/x86_64/src/intel64/intel64_handlers.c b/arch/x86_64/src/intel64/intel64_handlers.c new file mode 100644 index 00000000000..6743ad222fe --- /dev/null +++ b/arch/x86_64/src/intel64/intel64_handlers.c @@ -0,0 +1,217 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/intel64_handlers.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 "up_internal.h" +#include "sched/sched.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define X2APIC_EOI 0x80b + +#define APIC_EOI_ACK 0 + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: common_handler + * + * Description: + * Common logic for the ISR/IRQ handlers + * + ****************************************************************************/ + +#ifndef CONFIG_SUPPRESS_INTERRUPTS +static uint64_t *common_handler(int irq, uint64_t *regs) +{ + board_autoled_on(LED_INIRQ); + + /* Current regs non-zero indicates that we are processing an interrupt; + * g_current_regs is also used to manage interrupt level context switches. + * + * Nested interrupts are not supported. + */ + + DEBUGASSERT(g_current_regs == NULL); + g_current_regs = regs; + + /* Deliver the IRQ */ + + irq_dispatch(irq, regs); + +#if defined(CONFIG_ARCH_FPU) || defined(CONFIG_ARCH_ADDRENV) + /* Check for a context switch. If a context switch occurred, then + * g_current_regs will have a different value than it did on entry. If an + * interrupt level context switch has occurred, then restore the floating + * point state and the establish the correct address environment before + * returning from the interrupt. + */ + + if (regs != g_current_regs) + { +#ifdef CONFIG_ARCH_FPU + /* Restore floating point registers */ + + up_restorefpu((uint64_t *)g_current_regs); +#endif + +#ifdef CONFIG_ARCH_ADDRENV + /* Make sure that the address environment for the previously + * running task is closed down gracefully (data caches dump, + * MMU flushed) and set up the address environment for the new + * thread at the head of the ready-to-run list. + */ + + (void)group_addrenv(NULL); +#endif + } +#endif + + /* If a context switch occurred while processing the interrupt then + * g_current_regs may have change value. If we return any value different + * from the input regs, then the lower level will know that a context + * switch occurred during interrupt processing. + */ + + regs = (uint64_t *)g_current_regs; + + /* Set g_current_regs to NULL to indicate that we are no longer in an + * interrupt handler. + */ + + g_current_regs = NULL; + return regs; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: isr_handler + * + * Description: + * This gets called from ISR vector handling logic in broadwell_vectors.S + * + ****************************************************************************/ + +#define SIGFPE 8 + +uint64_t *isr_handler(uint64_t *regs, uint64_t irq) +{ +#ifdef CONFIG_SUPPRESS_INTERRUPTS + board_autoled_on(LED_INIRQ); + PANIC(); /* Doesn't return */ + return regs; /* To keep the compiler happy */ +#else + uint64_t *ret; + + DEBUGASSERT(g_current_regs == NULL); + g_current_regs = regs; + + switch (irq) + { + case 0: + case 16: + asm volatile("fnclex":::"memory"); + nxsig_kill(this_task()->pid, SIGFPE); + break; + + default: + /* Let's say, all ISR are asserted when REALLY BAD things happened. + * Don't even brother to recover, just dump the regs and PANIC. + */ + + _alert("PANIC:\n"); + _alert("Exception %lld occurred with error code %lld:\n", + irq, regs[REG_ERRCODE]); + + up_registerdump(regs); + + up_trash_cpu(); + break; + } + + /* Maybe we need a context switch */ + + regs = (uint64_t *)g_current_regs; + + /* Set g_current_regs to NULL to indicate that we are no longer in an + * interrupt handler. + */ + + g_current_regs = NULL; + return regs; +#endif +} + +/**************************************************************************** + * Name: isr_handler + * + * Description: + * This gets called from IRQ vector handling logic in intel64_vectors.S + * + ****************************************************************************/ + +uint64_t *irq_handler(uint64_t *regs, uint64_t irq_no) +{ +#ifdef CONFIG_SUPPRESS_INTERRUPTS + board_autoled_on(LED_INIRQ); + PANIC(); /* Doesn't return */ + return regs; /* To keep the compiler happy */ +#else + uint64_t *ret; + int irq; + + board_autoled_on(LED_INIRQ); + + /* Get the IRQ number */ + + irq = (int)irq_no; + + /* Dispatch the interrupt */ + + ret = common_handler(irq, regs); + + /* Send an EOI (end of interrupt) signal to the APIC */ + + write_msr(X2APIC_EOI, APIC_EOI_ACK); + board_autoled_off(LED_INIRQ); + return ret; +#endif +} diff --git a/arch/x86_64/src/intel64/intel64_head.S b/arch/x86_64/src/intel64/intel64_head.S new file mode 100644 index 00000000000..06d5934f038 --- /dev/null +++ b/arch/x86_64/src/intel64/intel64_head.S @@ -0,0 +1,458 @@ +/**************************************************************************** + * arch/x86/src/intel64/intel64_head.S + * + * 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 + + .file "intel64_head.S" + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +/* Memory Map: _sbss is the start of the BSS region (see ld.script) _ebss is + * the end of the BSS regsion (see ld.script). The idle task stack starts at + * the end of BSS and is of size CONFIG_IDLETHREAD_STACKSIZE. The IDLE thread + * is the thread that the system boots on and, eventually, becomes the idle, + * do nothing task that runs only when there is nothing else to run. The + * heap continues from there until the end of memory. See g_idle_topstack below. + */ + +#define STACKBASE ((_ebss + 0x1f) & 0xffffffe0) +#define IDLE_STACK (STACKBASE+CONFIG_IDLETHREAD_STACKSIZE) +#define HEAP_BASE (STACKBASE+CONFIG_IDLETHREAD_STACKSIZE) + +/**************************************************************************** + * Macros + ****************************************************************************/ + +/* Trace macros, use like trace 'i' to print char to serial port. */ + + .macro trace, ch +#ifdef CONFIG_DEBUG_FEATURES + mov $0x3f8, %dx + mov $\ch, %al + out %al, %dx +#endif + .endm + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + .global __pmode_entry /* The 32bit protected mode entry */ + .global __nxstart + .global __enable_sse3 + .global __enable_pcid + .global nx_start /* nx_start is defined elsewhere */ + .global up_lowsetup /* up_lowsetup is defined elsewhere */ + .global g_idle_topstack /* The end of the idle stack, the start of the heap */ + + /* These are the page tables */ + .global pdpt_low + .global pd_low + .global pt_low + + /* These are the GDT */ + .global gdt64_low + .global gdt64_ist_low + .global gdt64_low_end + + .global ist64_low + +/**************************************************************************** + * The multiboot2 header + ****************************************************************************/ + + .set HEADER_LENGTH, header_end - header_start + .set CHECKSUM, -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + HEADER_LENGTH) + +#ifndef CONFIG_ARCH_EXCLUDE_MULTIBOOT + .section ".multiboot", "a" + .align 8 + +header_start: + .long MULTIBOOT2_HEADER_MAGIC + .long MULTIBOOT_ARCHITECTURE_I386 + .long HEADER_LENGTH + .long CHECKSUM + + // multiboot tags go here + + .short MULTIBOOT_HEADER_TAG_END + .short 0 // flags, none set + .long 8 // size, including itself (short + short + long) +header_end: + +#endif + +/**************************************************************************** + * .text + ****************************************************************************/ + + .code32 + .section ".loader.text", "ax" + +/**************************************************************************** + * Name: __pmode_entry + * + * Description: + * Entry point for 32-bit protected mode + * Function to transit protected mode to 64-bit long mode + * + ****************************************************************************/ + + .type __pmode_entry, @function +__pmode_entry: +start32: + + // initialize rest of the page directory + lea pd_low, %edi + lea pt_low, %esi + + // Popluate the lower 4GB as non-present + // for ecx = 0...512 * 4 : Loop and setup the page directories + mov $0x800, %ecx // 512 * 3 +epd_loop: + mov %esi, %edx + or $(X86_PAGE_WR | X86_PAGE_PRESENT), %edx + mov %edx, 0(%edi) + add $(X86_PAGE_ENTRY_SIZE), %edi + + // for ebx = 0...1024: Loop and clear the page table of each page directory + mov $1024, %ebx +ept_loop: + movl $0x0, 0(%esi) + add $4, %esi + + // end for ebx + dec %ebx + jnz ept_loop + + // end for ecx + dec %ecx + jnz epd_loop + + // Temporary populate the lower 128MB on 1:1 mapping + lea pd_low, %edi + mov $(X86_PAGE_GLOBAL | X86_PAGE_WR | X86_PAGE_PRESENT | X86_PAGE_HUGE), %eax + + // for ecx = 0...64 : Loop and setup 64x 2MB page directories + mov $64, %ecx +pd_loop: + mov %eax, 0(%edi) + add $(HUGE_PAGE_SIZE), %eax + add $(X86_PAGE_ENTRY_SIZE), %edi + + // end for ecx + dec %ecx + jnz pd_loop + + // Populate the 1GB after 4GB boundary with Global mapping to kernel code + // This creates maps the lower 1GB to 4GB~5GB + lea pdpt_low, %edi + mov $(X86_PAGE_GLOBAL | X86_PAGE_WR | X86_PAGE_PRESENT | X86_PAGE_HUGE), %eax + + mov $0x4, %ecx + mov %eax, 0(%edi, %ecx, X86_PAGE_ENTRY_SIZE) + + // Enable PAE + mov %cr4, %eax + or $(X86_CR4_PAE | X86_CR4_PGE), %eax + mov %eax, %cr4 + + // Load the 4 level page table + // Level 1 and 2 were preset at build time in assembly for this loading + // process + // 4KiB page table is used + // Kernel mapped to 1GB HiMem + lea pml4, %eax + mov %eax, %cr3 + + movl $MSR_MTRR_DEF_TYPE, %ecx + rdmsr + or $MTRR_ENABLE, %eax + wrmsr + + movl $MSR_EFER, %ecx + rdmsr + or $EFER_LME, %eax + wrmsr + + // Enable paging related bits in CR0 + mov $(X86_CR0_PG | X86_CR0_WP | X86_CR0_PE), %eax + mov %eax, %cr0 + + // Enable FGSBASE + mov %cr4, %eax + or $X86_CR4_FGSBASE, %eax + mov %eax, %cr4 + + + // Load a GDT with 64bits mode set + lgdt gdt64_ptr + + // Long jump into 64 bit mode, updating cs to new GDT + ljmpl $(X86_GDT_CODE_SEL), $start64 + + .code64 +start64: + + // Set Segement Registers for proper iret, etc. operation + mov $(X86_GDT_DATA_SEL), %ax + mov %ax, %ss + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + + // Finally, we can start the OS + movabs $__nxstart, %rbx + jmp *%rbx + .size __pmode_entry, . - __pmode_entry + +/**************************************************************************** + * Name: __nxstart + * + * Description: + * Do low-level initialization and call nx_start + * + ****************************************************************************/ + + .section .text, "a" + .type __nxstart, @function + +__nxstart: + /* We are now in high memory, revoke the lower 128MB memory mapping */ + lea pd_low, %edi + mov $0, %eax + + // for ecx = 0...64 : Loop and setup 64x 2MB page directories + mov $64, %ecx +npd_loop: + mov %eax, 0(%edi) + add $(HUGE_PAGE_SIZE), %eax + add $(X86_PAGE_ENTRY_SIZE), %edi + + // end for ecx + dec %ecx + jnz npd_loop + + //clear out bss section + movabs $_sbss, %rbx + movabs $_ebss, %rdx +clear_bss: + movb $0, (%rbx) + inc %rbx + cmp %rbx, %rdx + jne clear_bss + + // Properly setup RSP to idle stack + movabs $idle_stack, %rbx + add $CONFIG_IDLETHREAD_STACKSIZE, %rbx + mov %rbx, %rsp + + + /* Initialize and start NuttX */ + call up_lowsetup /* Low-level, pre-OS initialization */ + + call nx_start /* Start NuttX */ + + /* NuttX will not return */ + /* We should never end up here */ + /* If we really do, then we are doomed, halting the processor for ever */ + + cli +hang: + hlt /* Halt machine should NuttX return */ + jmp hang + .size __nxstart, . - __nxstart + + +/**************************************************************************** + * Name: __enable_sse3 + * + * Description: + * Do low-level initialization SSE related processor setting + * + ****************************************************************************/ + + .type __enable_sse3, @function + +__enable_sse3: + // Enable SSE + mov %cr0, %rax + mov $(X86_CR0_EM), %rbx + not %rbx + and %rbx, %rax + or $(X86_CR0_MP), %rax + mov %rax, %cr0 + + // Enable Saving XMM context + mov %cr4, %rax + or $(X86_CR4_OSXFSR | X86_CR4_XMMEXCPT), %rax + mov %rax, %cr4 + + // Setup MXCSR, masking all SSE precision exception + ldmxcsr mxcsr_mem + + ret + + .size __enable_sse3, . - __enable_sse3 + + +/**************************************************************************** + * Name: __enable_pcid + * + * Description: + * Enable PCID support + * + ****************************************************************************/ + + .type __enable_pcid, @function + +__enable_pcid: + // Enable PCID and FGSBASE + mov %cr4, %rax + or $X86_CR4_PCIDE, %rax + mov %rax, %cr4 + + ret + + .size __enable_pcid, . - __enable_pcid + +/**************************************************************************** + * .data + ****************************************************************************/ + + .section ".loader.data", "ax" + + // IST for 64 bit long mode + // will be filled in up_irq + .align(16) +ist64_low: + .long 0 + .quad 0xdeadbeefdeadbee0 + .quad 0xdeadbeefdeadbee1 + .quad 0xdeadbeefdeadbee2 + .quad 0 + .quad 0 + .quad 0 + .quad 0 + .quad 0 + .quad 0 + .quad 0 + .quad 0 + .quad 0 + .word 0 + + // GDT for 64 bit long mode + .align(16) +gdt64_low: + .quad 0 + .quad X86_GDT_CODE64_ENTRY + .quad X86_GDT_DATA_ENTRY + .quad X86_GDT_CODE32_ENTRY + .quad X86_GDT_DATA_ENTRY + .quad X86_GDT_CODE64_ENTRY +gdt64_ist_low: + .quad 0x0 // TSS segment low + .quad 0x0 // TSS segment high +gdt64_low_end: + +gdt64_ptr: + .short gdt64_low_end - gdt64_low - 1 + .long gdt64_low + +mxcsr_mem: + .long 0x00001f80 + + .align(PAGE_SIZE) +pml4: + .quad pdpt_low + X86_PAGE_PRESENT + X86_PAGE_WR + + .align(PAGE_SIZE) +pdpt_low: + .quad pd_low + X86_PAGE_PRESENT + X86_PAGE_WR + .quad pd_2_low + X86_PAGE_PRESENT + X86_PAGE_WR + .quad pd_3_low + X86_PAGE_PRESENT + X86_PAGE_WR + .quad pd_4_low + X86_PAGE_PRESENT + X86_PAGE_WR + + .fill X86_NUM_PAGE_ENTRY - 4, X86_PAGE_ENTRY_SIZE, 0 + + .align(PAGE_SIZE) +pd_low: + .fill X86_NUM_PAGE_ENTRY, X86_PAGE_ENTRY_SIZE, 0 + + .align(PAGE_SIZE) +pd_2_low: + .fill X86_NUM_PAGE_ENTRY, X86_PAGE_ENTRY_SIZE, 0 + + .align(PAGE_SIZE) +pd_3_low: + .fill X86_NUM_PAGE_ENTRY, X86_PAGE_ENTRY_SIZE, 0 + + .align(PAGE_SIZE) +pd_4_low: + .fill X86_NUM_PAGE_ENTRY, X86_PAGE_ENTRY_SIZE, 0 + + .align(PAGE_SIZE) +pt_low: + .fill X86_NUM_PAGE_ENTRY * X86_NUM_PAGE_ENTRY, X86_PAGE_ENTRY_SIZE, 0 + .fill X86_NUM_PAGE_ENTRY * X86_NUM_PAGE_ENTRY, X86_PAGE_ENTRY_SIZE, 0 + .fill X86_NUM_PAGE_ENTRY * X86_NUM_PAGE_ENTRY, X86_PAGE_ENTRY_SIZE, 0 + .fill X86_NUM_PAGE_ENTRY * X86_NUM_PAGE_ENTRY, X86_PAGE_ENTRY_SIZE, 0 + +/**************************************************************************** + * .bss + ****************************************************************************/ + +/* The stack for the IDLE task thread is declared in .bss. NuttX boots and + * initializes on the IDLE thread, then at the completion of OS startup, this + * thread becomes the thread that executes when there is nothing else to + * do in the system (see up_idle()). + */ + + .section .bss, "a" + + .type idle_stack, @object + .comm idle_stack, CONFIG_IDLETHREAD_STACKSIZE, 32 + .size idle_stack, CONFIG_IDLETHREAD_STACKSIZE + +/**************************************************************************** + * .rodata + ****************************************************************************/ + + .section .rodata, "a" + +/* HEAP BASE: _sbss is the start of the BSS region (see ld.script) _ebss is + * the end of the BSS region (see liker script). The heap continues from there + * until the end of memory. + */ + + .type g_idle_topstack, @object +g_idle_topstack: + .quad _ebss + .size g_idle_topstack, . - g_idle_topstack + .end diff --git a/arch/x86_64/src/intel64/intel64_idle.c b/arch/x86_64/src/intel64/intel64_idle.c new file mode 100644 index 00000000000..229eb2b6045 --- /dev/null +++ b/arch/x86_64/src/intel64/intel64_idle.c @@ -0,0 +1,72 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/intel64_idle.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 "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_idle + * + * Description: + * up_idle() is the logic that will be executed when their is no other + * ready-to-run task. This is processor idle time and will continue until + * some interrupt occurs to cause a context switch from the idle task. + * + * Processing in this state may be processor-specific. e.g., this is where + * power management operations might be performed. + * + ****************************************************************************/ + +#ifndef CONFIG_ARCH_IDLE_CUSTOM +void up_idle(void) +{ +#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_TIMER_INTS) + /* If the system is idle and there are no timer interrupts, then process + * "fake" timer interrupts. Hopefully, something will wake up. + */ + + sched_process_timer(); +#else + asm volatile("hlt"); +#endif +} +#endif diff --git a/arch/x86_64/src/intel64/intel64_lowsetup.c b/arch/x86_64/src/intel64/intel64_lowsetup.c new file mode 100644 index 00000000000..ca9f07448aa --- /dev/null +++ b/arch/x86_64/src/intel64/intel64_lowsetup.c @@ -0,0 +1,96 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/intel64_lowsetup.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 "up_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_lowsetup + * + * Description: + * Called from intel64_head BEFORE starting the operating system in order + * perform any necessary, early initialization. + * + ****************************************************************************/ + +void up_lowsetup(void) +{ + /* we should be in long mode at this point*/ + + /* GDT is loaded with 64bit GDT */ + + /* Paging is enabled*/ + + /* Setup pointers for accessing Page table and GDT in high address */ + + pdpt = &pdpt_low + X86_64_LOAD_OFFSET; + pd = &pd_low + X86_64_LOAD_OFFSET; + pt = &pt_low + X86_64_LOAD_OFFSET; + + ist64 = (struct ist_s *)((void *)&ist64_low + X86_64_LOAD_OFFSET); + gdt64 = (struct gdt_entry_s *)((void *)&gdt64_low + X86_64_LOAD_OFFSET); + + /* reload the GDTR with mapped high memory address */ + + setgdt(gdt64, (uintptr_t)(&gdt64_low_end - &gdt64_low) - 1); + + /* Do some checking on CPU compatibilities */ + + x86_64_check_and_enable_capability(); + + /* perform board-specific initializations */ + + x86_64_boardinitialize(); + + /* Early serial driver initialization */ + + up_earlyserialinit(); + + x86_64_timer_calibrate_freq(); + +#ifdef CONFIG_LIB_SYSCALL + enable_syscall(); +#endif +} + diff --git a/arch/x86_64/src/intel64/intel64_rng.c b/arch/x86_64/src/intel64/intel64_rng.c new file mode 100644 index 00000000000..3c65cc075db --- /dev/null +++ b/arch/x86_64/src/intel64/intel64_rng.c @@ -0,0 +1,206 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/intel64_rng.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 + +#include + +#include "up_internal.h" + +#include + +#if defined(CONFIG_DEV_RANDOM) || defined(CONFIG_DEV_URANDOM_ARCH) + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int x86_rng_initialize(void); +static ssize_t x86_rngread(struct file *filep, char *buffer, size_t); + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct rng_dev_s +{ + sem_t rd_devsem; /* Threads can only exclusively access the RNG */ + sem_t rd_readsem; /* To block until the buffer is filled NOT used */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct rng_dev_s g_rngdev; + +static const struct file_operations g_rngops = +{ + 0, /* open */ + 0, /* close */ + x86_rngread, /* read */ + 0, /* write */ + 0, /* seek */ + 0 /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , 0 /* poll */ +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + , 0 /* unlink */ +#endif +}; + +/**************************************************************************** + * Private functions + ****************************************************************************/ + +/**************************************************************************** + * Name: x86_rng_initialize + ****************************************************************************/ + +static int x86_rng_initialize(void) +{ + _info("Initializing RNG\n"); + + memset(&g_rngdev, 0, sizeof(struct rng_dev_s)); + + nxsem_init(&g_rngdev.rd_devsem, 0, 1); + + return OK; +} + +/**************************************************************************** + * Name: x86_rngread + ****************************************************************************/ + +static ssize_t x86_rngread(struct file *filep, char *buffer, size_t buflen) +{ + for (; buflen > 8; buflen -= 8) + { + while (_rdrand64_step((unsigned long long *)buffer)) + { + sched_yield(); + } + + buffer += 8; + } + + for (; buflen > 4; buflen -= 4) + { + while (_rdrand32_step((unsigned int *)buffer)) + { + sched_yield(); + } + + buffer += 4; + } + + for (; buflen > 2; buflen -= 2) + { + while (_rdrand16_step((unsigned short *)buffer)) + { + sched_yield(); + } + + buffer += 2; + } + + if (buflen != 0) + { + unsigned short temp = 0; + + while (_rdrand16_step((unsigned short *)temp)) + { + sched_yield(); + } + + *buffer = (temp & 0xff); + } + + return buflen; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: devrandom_register + * + * Description: + * Initialize the RNG hardware and register the /dev/random driver. + * Must be called BEFORE devurandom_register. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_DEV_RANDOM +void devrandom_register(void) +{ + x86_rng_initialize(); + (void)register_driver("/dev/random", &g_rngops, 0444, NULL); +} +#endif + +/**************************************************************************** + * Name: devurandom_register + * + * Description: + * Register /dev/urandom + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_DEV_URANDOM_ARCH +void devurandom_register(void) +{ +#ifndef CONFIG_DEV_RANDOM + x86_rng_initialize(); +#endif + (void)register_driver("/dev/urandom", &g_rngops, 0444, NULL); +} +#endif + +#endif /* CONFIG_DEV_RANDOM || CONFIG_DEV_URANDOM_ARCH */ diff --git a/arch/x86_64/src/intel64/intel64_saveusercontext.S b/arch/x86_64/src/intel64/intel64_saveusercontext.S new file mode 100644 index 00000000000..d16e0efaacf --- /dev/null +++ b/arch/x86_64/src/intel64/intel64_saveusercontext.S @@ -0,0 +1,149 @@ +/************************************************************************** + * arch/x86/src/intel64/intel64_saveusercontext.S + * + * 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 "up_internal.h" + + .file "intel64_saveusercontext.S" + +/************************************************************************** + * Pre-processor Definitions + **************************************************************************/ + +/**************************************************************************** + * Macros + ****************************************************************************/ + +/* Trace macros, use like trace 'i' to print char to serial port. */ + + .macro chout, addr, ch +#ifdef CONFIG_DEBUG_FEATURES + mov $\addr, %dx + mov $\ch, %al + out %al, %dx +#endif + .endm + + .macro trace, ch +#ifdef CONFIG_DEBUG_FEATURES + push %eax + push %edx + chout 0x3f8, \ch + pop %edx + pop %eax +#endif + .endm + +/************************************************************************** + * .text + **************************************************************************/ + + .text +.code64 +/************************************************************************** + * Name: up_saveusercontext + * + * Full C prototype: + * int up_saveusercontext(uint32_t *regs); + * + * Description: + * Save the "user" context. It is not necessary to save all of the + * registers because it is acceptable for certain registers to be + * modified upon return from a subroutine call. On a context switch + * back to user mode, it will appear as a return from this function. + * + * According to the SysV x86_64 ABI, the RAX, RDI, RSI, RDX, RCX, r8 and r9 + * are to be free for use within a procedure or function, and need not + * be preserved. + * + * On entry, + * sp points to the return address + * rdi points to register save array + * + **************************************************************************/ + + .globl up_saveusercontext + .type up_saveusercontext, @function +up_saveusercontext: + + // callee saved regs + movq %rbx, (8*REG_RBX)(%rdi) + movq %r12, (8*REG_R12)(%rdi) + movq %r13, (8*REG_R13)(%rdi) + movq %r14, (8*REG_R14)(%rdi) + movq %r15, (8*REG_R15)(%rdi) + + // save xmm registers + fxsaveq (%rdi) + + /* Save the value of SP as will be at the time of the IRET that will + * appear to be the return from this function. + * + * CURRENT STACK IRET STACK + * ------------------------------ ----------------- + * RIP + * CS + * RFLAGS + * RSP + * ESP->Return address SS + * Argument Alignment (16bytes) + * + */ + + leaq 8(%rsp), %rcx + movq %rcx, (8*REG_RSP)(%rdi) + + /* Fetch the PC from the stack and save it in the save block */ + + movq 0(%rsp), %rcx + movq %rcx, (8*REG_RIP)(%rdi) + + /* Save the framepointer */ + + movq %rbp, (8*REG_RBP)(%rdi) + + /* Save EAX=1. This will be the "apparent" return value from this + * function when context is switch back to this thread. The non-zero + * return value is the indication that we have been resumed. + */ + + movq $1, (8*REG_RAX)(%rdi) + + /* Get and save the interrupt state */ + + pushf + pop %rcx + movq %rcx, (8*REG_RFLAGS)(%rdi) + + /* And return 0 -- The zero return value is the indication that that + * this is the original, "true" return from the function. + * + * 'ret' will remove the RIP from the top of the stack. + */ + + xor %rax, %rax + ret + .size up_saveusercontext, . - up_saveusercontext + .end diff --git a/arch/x86_64/src/intel64/intel64_serial.c b/arch/x86_64/src/intel64/intel64_serial.c new file mode 100644 index 00000000000..0d392ff88a7 --- /dev/null +++ b/arch/x86_64/src/intel64/intel64_serial.c @@ -0,0 +1,99 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/intel64_serial.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 "up_internal.h" + +/* This is a "stub" file to suppport up_putc if no real serial driver is + * configured. Normally, drivers/serial/uart_16550.c provides the serial + * driver for this platform. + */ + +#ifdef USE_SERIALDRIVER + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: uart_getreg(), uart_putreg() + * + * Description: + * These functions must be provided by the processor-specific code in order + * to correctly access 16550 registers + * + ****************************************************************************/ + +uart_datawidth_t uart_getreg(uart_addrwidth_t base, unsigned int offset) +{ + return inb(base + offset); +} + +void uart_putreg(uart_addrwidth_t base, unsigned int offset, + uart_datawidth_t value) +{ + /* Intel x86 platform require OUT2 of MCR being set + * for interrupt to be triggered. We make sure that bit is stuck at 1. + */ + + if (offset == UART_MCR_OFFSET) + { + value |= UART_MCR_OUT2; + } + + outb(value, base + offset); +} + +#else /* USE_SERIALDRIVER */ + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + up_lowputc('\r'); + } + + up_lowputc(ch); + return ch; +} + +#endif /* USE_SERIALDRIVER */ diff --git a/arch/x86_64/src/intel64/intel64_tickless.c b/arch/x86_64/src/intel64/intel64_tickless.c new file mode 100644 index 00000000000..24fcd5688f1 --- /dev/null +++ b/arch/x86_64/src/intel64/intel64_tickless.c @@ -0,0 +1,474 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/intel64_tickless.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. + * + ****************************************************************************/ + +/**************************************************************************** + * Tickless OS Support. + * + * When CONFIG_SCHED_TICKLESS is enabled, all support for timer interrupts + * is suppressed and the platform specific code is expected to provide the + * following custom functions. + * + * void sim_timer_initialize(void): Initializes the timer facilities. Called + * early in the intialization sequence (by up_intialize()). + * int up_timer_gettime(FAR struct timespec *ts): Returns the current + * time from the platform specific time source. + * int up_timer_cancel(void): Cancels the interval timer. + * int up_timer_start(FAR const struct timespec *ts): Start (or re-starts) + * the interval timer. + * + * The RTOS will provide the following interfaces for use by the platform- + * specific interval timer implementation: + * + * void sched_timer_expiration(void): Called by the platform-specific + * logic when the interval timer expires. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#ifdef CONFIG_SCHED_TICKLESS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NS_PER_USEC 1000UL +#define NS_PER_MSEC 1000000UL +#define NS_PER_SEC 1000000000UL + +#define TMR_IRQ IRQ14 + +#define ROUND_INT_DIV(s, d) (s + (d >> 1)) / d + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +unsigned long x86_64_timer_freq; + +static struct timespec g_goal_time_ts; +static uint64_t g_last_stop_time; +static uint64_t g_start_tsc; +static uint32_t g_timer_active; + +static irqstate_t g_tmr_sync_count; +static irqstate_t g_tmr_flags; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +void up_mask_tmr(void) +{ + /* Disable TSC Deadline interrupt */ + +#ifdef CONFIG_ARCH_INTEL64_HAVE_TSC_DEADLINE + write_msr(MSR_X2APIC_LVTT, TMR_IRQ | MSR_X2APIC_LVTT_TSC_DEADLINE | (1 << 16)); +#else + write_msr(MSR_X2APIC_LVTT, TMR_IRQ | (1 << 16)); +#endif + + /* Required when using TSC deadline mode. */ + + asm volatile("mfence" : : : "memory"); +} + +void up_unmask_tmr(void) +{ + /* Enable TSC Deadline interrupt */ + +#ifdef CONFIG_ARCH_INTEL64_HAVE_TSC_DEADLINE + write_msr(MSR_X2APIC_LVTT, TMR_IRQ | MSR_X2APIC_LVTT_TSC_DEADLINE); +#else + write_msr(MSR_X2APIC_LVTT, TMR_IRQ); +#endif + + /* Required when using TSC deadline mode. */ + + asm volatile("mfence" : : : "memory"); +} + +#ifndef CONFIG_SCHED_TICKLESS_ALARM +void up_timer_expire(void); +#else +void up_alarm_expire(void); +#endif + +void up_timer_initialize(void) +{ + g_last_stop_time = g_start_tsc = rdtsc(); + +#ifndef CONFIG_SCHED_TICKLESS_ALARM + (void)irq_attach(TMR_IRQ, (xcpt_t)up_timer_expire, NULL); +#else + (void)irq_attach(TMR_IRQ, (xcpt_t)up_alarm_expire, NULL); +#endif + + return; +} + +static inline uint64_t up_ts2tick(FAR const struct timespec *ts) +{ + return ROUND_INT_DIV((uint64_t)ts->tv_nsec * x86_64_timer_freq, NS_PER_SEC) + + (uint64_t)ts->tv_sec * x86_64_timer_freq; +} + +static inline void up_tick2ts(uint64_t tick, FAR struct timespec *ts) +{ + ts->tv_sec = (tick / x86_64_timer_freq); + ts->tv_nsec = (uint64_t)(ROUND_INT_DIV((tick % x86_64_timer_freq) * + NSEC_PER_SEC, x86_64_timer_freq)); +} + +static inline void up_tmr_sync_up(void) +{ + if (!g_tmr_sync_count) + { + g_tmr_flags = enter_critical_section(); + } + + g_tmr_sync_count++; +} + +static inline void up_tmr_sync_down(void) +{ + if (g_tmr_sync_count == 1) + { + leave_critical_section(g_tmr_flags); + } + + if (g_tmr_sync_count > 0) + { + g_tmr_sync_count--; + } +} + +/**************************************************************************** + * Name: up_timer_gettime + * + * Description: + * Return the elapsed time since power-up (or, more correctly, since + * sim_timer_initialize() was called). This function is functionally + * equivalent to: + * + * int clock_gettime(clockid_t clockid, FAR struct timespec *ts); + * + * when clockid is CLOCK_MONOTONIC. + * + * This function provides the basis for reporting the current time and + * also is used to eliminate error build-up from small erros in interval + * time calculations. + * + * Provided by platform-specific code and called from the RTOS base code. + * + * Input Parameters: + * ts - Provides the location in which to return the up-time. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + * Assumptions: + * Called from the normal tasking context. The implementation must + * provide whatever mutual exclusion is necessary for correct operation. + * This can include disabling interrupts in order to assure atomic register + * operations. + * + ****************************************************************************/ + +int up_timer_gettime(FAR struct timespec *ts) +{ + uint64_t diff = (rdtsc() - g_start_tsc); + up_tick2ts(diff, ts); + return OK; +} + +#ifndef CONFIG_SCHED_TICKLESS_ALARM + +/**************************************************************************** + * Name: up_timer_cancel + * + * Description: + * Cancel the interval timer and return the time remaining on the timer. + * These two steps need to be as nearly atomic as possible. + * sched_timer_expiration() will not be called unless the timer is + * restarted with up_timer_start(). + * + * If, as a race condition, the timer has already expired when this + * function is called, then that pending interrupt must be cleared so + * that up_timer_start() and the remaining time of zero should be + * returned. + * + * Provided by platform-specific code and called from the RTOS base code. + * + * Input Parameters: + * ts - Location to return the remaining time. Zero should be returned + * if the timer is not active. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + * Assumptions: + * May be called from interrupt level handling or from the normal tasking + * level. Interrupts may need to be disabled internally to assure + * non-reentrancy. + * + ****************************************************************************/ + +int up_timer_cancel(FAR struct timespec *ts) +{ + up_tmr_sync_up(); + + up_mask_tmr(); + + if (ts != NULL) + { + if (g_timer_active) + { + up_tick2ts(g_goal_time - rdtsc(), ts); + } + else + { + ts->tv_sec = 0; + ts->tv_nsec = 0; + } + } + + g_timer_active = 0; + + up_tmr_sync_down(); + + return OK; +} + +/**************************************************************************** + * Name: up_timer_start + * + * Description: + * Start the interval timer. sched_timer_expiration() will be + * called at the completion of the timeout (unless up_timer_cancel + * is called to stop the timing. + * + * Provided by platform-specific code and called from the RTOS base code. + * + * Input Parameters: + * ts - Provides the time interval until sched_timer_expiration() is + * called. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + * Assumptions: + * May be called from interrupt level handling or from the normal tasking + * level. Interrupts may need to be disabled internally to assure + * non-reentrancy. + * + ****************************************************************************/ + +int up_timer_start(FAR const struct timespec *ts) +{ + uint64_t ticks; + + up_tmr_sync_up(); + + ticks = up_ts2tick(ts) + rdtsc(); + + g_timer_active = 1; + + write_msr(MSR_IA32_TSC_DEADLINE, ticks); + + g_goal_time = ticks; + + up_unmask_tmr(); + + up_tmr_sync_down(); + return OK; +} + +/**************************************************************************** + * Name: up_timer_expire + * + * Description: + * Called as the IRQ handler for alarm expiration. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void up_timer_expire(void) +{ + g_timer_active = 0; + + up_mask_tmr(); + sched_timer_expiration(); + + return; +} + +#else /* CONFIG_SCHED_TICKLESS_ALARM */ + +/**************************************************************************** + * Name: up_timer_cancel + * + * Description: + * Cancel the interval timer and return the time remaining on the timer. + * These two steps need to be as nearly atomic as possible. + * sched_timer_expiration() will not be called unless the timer is + * restarted with up_timer_start(). + * + * If, as a race condition, the timer has already expired when this + * function is called, then that pending interrupt must be cleared so + * that up_timer_start() and the remaining time of zero should be + * returned. + * + * Provided by platform-specific code and called from the RTOS base code. + * + * Input Parameters: + * ts - Location to return the remaining time. Zero should be returned + * if the timer is not active. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + * Assumptions: + * May be called from interrupt level handling or from the normal tasking + * level. Interrupts may need to be disabled internally to assure + * non-reentrancy. + * + ****************************************************************************/ + +int up_alarm_cancel(FAR struct timespec *ts) +{ + up_tmr_sync_up(); + + up_mask_tmr(); + + if (ts != NULL) + { + up_timer_gettime(ts); + } + + g_timer_active = 0; + + up_tmr_sync_down(); + + return OK; +} + +/**************************************************************************** + * Name: up_timer_start + * + * Description: + * Start the interval timer. sched_timer_expiration() will be + * called at the completion of the timeout (unless up_timer_cancel + * is called to stop the timing. + * + * Provided by platform-specific code and called from the RTOS base code. + * + * Input Parameters: + * ts - Provides the time interval until sched_timer_expiration() is + * called. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure. + * + * Assumptions: + * May be called from interrupt level handling or from the normal tasking + * level. Interrupts may need to be disabled internally to assure + * non-reentrancy. + * + ****************************************************************************/ + +int up_alarm_start(FAR const struct timespec *ts) +{ + uint64_t ticks; + + up_tmr_sync_up(); + + up_unmask_tmr(); + + ticks = up_ts2tick(ts) + g_start_tsc; + + write_msr(MSR_IA32_TSC_DEADLINE, ticks); + + g_timer_active = 1; + + g_goal_time_ts.tv_sec = ts->tv_sec; + g_goal_time_ts.tv_nsec = ts->tv_nsec; + + up_tmr_sync_down(); + + tmrinfo("%d.%09d\n", ts->tv_sec, ts->tv_nsec); + tmrinfo("start\n"); + + return OK; +} + +/**************************************************************************** + * Name: up_timer_update + * + * Description: + * Called as the IRQ handler for alarm expiration. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void up_alarm_expire(void) +{ + struct timespec now; + + up_mask_tmr(); + tmrinfo("expire\n"); + + g_timer_active = 0; + + up_timer_gettime(&now); + + nxsched_alarm_expiration(&now); + + return; +} + +#endif /* CONFIG_SCHED_TICKLESS_ALARM */ +#endif /* CONFIG_SCHED_TICKLESS */ diff --git a/arch/x86_64/src/intel64/intel64_timerisr.c b/arch/x86_64/src/intel64/intel64_timerisr.c new file mode 100644 index 00000000000..9a572b915b3 --- /dev/null +++ b/arch/x86_64/src/intel64/intel64_timerisr.c @@ -0,0 +1,135 @@ +/**************************************************************************** + * arch/x86/src/intel64/intel64_timerisr.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 "clock/clock.h" +#include "up_internal.h" +#include "up_arch.h" + +#include + +#include "chip.h" +#include "intel64.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NS_PER_USEC 1000UL +#define NS_PER_MSEC 1000000UL +#define NS_PER_SEC 1000000000UL + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +unsigned long x86_64_timer_freq; + +static unsigned long tsc_overflow; +static unsigned long tsc_last; +static unsigned long tsc_overflows; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: apic_timer_set + * + * Description: + * Set a time for APIC timer to fire + * + ****************************************************************************/ + +void apic_timer_set(unsigned long timeout_ns) +{ + unsigned long long ticks = + (unsigned long long)timeout_ns * x86_64_timer_freq / NS_PER_SEC; +#ifdef CONFIG_ARCH_INTEL64_HAVE_TSC_DEADLINE + write_msr(MSR_IA32_TSC_DEADLINE, rdtsc() + ticks); +#else + write_msr(MSR_X2APIC_TMICT, ticks); +#endif +} + +/**************************************************************************** + * Function: intel64_timerisr + * + * Description: + * The timer ISR will perform a variety of services for various portions + * of the systems. + * + ****************************************************************************/ + +static int intel64_timerisr(int irq, uint32_t *regs, void *arg) +{ + /* Process timer interrupt */ + + nxsched_process_timer(); + apic_timer_set(CONFIG_USEC_PER_TICK * NS_PER_USEC); + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: up_timer_initialize + * + * Description: + * This function is called during start-up to initialize + * the timer interrupt. + * + ****************************************************************************/ + +void up_timer_initialize(void) +{ + unsigned long ecx; + uint32_t vector = IRQ0; + + (void)irq_attach(IRQ0, (xcpt_t)intel64_timerisr, NULL); + +#ifdef CONFIG_ARCH_INTEL64_HAVE_TSC_DEADLINE + vector |= MSR_X2APIC_LVTT_TSC_DEADLINE; +#endif + + write_msr(MSR_X2APIC_LVTT, vector); + + asm volatile("mfence" : : : "memory"); + + apic_timer_set(NS_PER_MSEC); + + return; +} diff --git a/arch/x86_64/src/intel64/intel64_vectors.S b/arch/x86_64/src/intel64/intel64_vectors.S new file mode 100644 index 00000000000..f7d703d7dc6 --- /dev/null +++ b/arch/x86_64/src/intel64/intel64_vectors.S @@ -0,0 +1,397 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/intel64_vector.S + * + * 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 + + .file "broadwell_vectors.S" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * .text + ****************************************************************************/ + + .text + .code64 + +/**************************************************************************** + * Public Symbols + ****************************************************************************/ + + .globl irq_handler + .globl isr_handler + .globl g_interrupt_stack + .globl g_interrupt_stack_end + .globl g_isr_stack + .globl g_isr_stack_end + +/**************************************************************************** + * Macros + ****************************************************************************/ + +/* Trace macros, use like trace 'i' to print char to serial port. */ + + .macro trace, ch + mov $0x3f8, %dx + mov $\ch, %al + out %al, %dx + .endm + +/* This macro creates a stub for an ISR which does NOT pass it's own + * error code (adds a dummy errcode byte). + */ + + .macro ISR_NOERRCODE, intno + .globl vector_isr\intno +vector_isr\intno: + cli /* Disable interrupts firstly. */ + + // CPU has sawitched to the ISR stack using IST + + pushq $0 /* Push a dummy error code. */ + + // Save rdi, rsi + pushq %rdi + pushq %rsi + movq $\intno, %rsi /* INT Number is saved to 2nd parameter of function call */ + jmp isr_common /* Go to the common ISR handler code. */ + .endm + +/* This macro creates a stub for an ISR which passes it's own + * error code. + */ + + .macro ISR_ERRCODE, intno + .globl vector_isr\intno +vector_isr\intno: + cli /* Disable interrupts firstly. */ + + // CPU has sawitched to the ISR stack using IST + + // Save rdi, rsi + pushq %rdi + pushq %rsi + movq $\intno, %rsi /* INT Number is saved to 2nd parameter of function call */ + jmp isr_common /* Go to the common ISR handler code. */ + .endm + +/* This macro creates a stub for an IRQ - the first parameter is + * the IRQ number, the second is the ISR number it is remapped to. + */ + + .macro IRQ, irqno, intno + .globl vector_irq\irqno +vector_irq\irqno: + cli /* Disable interrupts firstly. */ + + // CPU has switched to the IRQ stack using IST + + pushq $0 /* Push a dummy error code. */ + + // Save rdi, rsi + pushq %rdi + pushq %rsi + movq $\intno, %rsi /* INT Number is saved to 2nd parameter of function call */ + jmp irq_common /* Go to the common IRQ handler code. */ + .endm + +/**************************************************************************** + * IDT Vectors + ****************************************************************************/ +/* The following will be the vector addresses programmed into the IDT */ + + ISR_NOERRCODE ISR0 + .balign 16 + ISR_NOERRCODE ISR1 + .balign 16 + ISR_NOERRCODE ISR2 + .balign 16 + ISR_NOERRCODE ISR3 + .balign 16 + ISR_NOERRCODE ISR4 + .balign 16 + ISR_NOERRCODE ISR5 + .balign 16 + ISR_NOERRCODE ISR6 + .balign 16 + ISR_NOERRCODE ISR7 + .balign 16 + ISR_ERRCODE ISR8 + .balign 16 + ISR_NOERRCODE ISR9 + .balign 16 + ISR_ERRCODE ISR10 + .balign 16 + ISR_ERRCODE ISR11 + .balign 16 + ISR_ERRCODE ISR12 + .balign 16 + ISR_ERRCODE ISR13 + .balign 16 + ISR_ERRCODE ISR14 + .balign 16 + ISR_NOERRCODE ISR15 + .balign 16 + ISR_NOERRCODE ISR16 + .balign 16 + ISR_NOERRCODE ISR17 + .balign 16 + ISR_NOERRCODE ISR18 + .balign 16 + ISR_NOERRCODE ISR19 + .balign 16 + ISR_NOERRCODE ISR20 + .balign 16 + ISR_NOERRCODE ISR21 + .balign 16 + ISR_NOERRCODE ISR22 + .balign 16 + ISR_NOERRCODE ISR23 + .balign 16 + ISR_NOERRCODE ISR24 + .balign 16 + ISR_NOERRCODE ISR25 + .balign 16 + ISR_NOERRCODE ISR26 + .balign 16 + ISR_NOERRCODE ISR27 + .balign 16 + ISR_NOERRCODE ISR28 + .balign 16 + ISR_NOERRCODE ISR29 + .balign 16 + ISR_NOERRCODE ISR30 + .balign 16 + ISR_NOERRCODE ISR31 + .balign 16 + IRQ 0, IRQ0 + .balign 16 + IRQ 1, IRQ1 + .balign 16 + IRQ 2, IRQ2 + .balign 16 + IRQ 3, IRQ3 + .balign 16 + IRQ 4, IRQ4 + .balign 16 + IRQ 5, IRQ5 + .balign 16 + IRQ 6, IRQ6 + .balign 16 + IRQ 7, IRQ7 + .balign 16 + IRQ 8, IRQ8 + .balign 16 + IRQ 9, IRQ9 + .balign 16 + IRQ 10, IRQ10 + .balign 16 + IRQ 11, IRQ11 + .balign 16 + IRQ 12, IRQ12 + .balign 16 + IRQ 13, IRQ13 + .balign 16 + IRQ 14, IRQ14 + .balign 16 + IRQ 15, IRQ15 + .balign 16 + +/**************************************************************************** + * Name: isr_common + * + * Description: + * This is the common ISR logic. It saves the processor state, sets up for + * kernel mode segments, calls the C-level fault handler, and finally + * restores the stack frame. + * + ****************************************************************************/ + +isr_common: +/* trace 'S' */ + /* Already swap to the interrupt stack */ + /* stack is automatically recovered by iretq using task state */ + + /* x86_64 don't have pusha, we have to do things manually */ + /* RDI and RSI are pushed above for handling IRQ no */ + pushq %rdx + pushq %rcx + pushq %r8 + pushq %r9 + + pushq %r15 + pushq %r14 + pushq %r13 + pushq %r12 + pushq %r11 + pushq %r10 + pushq %rbp + pushq %rbx + pushq %rax + + mov %ds, %ax /* Lower 16-bits of rax. */ + pushq %rax /* Save the data segment descriptor */ + mov %es, %ax /* Lower 16-bits of rax. */ + pushq %rax /* Save the data segment descriptor */ + mov %gs, %ax /* Lower 16-bits of rax. */ + pushq %rax /* Save the data segment descriptor */ + mov %fs, %ax /* Lower 16-bits of rax. */ + pushq %rax /* Save the data segment descriptor */ + + /* align to 16-bytes boundary */ + leaq -8(%rsp), %rsp + + /* save xmm registers */ + leaq -512(%rsp), %rsp + fxsaveq (%rsp) + + + /* The current value of the SP points to the beginning of the state save + * structure. Save that in RDI as the input parameter to isr_handler. + */ + + mov %rsp, %rdi + call isr_handler + jmp .Lreturn + .size isr_common, . - isr_common + +/**************************************************************************** + * Name: irq_common + * + * Description: + * This is the common IRQ logic. It saves the processor state, sets up for + * kernel mode segments, calls the C-level fault handler, and finally + * restores the stack frame. + * + ****************************************************************************/ + + .type irq_common, @function +irq_common: +/* trace 'R' */ + /* Already swap to the interrupt stack */ + /* stack is automatically recovered by iretq using task state */ + + /* x86_64 don't have pusha, we have to do things manually */ + /* RDI and RSI are pushed above for handling IRQ no */ + pushq %rdx + pushq %rcx + pushq %r8 + pushq %r9 + + pushq %r15 + pushq %r14 + pushq %r13 + pushq %r12 + pushq %r11 + pushq %r10 + pushq %rbp + pushq %rbx + pushq %rax + + mov %ds, %ax /* Lower 16-bits of rax. */ + pushq %rax /* Save the data segment descriptor */ + mov %es, %ax /* Lower 16-bits of rax. */ + pushq %rax /* Save the data segment descriptor */ + mov %gs, %ax /* Lower 16-bits of rax. */ + pushq %rax /* Save the data segment descriptor */ + mov %fs, %ax /* Lower 16-bits of rax. */ + pushq %rax /* Save the data segment descriptor */ + + /* align to 16-bytes boundary */ + leaq -8(%rsp), %rsp + + /* save xmm registers */ + leaq -512(%rsp), %rsp + fxsaveq (%rsp) + + /* The current value of the SP points to the beginning of the state save + * structure. Save that in RDI as the input parameter to irq_handler. + */ + + mov %rsp, %rdi + call irq_handler + + /* The common return point for both isr_handler and irq_handler */ + +.Lreturn: + /* EAX may possibly hold a pointer to a different regiser save area on + * return. Are we switching to a new context? + */ + + cmp %rax, %rsp + je .Lnoswitch + + /* A context swith will be performed. EAX holds the address of the new + * register save structure. + * + * Jump to up_fullcontextrestore(). We perform a call here, but that function + * never returns. The address of the new register save block is the argument + * to the up_fullcontextrestore(). + */ + + mov %rax, %rdi + call up_fullcontextrestore + +.Lnoswitch: + fxrstorq (%rsp) + leaq 512(%rsp), %rsp + leaq 8(%rsp), %rsp + + popq %rax + mov %fs, %ax + popq %rax + mov %gs, %ax + popq %rax + mov %es, %ax + popq %rax + mov %ds, %ax + + popq %rax + popq %rbx + popq %rbp + popq %r10 + popq %r11 + popq %r12 + popq %r13 + popq %r14 + popq %r15 + + popq %r9 + popq %r8 + popq %rcx + popq %rdx + + popq %rsi + popq %rdi + + add $8, %rsp /* Cleans up the pushed error code */ + + iretq /* Pops 5 things at once: CS, RIP, RFLAGS and SS and RSP */ + .size irq_common, . - irq_common + .end + + diff --git a/arch/x86_64/src/intel64/up_createstack.c b/arch/x86_64/src/intel64/up_createstack.c new file mode 100644 index 00000000000..d13c0ec715f --- /dev/null +++ b/arch/x86_64/src/intel64/up_createstack.c @@ -0,0 +1,181 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/up_createstack.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 "up_arch.h" +#include "up_internal.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_create_stack + * + * Description: + * Allocate a stack for a new thread and setup up stack-related information + * in the TCB. + * + * The following TCB fields must be initialized by this function: + * + * - adj_stack_size: Stack size after adjustment for hardware, processor, + * etc. This value is retained only for debug purposes. + * - stack_alloc_ptr: Pointer to allocated stack + * - adj_stack_ptr: Adjusted stack_alloc_ptr for HW. The initial value of + * the stack pointer. + * + * Input Parameters: + * - tcb: The TCB of new task + * - stack_size: The requested stack size. At least this much + * must be allocated. + * - ttype: The thread type. This may be one of following (defined in + * include/nuttx/sched.h): + * + * TCB_FLAG_TTYPE_TASK Normal user task + * TCB_FLAG_TTYPE_PTHREAD User pthread + * TCB_FLAG_TTYPE_KERNEL Kernel thread + * + * This thread type is normally available in the flags field of the TCB, + * however, there are certain contexts where the TCB may not be fully + * initialized when up_create_stack is called. + * + * If CONFIG_BUILD_KERNEL is defined, then this thread type may affect + * how the stack is allocated. For example, kernel thread stacks should + * be allocated from protected kernel memory. Stacks for user tasks and + * threads must come from memory that is accessible to user code. + * + ****************************************************************************/ + +int up_create_stack(FAR struct tcb_s *tcb, size_t stack_size, uint8_t ttype) +{ + /* Is there already a stack allocated of a different size? Because of + * alignment issues, stack_size might erroneously appear to be of a + * different size. Fortunately, this is not a critical operation. + */ + + if (tcb->stack_alloc_ptr && tcb->adj_stack_size != stack_size) + { + /* Yes.. Release the old stack */ + + up_release_stack(tcb, ttype); + } + + /* Do we need to allocate a new stack? */ + + if (!tcb->stack_alloc_ptr) + { + /* Allocate the stack. If DEBUG is enabled (but not stack debug), + * then create a zeroed stack to make stack dumps easier to trace. + */ + +#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { + tcb->stack_alloc_ptr = (uint32_t *)kmm_malloc(stack_size); + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + + tcb->stack_alloc_ptr = (uint32_t *)kumm_malloc(stack_size); + } + +#ifdef CONFIG_DEBUG_FEATURES + /* Was the allocation successful? */ + + if (!tcb->stack_alloc_ptr) + { + serr("ERROR: Failed to allocate stack, size %d\n", stack_size); + } +#endif + } + + /* Did we successfully allocate a stack? */ + + if (tcb->stack_alloc_ptr) + { + size_t top_of_stack; + size_t size_of_stack; + + /* Yes.. If stack debug is enabled, then fill the stack with a + * recognizable value that we can use later to test for high + * water marks. + */ + +#ifdef CONFIG_STACK_COLORATION + memset(tcb->stack_alloc_ptr, 0xaa, stack_size); +#endif + + /* The x86_64 uses a push-down stack: the stack grows toward lower + * addresses in memory. The stack pointer register, points to the + * lowest, valid work address (the "top" of the stack). Items on + * the stack are referenced as positive quad-words offsets from sp. + */ + + top_of_stack = (uint64_t)tcb->stack_alloc_ptr + stack_size - 8; + + /* The intel64 stack must be aligned at word (16 byte) boundaries. If + * necessary top_of_stack must be rounded down to the next boundary. + * We intentionally align at 8 byte boundary, because at task_start, + * only frame pointer will be pushed, not instruction pointer. + */ + + top_of_stack &= ~0xff; + top_of_stack -= 0x8; + size_of_stack = top_of_stack - (uint64_t)tcb->stack_alloc_ptr + 8; + + /* Save the adjusted stack values in the struct tcb_s */ + + tcb->adj_stack_ptr = (uint64_t *)top_of_stack; + tcb->adj_stack_size = size_of_stack; + + board_autoled_on(LED_STACKCREATED); + return OK; + } + + return ERROR; +} diff --git a/arch/x86_64/src/intel64/up_initialstate.c b/arch/x86_64/src/intel64/up_initialstate.c new file mode 100644 index 00000000000..3f4d0c86524 --- /dev/null +++ b/arch/x86_64/src/intel64/up_initialstate.c @@ -0,0 +1,135 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/up_initialstate.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 "up_internal.h" +#include "up_arch.h" +#include "sched/sched.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_initial_state + * + * Description: + * A new thread is being started and a new TCB has been created. This + * function is called to initialize the processor specific portions of the + * new TCB. + * + * This function must setup the intial architecture registers and/or stack + * so that execution will begin at tcb->start on the next context switch. + * + ****************************************************************************/ + +extern uintptr_t tux_mm_new_pd1(void); + +void up_initial_state(struct tcb_s *tcb) +{ + struct xcptcontext *xcp = &tcb->xcp; + struct tcb_s *rtcb; + + /* Initialize the initial exception register context structure */ + + memset(xcp, 0, sizeof(struct xcptcontext)); + + /* set the FCW to 1f80 */ + + xcp->regs[1] = (uint64_t)0x0000037f00000000; + + /* set the MXCSR to 1f80 */ + + xcp->regs[3] = (uint64_t)0x0000000000001f80; + + /* set page table to share space with current process */ + + rtcb = this_task(); + + /* Save the initial stack pointer... the value of the stackpointer before + * the "interrupt occurs." + */ + + xcp->regs[REG_RSP] = (uint64_t)tcb->adj_stack_ptr; + xcp->regs[REG_RBP] = (uint64_t)tcb->adj_stack_ptr; + + /* Save the task entry point */ + + xcp->regs[REG_RIP] = (uint64_t)tcb->start; + + /* Set up the segment registers... assume the same segment as the caller. + * That is not a good assumption in the long run. + */ + + xcp->regs[REG_DS] = up_getds(); + xcp->regs[REG_CS] = up_getcs(); + xcp->regs[REG_SS] = up_getss(); + xcp->regs[REG_ES] = up_getes(); + + /* Aux GS and FS are set to be 0 */ + + /* used by some libc for TLS and segment reference */ + + xcp->regs[REG_GS] = 0; + xcp->regs[REG_FS] = 0; + + /* Set supervisor- or user-mode, depending on how NuttX is configured and + * what kind of thread is being started. Disable FIQs in any event + * + * If the kernel build is not selected, then all threads run in + * supervisor-mode. + */ + +#ifdef CONFIG_BUILD_KERNEL +# error "Missing logic for the CONFIG_BUILD_KERNEL build" +#endif + + /* Enable or disable interrupts, based on user configuration. If the IF + * bit is set, maskable interrupts will be enabled. + */ + +#ifndef CONFIG_SUPPRESS_INTERRUPTS + xcp->regs[REG_RFLAGS] = X86_64_RFLAGS_IF; +#endif +} + diff --git a/arch/x86_64/src/intel64/up_irq.c b/arch/x86_64/src/intel64/up_irq.c new file mode 100644 index 00000000000..c45987eb71b --- /dev/null +++ b/arch/x86_64/src/intel64/up_irq.c @@ -0,0 +1,549 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/up_irq.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 + +#include "up_arch.h" +#include "up_internal.h" +#include "intel64.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define UART_BASE 0x3f8 + +#define IRQ_STACK_SIZE 0x2000 + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void up_apic_init(void); +static void up_ioapic_init(void); +static void up_idtentry(unsigned int index, uint64_t base, uint16_t sel, + uint8_t flags, uint8_t ist); +static inline void up_idtinit(void); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +volatile uint64_t *g_current_regs; + +uint8_t g_interrupt_stack[IRQ_STACK_SIZE] __attribute__ ((aligned (16))); +uint8_t *g_interrupt_stack_end = g_interrupt_stack + IRQ_STACK_SIZE - 16; + +uint8_t g_isr_stack[IRQ_STACK_SIZE] __attribute__ ((aligned (16))); +uint8_t *g_isr_stack_end = g_isr_stack + IRQ_STACK_SIZE - 16; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct idt_entry_s idt_entries[256]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_ioapic_read + * + * Description: + * Read a IOAPIC register + * + ****************************************************************************/ + +uint32_t up_ioapic_read(uint32_t reg) +{ + mmio_write32((void *)IOAPIC_BASE + IOAPIC_REG_INDEX, reg); + return mmio_read32((void *)IOAPIC_BASE + IOAPIC_REG_DATA); +} + +/**************************************************************************** + * Name: up_ioapic_write + * + * Description: + * Write a IOAPIC register + * + ****************************************************************************/ + +void up_ioapic_write(uint32_t reg, uint32_t data) +{ + mmio_write32((void *)IOAPIC_BASE + IOAPIC_REG_INDEX, reg); + mmio_write32((void *)IOAPIC_BASE + IOAPIC_REG_DATA, data); +} + +/**************************************************************************** + * Name: up_ioapic_pin_set_vector + * + * Description: + * Bind a hardware IRQ number to APIC IRQ number + * + ****************************************************************************/ + +void up_ioapic_pin_set_vector(unsigned int pin, + enum ioapic_trigger_mode trigger_mode, + unsigned int vector) +{ + up_ioapic_write(IOAPIC_REG_TABLE + pin * 2 + 1, + up_apic_cpu_id() << (56 - 32)); + up_ioapic_write(IOAPIC_REG_TABLE + pin * 2, + trigger_mode | vector); +} + +/**************************************************************************** + * Name: up_ioapic_mask_pin + * + * Description: + * Mask an IO-APIC interrupt + * + ****************************************************************************/ + +void up_ioapic_mask_pin(unsigned int pin) +{ + uint32_t cur; + + cur = up_ioapic_read(IOAPIC_REG_TABLE + pin * 2); + up_ioapic_write(IOAPIC_REG_TABLE + pin * 2, + cur | IOAPIC_PIN_DISABLE); +} + +/**************************************************************************** + * Name: up_ioapic_unmask_pin + * + * Description: + * Unmask an IO-APIC interrupt + * + ****************************************************************************/ + +void up_ioapic_unmask_pin(unsigned int pin) +{ + uint32_t cur; + + cur = up_ioapic_read(IOAPIC_REG_TABLE + pin * 2); + up_ioapic_write(IOAPIC_REG_TABLE + pin * 2, + 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)ist64 & 0x00ffffff); /* Low address 1 */ + tss_l.base_high = (((uintptr_t)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)ist64 >> 32) & 0xffffffff); /* High address */ + + gdt64[X86_GDT_ISTL_SEL_NUM] = tss_l; + gdt64[X86_GDT_ISTH_SEL_NUM] = *((struct gdt_entry_s *)&tss_h); + + ist64->IST1 = (uintptr_t)g_interrupt_stack_end; + ist64->IST2 = (uintptr_t)g_isr_stack_end; + + asm volatile ("mov $0x30, %%ax; ltr %%ax":::"memory", "rax"); +} + +/**************************************************************************** + * Name: up_deinit_8259 + * + * Description: + * Initialize the Legacy 8259 PIC + * + ****************************************************************************/ + +static void up_deinit_8259(void) +{ + /* First do an initialization to for any pending interrupt to vanish */ + + /* Starts the initialization sequence (in cascade mode) */ + + outb(X86_PIC_INIT, X86_IO_PORT_PIC1_CMD); + outb(X86_PIC_INIT, X86_IO_PORT_PIC2_CMD); + + /* Remap the IRQ to 32~ in case of a spurious interrupt */ + + outb(IRQ0, X86_IO_PORT_PIC1_DATA); /* ICW2: Master PIC vector offset */ + outb(IRQ0 + 8, X86_IO_PORT_PIC2_DATA); /* ICW2: Slave PIC vector offset */ + + /* Tell the PICs they are in cascade */ + + /* ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100) */ + + outb(X86_PIC1_CASCADE, X86_IO_PORT_PIC1_DATA); + + /* ICW3: tell Slave PIC its cascade identity (0000 0010) */ + + outb(X86_PIC2_CASCADE, X86_IO_PORT_PIC2_DATA); + + /* Put the PICs into 8086 mode */ + + outb(X86_PIC_8086, X86_IO_PORT_PIC1_DATA); + outb(X86_PIC_8086, X86_IO_PORT_PIC2_DATA); + + /* Disable the 8259 PIC by masking all the interrupt and acking them */ + + outb(0xff, X86_IO_PORT_PIC1_DATA); + outb(0xff, X86_IO_PORT_PIC2_DATA); + outb(X86_PIC_EOI, X86_IO_PORT_PIC1_CMD); + outb(X86_PIC_EOI, X86_IO_PORT_PIC2_CMD); +} + +/**************************************************************************** + * Name: up_init_apic + * + * Description: + * Initialize the APIC + * + ****************************************************************************/ + +static void up_apic_init(void) +{ + uint32_t ver; + uint32_t icrl; + uint32_t apic_base; + + /* Enable the APIC in X2APIC MODE */ + + apic_base = read_msr(MSR_IA32_APIC_BASE) & 0xfffff000; + write_msr(MSR_IA32_APIC_BASE, apic_base | MSR_IA32_APIC_EN | + MSR_IA32_APIC_X2APIC | MSR_IA32_APIC_BSP); + + /* Enable the APIC and setup an spurious interrupt vector */ + + write_msr(MSR_X2APIC_SPIV, MSR_X2APIC_SPIV_EN | IRQ_SPURIOUS); + + /* Disable the LINT interrupt lines */ + + write_msr(MSR_X2APIC_LINT0, MSR_X2APIC_MASKED); + write_msr(MSR_X2APIC_LINT1, MSR_X2APIC_MASKED); + + /* Disable performance counter overflow interrupts on machines tha + * provide that interrupt entry. + */ + + ver = read_msr(MSR_X2APIC_VER); + if (((ver >> 16) & 0xff) >= 4) + { + write_msr(MSR_X2APIC_LVTPMR, MSR_X2APIC_MASKED); + } + + /* Map error interrupt to IRQ_ERROR. */ + + write_msr(MSR_X2APIC_LERR, MSR_X2APIC_MASKED); + + /* Clear error status register (requires back-to-back writes). */ + + write_msr(MSR_X2APIC_ESR, 0); + write_msr(MSR_X2APIC_ESR, 0); + + /* Ack any outstanding interrupts. */ + + write_msr(MSR_X2APIC_EOI, 0); + + /* Send an Init Level De-Assert to synchronize arbitration ID's. */ + + write_msr(MSR_X2APIC_ICR, MSR_X2APIC_ICR_BCAST | MSR_X2APIC_ICR_INIT | + MSR_X2APIC_ICR_LEVEL); + do + { + icrl = read_msr(MSR_X2APIC_ICR); + } + while (icrl & MSR_X2APIC_ICR_DELIVS); + + /* Enable interrupts on the APIC (but not on the processor). */ + + write_msr(MSR_X2APIC_TPR, 0); +} + +/**************************************************************************** + * Name: legacy_pic_irq_handler + * + * Description: + * This function will capture will legacy 8259 PIC IRQ using virtual wire mode + * + ****************************************************************************/ + +static int __attribute__((unused)) + legacy_pic_irq_handler(int irq, uint32_t *regs, void *arg) +{ + return 0; +} + +/**************************************************************************** + * Name: up_init_ioapic + * + * Description: + * Initialize the IOAPIC + * + ****************************************************************************/ + +static void up_ioapic_init(void) +{ + int i; + + up_map_region((void *)IOAPIC_BASE, HUGE_PAGE_SIZE, + X86_PAGE_PRESENT | X86_PAGE_WR | X86_PAGE_NOCACHE); + + /* Setup the IO-APIC, remap the interrupt to 32~ */ + + uint32_t maxintr = (up_ioapic_read(IOAPIC_REG_VER) >> 16) & 0xff; + + for (i = 0; i < maxintr; i++) + { + up_ioapic_pin_set_vector(i, TRIGGER_RISING_EDGE, IRQ0 + i); + up_ioapic_mask_pin(i); + } + + return; +} + +/**************************************************************************** + * Name: up_idtentry + * + * Description: + * Initialize one IDT entry. + * + ****************************************************************************/ + +static void up_idtentry(unsigned int index, uint64_t base, uint16_t sel, + uint8_t flags, uint8_t ist) +{ + struct idt_entry_s *entry = &idt_entries[index]; + + entry->lobase = base & 0xffff; + entry->hibase = (base >> 16) & 0xffff; + entry->xhibase = (base >> 32) & 0xffffffff; + entry->ist = ist & 0x7; + entry->sel = sel; + entry->zero = 0; + + /* We must uncomment the OR below when we get to using user-mode. It sets the + * interrupt gate's privilege level to 3. + */ + + entry->flags = flags; /* | 0x60 */ +} + +/**************************************************************************** + * Name: up_idtinit + * + * Description: + * Initialize the IDT. The Interrupt Descriptor Table (IDT) is a data + * structure used by the x86 architecture to implement an interrupt vector + * table. The IDT is used by the processor to determine the correct + * response to interrupts and exceptions. + * + ****************************************************************************/ + +struct idt_ptr_s idt_ptr; + +static inline void up_idtinit(void) +{ + memset(&idt_entries, 0, sizeof(struct idt_entry_s)*256); + + /* Set each ISR/IRQ to the appropriate vector with selector=8 and with + * 32-bit interrupt gate. Interrupt gate (vs. trap gate) will leave + * interrupts enabled when the IRS/IRQ handler is entered. + */ + + up_idtentry(ISR0, (uint64_t)vector_isr0 , 0x08, 0x8e, 0x2); + up_idtentry(ISR1, (uint64_t)vector_isr1 , 0x08, 0x8e, 0x2); + up_idtentry(ISR2, (uint64_t)vector_isr2 , 0x08, 0x8e, 0x2); + up_idtentry(ISR3, (uint64_t)vector_isr3 , 0x08, 0x8e, 0x2); + up_idtentry(ISR4, (uint64_t)vector_isr4 , 0x08, 0x8e, 0x2); + up_idtentry(ISR5, (uint64_t)vector_isr5 , 0x08, 0x8e, 0x2); + up_idtentry(ISR6, (uint64_t)vector_isr6 , 0x08, 0x8e, 0x2); + up_idtentry(ISR7, (uint64_t)vector_isr7 , 0x08, 0x8e, 0x2); + up_idtentry(ISR8, (uint64_t)vector_isr8 , 0x08, 0x8e, 0x2); + up_idtentry(ISR9, (uint64_t)vector_isr9 , 0x08, 0x8e, 0x2); + up_idtentry(ISR10, (uint64_t)vector_isr10, 0x08, 0x8e, 0x2); + up_idtentry(ISR11, (uint64_t)vector_isr11, 0x08, 0x8e, 0x2); + up_idtentry(ISR12, (uint64_t)vector_isr12, 0x08, 0x8e, 0x2); + up_idtentry(ISR13, (uint64_t)vector_isr13, 0x08, 0x8e, 0x2); + up_idtentry(ISR14, (uint64_t)vector_isr14, 0x08, 0x8e, 0x2); + up_idtentry(ISR15, (uint64_t)vector_isr15, 0x08, 0x8e, 0x2); + up_idtentry(ISR16, (uint64_t)vector_isr16, 0x08, 0x8e, 0x2); + up_idtentry(ISR17, (uint64_t)vector_isr17, 0x08, 0x8e, 0x2); + up_idtentry(ISR18, (uint64_t)vector_isr18, 0x08, 0x8e, 0x2); + up_idtentry(ISR19, (uint64_t)vector_isr19, 0x08, 0x8e, 0x2); + up_idtentry(ISR20, (uint64_t)vector_isr20, 0x08, 0x8e, 0x2); + up_idtentry(ISR21, (uint64_t)vector_isr21, 0x08, 0x8e, 0x2); + up_idtentry(ISR22, (uint64_t)vector_isr22, 0x08, 0x8e, 0x2); + up_idtentry(ISR23, (uint64_t)vector_isr23, 0x08, 0x8e, 0x2); + up_idtentry(ISR24, (uint64_t)vector_isr24, 0x08, 0x8e, 0x2); + up_idtentry(ISR25, (uint64_t)vector_isr25, 0x08, 0x8e, 0x2); + up_idtentry(ISR26, (uint64_t)vector_isr26, 0x08, 0x8e, 0x2); + up_idtentry(ISR27, (uint64_t)vector_isr27, 0x08, 0x8e, 0x2); + up_idtentry(ISR28, (uint64_t)vector_isr28, 0x08, 0x8e, 0x2); + up_idtentry(ISR29, (uint64_t)vector_isr29, 0x08, 0x8e, 0x2); + up_idtentry(ISR30, (uint64_t)vector_isr30, 0x08, 0x8e, 0x2); + up_idtentry(ISR31, (uint64_t)vector_isr31, 0x08, 0x8e, 0x2); + + up_idtentry(IRQ0, (uint64_t)vector_irq0, 0x08, 0x8e, 0x1); + up_idtentry(IRQ1, (uint64_t)vector_irq1, 0x08, 0x8e, 0x1); + up_idtentry(IRQ2, (uint64_t)vector_irq2, 0x08, 0x8e, 0x1); + up_idtentry(IRQ3, (uint64_t)vector_irq3, 0x08, 0x8e, 0x1); + up_idtentry(IRQ4, (uint64_t)vector_irq4, 0x08, 0x8e, 0x1); + up_idtentry(IRQ5, (uint64_t)vector_irq5, 0x08, 0x8e, 0x1); + up_idtentry(IRQ6, (uint64_t)vector_irq6, 0x08, 0x8e, 0x1); + up_idtentry(IRQ7, (uint64_t)vector_irq7, 0x08, 0x8e, 0x1); + up_idtentry(IRQ8, (uint64_t)vector_irq8, 0x08, 0x8e, 0x1); + up_idtentry(IRQ9, (uint64_t)vector_irq9, 0x08, 0x8e, 0x1); + up_idtentry(IRQ10, (uint64_t)vector_irq10, 0x08, 0x8e, 0x1); + up_idtentry(IRQ11, (uint64_t)vector_irq11, 0x08, 0x8e, 0x1); + up_idtentry(IRQ12, (uint64_t)vector_irq12, 0x08, 0x8e, 0x1); + up_idtentry(IRQ13, (uint64_t)vector_irq13, 0x08, 0x8e, 0x1); + up_idtentry(IRQ14, (uint64_t)vector_irq14, 0x08, 0x8e, 0x1); + up_idtentry(IRQ15, (uint64_t)vector_irq15, 0x08, 0x8e, 0x1); + + /* Then program the IDT */ + + setidt(&idt_entries, sizeof(struct idt_entry_s) * NR_IRQS - 1); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_irqinitialize + ****************************************************************************/ + +void up_irqinitialize(void) +{ + /* currents_regs is non-NULL only while processing an interrupt */ + + g_current_regs = NULL; + + /* Initialize the IST */ + + up_ist_init(); + + /* Disable 8259 PIC */ + + up_deinit_8259(); + + /* Initialize the APIC */ + + up_apic_init(); + + /* Initialize the IOAPIC */ + + up_ioapic_init(); + + /* Initialize the IDT */ + + up_idtinit(); + + /* And finally, enable interrupts */ + +#ifndef CONFIG_SUPPRESS_INTERRUPTS + up_irq_restore(X86_64_RFLAGS_IF); +#endif +} + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * Disable the IRQ line specified by 'irq' + * + ****************************************************************************/ + +void up_disable_irq(int irq) +{ + if (irq >= IRQ0) + { + up_ioapic_mask_pin(irq - IRQ0); + } +} + +/**************************************************************************** + * Name: up_enable_irq + * + * Description: + * Enable the IRQ line specified by 'irq' + * + ****************************************************************************/ + +void up_enable_irq(int irq) +{ + if (irq >= IRQ0) + { + up_ioapic_unmask_pin(irq - IRQ0); + } +} + +/**************************************************************************** + * Name: up_prioritize_irq + * + * Description: + * Set the priority of an IRQ. + * + * Since this API is not supported on all architectures, it should be + * avoided in common implementations where possible. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_IRQPRIO +int up_prioritize_irq(int irq, int priority) +{ +#warning "Missing Logic" + return OK; +} +#endif diff --git a/arch/x86_64/src/intel64/up_map_region.c b/arch/x86_64/src/intel64/up_map_region.c new file mode 100644 index 00000000000..a3efa9b2910 --- /dev/null +++ b/arch/x86_64/src/intel64/up_map_region.c @@ -0,0 +1,77 @@ +/**************************************************************************** + * arch/x86/src/intel64/up_map_region.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 "up_arch.h" +#include "up_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_map_region + * + * Description: + * Map a memory region as 1:1 by MMU + * + ****************************************************************************/ + +int up_map_region(void *base, int size, int flags) +{ + uint64_t bb; + uint64_t num_of_pages; + uint64_t entry; + uint64_t curr; + int i; + + /* Round to page boundary */ + + bb = (uint64_t)base & ~(PAGE_SIZE - 1); + + /* Increase size if the base address is rounded off */ + + size += (uint64_t)base - bb; + uint64_t num_of_pages = (size + PAGE_SIZE - 1) / PAGE_SIZE; + + if (bb > 0xffffffff) + { + return -1; /* Only < 4GB can be mapped */ + } + + curr = bb; + for (i = 0; i < num_of_pages; i++) + { + entry = (curr >> 12) & 0x7ffffff; + + pt[entry] = curr | flags; + curr += PAGE_SIZE; + } + + return 0; +} diff --git a/arch/x86_64/src/intel64/up_regdump.c b/arch/x86_64/src/intel64/up_regdump.c new file mode 100644 index 00000000000..942b4326ea8 --- /dev/null +++ b/arch/x86_64/src/intel64/up_regdump.c @@ -0,0 +1,152 @@ +/**************************************************************************** + * arch/x86/src/intel64/up_regdump.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 "up_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_registerdump + ****************************************************************************/ + +void print_mem(void *sp, size_t size +{ + char buf[9]; + int i; + int j; + + _alert("Memory Dump (%d bytes):\n", size); + + for (i = 0; i < size / 8; i++) + { + for (j = 0; j < 8; j++) + { + buf[j] = *((uint8_t *)(sp + i * 8 + j)); + if ((buf[j] > 126) || (buf[j] < 32)) + { + buf[j] = '.'; + } + } + + buf[8] = '\0'; + _alert(" %016llx\t%02x %02x %02x %02x %02x %02x %02x %02x\t%s\n", + (sp + i * 8), + *((uint8_t *)(sp + i * 8 + 0)), + *((uint8_t *)(sp + i * 8 + 1)), + *((uint8_t *)(sp + i * 8 + 2)), + *((uint8_t *)(sp + i * 8 + 3)), + *((uint8_t *)(sp + i * 8 + 4)), + *((uint8_t *)(sp + i * 8 + 5)), + *((uint8_t *)(sp + i * 8 + 6)), + *((uint8_t *)(sp + i * 8 + 7)), + buf); + } +} + +void backtrace(uint64_t rbp) +{ + int i; + int j; + + _alert("Frame Dump (64 bytes):\n"); + + for (i = 0; i < 16; i++) + { + if ((rbp < 0x200000) || (rbp > 0xffffffff)) + { + break; + } + + _alert(" %016llx\t%016llx\n", + *((uint64_t *)(rbp)), *((uint64_t *)(rbp + 1 * 8))); + + if ((rbp) && *((uint64_t *)(rbp + 1 * 8))) + { + rbp = *(uint64_t *)rbp; + } + else + { + break; + } + } +} + +void up_registerdump(uint64_t *regs) +{ + int i; + int j; + uint64_t mxcsr; + uint64_t cr2; + uint64_t rbp; + char buf[9]; + + asm volatile ("stmxcsr %0"::"m"(mxcsr):"memory"); + asm volatile ("mov %%cr2, %%rax; mov %%rax, %0"::"m"(cr2):"memory", "rax"); + _alert("----------------CUT HERE-----------------\n"); + _alert("Gerneral Informations:\n"); + _alert("CPL: %d, RPL: %d\n", regs[REG_CS] & 0x3, regs[REG_DS] & 0x3); + _alert("RIP: %016llx, RSP: %016llx\n", regs[REG_RIP], regs[REG_RSP]); + _alert("RBP: %016llx, RFLAGS: %016llx\n", + regs[REG_RBP], regs[REG_RFLAGS]); + _alert("MSR_STAR: %016llx, MSR_LSTAR: %016llx\n", + read_msr(0xc0000081), read_msr(0xc0000082)); + _alert("MXCSR: %016llx, MSR_FS_BASE: %016llx\n", + mxcsr, read_msr(MSR_FS_BASE)); + _alert("CR2: %016llx\n", cr2); + _alert("Selector Dump:\n"); + _alert("CS: %016llx, DS: %016llx, SS: %016llx\n", + regs[REG_CS], regs[REG_DS], regs[REG_SS]); + _alert("ES: %016llx, FS: %016llx, GS: %016llx\n", + regs[REG_ES], regs[REG_FS], regs[REG_GS]); + _alert("Register Dump:\n"); + _alert("RAX: %016llx, RBX: %016llx\n", regs[REG_RAX], regs[REG_RBX]); + _alert("RCX: %016llx, RDX: %016llx\n", regs[REG_RCX], regs[REG_RDX]); + _alert("RDI: %016llx, RSI: %016llx\n", regs[REG_RDI], regs[REG_RSI]); + _alert(" R8: %016llx, R9: %016llx\n", regs[REG_R8] , regs[REG_R9]); + _alert("R10: %016llx, R11: %016llx\n", regs[REG_R10], regs[REG_R11]); + _alert("R12: %016llx, R13: %016llx\n", regs[REG_R12], regs[REG_R13]); + _alert("R14: %016llx, R15: %016llx\n", regs[REG_R14], regs[REG_R15]); + _alert("Dumping Stack (+-64 bytes):\n"); + + if (regs[REG_RSP] > 0 && regs[REG_RSP] < 0x1000000) + { + print_mem(regs[REG_RSP] - 512, 128 * 0x200000 - regs[REG_RSP] + 512); + } + else + { + print_mem(regs[REG_RSP] - 512, 1024); + } + +#ifdef CONFIG_DEBUG_NOOPT + backtrace(regs[REG_RBP]); +#endif + _alert("-----------------------------------------\n"); +} diff --git a/arch/x86_64/src/intel64/up_releasestack.c b/arch/x86_64/src/intel64/up_releasestack.c new file mode 100644 index 00000000000..49d0895663c --- /dev/null +++ b/arch/x86_64/src/intel64/up_releasestack.c @@ -0,0 +1,112 @@ +/**************************************************************************** + * arch/x86/src/common/up_releasestack.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 "up_internal.h" +#include "arch/io.h" +#include "arch/irq.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_release_stack + * + * Description: + * A task has been stopped. Free all stack related resources retained in + * the defunct TCB. + * + * Input Parameters: + * - dtcb: The TCB containing information about the stack to be released + * - ttype: The thread type. This may be one of following (defined in + * include/nuttx/sched.h): + * + * TCB_FLAG_TTYPE_TASK Normal user task + * TCB_FLAG_TTYPE_PTHREAD User pthread + * TCB_FLAG_TTYPE_KERNEL Kernel thread + * + * This thread type is normally available in the flags field of the TCB, + * however, there are certain error recovery contexts where the TCB may + * not be fully initialized when up_release_stack is called. + * + * If CONFIG_BUILD_KERNEL is defined, then this thread type may affect + * how the stack is freed. For example, kernel thread stacks may have + * been allocated from protected kernel memory. Stacks for user tasks + * and threads must have come from memory that is accessible to user + * code. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) +{ + struct vma_s *ptr; + int i; + + /* Is there a stack allocated? */ + + if (dtcb->stack_alloc_ptr) + { +#if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) + /* Use the kernel allocator if this is a kernel thread */ + + if (ttype == TCB_FLAG_TTYPE_KERNEL) + { + sched_kfree(dtcb->stack_alloc_ptr); + } + else +#endif + { + /* Use the user-space allocator if this is a task or pthread */ + + sched_ufree(dtcb->stack_alloc_ptr); + } + + /* Mark the stack freed */ + + dtcb->stack_alloc_ptr = NULL; + } + + /* The size of the allocated stack is now zero */ + + dtcb->adj_stack_size = 0; +} diff --git a/arch/x86_64/src/intel64/up_restore_auxstate.c b/arch/x86_64/src/intel64/up_restore_auxstate.c new file mode 100644 index 00000000000..ddd536b03db --- /dev/null +++ b/arch/x86_64/src/intel64/up_restore_auxstate.c @@ -0,0 +1,56 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/up_restore_auxstate.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 "up_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_restore_auxstate + * + * Description: + * This function performs some additional action required to complete the + * CTX on intel64 processor. + * + ****************************************************************************/ + +void up_restore_auxstate(struct tcb_s *rtcb) +{ + /* Set PCID, avoid TLB flush */ + + set_pcid(rtcb->pid); +} diff --git a/arch/x86_64/src/intel64/up_rtc.c b/arch/x86_64/src/intel64/up_rtc.c new file mode 100644 index 00000000000..305b1a5cf71 --- /dev/null +++ b/arch/x86_64/src/intel64/up_rtc.c @@ -0,0 +1,174 @@ +/************************************************************************************ + * arch/arm/src/stm32/stm32_rtcounter.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 "up_arch.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Configuration ********************************************************************/ + +/* This is a hacky implementation based on TSC, we only support Hi-RES mode */ + +#ifdef CONFIG_RTC_HIRES +# ifndef CONFIG_RTC_FREQUENCY +# error "CONFIG_RTC_FREQUENCY is required for CONFIG_RTC_HIRES" +# endif +#endif + +#define NS_PER_USEC 1000UL +#define NS_PER_MSEC 1000000UL +#define NS_PER_SEC 1000000000UL + +/************************************************************************************ + * Private Types + ************************************************************************************/ + +/************************************************************************************ + * Private Data + ************************************************************************************/ + +/************************************************************************************ + * Public Data + ************************************************************************************/ + +#ifdef CONFIG_RTC_HIRES +volatile bool g_rtc_enabled = false; + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +static unsigned long rtc_freq; +static unsigned long rtc_overflow; +static unsigned long rtc_last; +static unsigned long rtc_overflows; + +/************************************************************************************ + * Private Functions + ************************************************************************************/ + +static unsigned long rtc_read(void) +{ + uint64_t tmr = rdtsc(); + + if (tmr < rtc_last) + { + tmr += (0xffffffffffffffffull - rtc_last); + } + + rtc_last = tmr; + tmr = (tmr / (rtc_freq / 1000000ul)) * 1000l; + return tmr; +} + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: up_rtc_initialize + * + * Description: + * Initialize the hardware RTC per the selected configuration. This function is + * called once during the OS initialization sequence + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +int up_rtc_initialize(void) +{ + rtc_freq = comm_region->tsc_khz * 1000L; + g_rtc_enabled = true; + + return OK; +} + +/************************************************************************************ + * Name: up_rtc_gettime + * + * Description: + * Get the current time from the high resolution RTC clock/counter. This interface + * is only supported by the high-resolution RTC/counter hardware implementation. + * It is used to replace the system timer. + * + * Input Parameters: + * tp - The location to return the high resolution time value. + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +int up_rtc_gettime(FAR struct timespec *tp) +{ + uint64_t tmp; + + tmp = rtc_read(); + tp->tv_sec = (tmp / NS_PER_SEC); + tp->tv_nsec = (tmp - (tp->tv_sec) * NS_PER_SEC); + + return OK; +} + +/************************************************************************************ + * Name: up_rtc_settime + * + * Description: + * Set the RTC to the provided time. All RTC implementations must be able to + * set their time based on a standard timespec. + * + * Input Parameters: + * tp - the time to use + * + * Returned Value: + * Zero (OK) on success; a negated errno on failure + * + ************************************************************************************/ + +int up_rtc_settime(FAR const struct timespec *tp) +{ + /* What so ever.. */ + + return OK; +} +#endif diff --git a/arch/x86_64/src/intel64/up_savestate.c b/arch/x86_64/src/intel64/up_savestate.c new file mode 100644 index 00000000000..b9b6baef41f --- /dev/null +++ b/arch/x86_64/src/intel64/up_savestate.c @@ -0,0 +1,50 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/up_savestate.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 "up_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_savestate + * + * Description: + * This function saves the interrupt level context information in the + * TCB. This would just be a up_copystate. + * + ****************************************************************************/ + +void up_savestate(uint64_t *regs) +{ + up_copystate(regs, (uint64_t *)g_current_regs); +} diff --git a/arch/x86_64/src/intel64/up_schedulesigaction.c b/arch/x86_64/src/intel64/up_schedulesigaction.c new file mode 100644 index 00000000000..5bb2848d070 --- /dev/null +++ b/arch/x86_64/src/intel64/up_schedulesigaction.c @@ -0,0 +1,185 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/up_schedulesigaction.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 "sched/sched.h" +#include "up_internal.h" +#include "up_arch.h" + +#ifndef CONFIG_DISABLE_SIGNALS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_schedule_sigaction + * + * Description: + * This function is called by the OS when one or more signal handling + * actions have been queued for execution. The architecture specific code + * must configure things so that the 'sigdeliver' callback is executed on + * the thread specified by 'tcb' as soon as possible. + * + * This function may be called from interrupt handling logic. + * + * This operation should not cause the task to be unblocked nor should it + * cause any immediate execution of sigdeliver. Typically, a few cases need + * to be considered: + * + * (1) This function may be called from an interrupt handler. During + * interrupt processing, all xcptcontext structures should be valid for + * all tasks. That structure should be modified to invoke sigdeliver() + * either on return from (this) interrupt or on some subsequent context + * switch to the recipient task. + * (2) If not in an interrupt handler and the tcb is NOT the currently + * executing task, then again just modify the saved xcptcontext + * structure for the recipient task so it will invoke sigdeliver when + * that task is later resumed. + * (3) If not in an interrupt handler and the tcb IS the currently + * executing task -- just call the signal handler now. + * + ****************************************************************************/ + +void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver) +{ + irqstate_t flags; + + sinfo("tcb=0x%p sigdeliver=0x%p\n", tcb, sigdeliver); + sinfo("rtcb=0x%p g_current_regs=0x%p\n", this_task(), g_current_regs); + + /* Make sure that interrupts are disabled */ + + flags = enter_critical_section(); + + /* Refuse to handle nested signal actions */ + + if (!tcb->xcp.sigdeliver) + { + /* First, handle some special cases when the signal is being delivered + * to the currently executing task. + */ + + if (tcb == this_task()) + { + /* CASE 1: We are not in an interrupt handler and a task is + * signalling itself for some reason. + */ + + if (!g_current_regs) + { + /* In this case just deliver the signal with a function call now. */ + + sigdeliver(tcb); + } + + /* CASE 2: We are in an interrupt handler AND the interrupted task + * is the same as the one that must receive the signal, then we will + * have to modify the return state as well as the state in the TCB. + * + * Hmmm... there looks like a latent bug here: The following logic + * would fail in the strange case where we are in an interrupt + * handler, the thread is signalling itself, but a context switch to + * another task has occurred so that g_current_regs does not refer to + * the thread of this_task()! + */ + + else + { + /* Save the return lr and cpsr and one scratch register. These + * will be restored by the signal trampoline after the signals + * have been delivered. + */ + + tcb->xcp.sigdeliver = sigdeliver; + tcb->xcp.saved_rip = g_current_regs[REG_RIP]; + tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP]; + tcb->xcp.saved_rflags = g_current_regs[REG_RFLAGS]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + g_current_regs[REG_RIP] = (uint64_t)up_sigdeliver; + g_current_regs[REG_RFLAGS] = 0; + + /* And make sure that the saved context in the TCB + * is the same as the interrupt return context. + */ + + up_savestate(tcb->xcp.regs); + } + } + + /* Otherwise, we are (1) signaling a task is not running + * from an interrupt handler or (2) we are not in an + * interrupt handler and the running task is signalling + * some non-running task. + */ + + else + { + /* Save the return lr and cpsr and one scratch register + * These will be restored by the signal trampoline after + * the signals have been delivered. + */ + + tcb->xcp.sigdeliver = sigdeliver; + tcb->xcp.saved_rip = tcb->xcp.regs[REG_RIP]; + tcb->xcp.saved_rsp = tcb->xcp.regs[REG_RSP]; + tcb->xcp.saved_rflags = tcb->xcp.regs[REG_RFLAGS]; + + /* Then set up to vector to the trampoline with interrupts + * disabled + */ + + tcb->xcp.regs[REG_RIP] = (uint64_t)up_sigdeliver; + tcb->xcp.regs[REG_RFLAGS] = 0; + } + } + + leave_critical_section(flags); +} + +#endif /* !CONFIG_DISABLE_SIGNALS */ diff --git a/arch/x86_64/src/intel64/up_sigdeliver.c b/arch/x86_64/src/intel64/up_sigdeliver.c new file mode 100644 index 00000000000..cce6f00cd2f --- /dev/null +++ b/arch/x86_64/src/intel64/up_sigdeliver.c @@ -0,0 +1,151 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/up_sigdeliver.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 "sched/sched.h" +#include "up_internal.h" +#include "up_arch.h" + +#ifndef CONFIG_DISABLE_SIGNALS + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_sigdeliver + * + * Description: + * This is the a signal handling trampoline. When a signal action was + * posted. The task context was mucked with and forced to branch to this + * location with interrupts disabled. + * + ****************************************************************************/ + +void up_sigdeliver(void) +{ + struct tcb_s *rtcb = this_task(); + sig_deliver_t sighandler; + uint64_t regs_area[XCPTCONTEXT_REGS + 2]; + uint64_t *regs; + + /* align regs to 16byte boundary for SSE instrucitons */ + + regs = (uint64_t *)(((uint64_t)(regs_area) + 15) & (~(uint64_t)15)); + + /* Save the errno. This must be preserved throughout the signal handling + * so that the user code final gets the correct errno value (probably + * EINTR). + */ + + int saved_errno = rtcb->pterrno; + + /* Save the real return state on the stack ASAP before any chance we went + * sleeping and break the register profile. We entered this function with + * interrupt disabled, therefore we don't have to worried being preempted + * by interrupt. + */ + + up_copystate(regs, rtcb->xcp.regs); + + /* grab on a copy of the signal hander function pointer before any + * possibility to be switched out. + */ + + ASSERT(rtcb->xcp.sigdeliver != NULL); + sighandler = rtcb->xcp.sigdeliver; + + board_autoled_on(LED_SIGNAL); + + sinfo("rtcb=%p sigdeliver=%p sigpendactionq.head=%p\n", + rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head); + +#ifndef CONFIG_SUPPRESS_INTERRUPTS + /* Then make sure that interrupts are enabled. Signal handlers must always + * run with interrupts enabled. + */ + + up_irq_enable(); +#endif + + /* Deliver the signals */ + + _err("Deliver signal to %llx: %llx\n", rtcb, rtcb->xcp.sigdeliver); + + sighandler(rtcb); + + /* Output any debug messages BEFORE restoring errno (because they may + * alter errno), then disable interrupts again and restore the original + * errno that is needed by the user logic (it is probably EINTR). + */ + + sinfo("Resuming\n"); + (void)up_irq_save(); + rtcb->pterrno = saved_errno; + + /* Modify the saved return state with the actual saved values in the + * TCB. This depends on the fact that nested signal handling is + * not supported. Therefore, these values will persist throughout the + * signal handling action. + * + * Keeping this data in the TCB resolves a security problem in protected + * and kernel mode: The regs[] array is visible on the user stack and + * could be modified by a hostile program. + */ + + regs[REG_RIP] = rtcb->xcp.saved_rip; + regs[REG_RSP] = rtcb->xcp.saved_rsp; + regs[REG_RFLAGS] = rtcb->xcp.saved_rflags; + rtcb->xcp.sigdeliver = NULL; /* Allows next handler to be scheduled */ + + /* Then restore the correct state for this thread of execution. */ + + board_autoled_off(LED_SIGNAL); + up_fullcontextrestore(regs); +} + +#endif /* !CONFIG_DISABLE_SIGNALS */ + diff --git a/arch/x86_64/src/intel64/up_stackframe.c b/arch/x86_64/src/intel64/up_stackframe.c new file mode 100644 index 00000000000..e8bcea49587 --- /dev/null +++ b/arch/x86_64/src/intel64/up_stackframe.c @@ -0,0 +1,127 @@ +/**************************************************************************** + * arch/x86_64/src/intel64/up_stackframe.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 "up_internal.h" + +/**************************************************************************** + * Pre-processor Macros + ****************************************************************************/ + +/* The initial stack point is aligned at 16 bytes boundaries. If + * necessary frame_size must be rounded up to the next boundary to retain + * this alignment. + */ + +#define STACK_ALIGNMENT 16 + +/* Stack alignment macros */ + +#define STACK_ALIGN_MASK (STACK_ALIGNMENT-1) +#define STACK_ALIGN_DOWN(a) ((a) & ~STACK_ALIGN_MASK) +#define STACK_ALIGN_UP(a) (((a) + STACK_ALIGN_MASK) & ~STACK_ALIGN_MASK) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_stack_frame + * + * Description: + * Allocate a stack frame in the TCB's stack to hold thread-specific data. + * This function may be called anytime after up_create_stack() or + * up_use_stack() have been called but before the task has been started. + * + * Thread data may be kept in the stack (instead of in the TCB) if it is + * accessed by the user code directly. This includes such things as + * argv[]. The stack memory is guaranteed to be in the same protection + * domain as the thread. + * + * The following TCB fields will be re-initialized: + * + * - adj_stack_size: Stack size after removal of the stack frame from + * the stack + * - adj_stack_ptr: Adjusted initial stack pointer after the frame has + * been removed from the stack. This will still be the initial value + * of the stack pointer when the task is started. + * + * Input Parameters: + * - tcb: The TCB of new task + * - frame_size: The size of the stack frame to allocate. + * + * Returned Value: + * - A pointer to bottom of the allocated stack frame. NULL will be + * returned on any failures. The alignment of the returned value is + * the same as the alignment of the stack itself. + * + ****************************************************************************/ + +FAR void *up_stack_frame(FAR struct tcb_s *tcb, size_t frame_size) +{ + uintptr_t topaddr; + + /* Align the frame_size */ + + frame_size = STACK_ALIGN_UP(frame_size); + + /* Is there already a stack allocated? Is it big enough? */ + + if (!tcb->stack_alloc_ptr || tcb->adj_stack_size <= frame_size) + { + return NULL; + } + + /* Save the adjusted stack values in the struct tcb_s */ + + topaddr = (uintptr_t)tcb->adj_stack_ptr - frame_size; + tcb->adj_stack_ptr = (FAR void *)topaddr; + tcb->adj_stack_size -= frame_size; + + /* Reset the initial stack pointer */ + + tcb->xcp.regs[REG_RSP] = (uint64_t)tcb->adj_stack_ptr; + + /* And return the pointer to the allocated region */ + + return (FAR void *)(topaddr + sizeof(uint64_t)); +} + diff --git a/arch/x86_64/src/intel64/up_usestack.c b/arch/x86_64/src/intel64/up_usestack.c new file mode 100644 index 00000000000..30e022c5c5f --- /dev/null +++ b/arch/x86_64/src/intel64/up_usestack.c @@ -0,0 +1,119 @@ +/**************************************************************************** + * arch/x86_64/src/common/up_usestack.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 "up_internal.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_use_stack + * + * Description: + * Setup up stack-related information in the TCB using pre-allocated stack + * memory. This function is called only from task_init() when a task or + * kernel thread is started (never for pthreads). + * + * The following TCB fields must be initialized: + * + * - adj_stack_size: Stack size after adjustment for hardware, + * processor, etc. This value is retained only for debug + * purposes. + * - stack_alloc_ptr: Pointer to allocated stack + * - adj_stack_ptr: Adjusted stack_alloc_ptr for HW. The + * initial value of the stack pointer. + * + * Input Parameters: + * - tcb: The TCB of new task + * - stack_size: The allocated stack size. + * + * NOTE: Unlike up_stack_create() and up_stack_release, this function + * does not require the task type (ttype) parameter. The TCB flags will + * always be set to provide the task type to up_use_stack() if it needs + * that information. + * + ****************************************************************************/ + +int up_use_stack(struct tcb_s *tcb, void *stack, size_t stack_size) +{ + size_t top_of_stack; + size_t size_of_stack; + + /* Is there already a stack allocated? */ + + if (tcb->stack_alloc_ptr) + { + /* Yes.. Release the old stack allocation */ + + up_release_stack(tcb, tcb->flags & TCB_FLAG_TTYPE_MASK); + } + + /* Save the new stack allocation */ + + tcb->stack_alloc_ptr = stack; + + /* The intel64 uses a push-down stack: the stack grows toward lower + * addresses in memory. The stack pointer register, points to the lowest, + * valid work address (the "top" of the stack). Items on the stack are + * referenced as positive word offsets from sp. + */ + + top_of_stack = (uint64_t)tcb->stack_alloc_ptr + stack_size - 8; + + /* The intel64 stack must be aligned at word (16 byte) boundaries. If + * necessary top_of_stack must be rounded down to the next boundary. + * We intentionally align at 8 byte boundary, because at task_start, only + * frame pointer will be pushed, not instruction pointer. + */ + + top_of_stack &= ~0xff; + top_of_stack -= 0x8; + size_of_stack = top_of_stack - (uint64_t)tcb->stack_alloc_ptr + 8; + + /* Save the adjusted stack values in the struct tcb_s */ + + tcb->adj_stack_ptr = (uint64_t *)top_of_stack; + tcb->adj_stack_size = size_of_stack; + + return OK; +} diff --git a/arch/x86_64/src/qemu/Kconfig b/arch/x86_64/src/qemu/Kconfig new file mode 100644 index 00000000000..f72f3c094ce --- /dev/null +++ b/arch/x86_64/src/qemu/Kconfig @@ -0,0 +1,4 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# diff --git a/boards/Kconfig b/boards/Kconfig index ccd14540241..5031eb43736 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -1200,6 +1200,13 @@ config ARCH_BOARD_QEMU_I486 Port of NuttX to QEMU in i486 mode. This port will also run on real i486 hardwared (Google the Bifferboard). +config ARCH_BOARD_INTEL64_QEMU + bool "Intel64 for Qemu simulator" + depends on ARCH_X86_64 || ARCH_INTEL64 + ---help--- + Port of NuttX to QEMU in intel64 mode. This port will also run on real + generic Intel64 hardware. + config ARCH_BOARD_RX65N bool "RX65N renesas board" depends on ARCH_CHIP_R5F565NEDDFC @@ -2164,6 +2171,7 @@ config ARCH_BOARD default "pic32mx7mmb" if ARCH_BOARD_PIC32MX7MMB default "pic32mz-starterkit" if ARCH_BOARD_PIC32MZ_STARTERKIT default "qemu-i486" if ARCH_BOARD_QEMU_I486 + default "intel64-qemu" if ARCH_BOARD_INTEL64_QEMU default "rx65n" if ARCH_BOARD_RX65N default "rx65n-rsk1mb" if ARCH_BOARD_RX65N_RSK1MB default "rx65n-rsk2mb" if ARCH_BOARD_RX65N_RSK2MB @@ -2829,6 +2837,9 @@ endif if ARCH_BOARD_QEMU_I486 source "boards/x86/qemu/qemu-i486/Kconfig" endif +if ARCH_BOARD_INTEL64_QEMU +source "boards/x86_64/intel64/qemu/Kconfig" +endif if ARCH_BOARD_RX65N source "boards/renesas/rx65n/rx65n/Kconfig" endif diff --git a/boards/x86_64/intel64/drivers/Kconfig b/boards/x86_64/intel64/drivers/Kconfig new file mode 100644 index 00000000000..f72f3c094ce --- /dev/null +++ b/boards/x86_64/intel64/drivers/Kconfig @@ -0,0 +1,4 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# diff --git a/boards/x86_64/intel64/qemu-intel64/Kconfig b/boards/x86_64/intel64/qemu-intel64/Kconfig new file mode 100644 index 00000000000..f72f3c094ce --- /dev/null +++ b/boards/x86_64/intel64/qemu-intel64/Kconfig @@ -0,0 +1,4 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# diff --git a/boards/x86_64/intel64/qemu-intel64/README.txt b/boards/x86_64/intel64/qemu-intel64/README.txt new file mode 100644 index 00000000000..46e44d1c4fe --- /dev/null +++ b/boards/x86_64/intel64/qemu-intel64/README.txt @@ -0,0 +1,186 @@ +README +====== + +This README file describes the contents of the build configurations available +for the NuttX QEMU x86_64 port. + +Contents +======== + + * Creating a bootable disk + * QEMU/KVM + - Running QEMU/KVM + * Bochs + - Building Bochs + - Running Bochs + * Real machine + * Toolchain + * FAQ + * Configurations + - ostest + +Creating a bootable disk +======================== + +This build supports multiboot2, which means that usual multiboot2 bootlaoders, e.g. grub can be used. +To create a bootable disk with grub2, create a directory named `iso` with grub configuration file and the compiled nuttx.elf. + +##### Directory and file hierarchy +``` + - iso/ + - boot/ + - grub/ + - grub.cfg + - nuttx.elf +``` + +##### grub.cfg + +The grub.cfg should contain the boot entry of Nuttx. +``` +set timeout=0 +set default=0 +menuentry "kernel" { + multiboot2 /boot/nuttx.elf + } +``` + +##### Making the disk + +Use the following command to create the disk. +P.S. In some distros, `grub-mkrescue` is called `grub2-mkrescue` +``` +grub-mkrescue -o boot.iso iso +``` + + +QEMU/KVM +==== + +QEMU is a generic and open source machine emulator and virtual machine. Here are +some links (which will probably be mostly outdated by the time your read this): + + Home Page: http://wiki.qemu.org/Main_Page + Downloads: http://wiki.qemu.org/Download + Documentation: http://wiki.qemu.org/Manual + +KVM is the Linux kernel hypervisor. +It supports creations of virtual machines in Linux systems. +It is usually coupled with Qemu as its I/O supporting layer. + +The qemu can be build from source or downloaded from distro repositories. +However, a modern CPU and KVM support are mandatory because the X2APIC is not available +in pure emulator mode. +This mean using this build with qemu in windows or old x86 machine can be frustrating. +In such case, looks the next section and use bochs emulator instead. + +Running QEMU +------------ + + In the top-level NuttX directory: + + qemu -cpu host -enable-kvm -m 2GB -cdrom boot.iso -nographic -serial mon:stdio + + This multiplex the qemu console and COM1 to your console. + Use control-a 1 and 2 to switch between. + Use control-a x to terminate the emulation. + + P.S. Make sure that you CPU supports the mandatory features. Look at Real machine + section for more information. + +Bochs +===== + +Bochs is also a generic and open source machine emulator and virtualizer. +It does very comprehensive emulation of x86 platform, even the state-of-art processors. +Here are some links (which will probably be mostly outdated by the time your read this): + + Home Page: http://bochs.sourceforge.net + +The bochs can be build from source. +Unlike qemu, it do not rely on KVM to support modern hardware features, therefor it can +also be used under windows. +When building bochs, remember to enable x86-64 support with "--enable-x86-64". +If you also want the support of SIMD instruction, enable them with "--enable-avx --enable-evex". + +Running Bochs +------------ + + First edit/check the .bochsrc + You can create one in the top-level Nuttx directory or bochs will use the one in your $HOME. + Remember to change the CPU model to one with mandatory features and enable the COM port. + + * Find and edit (You might adjust the IPS as you machine perform): + ``` + cpu: model=broadwell_ult, count=1, ips=50000000, reset_on_triple_fault=0, ignore_bad_msrs=0, msrs="msrs.def" a + ata0-master: type=cdrom, path="", status=inserted + + ``` + + * Add: + ``` + com1: enabled=1, mode=file, dev=com1.out + ``` + + In the top-level NuttX directory: + + ``` + bochs + ``` + + The emulator will drop into debugger mode. + Enter 'c' to start the emulation. + COM port output will be in the com1.out file. + + +Real machine +============ + +This port should work on real x86-64 machine with a proper CPU. +The mandatory CPU features are: + * TSC DEADLINE or APIC timer + * PCID + * X2APIC + +WARNING: IF you use TSC DEADLINE, make sure that your CPU's TSC DEADLINE timer is not buggy! + +Toolchains +========== + + Currently, only the Linux GCC toolchain is tested. + While building on a modern x86_64 PC, the default system GCC can be used. + +Configurations +============== + +Common Configuration Notes +-------------------------- + + 1. Each Qemu-intel64 configuration is maintained in a sub-directory + and can be selected as follow: + + tools/configure.sh qemu-intel64: + + Where is one of the configuration sub-directories described in + the following paragraph. + + 2. These configurations use the mconf-based configuration tool. To + change a configurations using that tool, you should: + + a. Build and install the kconfig-mconf tool. See nuttx/README.txt + see additional README.txt files in the NuttX tools repository. + + b. Execute 'make menuconfig' in nuttx/ in order to start the + reconfiguration process. + + 3. By default, all configurations assume the Linux. This is easily + reconfigured: + + CONFIG_HOST_LINUX=y + +Configuration Sub-Directories +----------------------------- + + ostest + + The "standard" NuttX examples/ostest configuration. diff --git a/boards/x86_64/intel64/qemu-intel64/configs/ostest/defconfig b/boards/x86_64/intel64/qemu-intel64/configs/ostest/defconfig new file mode 100644 index 00000000000..eb19359a092 --- /dev/null +++ b/boards/x86_64/intel64/qemu-intel64/configs/ostest/defconfig @@ -0,0 +1,114 @@ +# +# Automatically generated file; DO NOT EDIT. +# Nuttx/x86_64 Configuration +# + +CONFIG_BUILD_FLAT=y + +CONFIG_ARCH_X86_64=y +CONFIG_ARCH_INTEL64=y +CONFIG_ARCH_BOARD_QEMU=y + +CONFIG_ARCH="x86_64" +CONFIG_ARCH_CHIP="intel64" +CONFIG_ARCH_BOARD="qemu-intel64" + +CONFIG_ARCH_INTEL64_HAVE_TSC_DEADLINE=y +CONFIG_ARCH_INTEL64_CORE_FREQ_KHZ=2600000 +CONFIG_ARCH_INTEL64_HAVE_SSE3=y +CONFIG_ARCH_INTEL64_HAVE_PCID=y +CONFIG_ARCH_INTEL64_HAVE_RDRAND=y +CONFIG_ARCH_SIZET_LONG=y + +CONFIG_BOARD_LOOPSPERMSEC=999 +CONFIG_BOOT_RUNFROMEXTSRAM=y + +CONFIG_RAM_START=0x0 +CONFIG_RAM_SIZE=268435456 + +CONFIG_ARCH_BOARD_INTEL64_QEMU=y + +CONFIG_SCHED_TICKLESS=y +CONFIG_SCHED_TICKLESS_ALARM=y +CONFIG_SCHED_TICKLESS_LIMIT_MAX_SLEEP=y +CONFIG_USEC_PER_TICK=1 +CONFIG_SYSTEM_TIME64=y +CONFIG_CLOCK_MONOTONIC=y +CONFIG_START_YEAR=2011 +CONFIG_START_MONTH=3 +CONFIG_START_DAY=3 +CONFIG_MAX_WDOGPARMS=4 +CONFIG_PREALLOC_WDOGS=32 +CONFIG_WDOG_INTRESERVE=4 +CONFIG_PREALLOC_TIMERS=8 + +CONFIG_INIT_ENTRYPOINT=y +CONFIG_USER_ENTRYPOINT="ostest_main" +CONFIG_USERMAIN_PRIORITY=100 +CONFIG_RR_INTERVAL=0 +CONFIG_TASK_NAME_SIZE=31 +CONFIG_MAX_TASKS=64 +CONFIG_SCHED_HAVE_PARENT=y +CONFIG_SCHED_CHILD_STATUS=y +CONFIG_PREALLOC_CHILDSTATUS=16 +CONFIG_SCHED_WAITPID=y + +CONFIG_NPTHREAD_KEYS=4 +CONFIG_PTHREAD_MUTEX_TYPES=y +CONFIG_PTHREAD_MUTEX_ROBUST=y + +CONFIG_DEV_CONSOLE=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_NFILE_DESCRIPTORS=32 +CONFIG_NFILE_STREAMS=16 +CONFIG_NAME_MAX=32 +CONFIG_PATH_MAX=256 +CONFIG_PRIORITY_INHERITANCE=y +CONFIG_SEM_PREALLOCHOLDERS=16 +CONFIG_SEM_NNESTPRIO=16 + +CONFIG_SIG_DEFAULT=y + +CONFIG_SIG_SIGSTOP_ACTION=y +CONFIG_SIG_SIGKILL_ACTION=y +CONFIG_SIG_SIGPIPE_ACTION=y + +CONFIG_SIG_SIGCONDTIMEDOUT=16 + +CONFIG_PREALLOC_MQ_MSGS=32 +CONFIG_MQ_MAXMSGSIZE=32 + +CONFIG_IDLETHREAD_STACKSIZE=4194304 +CONFIG_USERMAIN_STACKSIZE=4194304 +CONFIG_PTHREAD_STACK_MIN=4194304 +CONFIG_PTHREAD_STACK_DEFAULT=4194304 + +CONFIG_ARCH_HAVE_SERIAL_TERMIOS=y +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +CONFIG_16550_UART=y +CONFIG_16550_UART0=y +CONFIG_16550_UART0_BASE=0x3f8 +CONFIG_16550_UART0_CLOCK=1843200 +CONFIG_16550_UART0_IRQ=36 +CONFIG_16550_UART0_BAUD=115200 +CONFIG_16550_UART0_PARITY=0 +CONFIG_16550_UART0_BITS=8 +CONFIG_16550_UART0_2STOP=0 +CONFIG_16550_UART0_RXBUFSIZE=16 +CONFIG_16550_UART0_TXBUFSIZE=16 +CONFIG_16550_UART0_SERIAL_CONSOLE=y +CONFIG_16550_REGINCR=1 +CONFIG_16550_REGWIDTH=8 +CONFIG_16550_ADDRWIDTH=16 + +CONFIG_SYSLOG_DEFAULT=y +CONFIG_CONSOLE_SYSLOG=y + +CONFIG_TESTING_OSTEST=y +CONFIG_TESTING_OSTEST_LOOPS=1 +CONFIG_TESTING_OSTEST_STACKSIZE=4149304 +CONFIG_TESTING_OSTEST_NBARRIER_THREADS=8 +CONFIG_TESTING_OSTEST_RR_RANGE=10000 +CONFIG_TESTING_OSTEST_RR_RUNS=10 +CONFIG_TESTING_OSTEST_WAITRESULT=y diff --git a/boards/x86_64/intel64/qemu-intel64/include/board.h b/boards/x86_64/intel64/qemu-intel64/include/board.h new file mode 100644 index 00000000000..22b12cbbf89 --- /dev/null +++ b/boards/x86_64/intel64/qemu-intel64/include/board.h @@ -0,0 +1,75 @@ +/**************************************************************************** + * boards/x86_64/intel/qemu/include/board.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 __BOARDS_X86_64_INTEL64_QEMU_INCLUDE_BOARD_H +#define __BOARDS_X86_64_INTEL64_QEMU_INCLUDE_BOARD_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Clocking *****************************************************************/ + +/* Programmable interval timer (PIT) */ + +#define PIT_CLOCK 1041816 /* PIT input clock */ + +/* LED definitions **********************************************************/ + +/* Button definitions *******************************************************/ + +/* Alternate pin selections *************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_X86_64_INTEL64_QEMU_INCLUDE_BOARD_H */ diff --git a/boards/x86_64/intel64/qemu-intel64/scripts/Make.defs b/boards/x86_64/intel64/qemu-intel64/scripts/Make.defs new file mode 100644 index 00000000000..ced23afcd56 --- /dev/null +++ b/boards/x86_64/intel64/qemu-intel64/scripts/Make.defs @@ -0,0 +1,93 @@ +############################################################################ +# boards/x86_64/intel64/qemu/scripts/Make.defs +# +# 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. +# +############################################################################ + +include ${TOPDIR}/.config +include ${TOPDIR}/tools/Config.mk + +HOSTOS = ${shell uname -o 2>/dev/null || echo "Other"} + +ifeq ($(CONFIG_DEBUG_SYMBOLS),y) + ARCHOPTIMIZATION = -g +endif + +ifneq ($(CONFIG_DEBUG_NOOPT),y) + ARCHOPTIMIZATION += -O2 -fno-optimize-sibling-calls -fno-omit-frame-pointer -fno-crossjumping -fno-delete-null-pointer-checks + +endif + +ifeq ($(WINTOOL),y) + # Windows-native toolchains + DIRLINK = $(TOPDIR)/tools/copydir.sh + DIRUNLINK = $(TOPDIR)/tools/unlink.sh + MKDEP = $(TOPDIR)/tools/mkwindeps.sh + ARCHINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}" + ARCHXXINCLUDES = -I. -isystem "${shell cygpath -w $(TOPDIR)/include}" -isystem "${shell cygpath -w $(TOPDIR)/include/cxx}" + ARCHSCRIPT = -T "${shell cygpath -w $(TOPDIR)/boards/$(CONFIG_ARCH)/$(CONFIG_ARCH_CHIP)/$(CONFIG_ARCH_BOARD)/scripts/qemu.ld}" + MAXOPTIMIZATION = -O2 +else + # Linux/Cygwin-native toolchain + MKDEP = $(TOPDIR)/tools/mkdeps$(HOSTEXEEXT) + ARCHINCLUDES = -I. -isystem $(TOPDIR)/include + ARCHXXINCLUDES = -I. -isystem $(TOPDIR)/include -isystem $(TOPDIR)/include/cxx + ARCHSCRIPT = -T$(TOPDIR)/boards/$(CONFIG_ARCH)/$(CONFIG_ARCH_CHIP)/$(CONFIG_ARCH_BOARD)/scripts/qemu.ld +endif + +ARCHCPUFLAGS = -fPIC -fno-builtin -fno-stack-protector -mno-red-zone -mrdrnd +ARCHPICFLAGS = -fPIC +ARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -Wundef +ARCHDEFINES = + +# We have to use a cross-development toolchain under Cygwin because the native +# Cygwin toolchains don't generate ELF binaries. + +ifeq ($(HOSTOS),Cygwin) +CROSSDEV = i486-nuttx-elf- +else +CROSSDEV = +endif + +CC = $(CROSSDEV)gcc +CPP = $(CROSSDEV)gcc -E +LD = $(CROSSDEV)ld +STRIP = $(CROSSDEV)strip --strip-unneeded +AR = $(CROSSDEV)ar rcs +NM = $(CROSSDEV)nm +OBJCOPY = $(CROSSDEV)objcopy +OBJDUMP = $(CROSSDEV)objdump + +CFLAGS = $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe +CPPFLAGS = $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) +AFLAGS = $(CFLAGS) -D__ASSEMBLY__ + +ASMEXT = .S +OBJEXT = .o +LIBEXT = .a +EXEEXT = .elf + +ifeq ($(CONFIG_DEBUG_SYMBOLS),y) + LDFLAGS += -g +endif + +MKDEP = $(TOPDIR)/tools/mkdeps$(HOSTEXEEXT) + +HOSTCC = gcc +HOSTINCLUDESv = -I. +HOSTCFLAGS = -Wall -Wstrict-prototypes -Wshadow -Wundef -g -pipe +HOSTLDFLAGS = diff --git a/boards/x86_64/intel64/qemu-intel64/scripts/qemu.ld b/boards/x86_64/intel64/qemu-intel64/scripts/qemu.ld new file mode 100644 index 00000000000..761935ad866 --- /dev/null +++ b/boards/x86_64/intel64/qemu-intel64/scripts/qemu.ld @@ -0,0 +1,114 @@ +/**************************************************************************** + * boards/x86_64/intel64/qemu/scripts/qemu.ld + * + * 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. + * + ****************************************************************************/ + +OUTPUT_ARCH(i386:x86-64) +ENTRY(__pmode_entry) +SECTIONS +{ + . = 0x4M; + _kernel_physical_start = .; + + .loader.text : { + . = ALIGN(8); + KEEP(*(.multiboot)) + *(.loader.text) + } + + .loader.rodata : { + *(.loader.rodata) + } + + .loader.data : { + *(.loader.data) + } + + .loader.bss : { + *(.loader.bss) + } + + . = ALIGN(0x1000); + _boot_end = .; + + . += 0x100000000; + _kernel_virtual_start = .; + + .text : AT(_boot_end) + { + _stext = ABSOLUTE(.); + . = ALIGN(8); + KEEP(*(.multiboot)) + *(.text .text.*) + *(.gnu.linkonce.t.*) + _etext = ABSOLUTE(.); + } + + .rodata ALIGN(0x1000) : AT ( (LOADADDR (.text) + SIZEOF (.text) + 0xFFF) & 0xFFFFFFFFFFFFF000 ) + { + _srodata = ABSOLUTE(.); + *(.rodata .rodata.*) + *(.fixup) + *(.gnu.warning) + *(.glue_7) + *(.glue_7t) + *(.got) + *(.gcc_except_table) + *(.gnu.linkonce.r.*) + *(.eh_frame) + _erodata = ABSOLUTE(.); + } + + .data ALIGN(0x1000) : AT ( (LOADADDR (.rodata) + SIZEOF (.rodata) + 0xFFF) & 0xFFFFFFFFFFFFF000 ) + { + _sdata = ABSOLUTE(.); + *(.data .data.*) + *(.gnu.linkonce.d.*) + CONSTRUCTORS + . = ALIGN(4); + _edata = ABSOLUTE(.); + } + + .bss ALIGN(0x1000) : AT ( (LOADADDR (.data) + SIZEOF (.data) + 0xFFF) & 0xFFFFFFFFFFFFF000 ) + { + _sbss = ABSOLUTE(.); + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = ABSOLUTE(.); + } + + _kernel_virtual_end = .; + + _kernel_physical_end = (LOADADDR (.bss) + SIZEOF (.bss) + 0xFFF) & 0xFFFFFFFFFFFFF000; + + /* Stabs debugging sections */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/x86_64/intel64/qemu-intel64/src/.gitignore b/boards/x86_64/intel64/qemu-intel64/src/.gitignore new file mode 100644 index 00000000000..726d936e1e3 --- /dev/null +++ b/boards/x86_64/intel64/qemu-intel64/src/.gitignore @@ -0,0 +1,2 @@ +/.depend +/Make.dep diff --git a/boards/x86_64/intel64/qemu-intel64/src/Makefile b/boards/x86_64/intel64/qemu-intel64/src/Makefile new file mode 100644 index 00000000000..990c43138fb --- /dev/null +++ b/boards/x86_64/intel64/qemu-intel64/src/Makefile @@ -0,0 +1,30 @@ +############################################################################ +# boards/x86_64/intel64/qemu/src/Makefile +# +# 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. +# +############################################################################ + +-include $(TOPDIR)/Make.defs + +ASRCS = +CSRCS = qemu_boot.c qemu_freq.c qemu_net.c + +ifeq ($(CONFIG_LIB_BOARDCTL),y) + CSRCS += qemu_appinit.c +endif + +include $(TOPDIR)/boards/Board.mk diff --git a/boards/x86_64/intel64/qemu-intel64/src/qemu_appinit.c b/boards/x86_64/intel64/qemu-intel64/src/qemu_appinit.c new file mode 100644 index 00000000000..50fcb30e601 --- /dev/null +++ b/boards/x86_64/intel64/qemu-intel64/src/qemu_appinit.c @@ -0,0 +1,64 @@ +/**************************************************************************** + * boards/x86_64/intel64/qemu/src/qemu_appinit.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 "up_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_app_initialize + * + * Description: + * Perform application specific initialization. This function is never + * called directly from application code, but only indirectly via the + * (non-standard) boardctl() interface using the command BOARDIOC_INIT. + * + * Input Parameters: + * arg - The boardctl() argument is passed to the board_app_initialize() + * implementation without modification. The argument has no + * meaning to NuttX; the meaning of the argument is a contract + * between the board-specific initialization logic and the + * matching application logic. The value cold be such things as a + * mode enumeration value, a set of DIP switch switch settings, a + * pointer to configuration data read from a file or serial FLASH, + * or whatever you would like to do with it. Every implementation + * should accept zero/NULL as a default configuration. + * + * Returned Value: + * Zero (OK) is returned on success; a negated errno value is returned on + * any failure to indicate the nature of the failure. + * + ****************************************************************************/ + +#ifdef CONFIG_LIB_BOARDCTL +int board_app_initialize(uintptr_t arg) +{ + return 0; +} +#endif /* CONFIG_LIB_BOARDCTL */ diff --git a/boards/x86_64/intel64/qemu-intel64/src/qemu_boot.c b/boards/x86_64/intel64/qemu-intel64/src/qemu_boot.c new file mode 100644 index 00000000000..d80e90535b2 --- /dev/null +++ b/boards/x86_64/intel64/qemu-intel64/src/qemu_boot.c @@ -0,0 +1,76 @@ +/**************************************************************************** + * boards/x86_64/intel64/qemu/src/qemu_boot.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 "up_arch.h" +#include "up_internal.h" + +#include "qemu_intel64.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: x86_64_boardinitialize + * + * Description: + * All x86_64 architectures must provide the following entry point. + * This entry point is called early in the initialization -- after all + * memory has been configured and mapped but before any devices have been + * initialized. + * + ****************************************************************************/ + +void x86_64_boardinitialize(void) +{ +#if defined(CONFIG_16550_UART0) && (CONFIG_16550_UART0_BASE == 0x3f8) + uart_putreg(CONFIG_16550_UART0_BASE, UART_MCR_OFFSET, UART_MCR_OUT2); +#endif + +#if defined(CONFIG_16550_UART1) && (CONFIG_16550_UART1_BASE == 0x3f8) + uart_putreg(CONFIG_16550_UART1_BASE, UART_MCR_OFFSET, UART_MCR_OUT2); +#endif + + /* Configure on-board LEDs if LED support has been selected. */ + +#ifdef CONFIG_ARCH_LEDS + board_autoled_initialize(); +#endif +} diff --git a/boards/x86_64/intel64/qemu-intel64/src/qemu_freq.c b/boards/x86_64/intel64/qemu-intel64/src/qemu_freq.c new file mode 100644 index 00000000000..ad3a945bc80 --- /dev/null +++ b/boards/x86_64/intel64/qemu-intel64/src/qemu_freq.c @@ -0,0 +1,96 @@ +/**************************************************************************** + * boards/x86_64/intel64/qemu/src/qemu_freq.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 + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern unsigned long x86_64_timer_freq; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: x86_64_timer_initialize + * + * Description: + * Initializes all platform-specific timer facilities. This function is + * called early in the initialization sequence by up_intialize(). + * On return, the current up-time should be available from + * up_timer_gettime() and the interval timer is ready for use (but not + * actively timing. + * + * Provided by platform-specific code and called from the architecture- + * specific logic. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + * Assumptions: + * Called early in the initialization sequence before any special + * concurrency protections are required. + * + ****************************************************************************/ + +void x86_64_timer_calibrate_freq(void) +{ +#ifdef CONFIG_ARCH_INTEL64_HAVE_TSC_DEADLINE + + unsigned long crystal_freq; + unsigned long numerator; + unsigned long denominator; + + asm volatile("cpuid" : "=c" (crystal_freq), "=b" (numerator), "=a" (denominator) + : "a" (X86_64_CPUID_TSC) + : "rdx", "memory"); + + if (numerator == 0 || denominator == 0 || crystal_freq == 0) + { + x86_64_timer_freq = CONFIG_ARCH_INTEL64_CORE_FREQ_KHZ * 1000L; + } + else + { + x86_64_timer_freq = crystal_freq / denominator * numerator; + } + +#else + x86_64_timer_freq = CONFIG_ARCH_INTEL64_APIC_FREQ_KHZ * 1000L; +#endif +} diff --git a/boards/x86_64/intel64/qemu-intel64/src/qemu_intel64.h b/boards/x86_64/intel64/qemu-intel64/src/qemu_intel64.h new file mode 100644 index 00000000000..a400d59975a --- /dev/null +++ b/boards/x86_64/intel64/qemu-intel64/src/qemu_intel64.h @@ -0,0 +1,52 @@ +/**************************************************************************** + * boards/x86_64/intel64/qemu/src/qemu_intel64.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 __BOARDS_X86_64_INTEL64_QEMU_SRC_QEMU_INTEL64_H +#define __BOARDS_X86_64_INTEL64_QEMU_SRC_QEMU_INTEL64_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* GPIO Pin Definitions *****************************************************/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_X86_64_INTEL64_QEMU_SRC_QEMU_INTEL64_H */ diff --git a/boards/x86_64/intel64/qemu-intel64/src/qemu_net.c b/boards/x86_64/intel64/qemu-intel64/src/qemu_net.c new file mode 100644 index 00000000000..28b1c86a99c --- /dev/null +++ b/boards/x86_64/intel64/qemu-intel64/src/qemu_net.c @@ -0,0 +1,59 @@ +/************************************************************************************ + * oards/x86_64/intel64/qemu/src/qemu_net.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 "up_arch.h" +#include "up_internal.h" + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/************************************************************************************ + * Name: up_netinitialize + * + * Description: + * All x86 architectures must provide the following function to setup the on board + * Ethernet device. This function is called in the initialization. + * + ************************************************************************************/ + +#ifdef CONFIG_NET +void up_netinitialize(void) +{ + return; +} +#endif +