Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,34 @@ Basic command to run the image without additional PCI devices attached::
qemu-system-x86_64 -m 2G -cpu host -smp 4 -enable-kvm \
-kernel nuttx -nographic -serial mon:stdio


knsh_romfs
----------

This is similar to the ``nsh`` configuration except that NuttX
is built as a kernel-mode, monolithic module, and the user applications
are built separately. It uses ROMFS to load the user-space applications.
This is intended to run on QEMU with COM serial port support.

Steps to build kernel image with user-space apps in ROMFS::

./tools/configure.sh qemu-intel64/knsh_romfs
make -j
make export -j
pushd ../apps
./tools/mkimport.sh -z -x ../nuttx/nuttx-export-*.tar.gz
make import -j
./tools/mkromfsimg.sh
mv boot_romfsimg.h ../nuttx/arch/x86_64/src/board/romfs_boot.c
popd
make -j

knsh_romfs_pci
--------------

This is similar to the ``knsh_romfs`` configuration except that it is intended
to run on a bare metal Intel hardware with PCI serial port support.

lvgl
----

Expand Down
9 changes: 9 additions & 0 deletions Documentation/platforms/x86_64/intel64/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ and use ``-cdrom boot.iso`` (multiboot2 framebuffer doesn't work with
Also, your GRUB configuration (``grub.cfg``) should insert the appropriate video
module, in many cases ``insmod all_video`` should be enough.

Kernel build
------------

Kernel build is supported.

.. warning::
IMPORTANT: the current implementation doesn't include any protection against
speculative execution vulnerabilities (Spectre, Meltdown and others) !

Creating a bootable disk
========================

Expand Down
2 changes: 1 addition & 1 deletion arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ config ARCH_X86_64
select LIBC_ARCH_ELF_64BIT if LIBC_ARCH_ELF
select ARCH_TOOLCHAIN_GNU
select ARCH_HAVE_BACKTRACE
select ARCH_HAVE_FORK
select ARCH_HAVE_FORK if !BUILD_KERNEL
select ARCH_HAVE_SETJMP
select ARCH_HAVE_PERF_EVENTS
---help---
Expand Down
526 changes: 284 additions & 242 deletions arch/x86_64/include/intel64/arch.h

Large diffs are not rendered by default.

49 changes: 48 additions & 1 deletion arch/x86_64/include/intel64/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,10 @@

#define IRQ_MSI_START IRQ32

/* Use IRQ17 for TLB shootdown */

#define SMP_IPI_TLBSHOOTDOWN_IRQ IRQ17

/* Common register save structure created by up_saveusercontext() and by
* ISR/IRQ interrupt processing.
*/
Expand Down Expand Up @@ -499,10 +503,27 @@ enum ioapic_trigger_mode
TRIGGER_LEVEL_ACTIVE_LOW = (1 << 15) | (1 << 13),
};

/* This structure represents the return state from a system call */

#ifdef CONFIG_LIB_SYSCALL
struct xcpt_syscall_s
{
uintptr_t sysreturn; /* The return address */
};
#endif

/* This struct defines the way the registers are stored */

struct xcptcontext
{
#ifdef CONFIG_BUILD_KERNEL
/* This is the saved address to use when returning from a user-space
* signal handler.
*/

uintptr_t sigreturn;
#endif

/* These are saved copies of instruction pointer and EFLAGS used during
* signal processing.
*/
Expand All @@ -511,9 +532,35 @@ struct xcptcontext
uint64_t saved_rflags;
uint64_t saved_rsp;

#ifdef CONFIG_ARCH_KERNEL_STACK
/* For kernel stack enabled we can't use tcb->xcp.regs[REG_RSP] as it may
* point to kernel stack if signaled task is waiting now in
* up_switch_context()
*/

uint64_t saved_ursp;
#endif

/* Register save area - allocated from stack in up_initial_state() */

uint64_t *regs;

#ifdef CONFIG_ARCH_ADDRENV
# ifdef CONFIG_ARCH_KERNEL_STACK
/* In this configuration, all syscalls execute from an internal kernel
* stack. Why? Because when we instantiate and initialize the address
* environment of the new user process, we will temporarily lose the
* address environment of the old user process, including its stack
* contents. The kernel C logic will crash immediately with no valid
* stack in place.
*/

uintptr_t *ustkptr; /* Saved user stack pointer */
uintptr_t *kstack; /* Allocate base of the (aligned) kernel stack */
uintptr_t *ktopstk; /* Top of kernel stack */
uintptr_t *kstkptr; /* Saved kernel stack pointer */
# endif
#endif
};
#endif

Expand Down Expand Up @@ -571,7 +618,7 @@ static inline void set_pcid(uint64_t pcid)

static inline void set_cr3(uint64_t cr3)
{
__asm__ volatile("mov %0, %%cr3" : "=rm"(cr3) : : "memory");
__asm__ volatile("mov %0, %%cr3" :: "r"(cr3));
}

static inline uint64_t get_cr3(void)
Expand Down
31 changes: 31 additions & 0 deletions arch/x86_64/include/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@
# include <arch/intel64/irq.h>
#endif

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

#define X86_64_CPUPRIV_USTACK_OFFSET (16)
#define X86_64_CPUPRIV_UVBASE_OFFSET (24)
#define X86_64_CPUPRIV_KTOPSTK_OFFSET (32)

/****************************************************************************
* Public Data
****************************************************************************/
Expand All @@ -65,6 +73,29 @@ struct intel64_cpu_s
*/

uint64_t *current_regs;

#ifdef CONFIG_LIB_SYSCALL
/* Current user RSP for syscall */

uint64_t *ustack;

/* Userspace virtual address */

uint64_t *uvbase;
#endif

#ifdef CONFIG_ARCH_KERNEL_STACK
/* Kernel stack pointer.
*
* We have to track the current kernel stack pointer to handle
* syscalls in kernel mode. All registers are occupied when entering
* syscall, so we cannot get this value from tcb in syscall handler.
* We keep referenve to kernel stack in CPU private data and update it
* at each context switch.
*/

uint64_t *ktopstk;
#endif
};

/****************************************************************************
Expand Down
94 changes: 70 additions & 24 deletions arch/x86_64/include/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,52 @@
* Pre-processor Definitions
****************************************************************************/

/* Configuration ************************************************************/

#ifndef CONFIG_BUILD_FLAT
# define CONFIG_SYS_RESERVED 4
#else
# define CONFIG_SYS_RESERVED 0
#endif

/* system calls */

#ifndef CONFIG_BUILD_FLAT
/* SYS call 0:
*
* void up_task_start(main_t taskentry, int argc, char *argv[])
* noreturn_function;
*/

# define SYS_task_start (0)

/* SYS call 1:
*
* void up_pthread_start((pthread_startroutine_t startup,
* pthread_startroutine_t entrypt, pthread_addr_t arg)
* noreturn_function
*/

# define SYS_pthread_start (1)

/* SYS call 2:
*
* void signal_handler(_sa_sigaction_t sighand,
* int signo, siginfo_t *info,
* void *ucontext);
*/

# define SYS_signal_handler (2)

/* SYS call 3:
*
* void signal_handler_return(void);
*/

# define SYS_signal_handler_return (3)

#endif /* !CONFIG_BUILD_FLAT */

/****************************************************************************
* Public Types
****************************************************************************/
Expand All @@ -57,15 +103,6 @@ extern "C"
#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,
Expand Down Expand Up @@ -126,24 +163,33 @@ static inline uintptr_t sys_call6(unsigned int nbr, uintptr_t parm1,
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__
uint64_t ret;

/* Registers modified by syscall instruction:
* RCX = RIP
* R11 = RFLAGS
* RIP = IA32_LSTAR (x86_64_syscall_entry)
*/

__asm__ volatile
(
"syscall"
: "=r"(reg0)
: "r"(reg0), "r"(reg1), "r"(reg2),
"r"(reg3), "r"(reg4), "r"(reg5), "r"(reg6)
: "memory"
"movq %1, %%rax\n"
"movq %2, %%rdi\n"
"movq %3, %%rsi\n"
"movq %4, %%rdx\n"
"movq %5, %%r10\n"
"movq %6, %%r8\n"
"movq %7, %%r9\n"
"syscall\n"
"movq %%rax, %0\n"
: "=r"(ret)
: "rm"(nbr), "rm"(parm1), "rm"(parm2),
"rm"(parm3), "rm"(parm4), "rm"(parm5),
"rm"(parm6)
: "memory", "rcx", "r11"
);

return reg0;
return ret;
}

#undef EXTERN
Expand Down
23 changes: 21 additions & 2 deletions arch/x86_64/src/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,17 @@ set(SRCS
x86_64_modifyreg32.c
x86_64_nputs.c
x86_64_switchcontext.c
x86_64_tcbinfo.c)
x86_64_tcbinfo.c
x86_64_tlb.c)

if(CONFIG_ARCH_HAVE_FORK)
list(APPEND SRCS x86_64_fork.c fork.S)
endif()

if(CONFIG_LIB_SYSCALL)
list(APPEND SRCS x86_64_syscall.c)
endif()

if(CONFIG_PCI)
list(APPEND SRCS x86_64_pci.c)
endif()
Expand All @@ -52,11 +57,25 @@ if(CONFIG_ARCH_USE_MMU)
endif()

if(CONFIG_ARCH_ADDRENV)
list(APPEND SRCS x86_64_addrenv.c x86_64_addrenv_perms.c)
list(APPEND SRCS x86_64_addrenv.c x86_64_pgalloc.c x86_64_addrenv_perms.c)
endif()

if(NOT CONFIG_BUILD_FLAT)
list(APPEND SRCS x86_64_task_start.c x86_64_pthread_start.c
x86_64_signal_dispatch.c)
endif()

if(NOT CONFIG_ALARM_ARCH)
list(APPEND SRCS x86_64_udelay.c x86_64_mdelay.c)
endif()

if(CONFIG_ARCH_KERNEL_STACK)
list(APPEND SRCS x86_64_addrenv_kstack.c)
endif()

if(NOT CONFIG_BUILD_FLAT)
list(APPEND SRCS x86_64_task_start.c x86_64_pthread_start.c
x86_64_signal_dispatch.c)
endif()

target_sources(arch PRIVATE ${SRCS})
Loading